Update UDA properties from restart file
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user