Fix GPMAINT for groups without control

If GPMAINT is used the group does not need a valid control object
This commit is contained in:
Tor Harald Sandve 2023-01-10 15:32:08 +01:00
parent c5be1226d7
commit ceb8d996aa
9 changed files with 86 additions and 39 deletions

View File

@ -95,29 +95,35 @@ RateType TargetCalculator::calcModeRateFromRates(const RateType* rates) const
} }
} }
double TargetCalculator::groupTarget(const Group::ProductionControls ctrl) const double TargetCalculator::groupTarget(const std::optional<Group::ProductionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const
{ {
if (!ctrl && !use_gpmaint_) {
OPM_DEFLOG_THROW(std::logic_error,
"Production group " + this->group_name_
+ "must either have a valid control or use GPMAINT",
deferred_logger);
}
switch (cmode_) { switch (cmode_) {
case Group::ProductionCMode::ORAT: case Group::ProductionCMode::ORAT:
return ctrl.oil_target; return ctrl->oil_target;
case Group::ProductionCMode::WRAT: case Group::ProductionCMode::WRAT:
return ctrl.water_target; return ctrl->water_target;
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;
} }
case Group::ProductionCMode::LRAT: case Group::ProductionCMode::LRAT:
return ctrl.liquid_target; return ctrl->liquid_target;
case Group::ProductionCMode::RESV: case Group::ProductionCMode::RESV:
{ {
if(use_gpmaint_) 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;
} }
default: default:
// Should never be here. // Should never be here.
@ -192,34 +198,40 @@ InjectionTargetCalculator::InjectionTargetCalculator(const Group::InjectionCMode
} }
double InjectionTargetCalculator::groupTarget(const Group::InjectionControls& ctrl, Opm::DeferredLogger& deferred_logger) const double InjectionTargetCalculator::groupTarget(const std::optional<Group::InjectionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const
{ {
if (!ctrl && !use_gpmaint_) {
OPM_DEFLOG_THROW(std::logic_error,
"Injection group " + this->group_name_
+ "must either have a valid control or use GPMAINT",
deferred_logger);
}
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_]; double 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<double>& 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; double voidage_rate = group_state_.injection_vrep_rate(ctrl->voidage_group) * ctrl->target_void_fraction;
double inj_reduction = 0.0; double 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;

View File

@ -59,7 +59,7 @@ namespace WellGroupHelpers
template <typename RateType> template <typename RateType>
RateType calcModeRateFromRates(const RateType* rates) const; RateType calcModeRateFromRates(const RateType* rates) const;
double groupTarget(const Group::ProductionControls ctrl) const; double groupTarget(const std::optional<Group::ProductionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const;
GuideRateModel::Target guideTargetMode() const; GuideRateModel::Target guideTargetMode() const;
@ -94,7 +94,7 @@ namespace WellGroupHelpers
return rates[pos_]; return rates[pos_];
} }
double groupTarget(const Group::InjectionControls& ctrl, Opm::DeferredLogger& deferred_logger) const; double groupTarget(const std::optional<Group::InjectionControls>& ctrl, Opm::DeferredLogger& deferred_logger) const;
GuideRateModel::Target guideTargetMode() const; GuideRateModel::Target guideTargetMode() const;

View File

@ -164,7 +164,8 @@ assembleControlEqProd(const WellState& well_state,
bhp, active_rates, bhp, active_rates,
rCoeff, rCoeff,
efficiencyFactor, efficiencyFactor,
control_eq); control_eq,
deferred_logger);
break; break;
} }
case Well::ProducerCMode::CMODE_UNDEFINED: { case Well::ProducerCMode::CMODE_UNDEFINED: {

View File

@ -154,8 +154,11 @@ getGroupInjectionControl(const Group& group,
return tcalc.calcModeRateFromRates(groupTargetReductions); return tcalc.calcModeRateFromRates(groupTargetReductions);
}; };
const double orig_target = tcalc.groupTarget(group.injectionControls(injectionPhase, std::optional<Group::InjectionControls> ctrl;
summaryState), if (!group.has_gpmaint_control(injectionPhase, currentGroupControl))
ctrl = group.injectionControls(injectionPhase, summaryState);
const double orig_target = tcalc.groupTarget(ctrl,
deferred_logger); deferred_logger);
const auto chain = WellGroupHelpers::groupChainTopBot(well_.name(), group.name(), const auto chain = WellGroupHelpers::groupChainTopBot(well_.name(), group.name(),
schedule, well_.currentStep()); schedule, well_.currentStep());
@ -213,7 +216,6 @@ getGroupInjectionTargetRate(const Group& group,
// Should not be here. // Should not be here.
assert(false); assert(false);
} }
auto currentGroupControl = group_state.injection_control(group.name(), injectionPhase); auto currentGroupControl = group_state.injection_control(group.name(), injectionPhase);
if (currentGroupControl == Group::InjectionCMode::FLD || if (currentGroupControl == Group::InjectionCMode::FLD ||
currentGroupControl == Group::InjectionCMode::NONE) { currentGroupControl == Group::InjectionCMode::NONE) {
@ -273,7 +275,12 @@ getGroupInjectionTargetRate(const Group& group,
return tcalc.calcModeRateFromRates(groupTargetReductions); return tcalc.calcModeRateFromRates(groupTargetReductions);
}; };
const double orig_target = tcalc.groupTarget(group.injectionControls(injectionPhase, summaryState), deferred_logger); std::optional<Group::InjectionControls> ctrl;
if (!group.has_gpmaint_control(injectionPhase, currentGroupControl))
ctrl = group.injectionControls(injectionPhase, summaryState);
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::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 size_t num_ancestors = chain.size() - 1; const size_t num_ancestors = chain.size() - 1;
@ -300,7 +307,8 @@ void WellGroupControls::getGroupProductionControl(const Group& group,
const std::vector<EvalWell>& rates, const std::vector<EvalWell>& rates,
const RateConvFunc& rateConverter, const RateConvFunc& rateConverter,
double efficiencyFactor, double efficiencyFactor,
EvalWell& control_eq) const EvalWell& control_eq,
DeferredLogger& deferred_logger) const
{ {
const Group::ProductionCMode& currentGroupControl = group_state.production_control(group.name()); const Group::ProductionCMode& currentGroupControl = group_state.production_control(group.name());
if (currentGroupControl == Group::ProductionCMode::FLD || if (currentGroupControl == Group::ProductionCMode::FLD ||
@ -324,7 +332,7 @@ void WellGroupControls::getGroupProductionControl(const Group& group,
getGroupProductionControl(parent, well_state, group_state, getGroupProductionControl(parent, well_state, group_state,
schedule, summaryState, bhp, schedule, summaryState, bhp,
rates, rateConverter, rates, rateConverter,
efficiencyFactor, control_eq); efficiencyFactor, control_eq, deferred_logger);
return; return;
} }
} }
@ -371,7 +379,11 @@ void WellGroupControls::getGroupProductionControl(const Group& group,
return tcalc.calcModeRateFromRates(groupTargetReductions); return tcalc.calcModeRateFromRates(groupTargetReductions);
}; };
const double orig_target = tcalc.groupTarget(group.productionControls(summaryState)); 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::groupChainTopBot(well_.name(), group.name(), const auto chain = WellGroupHelpers::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.
@ -399,7 +411,8 @@ getGroupProductionTargetRate(const Group& group,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summaryState, const SummaryState& summaryState,
const RateConvFunc& rateConverter, const RateConvFunc& rateConverter,
double efficiencyFactor) const double efficiencyFactor,
DeferredLogger& deferred_logger) const
{ {
const Group::ProductionCMode& currentGroupControl = group_state.production_control(group.name()); const Group::ProductionCMode& currentGroupControl = group_state.production_control(group.name());
if (currentGroupControl == Group::ProductionCMode::FLD || if (currentGroupControl == Group::ProductionCMode::FLD ||
@ -412,7 +425,8 @@ getGroupProductionTargetRate(const Group& group,
efficiencyFactor *= group.getGroupEfficiencyFactor(); efficiencyFactor *= group.getGroupEfficiencyFactor();
return getGroupProductionTargetRate(parent, well_state, group_state, return getGroupProductionTargetRate(parent, well_state, group_state,
schedule, summaryState, schedule, summaryState,
rateConverter, efficiencyFactor); rateConverter, efficiencyFactor,
deferred_logger);
} }
} }
@ -451,7 +465,11 @@ getGroupProductionTargetRate(const Group& group,
return tcalc.calcModeRateFromRates(groupTargetReductions); return tcalc.calcModeRateFromRates(groupTargetReductions);
}; };
const double orig_target = tcalc.groupTarget(group.productionControls(summaryState)); 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::groupChainTopBot(well_.name(), group.name(), const auto chain = WellGroupHelpers::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.
@ -505,7 +523,8 @@ getGroupProductionControl<__VA_ARGS__>(const Group&, \
const std::vector<__VA_ARGS__>&, \ const std::vector<__VA_ARGS__>&, \
const RateConvFunc& rateConverter, \ const RateConvFunc& rateConverter, \
double efficiencyFactor, \ double efficiencyFactor, \
__VA_ARGS__& control_eq) const; __VA_ARGS__& control_eq, \
DeferredLogger& deferred_logger) const; \
INSTANCE(DenseAd::Evaluation<double,3,0u>) INSTANCE(DenseAd::Evaluation<double,3,0u>)
INSTANCE(DenseAd::Evaluation<double,4,0u>) INSTANCE(DenseAd::Evaluation<double,4,0u>)

View File

@ -84,7 +84,8 @@ public:
const std::vector<EvalWell>& rates, const std::vector<EvalWell>& rates,
const RateConvFunc& rateConverter, const RateConvFunc& rateConverter,
double efficiencyFactor, double efficiencyFactor,
EvalWell& control_eq) const; EvalWell& control_eq,
DeferredLogger& deferred_logger) const;
double getGroupProductionTargetRate(const Group& group, double getGroupProductionTargetRate(const Group& group,
const WellState& well_state, const WellState& well_state,
@ -92,7 +93,8 @@ public:
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summaryState, const SummaryState& summaryState,
const RateConvFunc& rateConverter, const RateConvFunc& rateConverter,
double efficiencyFactor) const; double efficiencyFactor,
DeferredLogger& deferred_logger) const;
private: private:
const WellInterfaceGeneric& well_; //!< Reference to well interface const WellInterfaceGeneric& well_; //!< Reference to well interface

View File

@ -742,7 +742,6 @@ namespace WellGroupHelpers
default: default:
throw std::invalid_argument("Invalid Flow target type in GPMAINT"); throw std::invalid_argument("Invalid Flow target type in GPMAINT");
} }
auto& gpmaint_state = group_state.gpmaint(group.name()); auto& gpmaint_state = group_state.gpmaint(group.name());
double rate = gpm->rate(gpmaint_state, current_rate, error, dt); double rate = gpm->rate(gpmaint_state, current_rate, error, dt);
group_state.update_gpmaint_target(group.name(), std::max(0.0, sign * rate)); group_state.update_gpmaint_target(group.name(), std::max(0.0, sign * rate));
@ -1266,7 +1265,12 @@ namespace WellGroupHelpers
const std::vector<double>& groupSurfaceRates = group_state.production_rates(group_name); const std::vector<double>& groupSurfaceRates = group_state.production_rates(group_name);
return tcalc.calcModeRateFromRates(groupSurfaceRates); return tcalc.calcModeRateFromRates(groupSurfaceRates);
}; };
const double orig_target = tcalc.groupTarget(group.productionControls(summaryState));
std::optional<Group::ProductionControls> ctrl;
if (!group.has_gpmaint_control(currentGroupControl))
ctrl = group.productionControls(summaryState);
const double orig_target = tcalc.groupTarget(ctrl, deferred_logger);
// Assume we have a chain of groups as follows: BOTTOM -> MIDDLE -> TOP. // Assume we have a chain of groups as follows: BOTTOM -> MIDDLE -> TOP.
// Then ... // Then ...
// TODO finish explanation. // TODO finish explanation.
@ -1408,7 +1412,12 @@ namespace WellGroupHelpers
return tcalc.calcModeRateFromRates(groupSurfaceRates); return tcalc.calcModeRateFromRates(groupSurfaceRates);
}; };
const double orig_target = tcalc.groupTarget(group.injectionControls(injectionPhase, summaryState), deferred_logger); std::optional<Group::InjectionControls> ctrl;
if (!group.has_gpmaint_control(injectionPhase, currentGroupControl))
ctrl = group.injectionControls(injectionPhase, summaryState);
const double orig_target = tcalc.groupTarget(ctrl, deferred_logger);
// Assume we have a chain of groups as follows: BOTTOM -> MIDDLE -> TOP. // Assume we have a chain of groups as follows: BOTTOM -> MIDDLE -> TOP.
// Then ... // Then ...
// TODO finish explanation. // TODO finish explanation.

View File

@ -189,7 +189,8 @@ getGroupProductionTargetRate(const Group& group,
const GroupState& group_state, const GroupState& group_state,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summaryState, const SummaryState& summaryState,
double efficiencyFactor) const double efficiencyFactor,
DeferredLogger& deferred_logger) const
{ {
auto rCoeff = [this](const int id, const int region, std::vector<double>& coeff) auto rCoeff = [this](const int id, const int region, std::vector<double>& coeff)
{ {
@ -199,7 +200,8 @@ getGroupProductionTargetRate(const Group& group,
return WellGroupControls(*this).getGroupProductionTargetRate(group, well_state, return WellGroupControls(*this).getGroupProductionTargetRate(group, well_state,
group_state, schedule, group_state, schedule,
summaryState, summaryState,
rCoeff, efficiencyFactor); rCoeff, efficiencyFactor,
deferred_logger);
} }
template class WellInterfaceFluidSystem<BlackOilFluidSystem<double,BlackOilDefaultIndexTraits>>; template class WellInterfaceFluidSystem<BlackOilFluidSystem<double,BlackOilDefaultIndexTraits>>;

View File

@ -109,7 +109,8 @@ protected:
const GroupState& group_state, const GroupState& group_state,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summaryState, const SummaryState& summaryState,
double efficiencyFactor) const; double efficiencyFactor,
DeferredLogger& deferred_logger) const;
// For the conversion between the surface volume rate and reservoir voidage rate // For the conversion between the surface volume rate and reservoir voidage rate
const RateConverterType& rateConverter_; const RateConverterType& rateConverter_;

View File

@ -1049,7 +1049,8 @@ namespace Opm
group_state, group_state,
schedule, schedule,
summaryState, summaryState,
efficiencyFactor); efficiencyFactor,
deferred_logger);
// we don't want to scale with zero and get zero rates. // we don't want to scale with zero and get zero rates.
if (scale > 0) { if (scale > 0) {