Emit Group Control Target of Zero if Explicitly Assigned

If a simulation model explicitly assigns a target or limit of 0.0,
then we must honour that value in the restart file.  Use a more
complete condition to detect whether or not group level targets or
limits are defaulted in GCONPROD and/or GCONINJE.
This commit is contained in:
Bård Skaflestad 2022-05-12 11:26:16 +02:00
parent b36f415a96
commit adb84c15cc
2 changed files with 225 additions and 111 deletions

View File

@ -80,7 +80,7 @@ public:
bool operator==(const UDAValue& other) const;
bool operator!=(const UDAValue& other) const;
bool is_numeric() { return numeric_value; }
bool is_numeric() const { return numeric_value; }
template<class Serializer>
void serializeOp(Serializer& serializer)

View File

@ -771,6 +771,218 @@ allocate(const std::vector<int>& inteHead)
};
}
template <typename SGProp, class SGrpArray>
void assignGroupGasInjectionTargets(const Opm::Group& group,
const Opm::SummaryState& sumState,
SGProp&& sgprop,
SGrpArray& sGrp)
{
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SGroup::inj_index;
using M = ::Opm::UnitSystem::measure;
const auto& prop = group.injectionProperties(Opm::Phase::GAS);
const auto cntl = group.injectionControls(Opm::Phase::GAS, sumState);
if (group.has_control(Opm::Phase::GAS, Opm::Group::InjectionCMode::RATE) &&
(prop.surface_max_rate.is_numeric() || (cntl.surface_max_rate > 0.0)))
{
sGrp[Ix::gasSurfRateLimit] = sgprop(M::gas_surface_rate, cntl.surface_max_rate);
sGrp[65] = sGrp[Ix::gasSurfRateLimit];
}
if (group.has_control(Opm::Phase::GAS, Opm::Group::InjectionCMode::RESV) &&
(prop.resv_max_rate.is_numeric() || (cntl.resv_max_rate > 0.0)))
{
sGrp[Ix::gasResRateLimit] = sgprop(M::rate, cntl.resv_max_rate);
sGrp[66] = sGrp[Ix::gasResRateLimit];
}
if (group.has_control(Opm::Phase::GAS, Opm::Group::InjectionCMode::REIN) &&
(prop.target_reinj_fraction.is_numeric() || (cntl.target_reinj_fraction > 0.0)))
{
sGrp[Ix::gasReinjectionLimit] = cntl.target_reinj_fraction;
sGrp[67] = sGrp[Ix::gasReinjectionLimit];
}
if (group.has_control(Opm::Phase::GAS, Opm::Group::InjectionCMode::VREP) &&
(prop.target_void_fraction.is_numeric() || (cntl.target_void_fraction > 0.0)))
{
sGrp[Ix::gasVoidageLimit] = cntl.target_void_fraction;
sGrp[68] = sGrp[Ix::gasVoidageLimit];
}
sGrp[Ix::waterGuideRate] = cntl.guide_rate;
}
template <typename SGProp, class SGrpArray>
void assignGroupWaterInjectionTargets(const Opm::Group& group,
const Opm::SummaryState& sumState,
SGProp&& sgprop,
SGrpArray& sGrp)
{
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SGroup::inj_index;
using M = ::Opm::UnitSystem::measure;
const auto& prop = group.injectionProperties(Opm::Phase::WATER);
const auto cntl = group.injectionControls(Opm::Phase::WATER, sumState);
if (group.has_control(Opm::Phase::WATER, Opm::Group::InjectionCMode::RATE) &&
(prop.surface_max_rate.is_numeric() || (cntl.surface_max_rate > 0.0)))
{
sGrp[Ix::waterSurfRateLimit] = sgprop(M::liquid_surface_rate, cntl.surface_max_rate);
sGrp[61] = sGrp[Ix::waterSurfRateLimit];
}
if (group.has_control(Opm::Phase::WATER, Opm::Group::InjectionCMode::RESV) &&
(prop.resv_max_rate.is_numeric() || (cntl.resv_max_rate > 0.0)))
{
sGrp[Ix::waterResRateLimit] = sgprop(M::rate, cntl.resv_max_rate);
sGrp[62] = sGrp[Ix::waterResRateLimit];
}
if (group.has_control(Opm::Phase::WATER, Opm::Group::InjectionCMode::REIN) &&
(prop.target_reinj_fraction.is_numeric() || (cntl.target_reinj_fraction > 0.0)))
{
sGrp[Ix::waterReinjectionLimit] = cntl.target_reinj_fraction;
sGrp[63] = sGrp[Ix::waterReinjectionLimit];
}
if (group.has_control(Opm::Phase::WATER, Opm::Group::InjectionCMode::VREP) &&
(prop.target_void_fraction.is_numeric() || (cntl.target_void_fraction > 0.0)))
{
sGrp[Ix::waterVoidageLimit] = cntl.target_void_fraction;
sGrp[64] = sGrp[Ix::waterVoidageLimit];
}
sGrp[Ix::waterGuideRate] = cntl.guide_rate;
}
template <typename SGProp, class SGrpArray>
void assignGroupOilInjectionTargets(const Opm::Group& group,
const Opm::SummaryState& sumState,
SGProp&& sgprop,
SGrpArray& sGrp)
{
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SGroup::inj_index;
using M = ::Opm::UnitSystem::measure;
const auto& prop = group.injectionProperties(Opm::Phase::OIL);
const auto cntl = group.injectionControls(Opm::Phase::OIL, sumState);
if (group.has_control(Opm::Phase::OIL, Opm::Group::InjectionCMode::RATE) &&
(prop.surface_max_rate.is_numeric() || (cntl.surface_max_rate > 0.0)))
{
sGrp[Ix::oilSurfRateLimit] = sgprop(M::liquid_surface_rate, cntl.surface_max_rate);
sGrp[57] = sGrp[Ix::oilSurfRateLimit];
}
if (group.has_control(Opm::Phase::OIL, Opm::Group::InjectionCMode::RESV) &&
(prop.resv_max_rate.is_numeric() || (cntl.resv_max_rate > 0.0)))
{
sGrp[Ix::oilResRateLimit] = sgprop(M::rate, cntl.resv_max_rate);
sGrp[58] = sGrp[Ix::oilResRateLimit];
}
if (group.has_control(Opm::Phase::OIL, Opm::Group::InjectionCMode::REIN) &&
(prop.target_reinj_fraction.is_numeric() || (cntl.target_reinj_fraction > 0.0)))
{
sGrp[Ix::oilReinjectionLimit] = cntl.target_reinj_fraction;
sGrp[59] = sGrp[Ix::oilReinjectionLimit];
}
if (group.has_control(Opm::Phase::OIL, Opm::Group::InjectionCMode::VREP) &&
(prop.target_void_fraction.is_numeric() || (cntl.target_void_fraction > 0.0)))
{
sGrp[Ix::oilVoidageLimit] = cntl.target_void_fraction;
sGrp[60] = sGrp[Ix::oilVoidageLimit];
}
}
template <typename SGProp, class SGrpArray>
void assignGroupInjectionTargets(const Opm::Group& group,
const Opm::SummaryState& sumState,
SGProp&& sgprop,
SGrpArray& sGrp)
{
if (group.hasInjectionControl(Opm::Phase::GAS)) {
assignGroupGasInjectionTargets(group, sumState, std::forward<SGProp>(sgprop), sGrp);
}
if (group.hasInjectionControl(Opm::Phase::WATER)) {
assignGroupWaterInjectionTargets(group, sumState, std::forward<SGProp>(sgprop), sGrp);
}
if (group.hasInjectionControl(Opm::Phase::OIL)) {
assignGroupOilInjectionTargets(group, sumState, std::forward<SGProp>(sgprop), sGrp);
}
}
template <typename SGProp, class SGrpArray>
void assignGroupProductionTargets(const Opm::Group& group,
const Opm::SummaryState& sumState,
SGProp&& sgprop,
SGrpArray& sGrp)
{
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SGroup::prod_index;
using M = ::Opm::UnitSystem::measure;
const auto& prop = group.productionProperties();
const auto cntl = group.productionControls(sumState);
if (group.has_control(Opm::Group::ProductionCMode::ORAT) &&
(prop.oil_target.is_numeric() || (cntl.oil_target > 0.0)))
{
sGrp[Ix::OilRateLimit] = sgprop(M::liquid_surface_rate, cntl.oil_target);
sGrp[52] = sGrp[Ix::OilRateLimit]; // "ORAT" control
}
if (group.has_control(Opm::Group::ProductionCMode::WRAT) &&
(prop.water_target.is_numeric() || (cntl.water_target > 0.0)))
{
sGrp[Ix::WatRateLimit] = sgprop(M::liquid_surface_rate, cntl.water_target);
sGrp[53] = sGrp[Ix::WatRateLimit]; //"WRAT" control
}
if (group.has_control(Opm::Group::ProductionCMode::GRAT) &&
(prop.gas_target.is_numeric() || (cntl.gas_target > 0.0)))
{
sGrp[Ix::GasRateLimit] = sgprop(M::gas_surface_rate, cntl.gas_target);
sGrp[39] = sGrp[Ix::GasRateLimit];
}
if (group.has_control(Opm::Group::ProductionCMode::LRAT) &&
(prop.liquid_target.is_numeric() || (cntl.liquid_target > 0.0)))
{
sGrp[Ix::LiqRateLimit] = sgprop(M::liquid_surface_rate, cntl.liquid_target);
sGrp[54] = sGrp[Ix::LiqRateLimit]; //"LRAT" control
}
}
template <typename SGProp, class SGrpArray>
void assignGasLiftOptimisation(const Opm::GasLiftOpt::Group& group,
SGProp&& sgprop,
SGrpArray& sGrp)
{
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SGroup::prod_index;
using M = ::Opm::UnitSystem::measure;
const auto no_limit = -10.0f;
if (const auto& max_supply = group.max_lift_gas(); max_supply.has_value()) {
sGrp[Ix::GLOMaxSupply] = sgprop(M::gas_surface_rate, max_supply.value());
}
else {
sGrp[Ix::GLOMaxSupply] = no_limit;
}
if (const auto& max_total = group.max_total_gas(); max_total.has_value()) {
sGrp[Ix::GLOMaxRate] = sgprop(M::gas_surface_rate, max_total.value());
}
else {
sGrp[Ix::GLOMaxRate] = no_limit;
}
}
template <class SGrpArray>
void staticContrib(const Opm::Group& group,
const Opm::GasLiftOpt& glo,
@ -780,7 +992,6 @@ void staticContrib(const Opm::Group& group,
{
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SGroup::index;
using Isp = ::Opm::RestartIO::Helpers::VectorItems::SGroup::prod_index;
using Isi = ::Opm::RestartIO::Helpers::VectorItems::SGroup::inj_index;
using M = ::Opm::UnitSystem::measure;
const auto dflt = -1.0e+20f;
@ -816,8 +1027,7 @@ void staticContrib(const Opm::Group& group,
zero , zero // 110..111 (22)
};
const auto sz = static_cast<
decltype(init.size())>(sGrp.size());
const auto sz = static_cast<decltype(init.size())>(sGrp.size());
auto b = std::begin(init);
auto e = b + std::min(init.size(), sz);
@ -833,118 +1043,22 @@ void staticContrib(const Opm::Group& group,
sgprop(M::identity, group.getGroupEfficiencyFactor());
if (group.isProductionGroup()) {
const auto& prod_cntl = group.productionControls(sumState);
if (prod_cntl.oil_target > 0.) {
sGrp[Isp::OilRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.oil_target);
sGrp[52] = sGrp[Isp::OilRateLimit]; // "ORAT" control
}
if (prod_cntl.water_target > 0.) {
sGrp[Isp::WatRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.water_target);
sGrp[53] = sGrp[Isp::WatRateLimit]; //"WRAT" control
}
if (prod_cntl.gas_target > 0.) {
sGrp[Isp::GasRateLimit] = sgprop(M::gas_surface_rate, prod_cntl.gas_target);
sGrp[39] = sGrp[Isp::GasRateLimit];
}
if (prod_cntl.liquid_target > 0.) {
sGrp[Isp::LiqRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.liquid_target);
sGrp[54] = sGrp[Isp::LiqRateLimit]; //"LRAT" control
}
}
if (glo.has_group(group.name())) {
const auto& glo_group = glo.group(group.name());
const auto no_limit = -10.0f;
if (const auto& max_supply = glo_group.max_lift_gas(); max_supply.has_value()) {
sGrp[Isp::GLOMaxSupply] = sgprop(M::gas_surface_rate, max_supply.value());
}
else {
sGrp[Isp::GLOMaxSupply] = no_limit;
}
if (const auto& max_total = glo_group.max_total_gas(); max_total.has_value()) {
sGrp[Isp::GLOMaxRate] = sgprop(M::gas_surface_rate, max_total.value());
}
else {
sGrp[Isp::GLOMaxRate] = no_limit;
}
}
if ((group.name() == "FIELD") && (group.getGroupType() == Opm::Group::GroupType::NONE)) {
sGrp[Isp::GuideRate] = 0.;
sGrp[14] = 0.;
sGrp[19] = 0.;
sGrp[24] = 0.;
assignGroupProductionTargets(group, sumState, sgprop, sGrp);
}
if (group.isInjectionGroup()) {
if (group.hasInjectionControl(Opm::Phase::GAS)) {
const auto& inj_cntl = group.injectionControls(Opm::Phase::GAS, sumState);
if (inj_cntl.surface_max_rate > 0.) {
sGrp[Isi::gasSurfRateLimit] = sgprop(M::gas_surface_rate, inj_cntl.surface_max_rate);
sGrp[65] = sGrp[Isi::gasSurfRateLimit];
}
if (inj_cntl.resv_max_rate > 0.) {
sGrp[Isi::gasResRateLimit] = sgprop(M::rate, inj_cntl.resv_max_rate);
sGrp[66] = sGrp[Isi::gasResRateLimit];
}
if (inj_cntl.target_reinj_fraction > 0.) {
sGrp[Isi::gasReinjectionLimit] = inj_cntl.target_reinj_fraction;
sGrp[67] = sGrp[Isi::gasReinjectionLimit];
}
if (inj_cntl.target_void_fraction > 0.) {
sGrp[Isi::gasVoidageLimit] = inj_cntl.target_void_fraction;
sGrp[68] = sGrp[Isi::gasVoidageLimit];
}
assignGroupInjectionTargets(group, sumState, sgprop, sGrp);
}
sGrp[Isi::waterGuideRate] = inj_cntl.guide_rate;
}
if (group.hasInjectionControl(Opm::Phase::WATER)) {
const auto& inj_cntl = group.injectionControls(Opm::Phase::WATER, sumState);
if (inj_cntl.surface_max_rate > 0.) {
sGrp[Isi::waterSurfRateLimit] = sgprop(M::liquid_surface_rate, inj_cntl.surface_max_rate);
sGrp[61] = sGrp[Isi::waterSurfRateLimit];
}
if (inj_cntl.resv_max_rate > 0.) {
sGrp[Isi::waterResRateLimit] = sgprop(M::rate, inj_cntl.resv_max_rate);
sGrp[62] = sGrp[Isi::waterResRateLimit];
}
if (inj_cntl.target_reinj_fraction > 0.) {
sGrp[Isi::waterReinjectionLimit] = inj_cntl.target_reinj_fraction;
sGrp[63] = sGrp[Isi::waterReinjectionLimit];
}
if (inj_cntl.target_void_fraction > 0.) {
sGrp[Isi::waterVoidageLimit] = inj_cntl.target_void_fraction;
sGrp[64] = sGrp[Isi::waterVoidageLimit];
}
sGrp[Isi::waterGuideRate] = inj_cntl.guide_rate;
}
if (group.hasInjectionControl(Opm::Phase::OIL)) {
const auto& inj_cntl = group.injectionControls(Opm::Phase::OIL, sumState);
if (inj_cntl.surface_max_rate > 0.) {
sGrp[Isi::oilSurfRateLimit] = sgprop(M::liquid_surface_rate, inj_cntl.surface_max_rate);
sGrp[57] = sGrp[Isi::oilSurfRateLimit];
}
if (inj_cntl.resv_max_rate > 0.) {
sGrp[Isi::oilResRateLimit] = sgprop(M::rate, inj_cntl.resv_max_rate);
sGrp[58] = sGrp[Isi::oilResRateLimit];
}
if (inj_cntl.target_reinj_fraction > 0.) {
sGrp[Isi::oilReinjectionLimit] = inj_cntl.target_reinj_fraction;
sGrp[59] = sGrp[Isi::oilReinjectionLimit];
}
if (inj_cntl.target_void_fraction > 0.) {
sGrp[Isi::oilVoidageLimit] = inj_cntl.target_void_fraction;
sGrp[60] = sGrp[Isi::oilVoidageLimit];
}
}
if (glo.has_group(group.name())) {
assignGasLiftOptimisation(glo.group(group.name()), sgprop, sGrp);
}
if ((group.name() == "FIELD") && (group.getGroupType() == Opm::Group::GroupType::NONE)) {
sGrp[Isp::GuideRate] = 0.0;
sGrp[14] = 0.0;
sGrp[19] = 0.0;
sGrp[24] = 0.0;
}
}
} // SGrp