diff --git a/opm/simulators/wells/BlackoilWellModel.hpp b/opm/simulators/wells/BlackoilWellModel.hpp index a9949c567..cb0b84b7e 100644 --- a/opm/simulators/wells/BlackoilWellModel.hpp +++ b/opm/simulators/wells/BlackoilWellModel.hpp @@ -464,8 +464,9 @@ template class WellContributions; bool updateWellControlsAndNetwork(const bool mandatory_network_balance, const double dt, DeferredLogger& local_deferredLogger); - - void computeWellGroupThp(const double dt, DeferredLogger& local_deferredLogger); + + double computeWellGroupTarget(DeferredLogger& local_deferredLogger); + bool computeWellGroupThp(const double dt, DeferredLogger& local_deferredLogger); /// Update rank's notion of intersecting wells and their /// associate solution variables. diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index d507a56ad..f4e0adff8 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -1312,6 +1312,7 @@ updateAndCommunicateGroupData(const int reportStepIdx, phase_usage_, guideRate_, well_state, + summaryState_, this->groupState(), groupTargetReduction); std::vector groupTargetReductionInj(numPhases(), 0.0); @@ -1322,6 +1323,7 @@ updateAndCommunicateGroupData(const int reportStepIdx, phase_usage_, guideRate_, well_state, + summaryState_, this->groupState(), groupTargetReductionInj); diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index 1f71795ad..fbcd57337 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -1378,7 +1379,7 @@ namespace Opm { // The wells of such group should have a common THP and total phase rate(s) obeying (if possible) // the well group constraint set by GCONPROD template - void + bool BlackoilWellModel:: computeWellGroupThp(const double dt, DeferredLogger& local_deferredLogger) { @@ -1388,19 +1389,19 @@ namespace Opm { const Scalar thp_tolerance = balance.thp_tolerance(); if (!network.active()) { - return; + return false; } auto& well_state = this->wellState(); auto& group_state = this->groupState(); + bool well_group_thp_updated = false; for (const std::string& nodeName : network.node_names()) { const bool has_choke = network.node(nodeName).as_choke(); if (has_choke) { const auto& summary_state = this->simulator_.vanguard().summaryState(); const Group& group = this->schedule().getGroup(nodeName, reportStepIdx); - const auto ctrl = group.productionControls(summary_state); - const auto cmode = ctrl.cmode; + const auto pu = this->phase_usage_; //TODO: Auto choke combined with RESV control is not supported std::vector resv_coeff(pu.num_phases, 1.0); @@ -1408,10 +1409,43 @@ namespace Opm { if (group_state.has_grat_sales_target(group.name())) gratTargetFromSales = group_state.grat_sales_target(group.name()); + const auto ctrl = group.productionControls(summary_state); + auto cmode_tmp = ctrl.cmode; + Scalar target_tmp{0.0}; + bool fld_none = false; + if (cmode_tmp == Group::ProductionCMode::FLD || cmode_tmp == Group::ProductionCMode::NONE) { + fld_none = true; + // Target is set for an ancestor group. Target for autochoke group to be + // derived via group guide rates + const Scalar efficiencyFactor = 1.0; + const Group& parentGroup = this->schedule().getGroup(group.parent(), reportStepIdx); + auto target = WellGroupControls::getAutoChokeGroupProductionTargetRate( + group.name(), + parentGroup, + well_state, + group_state, + this->schedule(), + summary_state, + resv_coeff, + efficiencyFactor, + reportStepIdx, + pu, + &this->guideRate_, + local_deferredLogger); + target_tmp = target.first; + cmode_tmp = target.second; + } + const auto cmode = cmode_tmp; WGHelpers::TargetCalculator tcalc(cmode, pu, resv_coeff, gratTargetFromSales, nodeName, group_state, group.has_gpmaint_control(cmode)); - const Scalar orig_target = tcalc.groupTarget(ctrl, local_deferredLogger); + if (!fld_none) + { + // Target is set for the autochoke group itself + target_tmp = tcalc.groupTarget(ctrl, local_deferredLogger); + } + + const Scalar orig_target = target_tmp; auto mismatch = [&] (auto group_thp) { Scalar group_rate(0.0); @@ -1507,9 +1541,14 @@ namespace Opm { } // Use the group THP in computeNetworkPressures(). - group_state.update_well_group_thp(nodeName, well_group_thp); + const auto& current_well_group_thp = group_state.is_autochoke_group(nodeName) ? group_state.well_group_thp(nodeName) : 1e30; + if (std::abs(current_well_group_thp - well_group_thp) > balance.pressure_tolerance()) { + well_group_thp_updated = true; + group_state.update_well_group_thp(nodeName, well_group_thp); + } } } + return well_group_thp_updated; } template @@ -2267,19 +2306,21 @@ namespace Opm { if (this->shouldBalanceNetwork(episodeIdx, iterationIdx) || mandatory_network_balance) { const double dt = this->simulator_.timeStepSize(); // Calculate common THP for subsea manifold well group (item 3 of NODEPROP set to YES) - computeWellGroupThp(dt, deferred_logger); + bool well_group_thp_updated = computeWellGroupThp(dt, deferred_logger); constexpr int max_number_of_sub_iterations = 20; constexpr Scalar damping_factor = 0.1; + bool more_network_sub_update = false; for (int i = 0; i < max_number_of_sub_iterations; i++) { const auto local_network_imbalance = this->updateNetworkPressures(episodeIdx, damping_factor); const Scalar network_imbalance = comm.max(local_network_imbalance); const auto& balance = this->schedule()[episodeIdx].network_balance(); constexpr Scalar relaxation_factor = 10.0; const Scalar tolerance = relax_network_tolerance ? relaxation_factor * balance.pressure_tolerance() : balance.pressure_tolerance(); - more_network_update = this->networkActive() && network_imbalance > tolerance; - if (!more_network_update) + more_network_sub_update = this->networkActive() && network_imbalance > tolerance; + if (!more_network_sub_update) break; } + more_network_update = more_network_sub_update || well_group_thp_updated; } bool changed_well_group = false; diff --git a/opm/simulators/wells/FractionCalculator.cpp b/opm/simulators/wells/FractionCalculator.cpp index 9e7ae0ff3..2a7230c66 100644 --- a/opm/simulators/wells/FractionCalculator.cpp +++ b/opm/simulators/wells/FractionCalculator.cpp @@ -37,6 +37,7 @@ FractionCalculator:: FractionCalculator(const Schedule& schedule, const WellState& well_state, const GroupState& group_state, + const SummaryState& summary_state, const int report_step, const GuideRate* guide_rate, const GuideRateModel::Target target, @@ -46,6 +47,7 @@ FractionCalculator(const Schedule& schedule, : schedule_(schedule) , well_state_(well_state) , group_state_(group_state) + , summary_state_(summary_state) , report_step_(report_step) , guide_rate_(guide_rate) , target_(target) @@ -123,6 +125,7 @@ guideRateSum(const Group& group, total_guide_rate += guideRate(child_group, always_included_child); } } + for (const std::string& child_well : group.wells()) { bool included = (child_well == always_included_child); if (is_producer_) { @@ -174,6 +177,8 @@ groupControlledWells(const std::string& group_name, return WellGroupHelpers::groupControlledWells(schedule_, well_state_, this->group_state_, + this->summary_state_, + this->guide_rate_, report_step_, group_name, always_included_child, diff --git a/opm/simulators/wells/FractionCalculator.hpp b/opm/simulators/wells/FractionCalculator.hpp index d421f5c3d..06962a393 100644 --- a/opm/simulators/wells/FractionCalculator.hpp +++ b/opm/simulators/wells/FractionCalculator.hpp @@ -41,6 +41,7 @@ public: FractionCalculator(const Schedule& schedule, const WellState& well_state, const GroupState& group_state, + const SummaryState& summary_state, const int report_step, const GuideRate* guide_rate, const GuideRateModel::Target target, @@ -65,6 +66,7 @@ private: const Schedule& schedule_; const WellState& well_state_; const GroupState& group_state_; + const SummaryState& summary_state_; int report_step_; const GuideRate* guide_rate_; GuideRateModel::Target target_; diff --git a/opm/simulators/wells/GroupState.cpp b/opm/simulators/wells/GroupState.cpp index 008f772a0..f1a78796f 100644 --- a/opm/simulators/wells/GroupState.cpp +++ b/opm/simulators/wells/GroupState.cpp @@ -124,6 +124,13 @@ GroupState::well_group_thp(const std::string& gname) const return group_iter->second; } +template +bool GroupState:: +GroupState::is_autochoke_group(const std::string& gname) const +{ + return (this->group_thp.count(gname) > 0); +} + //------------------------------------------------------------------------- template diff --git a/opm/simulators/wells/GroupState.hpp b/opm/simulators/wells/GroupState.hpp index 70c0bf61e..e98a77d9f 100644 --- a/opm/simulators/wells/GroupState.hpp +++ b/opm/simulators/wells/GroupState.hpp @@ -56,6 +56,7 @@ public: void update_well_group_thp(const std::string& gname, const double& thp); Scalar well_group_thp(const std::string& gname) const; + bool is_autochoke_group(const std::string& gname) const; bool has_production_reduction_rates(const std::string& gname) const; void update_production_reduction_rates(const std::string& gname, diff --git a/opm/simulators/wells/WellBhpThpCalculator.cpp b/opm/simulators/wells/WellBhpThpCalculator.cpp index 6ac4abe39..8407c0908 100644 --- a/opm/simulators/wells/WellBhpThpCalculator.cpp +++ b/opm/simulators/wells/WellBhpThpCalculator.cpp @@ -1051,7 +1051,7 @@ bruteForceBracketCommonTHP(const std::function& eq, Scalar& min_thp, Scalar& max_thp) { bool bracket_found = false; - constexpr int sample_number = 1000; + constexpr int sample_number = 1000; constexpr Scalar interval = 1E5; Scalar eq_low = eq(min_thp); Scalar eq_high = 0.0; diff --git a/opm/simulators/wells/WellGroupControls.cpp b/opm/simulators/wells/WellGroupControls.cpp index acb623083..5ed3f3d3d 100644 --- a/opm/simulators/wells/WellGroupControls.cpp +++ b/opm/simulators/wells/WellGroupControls.cpp @@ -151,6 +151,7 @@ getGroupInjectionControl(const Group& group, WGHelpers::FractionCalculator fcalc(schedule, well_state, group_state, + summaryState, well_.currentStep(), well_.guideRate(), tcalc.guideTargetMode(), @@ -284,6 +285,7 @@ getGroupInjectionTargetRate(const Group& group, WGHelpers::FractionCalculator fcalc(schedule, well_state, group_state, + summaryState, well_.currentStep(), well_.guideRate(), tcalc.guideTargetMode(), @@ -401,6 +403,7 @@ getGroupProductionControl(const Group& group, WGHelpers::FractionCalculator fcalc(schedule, well_state, group_state, + summaryState, well_.currentStep(), well_.guideRate(), tcalc.guideTargetMode(), @@ -499,6 +502,7 @@ getGroupProductionTargetRate(const Group& group, WGHelpers::FractionCalculator fcalc(schedule, well_state, group_state, + summaryState, well_.currentStep(), well_.guideRate(), tcalc.guideTargetMode(), @@ -549,6 +553,107 @@ getGroupProductionTargetRate(const Group& group, return scale; } +template +std::pair WellGroupControls:: +getAutoChokeGroupProductionTargetRate(const std::string& name, + const Group& group, + const WellState& well_state, + const GroupState& group_state, + const Schedule& schedule, + const SummaryState& summaryState, + const std::vector& resv_coeff, + Scalar efficiencyFactor, + const int reportStepIdx, + const PhaseUsage& pu, + const GuideRate* guideRate, + DeferredLogger& deferred_logger) +{ + const Group::ProductionCMode& currentGroupControl = group_state.production_control(group.name()); + if (currentGroupControl == Group::ProductionCMode::FLD || + currentGroupControl == Group::ProductionCMode::NONE) { + if (!group.productionGroupControlAvailable()) { + return std::make_pair(1.0, currentGroupControl); + } else { + // Produce share of parents control + const auto& parent = schedule.getGroup(group.parent(), reportStepIdx); + efficiencyFactor *= group.getGroupEfficiencyFactor(); + return getAutoChokeGroupProductionTargetRate(name, parent, well_state, group_state, + schedule, summaryState, + resv_coeff, efficiencyFactor, reportStepIdx, pu, + guideRate, deferred_logger); + } + } + + if (!group.isProductionGroup()) { + return std::make_pair(1.0, currentGroupControl); + } + + // If we are here, we are at the topmost group to be visited in the recursion. + // This is the group containing the control we will check against. + + // Make conversion factors for RESV <-> surface rates. + // std::vector resv_coeff(well_.phaseUsage().num_phases, 1.0); + // rateConverter(0, well_.pvtRegionIdx(), group.name(), resv_coeff); // FIPNUM region 0 here, should use FIPNUM from WELSPECS. + + // gconsale may adjust the grat target. + // the adjusted rates is send to the targetCalculator + Scalar gratTargetFromSales = 0.0; + if (group_state.has_grat_sales_target(group.name())) + gratTargetFromSales = group_state.grat_sales_target(group.name()); + + WGHelpers::TargetCalculator tcalc(currentGroupControl, + pu, + resv_coeff, + gratTargetFromSales, + group.name(), + group_state, + group.has_gpmaint_control(currentGroupControl)); + + WGHelpers::FractionCalculator fcalc(schedule, + well_state, + group_state, + summaryState, + reportStepIdx, + guideRate, + tcalc.guideTargetMode(), + pu, + true, + Phase::OIL); + + auto localFraction = [&](const std::string& child) { + return fcalc.localFraction(child, child); //Note child needs to be passed to always include since the global isGrup map is not updated yet. + }; + + auto localReduction = [&](const std::string& group_name) { + const std::vector& groupTargetReductions = group_state.production_reduction_rates(group_name); + return tcalc.calcModeRateFromRates(groupTargetReductions); + }; + + std::optional ctrl; + if (!group.has_gpmaint_control(currentGroupControl)) + ctrl = group.productionControls(summaryState); + + const double orig_target = tcalc.groupTarget(ctrl, deferred_logger); + const auto chain = WellGroupHelpers::groupChainTopBot(name, group.name(), + schedule, reportStepIdx); + // Because 'name' is the last of the elements, and not an ancestor, we subtract one below. + const std::size_t num_ancestors = chain.size() - 1; + double target = orig_target; + for (std::size_t ii = 0; ii < num_ancestors; ++ii) { + if ((ii == 0) || guideRate->has(chain[ii])) { + // Apply local reductions only at the control level + // (top) and for levels where we have a specified + // group guide rate. + target -= localReduction(chain[ii]); + } + target *= localFraction(chain[ii+1]); + } + // Avoid negative target rates coming from too large local reductions. + const double target_rate = std::max(0.0, target / efficiencyFactor); + + return std::make_pair(target_rate, currentGroupControl); +} + #define INSTANTIATE(T,...) \ template void WellGroupControls:: \ getGroupInjectionControl(const Group&, \ diff --git a/opm/simulators/wells/WellGroupControls.hpp b/opm/simulators/wells/WellGroupControls.hpp index 77ca5e4b8..93ec7030d 100644 --- a/opm/simulators/wells/WellGroupControls.hpp +++ b/opm/simulators/wells/WellGroupControls.hpp @@ -24,6 +24,7 @@ #ifndef OPM_WELL_GROUP_CONTROLS_HEADER_INCLUDED #define OPM_WELL_GROUP_CONTROLS_HEADER_INCLUDED +#include #include #include #include @@ -37,6 +38,7 @@ class Group; template class GroupState; enum class InjectorType; using RegionId = int; +struct PhaseUsage; class Schedule; class SummaryState; template class WellInterfaceGeneric; @@ -99,6 +101,19 @@ public: Scalar efficiencyFactor, DeferredLogger& deferred_logger) const; + static std::pair getAutoChokeGroupProductionTargetRate(const std::string& name, + const Group& parent, + const WellState& well_state, + const GroupState& group_state, + const Schedule& schedule, + const SummaryState& summaryState, + const std::vector& resv_coeff, + Scalar efficiencyFactor, + const int reportStepIdx, + const PhaseUsage& pu, + const GuideRate* guideRate, + DeferredLogger& deferred_logger); + private: const WellInterfaceGeneric& well_; //!< Reference to well interface }; diff --git a/opm/simulators/wells/WellGroupHelpers.cpp b/opm/simulators/wells/WellGroupHelpers.cpp index f8206f282..2d3e0f944 100644 --- a/opm/simulators/wells/WellGroupHelpers.cpp +++ b/opm/simulators/wells/WellGroupHelpers.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ #include #include +#include #include #include #include @@ -347,6 +349,7 @@ updateGroupTargetReduction(const Group& group, const PhaseUsage& pu, const GuideRate& guide_rate, const WellState& wellState, + const SummaryState& summaryState, GroupState& group_state, std::vector& groupTargetReduction) { @@ -361,6 +364,7 @@ updateGroupTargetReduction(const Group& group, pu, guide_rate, wellState, + summaryState, group_state, subGroupTargetReduction); @@ -402,7 +406,7 @@ updateGroupTargetReduction(const Group& group, const bool individual_control = (currentGroupControl != Group::InjectionCMode::FLD && currentGroupControl != Group::InjectionCMode::NONE); const int num_group_controlled_wells - = groupControlledWells(schedule, wellState, group_state, reportStepIdx, subGroupName, "", !isInjector, phase); + = groupControlledWells(schedule, wellState, group_state, summaryState, &guide_rate, reportStepIdx, subGroupName, "", !isInjector, phase); if (individual_control || num_group_controlled_wells == 0) { groupTargetReduction[phase_pos] += subGroupEfficiency * sumWellSurfaceRates(subGroup, schedule, wellState, reportStepIdx, phase_pos, isInjector); @@ -418,7 +422,7 @@ updateGroupTargetReduction(const Group& group, const bool individual_control = (currentGroupControl != Group::ProductionCMode::FLD && currentGroupControl != Group::ProductionCMode::NONE); const int num_group_controlled_wells - = groupControlledWells(schedule, wellState, group_state, reportStepIdx, subGroupName, "", !isInjector, /*injectionPhaseNotUsed*/Phase::OIL); + = groupControlledWells(schedule, wellState, group_state, summaryState, &guide_rate, reportStepIdx, subGroupName, "", !isInjector, /*injectionPhaseNotUsed*/Phase::OIL); if (individual_control || num_group_controlled_wells == 0) { for (int phase = 0; phase < np; phase++) { groupTargetReduction[phase] @@ -468,10 +472,13 @@ updateGroupTargetReduction(const Group& group, groupTargetReduction[phase] += ws.surface_rates[phase] * efficiency; } } else { - if (ws.production_cmode != Well::ProducerCMode::GRUP) - for (int phase = 0; phase < np; phase++) { - groupTargetReduction[phase] -= ws.surface_rates[phase] * efficiency; + if ((ws.production_cmode != Well::ProducerCMode::GRUP)){ + if (!group.as_choke()) { + for (int phase = 0; phase < np; phase++) { + groupTargetReduction[phase] -= ws.surface_rates[phase] * efficiency; + } } + } } } if (isInjector) @@ -1091,6 +1098,8 @@ int WellGroupHelpers:: groupControlledWells(const Schedule& schedule, const WellState& well_state, const GroupState& group_state, + const SummaryState& summary_state, + const GuideRate* guideRate, const int report_step, const std::string& group_name, const std::string& always_included_child, @@ -1112,16 +1121,81 @@ groupControlledWells(const Schedule& schedule, if (included) { num_wells - += groupControlledWells(schedule, well_state, group_state, report_step, child_group, always_included_child, is_production_group, injection_phase); + += groupControlledWells(schedule, well_state, group_state, summary_state, guideRate, report_step, child_group, always_included_child, is_production_group, injection_phase); } } for (const std::string& child_well : group.wells()) { bool included = (child_well == always_included_child); if (is_production_group) { - included = included || well_state.isProductionGrup(child_well); + included = included || well_state.isProductionGrup(child_well) || group.as_choke(); } else { included = included || well_state.isInjectionGrup(child_well); } + const auto ctrl1 = group_state.production_control(group.name()); + if (group.as_choke() && ((ctrl1 == Group::ProductionCMode::FLD) || (ctrl1 == Group::ProductionCMode::NONE))){ + // The auto choke group has not own group control but inherits control from an ancestor group. + // Number of wells should be calculated as zero when wells of auto choke group do not deliver target. + // This behaviour is then similar to no-autochoke group with wells not on GRUP control. + // The rates of these wells are summed up. The parent group target is reduced with this rate. + // This reduced target becomes the target of the other child group of this parent. + const PhaseUsage& pu = well_state.phaseUsage(); + std::vector rates(pu.num_phases, 0.0); + for (int phase_pos = 0; phase_pos < pu.num_phases; ++phase_pos) { + rates[phase_pos] = WellGroupHelpers::sumWellSurfaceRates(group, + schedule, + well_state, + report_step, + phase_pos, + false); + } + + // Get the ancestor of the auto choke group that has group control (cmode != FLD, NONE) + const auto& control_group_name = control_group(group, group_state, report_step, schedule); + const auto& control_group = schedule.getGroup(control_group_name, report_step); + const auto& ctrl = control_group.productionControls(summary_state); + const auto& control_group_cmode = ctrl.cmode; + + const auto& group_guide_rate = group.productionControls(summary_state).guide_rate; + + if (group_guide_rate > 0) { + // Guide rate is not default for the auto choke group + Scalar gratTargetFromSales = 0.0; + if (group_state.has_grat_sales_target(control_group_name)) + gratTargetFromSales = group_state.grat_sales_target(control_group_name); + + std::vector resv_coeff(pu.num_phases, 1.0); + WGHelpers::TargetCalculator tcalc(control_group_cmode, + pu, + resv_coeff, + gratTargetFromSales, + group.name(), + group_state, + group.has_gpmaint_control(control_group_cmode)); + auto deferred_logger = Opm::DeferredLogger(); + const auto& control_group_target = tcalc.groupTarget(ctrl, deferred_logger); + + // Calculates the guide rate of the parent group with control. + // It is allowed that the guide rate of this group is defaulted. The guide rate will be derived from the children groups + const auto& control_group_guide_rate = getGuideRate(control_group_name, + schedule, + well_state, + group_state, + report_step, + guideRate, + tcalc.guideTargetMode(), + pu); + + if (control_group_guide_rate > 0) { + // Target rate for the auto choke group + const Scalar target_rate = control_group_target * group_guide_rate / control_group_guide_rate; + const Scalar current_rate = tcalc.calcModeRateFromRates(rates); + + if (current_rate < target_rate) + included = false; + } + } + } + if (included) { ++num_wells; } @@ -1160,6 +1234,27 @@ groupChainTopBot(const std::string& bottom, return chain; } +template +std::string +WellGroupHelpers:: +control_group(const Group& group, + const GroupState& group_state, + const int reportStepIdx, + const Schedule& schedule) +{ + const Group::ProductionCMode& currentGroupControl = group_state.production_control(group.name()); + + if (currentGroupControl == Group::ProductionCMode::FLD || currentGroupControl == Group::ProductionCMode::NONE) { + const auto& parent = schedule.getGroup(group.parent(), reportStepIdx); + return control_group(parent, + group_state, + reportStepIdx, + schedule); + } + + return group.name(); +} + template std::pair WellGroupHelpers:: @@ -1239,6 +1334,7 @@ checkGroupConstraintsProd(const std::string& name, WGHelpers::FractionCalculator fcalc(schedule, wellState, group_state, + summaryState, reportStepIdx, guideRate, tcalc.guideTargetMode(), @@ -1281,6 +1377,8 @@ checkGroupConstraintsProd(const std::string& name, const int num_gr_ctrl = groupControlledWells(schedule, wellState, group_state, + summaryState, + guideRate, reportStepIdx, chain[ii], "", @@ -1414,6 +1512,7 @@ checkGroupConstraintsInj(const std::string& name, WGHelpers::FractionCalculator fcalc(schedule, wellState, group_state, + summaryState, reportStepIdx, guideRate, tcalc.guideTargetMode(), @@ -1456,12 +1555,14 @@ checkGroupConstraintsInj(const std::string& name, for (std::size_t ii = 1; ii < num_ancestors; ++ii) { const int num_gr_ctrl = groupControlledWells(schedule, wellState, - group_state, - reportStepIdx, - chain[ii], - "", - /*is_producer*/ false, - injectionPhase); + group_state, + summaryState, + guideRate, + reportStepIdx, + chain[ii], + "", + /*is_producer*/ false, + injectionPhase); if (guideRate->has(chain[ii], injectionPhase) && num_gr_ctrl > 0) { local_reduction_level = ii; } diff --git a/opm/simulators/wells/WellGroupHelpers.hpp b/opm/simulators/wells/WellGroupHelpers.hpp index 4fc906a08..00db85713 100644 --- a/opm/simulators/wells/WellGroupHelpers.hpp +++ b/opm/simulators/wells/WellGroupHelpers.hpp @@ -105,6 +105,7 @@ public: const PhaseUsage& pu, const GuideRate& guide_rate, const WellState& wellState, + const SummaryState& summaryState, GroupState& group_state, std::vector& groupTargetReduction); @@ -247,6 +248,8 @@ public: static int groupControlledWells(const Schedule& schedule, const WellState& well_state, const GroupState& group_state, + const SummaryState& summary_state, + const GuideRate* guideRate, const int report_step, const std::string& group_name, const std::string& always_included_child, @@ -276,6 +279,12 @@ public: const Schedule& schedule, const int report_step); + static std::string + control_group(const Group& group, + const GroupState& group_state, + const int reportStepIdx, + const Schedule& schedule); + static std::pair checkGroupConstraintsProd(const std::string& name, const std::string& parent, diff --git a/opm/simulators/wells/WellInterfaceGeneric.cpp b/opm/simulators/wells/WellInterfaceGeneric.cpp index 8a9748768..26ffb2f36 100644 --- a/opm/simulators/wells/WellInterfaceGeneric.cpp +++ b/opm/simulators/wells/WellInterfaceGeneric.cpp @@ -518,6 +518,13 @@ WellInterfaceGeneric::getDynamicThpLimit() const return dynamic_thp_limit_; } +template +void WellInterfaceGeneric:: +setDynamicThpLimit(const std::optional thp_limit) +{ + dynamic_thp_limit_ = thp_limit; +} + template void WellInterfaceGeneric:: updatePerforatedCell(std::vector& is_cell_perforated)