Merge pull request #5295 from akva2/wellgrouphelpers_template_scalar

WellGroupHelpers: template Scalar type
This commit is contained in:
Atgeirr Flø Rasmussen
2024-04-22 13:14:23 +02:00
committed by GitHub
13 changed files with 2470 additions and 2135 deletions

View File

@@ -74,7 +74,12 @@ checkGroupInjectionConstraints(const Group& group,
if (currentControl != Group::InjectionCMode::RATE) if (currentControl != Group::InjectionCMode::RATE)
{ {
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true); current_rate += WellGroupHelpers<double>::sumWellSurfaceRates(group,
wellModel_.schedule(),
well_state,
reportStepIdx,
phasePos,
/*isInjector*/true);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
@@ -98,7 +103,12 @@ checkGroupInjectionConstraints(const Group& group,
if (currentControl != Group::InjectionCMode::RESV) if (currentControl != Group::InjectionCMode::RESV)
{ {
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellResRates(group, wellModel_.schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true); current_rate += WellGroupHelpers<double>::sumWellResRates(group,
wellModel_.schedule(),
well_state,
reportStepIdx,
phasePos,
/*isInjector*/true);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
@@ -123,17 +133,23 @@ checkGroupInjectionConstraints(const Group& group,
double production_Rate = 0.0; double production_Rate = 0.0;
const auto& controls = group.injectionControls(phase, wellModel_.summaryState()); const auto& controls = group.injectionControls(phase, wellModel_.summaryState());
const Group& groupRein = wellModel_.schedule().getGroup(controls.reinj_group, reportStepIdx); const Group& groupRein = wellModel_.schedule().getGroup(controls.reinj_group, reportStepIdx);
production_Rate += WellGroupHelpers::sumWellSurfaceRates(groupRein, wellModel_.schedule(), production_Rate += WellGroupHelpers<double>::sumWellSurfaceRates(groupRein,
well_state, reportStepIdx, wellModel_.schedule(),
phasePos, /*isInjector*/false); well_state,
reportStepIdx,
phasePos,
/*isInjector*/false);
// sum over all nodes // sum over all nodes
production_Rate = wellModel_.comm().sum(production_Rate); production_Rate = wellModel_.comm().sum(production_Rate);
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), current_rate += WellGroupHelpers<double>::sumWellSurfaceRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
phasePos, /*isInjector*/true); well_state,
reportStepIdx,
phasePos,
/*isInjector*/true);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
@@ -153,29 +169,46 @@ checkGroupInjectionConstraints(const Group& group,
double voidage_rate = 0.0; double voidage_rate = 0.0;
const auto& controls = group.injectionControls(phase, wellModel_.summaryState()); const auto& controls = group.injectionControls(phase, wellModel_.summaryState());
const Group& groupVoidage = wellModel_.schedule().getGroup(controls.voidage_group, reportStepIdx); const Group& groupVoidage = wellModel_.schedule().getGroup(controls.voidage_group, reportStepIdx);
voidage_rate += WellGroupHelpers::sumWellResRates(groupVoidage, wellModel_.schedule(), voidage_rate += WellGroupHelpers<double>::sumWellResRates(groupVoidage,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Aqua], false); well_state,
voidage_rate += WellGroupHelpers::sumWellResRates(groupVoidage, wellModel_.schedule(), reportStepIdx,
well_state, reportStepIdx, pu.phase_pos[BlackoilPhases::Aqua],
pu.phase_pos[BlackoilPhases::Liquid], false); false);
voidage_rate += WellGroupHelpers::sumWellResRates(groupVoidage, wellModel_.schedule(), voidage_rate += WellGroupHelpers<double>::sumWellResRates(groupVoidage,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Vapour], false); well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Liquid],
false);
voidage_rate += WellGroupHelpers<double>::sumWellResRates(groupVoidage,
wellModel_.schedule(),
well_state, reportStepIdx,
pu.phase_pos[BlackoilPhases::Vapour],
false);
// sum over all nodes // sum over all nodes
voidage_rate = wellModel_.comm().sum(voidage_rate); voidage_rate = wellModel_.comm().sum(voidage_rate);
double total_rate = 0.0; double total_rate = 0.0;
total_rate += WellGroupHelpers::sumWellResRates(group, wellModel_.schedule(), total_rate += WellGroupHelpers<double>::sumWellResRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Aqua], true); well_state,
total_rate += WellGroupHelpers::sumWellResRates(group, wellModel_.schedule(), reportStepIdx,
well_state, reportStepIdx, pu.phase_pos[BlackoilPhases::Aqua],
pu.phase_pos[BlackoilPhases::Liquid], true); true);
total_rate += WellGroupHelpers::sumWellResRates(group, wellModel_.schedule(), total_rate += WellGroupHelpers<double>::sumWellResRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Vapour], true); well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Liquid],
true);
total_rate += WellGroupHelpers<double>::sumWellResRates(group,
wellModel_.schedule(),
well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Vapour],
true);
// sum over all nodes // sum over all nodes
total_rate = wellModel_.comm().sum(total_rate); total_rate = wellModel_.comm().sum(total_rate);
@@ -208,9 +241,12 @@ checkGroupProductionConstraints(const Group& group,
if (currentControl != Group::ProductionCMode::ORAT) if (currentControl != Group::ProductionCMode::ORAT)
{ {
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), current_rate += WellGroupHelpers<double>::sumWellSurfaceRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Liquid], false); well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Liquid],
false);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
@@ -228,11 +264,13 @@ checkGroupProductionConstraints(const Group& group,
{ {
if (currentControl != Group::ProductionCMode::WRAT) if (currentControl != Group::ProductionCMode::WRAT)
{ {
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), current_rate += WellGroupHelpers<double>::sumWellSurfaceRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Aqua], false); well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Aqua],
false);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
@@ -250,9 +288,12 @@ checkGroupProductionConstraints(const Group& group,
if (currentControl != Group::ProductionCMode::GRAT) if (currentControl != Group::ProductionCMode::GRAT)
{ {
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), current_rate += WellGroupHelpers<double>::sumWellSurfaceRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Vapour], false); well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Vapour],
false);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
@@ -269,21 +310,30 @@ checkGroupProductionConstraints(const Group& group,
if (currentControl != Group::ProductionCMode::LRAT) if (currentControl != Group::ProductionCMode::LRAT)
{ {
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), current_rate += WellGroupHelpers<double>::sumWellSurfaceRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Liquid], false); well_state,
current_rate += WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), reportStepIdx,
well_state, reportStepIdx, pu.phase_pos[BlackoilPhases::Liquid],
pu.phase_pos[BlackoilPhases::Aqua], false); false);
current_rate += WellGroupHelpers<double>::sumWellSurfaceRates(group,
wellModel_.schedule(),
well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Aqua],
false);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
bool skip = false; bool skip = false;
if (controls.liquid_target == controls.oil_target) { if (controls.liquid_target == controls.oil_target) {
double current_water_rate = WellGroupHelpers::sumWellSurfaceRates(group, wellModel_.schedule(), double current_water_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Aqua], false); well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Aqua],
false);
current_water_rate = wellModel_.comm().sum(current_water_rate); current_water_rate = wellModel_.comm().sum(current_water_rate);
if (std::abs(current_water_rate) < 1e-12) { if (std::abs(current_water_rate) < 1e-12) {
skip = true; skip = true;
@@ -309,15 +359,24 @@ checkGroupProductionConstraints(const Group& group,
if (currentControl != Group::ProductionCMode::RESV) if (currentControl != Group::ProductionCMode::RESV)
{ {
double current_rate = 0.0; double current_rate = 0.0;
current_rate += WellGroupHelpers::sumWellResRates(group, wellModel_.schedule(), current_rate += WellGroupHelpers<double>::sumWellResRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Aqua], false); well_state,
current_rate += WellGroupHelpers::sumWellResRates(group, wellModel_.schedule(), reportStepIdx,
well_state, reportStepIdx, pu.phase_pos[BlackoilPhases::Aqua],
pu.phase_pos[BlackoilPhases::Liquid], false); false);
current_rate += WellGroupHelpers::sumWellResRates(group, wellModel_.schedule(), current_rate += WellGroupHelpers<double>::sumWellResRates(group,
well_state, reportStepIdx, wellModel_.schedule(),
pu.phase_pos[BlackoilPhases::Vapour], false); well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Liquid],
false);
current_rate += WellGroupHelpers<double>::sumWellResRates(group,
wellModel_.schedule(),
well_state,
reportStepIdx,
pu.phase_pos[BlackoilPhases::Vapour],
false);
// sum over all nodes // sum over all nodes
current_rate = wellModel_.comm().sum(current_rate); current_rate = wellModel_.comm().sum(current_rate);
@@ -457,11 +516,10 @@ actionOnBrokenConstraints(const Group& group,
break; break;
} }
case Group::ExceedAction::WELL: { case Group::ExceedAction::WELL: {
std::tie(worst_offending_well, std::ignore) = std::tie(worst_offending_well, std::ignore) =
WellGroupHelpers::worstOffendingWell(group, wellModel_.schedule(), reportStepIdx, WellGroupHelpers<double>::worstOffendingWell(group, wellModel_.schedule(), reportStepIdx,
newControl, wellModel_.phaseUsage(), newControl, wellModel_.phaseUsage(),
wellModel_.comm(), well_state, deferred_logger); wellModel_.comm(), well_state, deferred_logger);
break; break;
} }
case Group::ExceedAction::PLUG: { case Group::ExceedAction::PLUG: {
@@ -520,13 +578,13 @@ updateGroupIndividualControl(const Group& group,
Group::InjectionCMode2String(changed_this.first)); Group::InjectionCMode2String(changed_this.first));
this->actionOnBrokenConstraints(group, changed_this.first, phase, this->actionOnBrokenConstraints(group, changed_this.first, phase,
group_state, deferred_logger); group_state, deferred_logger);
WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed_this.second, WellGroupHelpers<double>::updateWellRatesFromGroupTargetScale(changed_this.second,
group, group,
wellModel_.schedule(), wellModel_.schedule(),
reportStepIdx, reportStepIdx,
/* isInjector */ false, /* isInjector */ false,
wellModel_.groupState(), wellModel_.groupState(),
well_state); well_state);
changed = true; changed = true;
} }
} }
@@ -549,13 +607,13 @@ updateGroupIndividualControl(const Group& group,
if(changed) { if(changed) {
switched_prod.insert_or_assign(group.name(), switched_prod.insert_or_assign(group.name(),
Group::ProductionCMode2String(changed_this.first)); Group::ProductionCMode2String(changed_this.first));
WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed_this.second, WellGroupHelpers<double>::updateWellRatesFromGroupTargetScale(changed_this.second,
group, group,
wellModel_.schedule(), wellModel_.schedule(),
reportStepIdx, reportStepIdx,
/* isInjector */ false, /* isInjector */ false,
wellModel_.groupState(), wellModel_.groupState(),
well_state); well_state);
} else if (worst_offending_well) { } else if (worst_offending_well) {
closed_offending_wells.insert_or_assign(group.name(), closed_offending_wells.insert_or_assign(group.name(),
std::make_pair(Group::ProductionCMode2String(changed_this.first), *worst_offending_well)); std::make_pair(Group::ProductionCMode2String(changed_this.first), *worst_offending_well));

View File

@@ -450,8 +450,18 @@ checkGconsaleLimits(const Group& group,
const Group::ProductionCMode& oldProductionControl = this->groupState().production_control(group.name()); const Group::ProductionCMode& oldProductionControl = this->groupState().production_control(group.name());
int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour]; int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
double production_rate = WellGroupHelpers::sumWellSurfaceRates(group, schedule(), well_state, reportStepIdx, gasPos, /*isInjector*/false); double production_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
double injection_rate = WellGroupHelpers::sumWellSurfaceRates(group, schedule(), well_state, reportStepIdx, gasPos, /*isInjector*/true); schedule(),
well_state,
reportStepIdx,
gasPos,
/*isInjector*/false);
double injection_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
schedule(),
well_state,
reportStepIdx,
gasPos,
/*isInjector*/true);
// sum over all nodes // sum over all nodes
injection_rate = comm_.sum(injection_rate); injection_rate = comm_.sum(injection_rate);
@@ -585,7 +595,12 @@ checkGroupHigherConstraints(const Group& group,
calcInjRates(fipnum, pvtreg, resv_coeff_inj); calcInjRates(fipnum, pvtreg, resv_coeff_inj);
for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) { for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) {
const double local_current_rate = WellGroupHelpers::sumWellSurfaceRates(group, schedule(), this->wellState(), reportStepIdx, phasePos, /* isInjector */ true); const double local_current_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
schedule(),
this->wellState(),
reportStepIdx,
phasePos,
/* isInjector */ true);
// Sum over all processes // Sum over all processes
rates[phasePos] = comm_.sum(local_current_rate); rates[phasePos] = comm_.sum(local_current_rate);
} }
@@ -595,29 +610,35 @@ checkGroupHigherConstraints(const Group& group,
auto currentControl = this->groupState().injection_control(group.name(), phase); auto currentControl = this->groupState().injection_control(group.name(), phase);
if (currentControl != Group::InjectionCMode::FLD && group.injectionGroupControlAvailable(phase)) { if (currentControl != Group::InjectionCMode::FLD && group.injectionGroupControlAvailable(phase)) {
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx); const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
const auto [is_changed, scaling_factor] = WellGroupHelpers::checkGroupConstraintsInj( const auto [is_changed, scaling_factor] =
group.name(), WellGroupHelpers<double>::checkGroupConstraintsInj(group.name(),
group.parent(), group.parent(),
parentGroup, parentGroup,
this->wellState(), this->wellState(),
this->groupState(), this->groupState(),
reportStepIdx, reportStepIdx,
&guideRate_, &guideRate_,
rates.data(), rates.data(),
phase, phase,
phase_usage_, phase_usage_,
group.getGroupEfficiencyFactor(), group.getGroupEfficiencyFactor(),
schedule(), schedule(),
summaryState_, summaryState_,
resv_coeff_inj, resv_coeff_inj,
deferred_logger); deferred_logger);
if (is_changed) { if (is_changed) {
switched_inj_groups_.insert_or_assign({group.name(), phase}, Group::InjectionCMode2String(Group::InjectionCMode::FLD)); switched_inj_groups_.insert_or_assign({group.name(), phase}, Group::InjectionCMode2String(Group::InjectionCMode::FLD));
BlackoilWellModelConstraints(*this). BlackoilWellModelConstraints(*this).
actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, actionOnBrokenConstraints(group, Group::InjectionCMode::FLD,
phase, this->groupState(), phase, this->groupState(),
deferred_logger); deferred_logger);
WellGroupHelpers::updateWellRatesFromGroupTargetScale(scaling_factor, group, schedule(), reportStepIdx, /* isInjector */ true, this->groupState(), this->wellState()); WellGroupHelpers<double>::updateWellRatesFromGroupTargetScale(scaling_factor,
group,
schedule(),
reportStepIdx,
/* isInjector */ true,
this->groupState(),
this->wellState());
changed = true; changed = true;
} }
} }
@@ -627,7 +648,12 @@ checkGroupHigherConstraints(const Group& group,
if (!isField && group.isProductionGroup()) { if (!isField && group.isProductionGroup()) {
// Obtain rates for group. // Obtain rates for group.
for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) { for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) {
const double local_current_rate = WellGroupHelpers::sumWellSurfaceRates(group, schedule(), this->wellState(), reportStepIdx, phasePos, /* isInjector */ false); const double local_current_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
schedule(),
this->wellState(),
reportStepIdx,
phasePos,
/* isInjector */ false);
// Sum over all processes // Sum over all processes
rates[phasePos] = -comm_.sum(local_current_rate); rates[phasePos] = -comm_.sum(local_current_rate);
} }
@@ -637,21 +663,21 @@ checkGroupHigherConstraints(const Group& group,
const Group::ProductionCMode& currentControl = this->groupState().production_control(group.name()); const Group::ProductionCMode& currentControl = this->groupState().production_control(group.name());
if (currentControl != Group::ProductionCMode::FLD && group.productionGroupControlAvailable()) { if (currentControl != Group::ProductionCMode::FLD && group.productionGroupControlAvailable()) {
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx); const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
const auto [is_changed, scaling_factor] = WellGroupHelpers::checkGroupConstraintsProd( const auto [is_changed, scaling_factor] =
group.name(), WellGroupHelpers<double>::checkGroupConstraintsProd(group.name(),
group.parent(), group.parent(),
parentGroup, parentGroup,
this->wellState(), this->wellState(),
this->groupState(), this->groupState(),
reportStepIdx, reportStepIdx,
&guideRate_, &guideRate_,
rates.data(), rates.data(),
phase_usage_, phase_usage_,
group.getGroupEfficiencyFactor(), group.getGroupEfficiencyFactor(),
schedule(), schedule(),
summaryState_, summaryState_,
resv_coeff, resv_coeff,
deferred_logger); deferred_logger);
if (is_changed) { if (is_changed) {
const auto group_limit_action = group.productionControls(summaryState_).group_limit_action; const auto group_limit_action = group.productionControls(summaryState_).group_limit_action;
std::optional<std::string> worst_offending_well = std::nullopt; std::optional<std::string> worst_offending_well = std::nullopt;
@@ -664,8 +690,15 @@ checkGroupHigherConstraints(const Group& group,
deferred_logger); deferred_logger);
if (changed) { if (changed) {
switched_prod_groups_.insert_or_assign(group.name(), Group::ProductionCMode2String(Group::ProductionCMode::FLD)); switched_prod_groups_.insert_or_assign(group.name(),
WellGroupHelpers::updateWellRatesFromGroupTargetScale(scaling_factor, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); Group::ProductionCMode2String(Group::ProductionCMode::FLD));
WellGroupHelpers<double>::updateWellRatesFromGroupTargetScale(scaling_factor,
group,
schedule(),
reportStepIdx,
/* isInjector */ false,
this->groupState(),
this->wellState());
} }
} }
} }
@@ -808,8 +841,17 @@ updateWsolvent(const Group& group,
int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour]; int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
const auto& controls = group.injectionControls(Phase::GAS, summaryState_); const auto& controls = group.injectionControls(Phase::GAS, summaryState_);
const Group& groupRein = schedule_.getGroup(controls.reinj_group, reportStepIdx); const Group& groupRein = schedule_.getGroup(controls.reinj_group, reportStepIdx);
double gasProductionRate = WellGroupHelpers::sumWellSurfaceRates(groupRein, schedule_, wellState, reportStepIdx, gasPos, /*isInjector*/false); double gasProductionRate = WellGroupHelpers<double>::sumWellSurfaceRates(groupRein,
double solventProductionRate = WellGroupHelpers::sumSolventRates(groupRein, schedule_, wellState, reportStepIdx, /*isInjector*/false); schedule_,
wellState,
reportStepIdx,
gasPos,
/*isInjector*/false);
double solventProductionRate = WellGroupHelpers<double>::sumSolventRates(groupRein,
schedule_,
wellState,
reportStepIdx,
/*isInjector*/false);
solventProductionRate = comm_.sum(solventProductionRate); solventProductionRate = comm_.sum(solventProductionRate);
gasProductionRate = comm_.sum(gasProductionRate); gasProductionRate = comm_.sum(gasProductionRate);
@@ -956,12 +998,12 @@ assignNodeValues(std::map<std::string, data::NodeData>& nodevalues, const int re
const auto& network = schedule()[reportStepIdx].network(); const auto& network = schedule()[reportStepIdx].network();
if (!network.active()) return; if (!network.active()) return;
auto converged_pressures = WellGroupHelpers::computeNetworkPressures(network, auto converged_pressures = WellGroupHelpers<double>::computeNetworkPressures(network,
this->wellState(), this->wellState(),
this->groupState(), this->groupState(),
*(vfp_properties_->getProd()), *(vfp_properties_->getProd()),
schedule(), schedule(),
reportStepIdx); reportStepIdx);
for (const auto& [node, converged_pressure] : converged_pressures) { for (const auto& [node, converged_pressure] : converged_pressures) {
auto it = nodevalues.find(node); auto it = nodevalues.find(node);
assert(it != nodevalues.end() ); assert(it != nodevalues.end() );
@@ -1011,20 +1053,63 @@ updateAndCommunicateGroupData(const int reportStepIdx,
// the group target reduction rates needs to be update since wells may have switched to/from GRUP control // the group target reduction rates needs to be update since wells may have switched to/from GRUP control
// The group target reduction does not honor NUPCOL. // The group target reduction does not honor NUPCOL.
std::vector<double> groupTargetReduction(numPhases(), 0.0); std::vector<double> groupTargetReduction(numPhases(), 0.0);
WellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ false, phase_usage_, guideRate_, well_state, this->groupState(), groupTargetReduction); WellGroupHelpers<double>::updateGroupTargetReduction(fieldGroup,
schedule(),
reportStepIdx,
/*isInjector*/ false,
phase_usage_,
guideRate_,
well_state,
this->groupState(),
groupTargetReduction);
std::vector<double> groupTargetReductionInj(numPhases(), 0.0); std::vector<double> groupTargetReductionInj(numPhases(), 0.0);
WellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ true, phase_usage_, guideRate_, well_state, this->groupState(), groupTargetReductionInj); WellGroupHelpers<double>::updateGroupTargetReduction(fieldGroup,
schedule(),
reportStepIdx,
/*isInjector*/ true,
phase_usage_,
guideRate_,
well_state,
this->groupState(),
groupTargetReductionInj);
WellGroupHelpers::updateREINForGroups(fieldGroup, schedule(), reportStepIdx, phase_usage_, summaryState_, well_state_nupcol, this->groupState(), comm_.rank()==0); WellGroupHelpers<double>::updateREINForGroups(fieldGroup,
WellGroupHelpers::updateVREPForGroups(fieldGroup, schedule(), reportStepIdx, well_state_nupcol, this->groupState()); schedule(),
reportStepIdx,
phase_usage_,
summaryState_,
well_state_nupcol,
this->groupState(),
comm_.rank() == 0);
WellGroupHelpers<double>::updateVREPForGroups(fieldGroup,
schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
WellGroupHelpers::updateReservoirRatesInjectionGroups(fieldGroup, schedule(), reportStepIdx, well_state_nupcol, this->groupState()); WellGroupHelpers<double>::updateReservoirRatesInjectionGroups(fieldGroup,
WellGroupHelpers::updateSurfaceRatesInjectionGroups(fieldGroup, schedule(), reportStepIdx, well_state_nupcol, this->groupState()); schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
WellGroupHelpers<double>::updateSurfaceRatesInjectionGroups(fieldGroup,
schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
WellGroupHelpers::updateGroupProductionRates(fieldGroup, schedule(), reportStepIdx, well_state_nupcol, this->groupState()); WellGroupHelpers<double>::updateGroupProductionRates(fieldGroup,
schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
// We use the rates from the previous time-step to reduce oscillations // We use the rates from the previous time-step to reduce oscillations
WellGroupHelpers::updateWellRates(fieldGroup, schedule(), reportStepIdx, this->prevWellState(), well_state); WellGroupHelpers<double>::updateWellRates(fieldGroup,
schedule(),
reportStepIdx,
this->prevWellState(),
well_state);
// Set ALQ for off-process wells to zero // Set ALQ for off-process wells to zero
for (const auto& wname : schedule().wellNames(reportStepIdx)) { for (const auto& wname : schedule().wellNames(reportStepIdx)) {
@@ -1151,12 +1236,12 @@ updateNetworkPressures(const int reportStepIdx)
const auto previous_node_pressures = node_pressures_; const auto previous_node_pressures = node_pressures_;
node_pressures_ = WellGroupHelpers::computeNetworkPressures(network, node_pressures_ = WellGroupHelpers<double>::computeNetworkPressures(network,
this->wellState(), this->wellState(),
this->groupState(), this->groupState(),
*(vfp_properties_->getProd()), *(vfp_properties_->getProd()),
schedule(), schedule(),
reportStepIdx); reportStepIdx);
// here, the network imbalance is the difference between the previous nodal pressure and the new nodal pressure // here, the network imbalance is the difference between the previous nodal pressure and the new nodal pressure
double network_imbalance = 0.; double network_imbalance = 0.;
@@ -1225,7 +1310,11 @@ calculateEfficiencyFactors(const int reportStepIdx)
for (auto& well : well_container_generic_) { for (auto& well : well_container_generic_) {
const Well& wellEcl = well->wellEcl(); const Well& wellEcl = well->wellEcl();
double well_efficiency_factor = wellEcl.getEfficiencyFactor(); double well_efficiency_factor = wellEcl.getEfficiencyFactor();
WellGroupHelpers::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(), reportStepIdx), schedule(), reportStepIdx, well_efficiency_factor); WellGroupHelpers<double>::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(),
reportStepIdx),
schedule(),
reportStepIdx,
well_efficiency_factor);
well->setWellEfficiencyFactor(well_efficiency_factor); well->setWellEfficiencyFactor(well_efficiency_factor);
} }
} }

View File

@@ -328,7 +328,7 @@ getGuideRateValues(const Well& well) const
return grval; return grval;
} }
const auto qs = WellGroupHelpers:: const auto qs = WellGroupHelpers<double>::
getWellRateVector(wellModel_.wellState(), wellModel_.phaseUsage(), wname); getWellRateVector(wellModel_.wellState(), wellModel_.phaseUsage(), wname);
this->getGuideRateValues(qs, well.isInjector(), wname, grval); this->getGuideRateValues(qs, well.isInjector(), wname, grval);
@@ -355,7 +355,7 @@ getGuideRateValues(const Group& group) const
return grval; return grval;
} }
const auto qs = WellGroupHelpers:: const auto qs = WellGroupHelpers<double>::
getProductionGroupRateVector(wellModel_.groupState(), wellModel_.phaseUsage(), gname); getProductionGroupRateVector(wellModel_.groupState(), wellModel_.phaseUsage(), gname);
const auto is_inj = false; // This procedure only applies to G*PGR. const auto is_inj = false; // This procedure only applies to G*PGR.
@@ -433,7 +433,7 @@ assignWellGuideRates(data::Wells& wsrpt,
const auto get_gr = parent const auto get_gr = parent
|| RetrieveWellGuideRate{wellModel_.guideRate(), wname}; || RetrieveWellGuideRate{wellModel_.guideRate(), wname};
const auto qs = WellGroupHelpers:: const auto qs = WellGroupHelpers<double>::
getWellRateVector(wellModel_.wellState(), wellModel_.phaseUsage(), wname); getWellRateVector(wellModel_.wellState(), wellModel_.phaseUsage(), wname);
auto getGR = [this, &wname, &qs](const GuideRateModel::Target t) auto getGR = [this, &wname, &qs](const GuideRateModel::Target t)

View File

@@ -343,16 +343,16 @@ namespace Opm {
const auto& fieldGroup = const auto& fieldGroup =
this->schedule().getGroup("FIELD", reportStepIdx); this->schedule().getGroup("FIELD", reportStepIdx);
WellGroupHelpers::setCmodeGroup(fieldGroup, WellGroupHelpers<Scalar>::setCmodeGroup(fieldGroup,
this->schedule(), this->schedule(),
this->summaryState(), this->summaryState(),
reportStepIdx, reportStepIdx,
this->groupState()); this->groupState());
// Define per region average pressure calculators for use by // Define per region average pressure calculators for use by
// pressure maintenance groups (GPMAINT keyword). // pressure maintenance groups (GPMAINT keyword).
if (this->schedule()[reportStepIdx].has_gpmaint()) { if (this->schedule()[reportStepIdx].has_gpmaint()) {
WellGroupHelpers::setRegionAveragePressureCalculator WellGroupHelpers<Scalar>::setRegionAveragePressureCalculator
(fieldGroup, (fieldGroup,
this->schedule(), this->schedule(),
reportStepIdx, reportStepIdx,
@@ -505,10 +505,20 @@ namespace Opm {
//update guide rates //update guide rates
const auto& comm = simulator_.vanguard().grid().comm(); const auto& comm = simulator_.vanguard().grid().comm();
std::vector<double> pot(numPhases(), 0.0); std::vector<double> pot(this->numPhases(), 0.0);
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx); const Group& fieldGroup = this->schedule().getGroup("FIELD", reportStepIdx);
WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime, WellGroupHelpers<double>::updateGuideRates(fieldGroup,
this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger); this->schedule(),
summaryState,
this->phase_usage_,
reportStepIdx,
simulationTime,
this->wellState(),
this->groupState(),
comm,
&this->guideRate_,
pot,
local_deferredLogger);
std::string exc_msg; std::string exc_msg;
auto exc_type = ExceptionType::NONE; auto exc_type = ExceptionType::NONE;
// update gpmaint targets // update gpmaint targets
@@ -517,8 +527,13 @@ namespace Opm {
calculator.second->template defineState<ElementContext>(simulator_); calculator.second->template defineState<ElementContext>(simulator_);
} }
const double dt = simulator_.timeStepSize(); const double dt = simulator_.timeStepSize();
WellGroupHelpers::updateGpMaintTargetForGroups(fieldGroup, WellGroupHelpers<double>::updateGpMaintTargetForGroups(fieldGroup,
schedule_, regionalAveragePressureCalculator_, reportStepIdx, dt, this->wellState(), this->groupState()); this->schedule_,
regionalAveragePressureCalculator_,
reportStepIdx,
dt,
this->wellState(),
this->groupState());
} }
try { try {
// Compute initial well solution for new wells and injectors that change injection type i.e. WAG. // Compute initial well solution for new wells and injectors that change injection type i.e. WAG.
@@ -574,8 +589,11 @@ namespace Opm {
well->init(&phase_usage_, depth_, gravity_, local_num_cells_, B_avg_, true); well->init(&phase_usage_, depth_, gravity_, local_num_cells_, B_avg_, true);
double well_efficiency_factor = wellEcl.getEfficiencyFactor(); double well_efficiency_factor = wellEcl.getEfficiencyFactor();
WellGroupHelpers::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(), timeStepIdx), WellGroupHelpers<double>::accumulateGroupEfficiencyFactor(this->schedule().getGroup(wellEcl.groupName(),
schedule(), timeStepIdx, well_efficiency_factor); timeStepIdx),
this->schedule(),
timeStepIdx,
well_efficiency_factor);
well->setWellEfficiencyFactor(well_efficiency_factor); well->setWellEfficiencyFactor(well_efficiency_factor);
well->setVFPProperties(vfp_properties_.get()); well->setVFPProperties(vfp_properties_.get());
@@ -1191,13 +1209,22 @@ namespace Opm {
const double simulationTime = simulator_.time(); const double simulationTime = simulator_.time();
const auto& comm = simulator_.vanguard().grid().comm(); const auto& comm = simulator_.vanguard().grid().comm();
const auto& summaryState = simulator_.vanguard().summaryState(); const auto& summaryState = simulator_.vanguard().summaryState();
std::vector<double> pot(numPhases(), 0.0); std::vector<double> pot(this->numPhases(), 0.0);
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx); const Group& fieldGroup = this->schedule().getGroup("FIELD", reportStepIdx);
WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime, WellGroupHelpers<double>::updateGuideRates(fieldGroup,
this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger); this->schedule(),
summaryState,
this->phase_usage_,
reportStepIdx,
simulationTime,
this->wellState(),
this->groupState(),
comm,
&this->guideRate_,
pot,
local_deferredLogger);
} }
return {more_network_update, well_group_control_changed}; return {more_network_update, well_group_control_changed};
} }

View File

@@ -30,17 +30,19 @@
#include <cassert> #include <cassert>
namespace Opm::WellGroupHelpers { namespace Opm::WGHelpers {
FractionCalculator::FractionCalculator(const Schedule& schedule, template<class Scalar>
const WellState<double>& well_state, FractionCalculator<Scalar>::
const GroupState<double>& group_state, FractionCalculator(const Schedule& schedule,
const int report_step, const WellState<Scalar>& well_state,
const GuideRate* guide_rate, const GroupState<Scalar>& group_state,
const GuideRateModel::Target target, const int report_step,
const PhaseUsage& pu, const GuideRate* guide_rate,
const bool is_producer, const GuideRateModel::Target target,
const Phase injection_phase) const PhaseUsage& pu,
const bool is_producer,
const Phase injection_phase)
: schedule_(schedule) : schedule_(schedule)
, well_state_(well_state) , well_state_(well_state)
, group_state_(group_state) , group_state_(group_state)
@@ -53,11 +55,13 @@ FractionCalculator::FractionCalculator(const Schedule& schedule,
{ {
} }
double FractionCalculator::fraction(const std::string& name, template<class Scalar>
const std::string& control_group_name, Scalar FractionCalculator<Scalar>::
const bool always_include_this) fraction(const std::string& name,
const std::string& control_group_name,
const bool always_include_this)
{ {
double fraction = 1.0; Scalar fraction = 1.0;
std::string current = name; std::string current = name;
while (current != control_group_name) { while (current != control_group_name) {
fraction *= localFraction(current, always_include_this ? name : ""); fraction *= localFraction(current, always_include_this ? name : "");
@@ -66,17 +70,19 @@ double FractionCalculator::fraction(const std::string& name,
return fraction; return fraction;
} }
double FractionCalculator::localFraction(const std::string& name, template<class Scalar>
const std::string& always_included_child) Scalar FractionCalculator<Scalar>::
localFraction(const std::string& name,
const std::string& always_included_child)
{ {
const double my_guide_rate = guideRate(name, always_included_child); const Scalar my_guide_rate = guideRate(name, always_included_child);
const Group& parent_group = schedule_.getGroup(parent(name), report_step_); const Group& parent_group = schedule_.getGroup(parent(name), report_step_);
const double total_guide_rate = guideRateSum(parent_group, always_included_child); const Scalar total_guide_rate = guideRateSum(parent_group, always_included_child);
// the total guide gate is the same as my_guide rate // the total guide gate is the same as my_guide rate
// the well/group is probably on its own, i.e. return 1 // the well/group is probably on its own, i.e. return 1
// even is its guide_rate is zero // even is its guide_rate is zero
const double guide_rate_epsilon = 1e-12; const Scalar guide_rate_epsilon = 1e-12;
if ( std::abs(my_guide_rate - total_guide_rate) < guide_rate_epsilon ) if ( std::abs(my_guide_rate - total_guide_rate) < guide_rate_epsilon )
return 1.0; return 1.0;
@@ -84,7 +90,9 @@ double FractionCalculator::localFraction(const std::string& name,
return my_guide_rate / total_guide_rate; return my_guide_rate / total_guide_rate;
} }
std::string FractionCalculator::parent(const std::string& name) template<class Scalar>
std::string FractionCalculator<Scalar>::
parent(const std::string& name)
{ {
if (schedule_.hasWell(name)) { if (schedule_.hasWell(name)) {
return schedule_.getWell(name, report_step_).groupName(); return schedule_.getWell(name, report_step_).groupName();
@@ -93,10 +101,12 @@ std::string FractionCalculator::parent(const std::string& name)
} }
} }
double FractionCalculator::guideRateSum(const Group& group, template<class Scalar>
const std::string& always_included_child) Scalar FractionCalculator<Scalar>::
guideRateSum(const Group& group,
const std::string& always_included_child)
{ {
double total_guide_rate = 0.0; Scalar total_guide_rate = 0.0;
for (const std::string& child_group : group.groups()) { for (const std::string& child_group : group.groups()) {
bool included = (child_group == always_included_child); bool included = (child_group == always_included_child);
if (is_producer_) { if (is_producer_) {
@@ -128,11 +138,14 @@ double FractionCalculator::guideRateSum(const Group& group,
return total_guide_rate; return total_guide_rate;
} }
double FractionCalculator::guideRate(const std::string& name, const std::string& always_included_child) template<class Scalar>
Scalar FractionCalculator<Scalar>::
guideRate(const std::string& name,
const std::string& always_included_child)
{ {
if (schedule_.hasWell(name, report_step_)) { if (schedule_.hasWell(name, report_step_)) {
return WellGroupHelpers::getGuideRate(name, schedule_, well_state_, group_state_, return WellGroupHelpers<Scalar>::getGuideRate(name, schedule_, well_state_, group_state_,
report_step_, guide_rate_, target_, pu_); report_step_, guide_rate_, target_, pu_);
} else { } else {
if (groupControlledWells(name, always_included_child) > 0) { if (groupControlledWells(name, always_included_child) > 0) {
if (is_producer_ && guide_rate_->has(name)) { if (is_producer_ && guide_rate_->has(name)) {
@@ -153,25 +166,31 @@ double FractionCalculator::guideRate(const std::string& name, const std::string&
} }
} }
int FractionCalculator::groupControlledWells(const std::string& group_name, template<class Scalar>
const std::string& always_included_child) int FractionCalculator<Scalar>::
groupControlledWells(const std::string& group_name,
const std::string& always_included_child)
{ {
return WellGroupHelpers::groupControlledWells(schedule_, return WellGroupHelpers<Scalar>::groupControlledWells(schedule_,
well_state_, well_state_,
this->group_state_, this->group_state_,
report_step_, report_step_,
group_name, group_name,
always_included_child, always_included_child,
is_producer_, is_producer_,
injection_phase_); injection_phase_);
} }
GuideRate::RateVector FractionCalculator::getGroupRateVector(const std::string& group_name) template<class Scalar>
GuideRate::RateVector FractionCalculator<Scalar>::
getGroupRateVector(const std::string& group_name)
{ {
assert(is_producer_); assert(is_producer_);
return WellGroupHelpers::getProductionGroupRateVector(this->group_state_, return WellGroupHelpers<Scalar>::getProductionGroupRateVector(this->group_state_,
this->pu_, this->pu_,
group_name); group_name);
} }
template class FractionCalculator<double>;
} // namespace Opm::WGHelpers } // namespace Opm::WGHelpers

View File

@@ -32,38 +32,39 @@ class Schedule;
template<class Scalar> class WellState; template<class Scalar> class WellState;
} }
namespace Opm::WellGroupHelpers { namespace Opm::WGHelpers {
template<class Scalar>
class FractionCalculator class FractionCalculator
{ {
public: public:
FractionCalculator(const Schedule& schedule, FractionCalculator(const Schedule& schedule,
const WellState<double>& well_state, const WellState<Scalar>& well_state,
const GroupState<double>& group_state, const GroupState<Scalar>& group_state,
const int report_step, const int report_step,
const GuideRate* guide_rate, const GuideRate* guide_rate,
const GuideRateModel::Target target, const GuideRateModel::Target target,
const PhaseUsage& pu, const PhaseUsage& pu,
const bool is_producer, const bool is_producer,
const Phase injection_phase); const Phase injection_phase);
double fraction(const std::string& name, Scalar fraction(const std::string& name,
const std::string& control_group_name, const std::string& control_group_name,
const bool always_include_this); const bool always_include_this);
double localFraction(const std::string& name, Scalar localFraction(const std::string& name,
const std::string& always_included_child); const std::string& always_included_child);
private: private:
std::string parent(const std::string& name); std::string parent(const std::string& name);
double guideRateSum(const Group& group, Scalar guideRateSum(const Group& group,
const std::string& always_included_child); const std::string& always_included_child);
double guideRate(const std::string& name, Scalar guideRate(const std::string& name,
const std::string& always_included_child); const std::string& always_included_child);
int groupControlledWells(const std::string& group_name, int groupControlledWells(const std::string& group_name,
const std::string& always_included_child); const std::string& always_included_child);
GuideRate::RateVector getGroupRateVector(const std::string& group_name); GuideRate::RateVector getGroupRateVector(const std::string& group_name);
const Schedule& schedule_; const Schedule& schedule_;
const WellState<double>& well_state_; const WellState<Scalar>& well_state_;
const GroupState<double>& group_state_; const GroupState<Scalar>& group_state_;
int report_step_; int report_step_;
const GuideRate* guide_rate_; const GuideRate* guide_rate_;
GuideRateModel::Target target_; GuideRateModel::Target target_;
@@ -72,6 +73,6 @@ private:
Phase injection_phase_; Phase injection_phase_;
}; };
} // namespace Opm::WellGroupHelpers } // namespace Opm::WGHelpers
#endif // OPM_FRACTION_CALCULATOR_HEADER_INCLUDED #endif // OPM_FRACTION_CALCULATOR_HEADER_INCLUDED

View File

@@ -77,9 +77,12 @@ GroupEconomicLimitsChecker(const BlackoilWellModelGeneric& well_model,
auto phase_idx = this->phase_idx_map_[i]; auto phase_idx = this->phase_idx_map_[i];
this->phase_idx_reverse_map_[phase_idx] = static_cast<int>(i); this->phase_idx_reverse_map_[phase_idx] = static_cast<int>(i);
auto phase_pos = this->well_model_.phaseUsage().phase_pos[phase_idx]; auto phase_pos = this->well_model_.phaseUsage().phase_pos[phase_idx];
Scalar production_rate = WellGroupHelpers::sumWellSurfaceRates( Scalar production_rate = WellGroupHelpers<Scalar>::sumWellSurfaceRates(this->group_,
this->group_, this->schedule_, this->well_state_, this->schedule_,
this->report_step_idx_, phase_pos, /*isInjector*/false); this->well_state_,
this->report_step_idx_,
phase_pos,
/*isInjector*/false);
this->production_rates_[i] = this->well_model_.comm().sum(production_rate); this->production_rates_[i] = this->well_model_.comm().sum(production_rate);
} }
} }

View File

@@ -26,24 +26,20 @@
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp> #include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
#include <opm/simulators/wells/GroupState.hpp> #include <opm/simulators/wells/GroupState.hpp>
#include <algorithm>
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
#include <type_traits>
namespace Opm namespace Opm::WGHelpers {
{
namespace WellGroupHelpers template<class Scalar>
{ TargetCalculator<Scalar>::
TargetCalculator(const Group::ProductionCMode cmode,
TargetCalculator::TargetCalculator(const Group::ProductionCMode cmode, const PhaseUsage& pu,
const PhaseUsage& pu, const std::vector<Scalar>& resv_coeff,
const std::vector<double>& resv_coeff, const Scalar group_grat_target_from_sales,
const double group_grat_target_from_sales, const std::string& group_name,
const std::string& group_name, const GroupState<Scalar>& group_state,
const GroupState<double>& group_state, const bool use_gpmaint)
const bool use_gpmaint)
: cmode_(cmode) : cmode_(cmode)
, pu_(pu) , pu_(pu)
, resv_coeff_(resv_coeff) , resv_coeff_(resv_coeff)
@@ -55,8 +51,9 @@ TargetCalculator::TargetCalculator(const Group::ProductionCMode cmode,
{ {
} }
template<class Scalar>
template <typename RateType> template <typename RateType>
RateType TargetCalculator::calcModeRateFromRates(const RateType* rates) const RateType TargetCalculator<Scalar>::calcModeRateFromRates(const RateType* rates) const
{ {
switch (cmode_) { switch (cmode_) {
case Group::ProductionCMode::ORAT: { case Group::ProductionCMode::ORAT: {
@@ -95,7 +92,10 @@ RateType TargetCalculator::calcModeRateFromRates(const RateType* rates) const
} }
} }
double TargetCalculator::groupTarget(const std::optional<Group::ProductionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const template<class Scalar>
Scalar TargetCalculator<Scalar>::
groupTarget(const std::optional<Group::ProductionControls>& ctrl,
DeferredLogger& deferred_logger) const
{ {
if (!ctrl && !use_gpmaint_) { if (!ctrl && !use_gpmaint_) {
OPM_DEFLOG_THROW(std::logic_error, OPM_DEFLOG_THROW(std::logic_error,
@@ -111,7 +111,7 @@ double TargetCalculator::groupTarget(const std::optional<Group::ProductionContro
case Group::ProductionCMode::GRAT: case Group::ProductionCMode::GRAT:
{ {
// gas target may have been adjusted by GCONSALE // gas target may have been adjusted by GCONSALE
if ( group_grat_target_from_sales_ > 0) if (group_grat_target_from_sales_ > 0)
return group_grat_target_from_sales_; return group_grat_target_from_sales_;
return ctrl->gas_target; return ctrl->gas_target;
@@ -120,7 +120,7 @@ double TargetCalculator::groupTarget(const std::optional<Group::ProductionContro
return ctrl->liquid_target; return ctrl->liquid_target;
case Group::ProductionCMode::RESV: case Group::ProductionCMode::RESV:
{ {
if(use_gpmaint_ && this->group_state_.has_gpmaint_target(this->group_name_)) if (use_gpmaint_ && this->group_state_.has_gpmaint_target(this->group_name_))
return this->group_state_.gpmaint_target(this->group_name_); return this->group_state_.gpmaint_target(this->group_name_);
return ctrl->resv_target; return ctrl->resv_target;
@@ -132,7 +132,9 @@ double TargetCalculator::groupTarget(const std::optional<Group::ProductionContro
} }
} }
GuideRateModel::Target TargetCalculator::guideTargetMode() const template<class Scalar>
GuideRateModel::Target
TargetCalculator<Scalar>::guideTargetMode() const
{ {
switch (cmode_) { switch (cmode_) {
case Group::ProductionCMode::ORAT: case Group::ProductionCMode::ORAT:
@@ -152,15 +154,17 @@ GuideRateModel::Target TargetCalculator::guideTargetMode() const
} }
} }
InjectionTargetCalculator::InjectionTargetCalculator(const Group::InjectionCMode& cmode, template<class Scalar>
const PhaseUsage& pu, InjectionTargetCalculator<Scalar>::
const std::vector<double>& resv_coeff, InjectionTargetCalculator(const Group::InjectionCMode& cmode,
const std::string& group_name, const PhaseUsage& pu,
const double sales_target, const std::vector<Scalar>& resv_coeff,
const GroupState<double>& group_state, const std::string& group_name,
const Phase& injection_phase, const Scalar sales_target,
const bool use_gpmaint, const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger) const Phase& injection_phase,
const bool use_gpmaint,
DeferredLogger& deferred_logger)
: cmode_(cmode) : cmode_(cmode)
, pu_(pu) , pu_(pu)
, resv_coeff_(resv_coeff) , resv_coeff_(resv_coeff)
@@ -197,8 +201,10 @@ InjectionTargetCalculator::InjectionTargetCalculator(const Group::InjectionCMode
} }
} }
template<class Scalar>
double InjectionTargetCalculator::groupTarget(const std::optional<Group::InjectionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const Scalar InjectionTargetCalculator<Scalar>::
groupTarget(const std::optional<Group::InjectionControls>& ctrl,
DeferredLogger& deferred_logger) const
{ {
if (!ctrl && !use_gpmaint_) { if (!ctrl && !use_gpmaint_) {
OPM_DEFLOG_THROW(std::logic_error, OPM_DEFLOG_THROW(std::logic_error,
@@ -208,32 +214,32 @@ double InjectionTargetCalculator::groupTarget(const std::optional<Group::Injecti
} }
switch (cmode_) { switch (cmode_) {
case Group::InjectionCMode::RATE: case Group::InjectionCMode::RATE:
if(use_gpmaint_ && this->group_state_.has_gpmaint_target(this->group_name_)) if (use_gpmaint_ && this->group_state_.has_gpmaint_target(this->group_name_))
return this->group_state_.gpmaint_target(this->group_name_); return this->group_state_.gpmaint_target(this->group_name_);
return ctrl->surface_max_rate; return ctrl->surface_max_rate;
case Group::InjectionCMode::RESV: case Group::InjectionCMode::RESV:
if(use_gpmaint_ && this->group_state_.has_gpmaint_target(this->group_name_)) if (use_gpmaint_ && this->group_state_.has_gpmaint_target(this->group_name_))
return this->group_state_.gpmaint_target(this->group_name_) / resv_coeff_[pos_]; return this->group_state_.gpmaint_target(this->group_name_) / resv_coeff_[pos_];
return ctrl->resv_max_rate / resv_coeff_[pos_]; return ctrl->resv_max_rate / resv_coeff_[pos_];
case Group::InjectionCMode::REIN: { case Group::InjectionCMode::REIN: {
double production_rate = this->group_state_.injection_rein_rates(ctrl->reinj_group)[pos_]; Scalar production_rate = this->group_state_.injection_rein_rates(ctrl->reinj_group)[pos_];
return ctrl->target_reinj_fraction * production_rate; return ctrl->target_reinj_fraction * production_rate;
} }
case Group::InjectionCMode::VREP: { case Group::InjectionCMode::VREP: {
const std::vector<double>& group_injection_reductions = this->group_state_.injection_reduction_rates(this->group_name_); const std::vector<Scalar>& group_injection_reductions = this->group_state_.injection_reduction_rates(this->group_name_);
double voidage_rate = group_state_.injection_vrep_rate(ctrl->voidage_group) * ctrl->target_void_fraction; Scalar voidage_rate = group_state_.injection_vrep_rate(ctrl->voidage_group) * ctrl->target_void_fraction;
double inj_reduction = 0.0; Scalar inj_reduction = 0.0;
if (ctrl->phase != Phase::WATER) if (ctrl->phase != Phase::WATER)
inj_reduction += group_injection_reductions[pu_.phase_pos[BlackoilPhases::Aqua]] inj_reduction += group_injection_reductions[pu_.phase_pos[BlackoilPhases::Aqua]]
* resv_coeff_[pu_.phase_pos[BlackoilPhases::Aqua]]; * resv_coeff_[pu_.phase_pos[BlackoilPhases::Aqua]];
if (ctrl->phase != Phase::OIL) if (ctrl->phase != Phase::OIL)
inj_reduction += group_injection_reductions[pu_.phase_pos[BlackoilPhases::Liquid]] inj_reduction += group_injection_reductions[pu_.phase_pos[BlackoilPhases::Liquid]]
* resv_coeff_[pu_.phase_pos[BlackoilPhases::Liquid]]; * resv_coeff_[pu_.phase_pos[BlackoilPhases::Liquid]];
if (ctrl->phase != Phase::GAS) if (ctrl->phase != Phase::GAS)
inj_reduction += group_injection_reductions[pu_.phase_pos[BlackoilPhases::Vapour]] inj_reduction += group_injection_reductions[pu_.phase_pos[BlackoilPhases::Vapour]]
* resv_coeff_[pu_.phase_pos[BlackoilPhases::Vapour]]; * resv_coeff_[pu_.phase_pos[BlackoilPhases::Vapour]];
voidage_rate -= inj_reduction; voidage_rate -= inj_reduction;
return voidage_rate / resv_coeff_[pos_]; return voidage_rate / resv_coeff_[pos_];
} }
@@ -241,7 +247,7 @@ double InjectionTargetCalculator::groupTarget(const std::optional<Group::Injecti
assert(pos_ == pu_.phase_pos[BlackoilPhases::Vapour]); assert(pos_ == pu_.phase_pos[BlackoilPhases::Vapour]);
// Gas injection rate = Total gas production rate + gas import rate - gas consumption rate - sales rate; // Gas injection rate = Total gas production rate + gas import rate - gas consumption rate - sales rate;
// Gas import and consumption is already included in the REIN rates // Gas import and consumption is already included in the REIN rates
double inj_rate = group_state_.injection_rein_rates(this->group_name_)[pos_]; Scalar inj_rate = group_state_.injection_rein_rates(this->group_name_)[pos_];
inj_rate -= sales_target_; inj_rate -= sales_target_;
return inj_rate; return inj_rate;
} }
@@ -253,13 +259,18 @@ double InjectionTargetCalculator::groupTarget(const std::optional<Group::Injecti
} }
} }
GuideRateModel::Target InjectionTargetCalculator::guideTargetMode() const template<class Scalar>
GuideRateModel::Target
InjectionTargetCalculator<Scalar>::guideTargetMode() const
{ {
return target_; return target_;
} }
#define INSTANCE_TARGET_CALCULATOR(...) \ #define INSTANCE_TARGET_CALCULATOR(...) \
template __VA_ARGS__ TargetCalculator::calcModeRateFromRates<__VA_ARGS__>(const __VA_ARGS__* rates) const; template __VA_ARGS__ TargetCalculator<double>::calcModeRateFromRates<__VA_ARGS__>(const __VA_ARGS__* rates) const;
template class TargetCalculator<double>;
template class InjectionTargetCalculator<double>;
INSTANCE_TARGET_CALCULATOR(double) INSTANCE_TARGET_CALCULATOR(double)
INSTANCE_TARGET_CALCULATOR(DenseAd::Evaluation<double,3,0>) INSTANCE_TARGET_CALCULATOR(DenseAd::Evaluation<double,3,0>)
@@ -279,6 +290,4 @@ INSTANCE_TARGET_CALCULATOR(DenseAd::Evaluation<double,-1,9>)
INSTANCE_TARGET_CALCULATOR(DenseAd::Evaluation<double,-1,10>) INSTANCE_TARGET_CALCULATOR(DenseAd::Evaluation<double,-1,10>)
INSTANCE_TARGET_CALCULATOR(DenseAd::Evaluation<double,-1,11>) INSTANCE_TARGET_CALCULATOR(DenseAd::Evaluation<double,-1,11>)
} // namespace WellGroupHelpers } // namespace Opm::WGHelpers
} // namespace Opm

View File

@@ -28,89 +28,92 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace Opm namespace Opm {
{
class DeferredLogger; class DeferredLogger;
template<class Scalar> class GroupState; template<class Scalar> class GroupState;
struct PhaseUsage; struct PhaseUsage;
namespace WellGroupHelpers namespace WGHelpers {
/// Based on a group control mode, extract or calculate rates, and
/// provide other conveniences.
template<class Scalar>
class TargetCalculator
{ {
public:
TargetCalculator(const Group::ProductionCMode cmode,
const PhaseUsage& pu,
const std::vector<Scalar>& resv_coeff,
const Scalar group_grat_target_from_sales,
const std::string& group_name,
const GroupState<Scalar>& group_state,
const bool use_gpmaint);
/// Based on a group control mode, extract or calculate rates, and template <typename RateType>
/// provide other conveniences. RateType calcModeRateFromRates(const std::vector<RateType>& rates) const
class TargetCalculator
{ {
public: return calcModeRateFromRates(rates.data());
TargetCalculator(const Group::ProductionCMode cmode, }
const PhaseUsage& pu,
const std::vector<double>& resv_coeff,
const double group_grat_target_from_sales,
const std::string& group_name,
const GroupState<double>& group_state,
const bool use_gpmaint);
template <typename RateType> template <typename RateType>
RateType calcModeRateFromRates(const std::vector<RateType>& rates) const RateType calcModeRateFromRates(const RateType* rates) const;
{
return calcModeRateFromRates(rates.data());
}
template <typename RateType> Scalar groupTarget(const std::optional<Group::ProductionControls>& ctrl,
RateType calcModeRateFromRates(const RateType* rates) const; DeferredLogger& deferred_logger) const;
double groupTarget(const std::optional<Group::ProductionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const; GuideRateModel::Target guideTargetMode() const;
GuideRateModel::Target guideTargetMode() const; private:
Group::ProductionCMode cmode_;
const PhaseUsage& pu_;
const std::vector<Scalar>& resv_coeff_;
const Scalar group_grat_target_from_sales_;
const std::string& group_name_;
const GroupState<Scalar>& group_state_;
bool use_gpmaint_;
};
private: /// Based on a group control mode, extract or calculate rates, and
Group::ProductionCMode cmode_; /// provide other conveniences.
const PhaseUsage& pu_; template<class Scalar>
const std::vector<double>& resv_coeff_; class InjectionTargetCalculator
const double group_grat_target_from_sales_; {
const std::string& group_name_; public:
const GroupState<double>& group_state_; InjectionTargetCalculator(const Group::InjectionCMode& cmode,
bool use_gpmaint_; const PhaseUsage& pu,
}; const std::vector<Scalar>& resv_coeff,
const std::string& group_name,
const Scalar sales_target,
const GroupState<Scalar>& group_state,
const Phase& injection_phase,
const bool use_gpmaint,
DeferredLogger& deferred_logger);
/// Based on a group control mode, extract or calculate rates, and template <typename RateVec>
/// provide other conveniences. auto calcModeRateFromRates(const RateVec& rates) const
class InjectionTargetCalculator
{ {
public: return rates[pos_];
InjectionTargetCalculator(const Group::InjectionCMode& cmode, }
const PhaseUsage& pu,
const std::vector<double>& resv_coeff,
const std::string& group_name,
const double sales_target,
const GroupState<double>& group_state,
const Phase& injection_phase,
const bool use_gpmaint,
DeferredLogger& deferred_logger);
template <typename RateVec> Scalar groupTarget(const std::optional<Group::InjectionControls>& ctrl,
auto calcModeRateFromRates(const RateVec& rates) const DeferredLogger& deferred_logger) const;
{
return rates[pos_];
}
double groupTarget(const std::optional<Group::InjectionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const; GuideRateModel::Target guideTargetMode() const;
GuideRateModel::Target guideTargetMode() const; private:
Group::InjectionCMode cmode_;
const PhaseUsage& pu_;
const std::vector<Scalar>& resv_coeff_;
const std::string& group_name_;
Scalar sales_target_;
const GroupState<Scalar>& group_state_;
bool use_gpmaint_;
int pos_;
GuideRateModel::Target target_;
};
private: } // namespace WGHelpers
Group::InjectionCMode cmode_;
const PhaseUsage& pu_;
const std::vector<double>& resv_coeff_;
const std::string& group_name_;
double sales_target_;
const GroupState<double>& group_state_;
bool use_gpmaint_;
int pos_;
GuideRateModel::Target target_;
};
} // namespace WellGroupHelpers
} // namespace Opm } // namespace Opm

View File

@@ -74,21 +74,21 @@ checkGroupConstraintsInj(const Group& group,
const auto& ws = well_state.well(well_.indexOfWell()); const auto& ws = well_state.well(well_.indexOfWell());
// Call check for the well's injection phase. // Call check for the well's injection phase.
return WellGroupHelpers::checkGroupConstraintsInj(well_.name(), return WellGroupHelpers<double>::checkGroupConstraintsInj(well_.name(),
well_.wellEcl().groupName(), well_.wellEcl().groupName(),
group, group,
well_state, well_state,
group_state, group_state,
well_.currentStep(), well_.currentStep(),
well_.guideRate(), well_.guideRate(),
ws.surface_rates.data(), ws.surface_rates.data(),
injectionPhase, injectionPhase,
well_.phaseUsage(), well_.phaseUsage(),
efficiencyFactor, efficiencyFactor,
schedule, schedule,
summaryState, summaryState,
resv_coeff, resv_coeff,
deferred_logger); deferred_logger);
} }
std::pair<bool, double> std::pair<bool, double>
@@ -107,20 +107,20 @@ checkGroupConstraintsProd(const Group& group,
rateConverter(0, well_.pvtRegionIdx(), group.name(), resv_coeff); // FIPNUM region 0 here, should use FIPNUM from WELSPECS. rateConverter(0, well_.pvtRegionIdx(), group.name(), resv_coeff); // FIPNUM region 0 here, should use FIPNUM from WELSPECS.
const auto& ws = well_state.well(well_.indexOfWell()); const auto& ws = well_state.well(well_.indexOfWell());
return WellGroupHelpers::checkGroupConstraintsProd(well_.name(), return WellGroupHelpers<double>::checkGroupConstraintsProd(well_.name(),
well_.wellEcl().groupName(), well_.wellEcl().groupName(),
group, group,
well_state, well_state,
group_state, group_state,
well_.currentStep(), well_.currentStep(),
well_.guideRate(), well_.guideRate(),
ws.surface_rates.data(), ws.surface_rates.data(),
well_.phaseUsage(), well_.phaseUsage(),
efficiencyFactor, efficiencyFactor,
schedule, schedule,
summaryState, summaryState,
resv_coeff, resv_coeff,
deferred_logger); deferred_logger);
} }
bool WellGroupConstraints:: bool WellGroupConstraints::

View File

@@ -136,17 +136,27 @@ getGroupInjectionControl(const Group& group,
const auto& gconsale = schedule[well_.currentStep()].gconsale().get(group.name(), summaryState); const auto& gconsale = schedule[well_.currentStep()].gconsale().get(group.name(), summaryState);
sales_target = gconsale.sales_target; sales_target = gconsale.sales_target;
} }
WellGroupHelpers::InjectionTargetCalculator tcalc(currentGroupControl, pu,
resv_coeff, group.name(), WGHelpers::InjectionTargetCalculator tcalc(currentGroupControl,
sales_target, group_state, pu,
injectionPhase, resv_coeff,
group.has_gpmaint_control(injectionPhase, currentGroupControl), group.name(),
deferred_logger); sales_target,
WellGroupHelpers::FractionCalculator fcalc(schedule, well_state, group_state,
group_state, well_.currentStep(), injectionPhase,
well_.guideRate(), group.has_gpmaint_control(injectionPhase,
tcalc.guideTargetMode(), currentGroupControl),
pu, false, injectionPhase); deferred_logger);
WGHelpers::FractionCalculator fcalc(schedule,
well_state,
group_state,
well_.currentStep(),
well_.guideRate(),
tcalc.guideTargetMode(),
pu,
false,
injectionPhase);
auto localFraction = [&](const std::string& child) { auto localFraction = [&](const std::string& child) {
return fcalc.localFraction(child, child); return fcalc.localFraction(child, child);
@@ -163,8 +173,8 @@ getGroupInjectionControl(const Group& group,
const double orig_target = tcalc.groupTarget(ctrl, const double orig_target = tcalc.groupTarget(ctrl,
deferred_logger); deferred_logger);
const auto chain = WellGroupHelpers::groupChainTopBot(well_.name(), group.name(), const auto chain = WellGroupHelpers<double>::groupChainTopBot(well_.name(), group.name(),
schedule, well_.currentStep()); schedule, well_.currentStep());
// Because 'name' is the last of the elements, and not an ancestor, we subtract one below. // 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; const std::size_t num_ancestors = chain.size() - 1;
double target = orig_target; double target = orig_target;
@@ -260,14 +270,26 @@ getGroupInjectionTargetRate(const Group& group,
const auto& gconsale = schedule[well_.currentStep()].gconsale().get(group.name(), summaryState); const auto& gconsale = schedule[well_.currentStep()].gconsale().get(group.name(), summaryState);
sales_target = gconsale.sales_target; sales_target = gconsale.sales_target;
} }
WellGroupHelpers::InjectionTargetCalculator tcalc(currentGroupControl, pu, resv_coeff, WGHelpers::InjectionTargetCalculator tcalc(currentGroupControl,
group.name(), sales_target, group_state, pu,
injectionPhase, resv_coeff,
group.has_gpmaint_control(injectionPhase, currentGroupControl), group.name(),
deferred_logger); sales_target,
WellGroupHelpers::FractionCalculator fcalc(schedule, well_state, group_state, group_state,
well_.currentStep(), well_.guideRate(), injectionPhase,
tcalc.guideTargetMode(), pu, false, injectionPhase); group.has_gpmaint_control(injectionPhase,
currentGroupControl),
deferred_logger);
WGHelpers::FractionCalculator fcalc(schedule,
well_state,
group_state,
well_.currentStep(),
well_.guideRate(),
tcalc.guideTargetMode(),
pu,
false,
injectionPhase);
auto localFraction = [&](const std::string& child) { 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. return fcalc.localFraction(child, child); //Note child needs to be passed to always include since the global isGrup map is not updated yet.
@@ -284,7 +306,10 @@ getGroupInjectionTargetRate(const Group& group,
const double orig_target = tcalc.groupTarget(ctrl, deferred_logger); const double orig_target = tcalc.groupTarget(ctrl, deferred_logger);
const auto chain = WellGroupHelpers::groupChainTopBot(well_.name(), group.name(), schedule, well_.currentStep()); const auto chain = WellGroupHelpers<double>::groupChainTopBot(well_.name(),
group.name(),
schedule,
well_.currentStep());
// Because 'name' is the last of the elements, and not an ancestor, we subtract one below. // 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; const std::size_t num_ancestors = chain.size() - 1;
double target = orig_target; double target = orig_target;
@@ -363,15 +388,23 @@ void WellGroupControls::getGroupProductionControl(const Group& group,
if (group_state.has_grat_sales_target(group.name())) if (group_state.has_grat_sales_target(group.name()))
gratTargetFromSales = group_state.grat_sales_target(group.name()); gratTargetFromSales = group_state.grat_sales_target(group.name());
WellGroupHelpers::TargetCalculator tcalc(currentGroupControl, pu, resv_coeff, WGHelpers::TargetCalculator tcalc(currentGroupControl,
gratTargetFromSales, group.name(), pu,
group_state, resv_coeff,
group.has_gpmaint_control(currentGroupControl)); gratTargetFromSales,
WellGroupHelpers::FractionCalculator fcalc(schedule, well_state, group_state, group.name(),
well_.currentStep(), group_state,
well_.guideRate(), group.has_gpmaint_control(currentGroupControl));
tcalc.guideTargetMode(),
pu, true, Phase::OIL); WGHelpers::FractionCalculator fcalc(schedule,
well_state,
group_state,
well_.currentStep(),
well_.guideRate(),
tcalc.guideTargetMode(),
pu,
true,
Phase::OIL);
auto localFraction = [&](const std::string& child) { auto localFraction = [&](const std::string& child) {
return fcalc.localFraction(child, child); return fcalc.localFraction(child, child);
@@ -387,8 +420,8 @@ void WellGroupControls::getGroupProductionControl(const Group& group,
ctrl = group.productionControls(summaryState); ctrl = group.productionControls(summaryState);
const double orig_target = tcalc.groupTarget(ctrl, deferred_logger); const double orig_target = tcalc.groupTarget(ctrl, deferred_logger);
const auto chain = WellGroupHelpers::groupChainTopBot(well_.name(), group.name(), const auto chain = WellGroupHelpers<double>::groupChainTopBot(well_.name(), group.name(),
schedule, well_.currentStep()); schedule, well_.currentStep());
// Because 'name' is the last of the elements, and not an ancestor, we subtract one below. // 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; const std::size_t num_ancestors = chain.size() - 1;
double target = orig_target; double target = orig_target;
@@ -452,12 +485,23 @@ getGroupProductionTargetRate(const Group& group,
if (group_state.has_grat_sales_target(group.name())) if (group_state.has_grat_sales_target(group.name()))
gratTargetFromSales = group_state.grat_sales_target(group.name()); gratTargetFromSales = group_state.grat_sales_target(group.name());
WellGroupHelpers::TargetCalculator tcalc(currentGroupControl, pu, resv_coeff, gratTargetFromSales, group.name(), group_state, group.has_gpmaint_control(currentGroupControl)); WGHelpers::TargetCalculator tcalc(currentGroupControl,
WellGroupHelpers::FractionCalculator fcalc(schedule, well_state, group_state, pu,
well_.currentStep(), resv_coeff,
well_.guideRate(), gratTargetFromSales,
tcalc.guideTargetMode(), group.name(),
pu, true, Phase::OIL); group_state,
group.has_gpmaint_control(currentGroupControl));
WGHelpers::FractionCalculator fcalc(schedule,
well_state,
group_state,
well_.currentStep(),
well_.guideRate(),
tcalc.guideTargetMode(),
pu,
true,
Phase::OIL);
auto localFraction = [&](const std::string& child) { 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. return fcalc.localFraction(child, child); //Note child needs to be passed to always include since the global isGrup map is not updated yet.
@@ -473,8 +517,8 @@ getGroupProductionTargetRate(const Group& group,
ctrl = group.productionControls(summaryState); ctrl = group.productionControls(summaryState);
const double orig_target = tcalc.groupTarget(ctrl, deferred_logger); const double orig_target = tcalc.groupTarget(ctrl, deferred_logger);
const auto chain = WellGroupHelpers::groupChainTopBot(well_.name(), group.name(), const auto chain = WellGroupHelpers<double>::groupChainTopBot(well_.name(), group.name(),
schedule, well_.currentStep()); schedule, well_.currentStep());
// Because 'name' is the last of the elements, and not an ancestor, we subtract one below. // 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; const std::size_t num_ancestors = chain.size() - 1;
double target = orig_target; double target = orig_target;
@@ -545,4 +589,5 @@ INSTANCE(DenseAd::Evaluation<double,-1,8u>)
INSTANCE(DenseAd::Evaluation<double,-1,9u>) INSTANCE(DenseAd::Evaluation<double,-1,9u>)
INSTANCE(DenseAd::Evaluation<double,-1,10u>) INSTANCE(DenseAd::Evaluation<double,-1,10u>)
INSTANCE(DenseAd::Evaluation<double,-1,11u>) INSTANCE(DenseAd::Evaluation<double,-1,11u>)
} // namespace Opm } // namespace Opm

File diff suppressed because it is too large Load Diff

View File

@@ -29,8 +29,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace Opm namespace Opm {
{
class DeferredLogger; class DeferredLogger;
class Group; class Group;
@@ -44,265 +43,254 @@ class FieldPropsManager;
namespace Network { class ExtNetwork; } namespace Network { class ExtNetwork; }
namespace WellGroupHelpers template<class Scalar>
class WellGroupHelpers
{ {
public:
static void setCmodeGroup(const Group& group,
const Schedule& schedule,
const SummaryState& summaryState,
const int reportStepIdx,
GroupState<Scalar>& group_state);
static void accumulateGroupEfficiencyFactor(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
Scalar& factor);
static Scalar sumWellSurfaceRates(const Group& group,
const Schedule& schedule,
const WellState<Scalar>& wellState,
const int reportStepIdx,
const int phasePos,
const bool injector);
void setCmodeGroup(const Group& group, /// Returns the name of the worst offending well and its fraction (i.e. violated_phase / preferred_phase)
const Schedule& schedule, static std::pair<std::optional<std::string>, Scalar>
const SummaryState& summaryState,
const int reportStepIdx,
GroupState<double>& group_state);
void accumulateGroupEfficiencyFactor(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
double& factor);
double sumWellSurfaceRates(const Group& group,
const Schedule& schedule,
const WellState<double>& wellState,
const int reportStepIdx,
const int phasePos,
const bool injector);
double sumWellResRates(const Group& group,
const Schedule& schedule,
const WellState<double>& wellState,
const int reportStepIdx,
const int phasePos,
const bool injector);
double sumSolventRates(const Group& group,
const Schedule& schedule,
const WellState<double>& wellState,
const int reportStepIdx,
const bool injector);
void updateGroupTargetReduction(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const bool isInjector,
const PhaseUsage& pu,
const GuideRate& guide_rate,
const WellState<double>& wellState,
GroupState<double>& group_state,
std::vector<double>& groupTargetReduction);
void updateGuideRates(const Group& group,
const Schedule& schedule,
const SummaryState& summary_state,
const PhaseUsage& pu,
int report_step,
double sim_time,
WellState<double>& well_state,
const GroupState<double>& group_state,
const Parallel::Communication& comm,
GuideRate* guide_rate,
std::vector<double>& pot,
Opm::DeferredLogger& deferred_logge);
void updateGuideRateForProductionGroups(const Group& group,
const Schedule& schedule,
const PhaseUsage& pu,
const int reportStepIdx,
const double& simTime,
WellState<double>& wellState,
const GroupState<double>& group_state,
const Parallel::Communication& comm,
GuideRate* guideRate,
std::vector<double>& pot);
void updateGuideRatesForWells(const Schedule& schedule,
const PhaseUsage& pu,
const int reportStepIdx,
const double& simTime,
const WellState<double>& wellState,
const Parallel::Communication& comm,
GuideRate* guideRate);
void updateGuideRatesForInjectionGroups(const Group& group,
const Schedule& schedule,
const SummaryState& summaryState,
const Opm::PhaseUsage& pu,
const int reportStepIdx,
const WellState<double>& wellState,
const GroupState<double>& group_state,
GuideRate* guideRate,
Opm::DeferredLogger& deferred_logger);
void updateVREPForGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<double>& wellState,
GroupState<double>& group_state);
void updateReservoirRatesInjectionGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<double>& wellState,
GroupState<double>& group_state);
void updateSurfaceRatesInjectionGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<double>& wellState,
GroupState<double>& group_state);
void updateWellRates(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<double>& wellStateNupcol,
WellState<double>& wellState);
void updateGroupProductionRates(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<double>& wellState,
GroupState<double>& group_state);
void updateWellRatesFromGroupTargetScale(const double scale,
const Group& group,
const Schedule& schedule,
const int reportStepIdx,
bool isInjector,
const GroupState<double>& group_state,
WellState<double>& wellState);
void updateREINForGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const PhaseUsage& pu,
const SummaryState& st,
const WellState<double>& wellState,
GroupState<double>& group_state,
bool sum_rank);
/// Returns the name of the worst offending well and its fraction
/// (i.e. violated_phase / preferred_phase)
std::pair<std::optional<std::string>, double>
worstOffendingWell(const Group& group, worstOffendingWell(const Group& group,
const Schedule& schedule, const Schedule& schedule,
const int reportStepIdx, const int reportStepIdx,
const Group::ProductionCMode& offendedControl, const Group::ProductionCMode& offendedControl,
const PhaseUsage& pu, const PhaseUsage& pu,
const Parallel::Communication& comm, const Parallel::Communication& comm,
const WellState<double>& wellState, const WellState<Scalar>& wellState,
DeferredLogger& deferred_logger); DeferredLogger& deferred_logger);
template <class RegionalValues> static Scalar sumWellResRates(const Group& group,
void updateGpMaintTargetForGroups(const Group& group, const Schedule& schedule,
const Schedule& schedule, const WellState<Scalar>& wellState,
const RegionalValues& regional_values, const int reportStepIdx,
const int reportStepIdx, const int phasePos,
const double dt, const bool injector);
const WellState<double>& well_state,
GroupState<double>& group_state);
std::map<std::string, double> static Scalar sumSolventRates(const Group& group,
computeNetworkPressures(const Opm::Network::ExtNetwork& network, const Schedule& schedule,
const WellState<double>& well_state, const WellState<Scalar>& wellState,
const GroupState<double>& group_state, const int reportStepIdx,
const bool injector);
static void updateGroupTargetReduction(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const bool isInjector,
const PhaseUsage& pu,
const GuideRate& guide_rate,
const WellState<Scalar>& wellState,
GroupState<Scalar>& group_state,
std::vector<Scalar>& groupTargetReduction);
static void updateGuideRates(const Group& group,
const Schedule& schedule,
const SummaryState& summary_state,
const PhaseUsage& pu,
int report_step,
double sim_time,
WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state,
const Parallel::Communication& comm,
GuideRate* guide_rate,
std::vector<Scalar>& pot,
DeferredLogger& deferred_logger);
static void updateGuideRateForProductionGroups(const Group& group,
const Schedule& schedule,
const PhaseUsage& pu,
const int reportStepIdx,
const double& simTime,
WellState<Scalar>& wellState,
const GroupState<Scalar>& group_state,
const Parallel::Communication& comm,
GuideRate* guideRate,
std::vector<Scalar>& pot);
static void updateGuideRatesForWells(const Schedule& schedule,
const PhaseUsage& pu,
const int reportStepIdx,
const double& simTime,
const WellState<Scalar>& wellState,
const Parallel::Communication& comm,
GuideRate* guideRate);
static void updateGuideRatesForInjectionGroups(const Group& group,
const Schedule& schedule,
const SummaryState& summaryState,
const PhaseUsage& pu,
const int reportStepIdx,
const WellState<Scalar>& wellState,
const GroupState<Scalar>& group_state,
GuideRate* guideRate,
DeferredLogger& deferred_logger);
static void updateVREPForGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<Scalar>& wellState,
GroupState<Scalar>& group_state);
template <class RegionalValues>
static void updateGpMaintTargetForGroups(const Group& group,
const Schedule& schedule,
const RegionalValues& regional_values,
const int reportStepIdx,
const double dt,
const WellState<Scalar>& well_state,
GroupState<Scalar>& group_state);
static void updateReservoirRatesInjectionGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<Scalar>& wellState,
GroupState<Scalar>& group_state);
static void updateSurfaceRatesInjectionGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<Scalar>& wellState,
GroupState<Scalar>& group_state);
static void updateWellRates(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<Scalar>& wellStateNupcol,
WellState<Scalar>& wellState);
static void updateGroupProductionRates(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const WellState<Scalar>& wellState,
GroupState<Scalar>& group_state);
static void updateWellRatesFromGroupTargetScale(const Scalar scale,
const Group& group,
const Schedule& schedule,
const int reportStepIdx,
bool isInjector,
const GroupState<Scalar>& group_state,
WellState<Scalar>& wellState);
static void updateREINForGroups(const Group& group,
const Schedule& schedule,
const int reportStepIdx,
const PhaseUsage& pu,
const SummaryState& st,
const WellState<Scalar>& wellState,
GroupState<Scalar>& group_state,
bool sum_rank);
static std::map<std::string, Scalar>
computeNetworkPressures(const Network::ExtNetwork& network,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state,
const VFPProdProperties& vfp_prod_props, const VFPProdProperties& vfp_prod_props,
const Schedule& schedule, const Schedule& schedule,
const int report_time_step); const int report_time_step);
GuideRate::RateVector static GuideRate::RateVector
getWellRateVector(const WellState<double>& well_state, getWellRateVector(const WellState<Scalar>& well_state,
const PhaseUsage& pu, const PhaseUsage& pu,
const std::string& name); const std::string& name);
GuideRate::RateVector static GuideRate::RateVector
getProductionGroupRateVector(const GroupState<double>& group_state, getProductionGroupRateVector(const GroupState<Scalar>& group_state,
const PhaseUsage& pu, const PhaseUsage& pu,
const std::string& group_name); const std::string& group_name);
double getGuideRate(const std::string& name, static Scalar getGuideRate(const std::string& name,
const Schedule& schedule, const Schedule& schedule,
const WellState<double>& wellState, const WellState<Scalar>& wellState,
const GroupState<double>& group_state, const GroupState<Scalar>& group_state,
const int reportStepIdx, const int reportStepIdx,
const GuideRate* guideRate, const GuideRate* guideRate,
const GuideRateModel::Target target, const GuideRateModel::Target target,
const PhaseUsage& pu); const PhaseUsage& pu);
static Scalar getGuideRateInj(const std::string& name,
const Schedule& schedule,
const WellState<Scalar>& wellState,
const GroupState<Scalar>& group_state,
const int reportStepIdx,
const GuideRate* guideRate,
const GuideRateModel::Target target,
const Phase& injectionPhase,
const PhaseUsage& pu);
double getGuideRateInj(const std::string& name, static int groupControlledWells(const Schedule& schedule,
const Schedule& schedule, const WellState<Scalar>& well_state,
const WellState<double>& wellState, const GroupState<Scalar>& group_state,
const GroupState<double>& group_state, const int report_step,
const int reportStepIdx, const std::string& group_name,
const GuideRate* guideRate, const std::string& always_included_child,
const GuideRateModel::Target target, const bool is_production_group,
const Phase& injectionPhase, const Phase injection_phase);
const PhaseUsage& pu);
int groupControlledWells(const Schedule& schedule, static std::pair<bool, Scalar>
const WellState<double>& well_state, checkGroupConstraintsInj(const std::string& name,
const GroupState<double>& group_state, const std::string& parent,
const int report_step, const Group& group,
const std::string& group_name, const WellState<Scalar>& wellState,
const std::string& always_included_child, const GroupState<Scalar>& group_state,
const bool is_production_group, const int reportStepIdx,
const Phase injection_phase); const GuideRate* guideRate,
const Scalar* rates,
Phase injectionPhase,
const PhaseUsage& pu,
const Scalar efficiencyFactor,
const Schedule& schedule,
const SummaryState& summaryState,
const std::vector<Scalar>& resv_coeff,
DeferredLogger& deferred_logger);
static std::vector<std::string>
groupChainTopBot(const std::string& bottom,
const std::string& top,
const Schedule& schedule,
const int report_step);
std::pair<bool, double> checkGroupConstraintsInj(const std::string& name, static std::pair<bool, Scalar>
const std::string& parent, checkGroupConstraintsProd(const std::string& name,
const Group& group, const std::string& parent,
const WellState<double>& wellState, const Group& group,
const GroupState<double>& group_state, const WellState<Scalar>& wellState,
const int reportStepIdx, const GroupState<Scalar>& group_state,
const GuideRate* guideRate, const int reportStepIdx,
const double* rates, const GuideRate* guideRate,
Phase injectionPhase, const Scalar* rates,
const PhaseUsage& pu, const PhaseUsage& pu,
const double efficiencyFactor, const Scalar efficiencyFactor,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summaryState, const SummaryState& summaryState,
const std::vector<double>& resv_coeff, const std::vector<Scalar>& resv_coeff,
DeferredLogger& deferred_logger); DeferredLogger& deferred_logger);
std::vector<std::string> groupChainTopBot(const std::string& bottom,
const std::string& top,
const Schedule& schedule,
const int report_step);
std::pair<bool, double> checkGroupConstraintsProd(const std::string& name,
const std::string& parent,
const Group& group,
const WellState<double>& wellState,
const GroupState<double>& group_state,
const int reportStepIdx,
const GuideRate* guideRate,
const double* rates,
const PhaseUsage& pu,
const double efficiencyFactor,
const Schedule& schedule,
const SummaryState& summaryState,
const std::vector<double>& resv_coeff,
DeferredLogger& deferred_logger);
template <class AverageRegionalPressureType> template <class AverageRegionalPressureType>
void setRegionAveragePressureCalculator(const Group& group, static void setRegionAveragePressureCalculator(const Group& group,
const Schedule& schedule, const Schedule& schedule,
const int reportStepIdx, const int reportStepIdx,
const FieldPropsManager& fp, const FieldPropsManager& fp,
const PhaseUsage& pu, const PhaseUsage& pu,
std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>& regionalAveragePressureCalculator); std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>& regionalAveragePressureCalculator);
};
} // namespace WellGroupHelpers
} // namespace Opm } // namespace Opm