diff --git a/opm/simulators/wells/BlackoilWellModel.hpp b/opm/simulators/wells/BlackoilWellModel.hpp index 7399c1de8..75163d99b 100644 --- a/opm/simulators/wells/BlackoilWellModel.hpp +++ b/opm/simulators/wells/BlackoilWellModel.hpp @@ -282,6 +282,11 @@ namespace Opm { void prepareTimeStep(DeferredLogger& deferred_logger); void initPrimaryVariablesEvaluation() const; void updateWellControls(DeferredLogger& deferred_logger, const bool checkGroupControls); + + void updateAndCommunicate(const int reportStepIdx, + const int iterationIdx, + DeferredLogger& deferred_logger); + WellInterfacePtr getWell(const std::string& well_name) const; bool hasWell(const std::string& well_name) const; diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index f55e80755..63c94adaa 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -780,7 +780,7 @@ checkGconsaleLimits(const Group& group, deferred_logger.info(ss.str()); } -void +bool BlackoilWellModelGeneric:: checkGroupHigherConstraints(const Group& group, DeferredLogger& deferred_logger, @@ -797,6 +797,7 @@ checkGroupHigherConstraints(const Group& group, ? pvt_region_idx_[0] : pvt_region_idx_[well_perf_data_[0][0].cell_index]; + bool changed = false; if ( comm_.size() > 1) { // Just like in the sequential case the pvtregion is determined @@ -832,7 +833,7 @@ checkGroupHigherConstraints(const Group& group, auto currentControl = this->groupState().injection_control(group.name(), phase); if (currentControl != Group::InjectionCMode::FLD && group.injectionGroupControlAvailable(phase)) { const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx); - const std::pair changed = WellGroupHelpers::checkGroupConstraintsInj( + const std::pair changed_this = WellGroupHelpers::checkGroupConstraintsInj( group.name(), group.parent(), parentGroup, @@ -848,10 +849,11 @@ checkGroupHigherConstraints(const Group& group, summaryState_, resv_coeff_inj, deferred_logger); - if (changed.first) { + if (changed_this.first) { switched_groups.insert(group.name()); actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, deferred_logger); - WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ true, this->groupState(), this->wellState()); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed_this.second, group, schedule(), reportStepIdx, /* isInjector */ true, this->groupState(), this->wellState()); + changed = true; } } } @@ -870,7 +872,7 @@ checkGroupHigherConstraints(const Group& group, const Group::ProductionCMode& currentControl = this->groupState().production_control(group.name()); if (currentControl != Group::ProductionCMode::FLD && group.productionGroupControlAvailable()) { const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx); - const std::pair changed = WellGroupHelpers::checkGroupConstraintsProd( + const std::pair changed_this = WellGroupHelpers::checkGroupConstraintsProd( group.name(), group.parent(), parentGroup, @@ -885,28 +887,33 @@ checkGroupHigherConstraints(const Group& group, summaryState_, resv_coeff, deferred_logger); - if (changed.first) { + if (changed_this.first) { switched_groups.insert(group.name()); const auto exceed_action = group.productionControls(summaryState_).exceed_action; actionOnBrokenConstraints(group, exceed_action, Group::ProductionCMode::FLD, deferred_logger); - WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed_this.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); + changed = true; } } } // call recursively down the group hiearchy for (const std::string& groupName : group.groups()) { - checkGroupHigherConstraints( schedule().getGroup(groupName, reportStepIdx), deferred_logger, reportStepIdx, switched_groups); - } + bool changed_this = checkGroupHigherConstraints( schedule().getGroup(groupName, reportStepIdx), deferred_logger, reportStepIdx, switched_groups); + changed = changed || changed_this; + } + + return changed; } -void +bool BlackoilWellModelGeneric:: updateGroupIndividualControl(const Group& group, DeferredLogger& deferred_logger, const int reportStepIdx, std::set& switched_groups) { + bool changed = false; const bool skip = switched_groups.count(group.name()); if (!skip && group.isInjectionGroup()) { @@ -915,33 +922,38 @@ updateGroupIndividualControl(const Group& group, if (!group.hasInjectionControl(phase)) { continue; } - const auto& changed = checkGroupInjectionConstraints(group, reportStepIdx, phase); - if (changed.first != Group::InjectionCMode::NONE) + const auto& changed_this = checkGroupInjectionConstraints(group, reportStepIdx, phase); + if (changed_this.first != Group::InjectionCMode::NONE) { switched_groups.insert(group.name()); - actionOnBrokenConstraints(group, changed.first, phase, deferred_logger); - WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); + actionOnBrokenConstraints(group, changed_this.first, phase, deferred_logger); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed_this.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); + changed = true; } } } if (!skip && group.isProductionGroup()) { - const auto& changed = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger); + const auto& changed_this = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger); const auto controls = group.productionControls(summaryState_); - if (changed.first != Group::ProductionCMode::NONE) + if (changed_this.first != Group::ProductionCMode::NONE) { switched_groups.insert(group.name()); - actionOnBrokenConstraints(group, controls.exceed_action, changed.first, deferred_logger); - WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); + actionOnBrokenConstraints(group, controls.exceed_action, changed_this.first, deferred_logger); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed_this.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); + changed = true; } } // call recursively down the group hiearchy for (const std::string& groupName : group.groups()) { - updateGroupIndividualControl( schedule().getGroup(groupName, reportStepIdx), deferred_logger, reportStepIdx, switched_groups); + bool changed_this = updateGroupIndividualControl( schedule().getGroup(groupName, reportStepIdx), deferred_logger, reportStepIdx, switched_groups); + changed = changed || changed_this; } + + return changed; } -void +bool BlackoilWellModelGeneric:: updateGroupIndividualControls(DeferredLogger& deferred_logger, std::set& switched_groups, @@ -952,21 +964,21 @@ updateGroupIndividualControls(DeferredLogger& deferred_logger, // don't switch group control when iterationIdx > nupcol // to avoid oscilations between group controls if (iterationIdx > nupcol) - return; + return false; const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx); - updateGroupIndividualControl(fieldGroup, deferred_logger, - reportStepIdx, switched_groups); + return updateGroupIndividualControl(fieldGroup, deferred_logger, + reportStepIdx, switched_groups); } -void +bool BlackoilWellModelGeneric:: updateGroupHigherControls(DeferredLogger& deferred_logger, const int reportStepIdx, std::set& switched_groups) { const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx); - checkGroupHigherConstraints(fieldGroup, deferred_logger, reportStepIdx, switched_groups); + return checkGroupHigherConstraints(fieldGroup, deferred_logger, reportStepIdx, switched_groups); } void diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index c0b1c31b9..114662f76 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -304,22 +304,22 @@ protected: const int reportStepIdx, DeferredLogger& deferred_logger); - void checkGroupHigherConstraints(const Group& group, + bool checkGroupHigherConstraints(const Group& group, DeferredLogger& deferred_logger, const int reportStepIdx, std::set& switched_groups); - void updateGroupIndividualControl(const Group& group, + bool updateGroupIndividualControl(const Group& group, DeferredLogger& deferred_logger, const int reportStepIdx, std::set& switched_groups); - void updateGroupIndividualControls(DeferredLogger& deferred_logger, + bool updateGroupIndividualControls(DeferredLogger& deferred_logger, std::set& switched_groups, const int reportStepIdx, const int iterationIdx); - void updateGroupHigherControls(DeferredLogger& deferred_logger, + bool updateGroupHigherControls(DeferredLogger& deferred_logger, const int reportStepIdx, std::set& switched_groups); diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index 8b4ce6847..60772e9b2 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -1277,6 +1277,7 @@ namespace Opm { const int episodeIdx = ebosSimulator_.episodeIndex(); const int iterationIdx = ebosSimulator_.model().newtonMethod().numIterations(); + const auto& comm = ebosSimulator_.vanguard().grid().comm(); updateAndCommunicateGroupData(episodeIdx, iterationIdx); updateNetworkPressures(episodeIdx); @@ -1286,40 +1287,67 @@ namespace Opm { if (checkGroupControls) { // Check group individual constraints. - updateGroupIndividualControls(deferred_logger, switched_groups, - episodeIdx, iterationIdx); + bool changed_individual = updateGroupIndividualControls(deferred_logger, switched_groups, + episodeIdx, iterationIdx); + + if (changed_individual) + updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger); // Check group's constraints from higher levels. - updateGroupHigherControls(deferred_logger, - episodeIdx, - switched_groups); + bool changed_higher = updateGroupHigherControls(deferred_logger, + episodeIdx, + switched_groups); - updateAndCommunicateGroupData(episodeIdx, iterationIdx); + if (changed_higher) + updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger); // Check wells' group constraints and communicate. + bool changed_well_group = false; for (const auto& well : well_container_) { const auto mode = WellInterface::IndividualOrGroup::Group; - const bool changed = well->updateWellControl(ebosSimulator_, mode, this->wellState(), this->groupState(), deferred_logger); - if (changed) { + const bool changed_well = well->updateWellControl(ebosSimulator_, mode, this->wellState(), this->groupState(), deferred_logger); + if (changed_well) { switched_wells.insert(well->name()); + changed_well_group = changed_well || changed_well_group; } } - updateAndCommunicateGroupData(episodeIdx, iterationIdx); + changed_well_group = comm.sum(changed_well_group); + if (changed_well_group) + updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger); } // Check individual well constraints and communicate. + bool changed_well_individual = false; for (const auto& well : well_container_) { if (switched_wells.count(well->name())) { continue; } const auto mode = WellInterface::IndividualOrGroup::Individual; - well->updateWellControl(ebosSimulator_, mode, this->wellState(), this->groupState(), deferred_logger); + const bool changed_well = well->updateWellControl(ebosSimulator_, mode, this->wellState(), this->groupState(), deferred_logger); + if (changed_well) { + changed_well_individual = changed_well || changed_well_individual; + } } - updateAndCommunicateGroupData(episodeIdx, iterationIdx); + changed_well_individual = comm.sum(changed_well_individual); + if (changed_well_individual) + updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger); } - + template + void + BlackoilWellModel:: + updateAndCommunicate(const int reportStepIdx, + const int iterationIdx, + DeferredLogger& deferred_logger) + { + updateAndCommunicateGroupData(reportStepIdx, iterationIdx); + // if a well or group change control it affects all wells that are under the same group + for (const auto& well : well_container_) { + well->updateWellStateWithTarget(ebosSimulator_, this->groupState(), this->wellState(), deferred_logger); + } + updateAndCommunicateGroupData(reportStepIdx, iterationIdx); + } template void