Update UDA properties from restart file

This commit is contained in:
Joakim Hove
2021-08-25 15:04:45 +02:00
parent d8d6749337
commit 5e2bff42cf
10 changed files with 225 additions and 16 deletions

View File

@@ -132,7 +132,7 @@ struct GroupInjectionProperties {
explicit GroupInjectionProperties(std::string group_name_arg);
GroupInjectionProperties(std::string group_name_arg, Phase phase, const UnitSystem& unit_system);
std::string group_name{};
std::string name{};
Phase phase = Phase::WATER;
InjectionCMode cmode = InjectionCMode::NONE;
UDAValue surface_max_rate;
@@ -152,12 +152,12 @@ struct GroupInjectionProperties {
bool operator!=(const GroupInjectionProperties& other) const;
bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const;
bool uda_phase() const;
void update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value);
template<class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(this->group_name);
serializer(this->name);
serializer(phase);
serializer(cmode);
surface_max_rate.serializeOp(serializer);
@@ -209,6 +209,7 @@ struct GroupProductionProperties {
bool operator==(const GroupProductionProperties& other) const;
bool operator!=(const GroupProductionProperties& other) const;
bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const;
void update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value);
template<class Serializer>
void serializeOp(Serializer& serializer)

View File

@@ -191,7 +191,8 @@ namespace UDQ {
bool leadingSpace(UDQTokenType token_type);
bool group_control(UDAControl control);
bool well_control(UDAControl control);
bool injection_control(UDAControl control);
bool production_control(UDAControl control);
std::string typeName(UDQVarType var_type);
UDAKeyword keyword(UDAControl control);

View File

@@ -292,6 +292,7 @@ public:
void setBHPLimit(const double limit);
InjectionControls controls(const UnitSystem& unit_system, const SummaryState& st, double udq_default) const;
bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const;
void update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value);
template<class Serializer>
void serializeOp(Serializer& serializer)
@@ -418,6 +419,7 @@ public:
void clearControls();
ProductionControls controls(const SummaryState& st, double udq_default) const;
bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const;
void update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value);
void setBHPLimit(const double limit);
int productionControls() const { return this->m_productionControls; }

View File

@@ -228,7 +228,7 @@ Group::GroupInjectionProperties::GroupInjectionProperties(std::string group_name
Group::GroupInjectionProperties::GroupInjectionProperties(std::string group_name_arg,
const Phase phase_arg,
const UnitSystem& unit_system)
: group_name { std::move(group_name_arg) }
: name { std::move(group_name_arg) }
, phase { phase_arg }
, surface_max_rate { unit_system.getDimension((phase == Phase::WATER)
? UnitSystem::measure::liquid_surface_rate
@@ -258,7 +258,7 @@ Group::GroupInjectionProperties Group::GroupInjectionProperties::serializeObject
bool Group::GroupInjectionProperties::operator==(const GroupInjectionProperties& other) const {
return
this->group_name == other.group_name &&
this->name == other.name &&
this->phase == other.phase &&
this->cmode == other.cmode &&
this->surface_max_rate == other.surface_max_rate &&
@@ -280,10 +280,10 @@ bool Group::GroupInjectionProperties::operator!=(const GroupInjectionProperties&
bool Group::GroupInjectionProperties::updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const {
int update_count = 0;
update_count += active.update(udq_config, this->surface_max_rate, this->group_name, UDAControl::GCONINJE_SURFACE_MAX_RATE);
update_count += active.update(udq_config, this->resv_max_rate, this->group_name, UDAControl::GCONINJE_RESV_MAX_RATE);
update_count += active.update(udq_config, this->target_reinj_fraction, this->group_name, UDAControl::GCONINJE_TARGET_REINJ_FRACTION);
update_count += active.update(udq_config, this->target_void_fraction, this->group_name, UDAControl::GCONINJE_TARGET_VOID_FRACTION);
update_count += active.update(udq_config, this->surface_max_rate, this->name, UDAControl::GCONINJE_SURFACE_MAX_RATE);
update_count += active.update(udq_config, this->resv_max_rate, this->name, UDAControl::GCONINJE_RESV_MAX_RATE);
update_count += active.update(udq_config, this->target_reinj_fraction, this->name, UDAControl::GCONINJE_TARGET_REINJ_FRACTION);
update_count += active.update(udq_config, this->target_void_fraction, this->name, UDAControl::GCONINJE_TARGET_VOID_FRACTION);
return (update_count > 0);
}
@@ -304,6 +304,34 @@ bool Group::GroupInjectionProperties::uda_phase() const {
return false;
}
void Group::GroupInjectionProperties::update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value)
{
switch (control) {
case UDAControl::GCONINJE_SURFACE_MAX_RATE:
this->surface_max_rate = value;
udq_active.update(udq_config, this->surface_max_rate, this->name, UDAControl::GCONINJE_SURFACE_MAX_RATE);
break;
case UDAControl::GCONINJE_RESV_MAX_RATE:
this->resv_max_rate = value;
udq_active.update(udq_config, this->resv_max_rate, this->name, UDAControl::GCONINJE_RESV_MAX_RATE);
break;
case UDAControl::GCONINJE_TARGET_REINJ_FRACTION:
this->target_reinj_fraction = value;
udq_active.update(udq_config, this->target_reinj_fraction, this->name, UDAControl::GCONINJE_TARGET_REINJ_FRACTION);
break;
case UDAControl::GCONINJE_TARGET_VOID_FRACTION:
this->target_void_fraction = value;
udq_active.update(udq_config, this->target_void_fraction, this->name, UDAControl::GCONINJE_TARGET_VOID_FRACTION);
break;
default:
throw std::logic_error("Invalid UDA control");
}
}
Group::GroupProductionProperties::GroupProductionProperties() :
GroupProductionProperties(UnitSystem(UnitSystem::UnitType::UNIT_TYPE_METRIC), "")
@@ -364,6 +392,33 @@ bool Group::GroupProductionProperties::updateUDQActive(const UDQConfig& udq_conf
return (update_count > 0);
}
void Group::GroupProductionProperties::update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value) {
switch (control) {
case UDAControl::GCONPROD_OIL_TARGET:
this->oil_target = value;
udq_active.update(udq_config, this->oil_target, this->name, UDAControl::GCONPROD_OIL_TARGET);
break;
case UDAControl::GCONPROD_WATER_TARGET:
this->water_target = value;
udq_active.update(udq_config, this->water_target, this->name, UDAControl::GCONPROD_WATER_TARGET);
break;
case UDAControl::GCONPROD_GAS_TARGET:
this->gas_target = value;
udq_active.update(udq_config, this->gas_target, this->name, UDAControl::GCONPROD_GAS_TARGET);
break;
case UDAControl::GCONPROD_LIQUID_TARGET:
this->liquid_target = value;
udq_active.update(udq_config, this->liquid_target, this->name, UDAControl::GCONPROD_LIQUID_TARGET);
break;
default:
throw std::logic_error("Invalid UDA control");
}
}
bool Group::productionGroupControlAvailable() const {
if (this->m_name == "FIELD")

View File

@@ -1428,12 +1428,41 @@ namespace {
}
}
this->snapshots.back().udq.update( UDQConfig(this->m_static.m_runspec.udqParams(), rst_state) );
for (const auto& [control, value, wgname] : UDQActive::load_rst( this->m_static.m_unit_system, this->snapshots.back().udq(), rst_state, this->wellNames(report_step), this->groupNames(report_step))) {
if (UDQ::well_control(control)) {
auto& well = this->getWell(wgname, report_step);
} else {
auto& group = this->getGroup(wgname, report_step);
const auto& uda_records = UDQActive::load_rst( this->m_static.m_unit_system, this->snapshots.back().udq(), rst_state, this->wellNames(report_step), this->groupNames(report_step));
if (!uda_records.empty()) {
const auto& udq_config = this->snapshots.back().udq();
auto udq_active = this->snapshots.back().udq_active();
for (const auto& [control, value, wgname, ig_phase] : uda_records) {
if (UDQ::well_control(control)) {
auto& well = this->snapshots.back().wells.get(wgname);
if (UDQ::injection_control(control)) {
auto injection_properties = std::make_shared<Well::WellInjectionProperties>(well.getInjectionProperties());
injection_properties->update_uda(udq_config, udq_active, control, value);
well.updateInjection(std::move(injection_properties));
}
if (UDQ::production_control(control)) {
auto production_properties = std::make_shared<Well::WellProductionProperties>(well.getProductionProperties());
production_properties->update_uda(udq_config, udq_active, control, value);
well.updateProduction(std::move(production_properties));
}
} else {
auto& group = this->snapshots.back().groups.get(wgname);
if (UDQ::injection_control(control)) {
auto injection_properties = group.injectionProperties(ig_phase.value());
injection_properties.update_uda(udq_config, udq_active, control, value);
group.updateInjection(injection_properties);
}
if (UDQ::production_control(control)) {
auto production_properties = group.productionProperties();
production_properties.update_uda(udq_config, udq_active, control, value);
group.updateProduction(production_properties);
}
}
}
this->snapshots.back().udq_active.update( std::move(udq_active) );
}
}

View File

@@ -44,7 +44,7 @@ std::vector<UDQActive::RstRecord> UDQActive::load_rst(const UnitSystem& units,
if (UDQ::well_control(record.control))
records.emplace_back(record.control, uda, well_names[wg_index]);
else {
if (UDQ::production_control)
if (UDQ::production_control(record.control))
records.emplace_back(record.control, uda, group_names[wg_index]);
else
records.emplace_back(record.control, uda, group_names[wg_index], rst_active.ig_phase[wg_index]);

View File

@@ -501,6 +501,27 @@ bool well_control(UDAControl control) {
return !group_control(control);
}
bool injection_control(UDAControl control) {
switch (control) {
case UDAControl::WCONINJE_RATE:
case UDAControl::WCONINJE_RESV:
case UDAControl::WCONINJE_BHP:
case UDAControl::WCONINJE_THP:
case UDAControl::GCONINJE_SURFACE_MAX_RATE:
case UDAControl::GCONINJE_RESV_MAX_RATE:
case UDAControl::GCONINJE_TARGET_REINJ_FRACTION:
case UDAControl::GCONINJE_TARGET_VOID_FRACTION:
return true;
default:
return false;
}
}
bool production_control(UDAControl control) {
return !injection_control(control);
}
UDAControl udaControl(int uda_code) {
switch (uda_code) {
case 300004:

View File

@@ -308,4 +308,33 @@ namespace Opm {
return (update_count > 0);
}
void Well::WellInjectionProperties::update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value) {
switch (control) {
case UDAControl::WCONINJE_RATE:
this->surfaceInjectionRate = value;
udq_active.update(udq_config, this->surfaceInjectionRate, this->name, UDAControl::WCONINJE_RATE);
break;
case UDAControl::WCONINJE_RESV:
this->reservoirInjectionRate = value;
udq_active.update(udq_config, this->reservoirInjectionRate, this->name, UDAControl::WCONINJE_RESV);
break;
case UDAControl::WCONINJE_BHP:
this->BHPTarget = value;
udq_active.update(udq_config, this->BHPTarget, this->name, UDAControl::WCONINJE_BHP);
break;
case UDAControl::WCONINJE_THP:
this->BHPTarget = value;
udq_active.update(udq_config, this->THPTarget, this->name, UDAControl::WCONINJE_THP);
break;
default:
throw std::logic_error("Invalid UDA control");
}
}
}

View File

@@ -375,4 +375,47 @@ void Well::WellProductionProperties::handleWCONHIST(const std::optional<VFPProdT
return (update_count > 0);
}
void Well::WellProductionProperties::update_uda(const UDQConfig& udq_config, UDQActive& udq_active, UDAControl control, const UDAValue& value) {
switch (control) {
case UDAControl::WCONPROD_ORAT:
this->OilRate = value;
udq_active.update(udq_config, this->OilRate, this->name, UDAControl::WCONPROD_ORAT);
break;
case UDAControl::WCONPROD_GRAT:
this->GasRate = value;
udq_active.update(udq_config, this->GasRate, this->name, UDAControl::WCONPROD_GRAT);
break;
case UDAControl::WCONPROD_WRAT:
this->WaterRate = value;
udq_active.update(udq_config, this->WaterRate, this->name, UDAControl::WCONPROD_WRAT);
break;
case UDAControl::WCONPROD_LRAT:
this->LiquidRate = value;
udq_active.update(udq_config, this->LiquidRate, this->name, UDAControl::WCONPROD_LRAT);
break;
case UDAControl::WCONPROD_RESV:
this->ResVRate = value;
udq_active.update(udq_config, this->ResVRate, this->name, UDAControl::WCONPROD_RESV);
break;
case UDAControl::WCONPROD_BHP:
this->BHPTarget = value;
udq_active.update(udq_config, this->BHPTarget, this->name, UDAControl::WCONPROD_BHP);
break;
case UDAControl::WCONPROD_THP:
this->BHPTarget = value;
udq_active.update(udq_config, this->THPTarget, this->name, UDAControl::WCONPROD_THP);
break;
default:
throw std::logic_error("Invalid UDA control");
}
}
} // namespace Opm

View File

@@ -143,3 +143,31 @@ BOOST_AUTO_TEST_CASE(LoadRestartSim) {
compare_sched("SPE1CASE2.DATA", "SPE1CASE2_RESTART_SKIPREST.DATA", "SPE1CASE2.X0060", 60);
compare_sched("SPE1CASE2.DATA", "SPE1CASE2_RESTART.DATA", "SPE1CASE2.X0060", 60);
}
BOOST_AUTO_TEST_CASE(LoadUDQRestartSim) {
const auto& [sched, restart_sched] = load_schedule_pair("UDQ_WCONPROD.DATA", "UDQ_WCONPROD_RESTART.DATA", "UDQ_WCONPROD.X0006", 6);
std::size_t report_step = 10;
SummaryState st(TimeService::now());
st.update_well_var("OPL02", "WUOPRL", 1);
st.update_well_var("OPL02", "WULPRL", 11);
st.update_well_var("OPU02", "WUOPRU", 111);
st.update_well_var("OPU02", "WULPRU", 1111);
for (const auto& wname : sched.wellNames(report_step)) {
const auto& well = sched.getWell(wname, report_step);
const auto& rst_well = restart_sched.getWell(wname, report_step);
if (well.isProducer()) {
const auto& controls = well.productionControls(st);
auto rst_controls = rst_well.productionControls(st);
/*
The cmode in the base case is the cmode set by the input deck,
whereas the cmode in restart case is what cmode was active when
the restart file was written - these can deviate.
*/
rst_controls.cmode = controls.cmode;
BOOST_CHECK( controls == rst_controls );
}
}
}