Merge pull request #5754 from plgbrts/ac-group-guide-rates

Allow group guide rates in case that a group is an auto choke group
This commit is contained in:
Tor Harald Sandve
2024-12-20 07:54:57 +01:00
committed by GitHub
13 changed files with 321 additions and 25 deletions

View File

@@ -464,8 +464,9 @@ template<class Scalar> 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.

View File

@@ -1312,6 +1312,7 @@ updateAndCommunicateGroupData(const int reportStepIdx,
phase_usage_,
guideRate_,
well_state,
summaryState_,
this->groupState(),
groupTargetReduction);
std::vector<Scalar> groupTargetReductionInj(numPhases(), 0.0);
@@ -1322,6 +1323,7 @@ updateAndCommunicateGroupData(const int reportStepIdx,
phase_usage_,
guideRate_,
well_state,
summaryState_,
this->groupState(),
groupTargetReductionInj);

View File

@@ -43,6 +43,7 @@
#include <opm/simulators/wells/ParallelWBPCalculation.hpp>
#include <opm/simulators/wells/VFPProperties.hpp>
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
#include <opm/simulators/wells/WellGroupControls.hpp>
#include <opm/simulators/wells/WellGroupHelpers.hpp>
#include <opm/simulators/wells/TargetCalculator.hpp>
@@ -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 <typename TypeTag>
void
bool
BlackoilWellModel<TypeTag>::
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<Scalar> 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<Scalar>::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<typename TypeTag>
@@ -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;

View File

@@ -37,6 +37,7 @@ FractionCalculator<Scalar>::
FractionCalculator(const Schedule& schedule,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& 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<Scalar>::groupControlledWells(schedule_,
well_state_,
this->group_state_,
this->summary_state_,
this->guide_rate_,
report_step_,
group_name,
always_included_child,

View File

@@ -41,6 +41,7 @@ public:
FractionCalculator(const Schedule& schedule,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& 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<Scalar>& well_state_;
const GroupState<Scalar>& group_state_;
const SummaryState& summary_state_;
int report_step_;
const GuideRate* guide_rate_;
GuideRateModel::Target target_;

View File

@@ -124,6 +124,13 @@ GroupState::well_group_thp(const std::string& gname) const
return group_iter->second;
}
template<class Scalar>
bool GroupState<Scalar>::
GroupState::is_autochoke_group(const std::string& gname) const
{
return (this->group_thp.count(gname) > 0);
}
//-------------------------------------------------------------------------
template<class Scalar>

View File

@@ -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,

View File

@@ -1051,7 +1051,7 @@ bruteForceBracketCommonTHP(const std::function<Scalar(const Scalar)>& 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;

View File

@@ -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<class Scalar>
std::pair<Scalar, Group::ProductionCMode> WellGroupControls<Scalar>::
getAutoChokeGroupProductionTargetRate(const std::string& name,
const Group& group,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state,
const Schedule& schedule,
const SummaryState& summaryState,
const std::vector<Scalar>& 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<double> 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<Scalar>& groupTargetReductions = group_state.production_reduction_rates(group_name);
return tcalc.calcModeRateFromRates(groupTargetReductions);
};
std::optional<Group::ProductionControls> ctrl;
if (!group.has_gpmaint_control(currentGroupControl))
ctrl = group.productionControls(summaryState);
const double orig_target = tcalc.groupTarget(ctrl, deferred_logger);
const auto chain = WellGroupHelpers<Scalar>::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<T>:: \
getGroupInjectionControl(const Group&, \

View File

@@ -24,6 +24,7 @@
#ifndef OPM_WELL_GROUP_CONTROLS_HEADER_INCLUDED
#define OPM_WELL_GROUP_CONTROLS_HEADER_INCLUDED
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
#include <string>
#include <functional>
#include <optional>
@@ -37,6 +38,7 @@ class Group;
template<class Scalar> class GroupState;
enum class InjectorType;
using RegionId = int;
struct PhaseUsage;
class Schedule;
class SummaryState;
template<class Scalar> class WellInterfaceGeneric;
@@ -99,6 +101,19 @@ public:
Scalar efficiencyFactor,
DeferredLogger& deferred_logger) const;
static std::pair<Scalar, Group::ProductionCMode> getAutoChokeGroupProductionTargetRate(const std::string& name,
const Group& parent,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state,
const Schedule& schedule,
const SummaryState& summaryState,
const std::vector<Scalar>& resv_coeff,
Scalar efficiencyFactor,
const int reportStepIdx,
const PhaseUsage& pu,
const GuideRate* guideRate,
DeferredLogger& deferred_logger);
private:
const WellInterfaceGeneric<Scalar>& well_; //!< Reference to well interface
};

View File

@@ -26,6 +26,7 @@
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
#include <opm/input/eclipse/Schedule/Group/GPMaint.hpp>
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
@@ -35,6 +36,7 @@
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
#include <opm/simulators/utils/ParallelCommunication.hpp>
#include <opm/simulators/wells/BlackoilWellModelConstraints.hpp>
#include <opm/simulators/wells/FractionCalculator.hpp>
#include <opm/simulators/wells/GroupState.hpp>
#include <opm/simulators/wells/RegionAverageCalculator.hpp>
@@ -347,6 +349,7 @@ updateGroupTargetReduction(const Group& group,
const PhaseUsage& pu,
const GuideRate& guide_rate,
const WellState<Scalar>& wellState,
const SummaryState& summaryState,
GroupState<Scalar>& group_state,
std::vector<Scalar>& 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<Scalar>::
groupControlledWells(const Schedule& schedule,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& 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<Scalar> rates(pu.num_phases, 0.0);
for (int phase_pos = 0; phase_pos < pu.num_phases; ++phase_pos) {
rates[phase_pos] = WellGroupHelpers<Scalar>::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<Scalar> 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<class Scalar>
std::string
WellGroupHelpers<Scalar>::
control_group(const Group& group,
const GroupState<Scalar>& 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<class Scalar>
std::pair<bool, Scalar>
WellGroupHelpers<Scalar>::
@@ -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;
}

View File

@@ -105,6 +105,7 @@ public:
const PhaseUsage& pu,
const GuideRate& guide_rate,
const WellState<Scalar>& wellState,
const SummaryState& summaryState,
GroupState<Scalar>& group_state,
std::vector<Scalar>& groupTargetReduction);
@@ -247,6 +248,8 @@ public:
static int groupControlledWells(const Schedule& schedule,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& 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<Scalar>& group_state,
const int reportStepIdx,
const Schedule& schedule);
static std::pair<bool, Scalar>
checkGroupConstraintsProd(const std::string& name,
const std::string& parent,

View File

@@ -518,6 +518,13 @@ WellInterfaceGeneric<Scalar>::getDynamicThpLimit() const
return dynamic_thp_limit_;
}
template<class Scalar>
void WellInterfaceGeneric<Scalar>::
setDynamicThpLimit(const std::optional<Scalar> thp_limit)
{
dynamic_thp_limit_ = thp_limit;
}
template<class Scalar>
void WellInterfaceGeneric<Scalar>::
updatePerforatedCell(std::vector<bool>& is_cell_perforated)