From 6af909778c33488360a4bc5bb3bdcce2cdecd9c6 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Thu, 1 Jul 2021 07:31:48 +0200 Subject: [PATCH] Load UDQConfig and UDQState from restart data --- .../EclipseState/Schedule/UDQ/UDQConfig.hpp | 7 ++ .../EclipseState/Schedule/UDQ/UDQState.hpp | 7 ++ .../EclipseState/Schedule/UDQ/UDQConfig.cpp | 25 ++++++- .../EclipseState/Schedule/UDQ/UDQState.cpp | 34 +++++++++ tests/parser/UDQTests.cpp | 2 +- tests/test_AggregateUDQData.cpp | 69 +++++++++++++++---- 6 files changed, 128 insertions(+), 16 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp index c81673492..cc9ff41f0 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp @@ -43,10 +43,16 @@ namespace Opm { class KeywordLocation; class WellMatcher; + namespace RestartIO { + class RstState; + } + + class UDQConfig { public: UDQConfig() = default; explicit UDQConfig(const UDQParams& params); + UDQConfig(const UDQParams& params, const RestartIO::RstState& rst_state); static UDQConfig serializeObject(); @@ -58,6 +64,7 @@ namespace Opm { void add_unit(const std::string& keyword, const std::string& unit); void add_update(const std::string& keyword, std::size_t report_step, const KeywordLocation& location, const std::vector& data); void add_assign(const std::string& quantity, const std::vector& selector, double value, std::size_t report_step); + void add_assign(const std::string& quantity, const std::unordered_set& selector, double value, std::size_t report_step); void add_define(const std::string& quantity, const KeywordLocation& location, const std::vector& expression, std::size_t report_step); void eval(std::size_t report_step, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const; diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp index b0a75af9c..051ac7ce3 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp @@ -28,11 +28,18 @@ namespace Opm { + +namespace RestartIO { + class RstState; +} + class UDQState { public: UDQState(double undefined); bool has(const std::string& key) const; + void load_rst(const RestartIO::RstState& rst_state); + bool has_well_var(const std::string& well, const std::string& key) const; bool has_group_var(const std::string& group, const std::string& key) const; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp index 00d60aa80..2c622315e 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp @@ -19,7 +19,7 @@ #include - +#include #include #include #include @@ -47,6 +47,18 @@ namespace Opm { {} + UDQConfig::UDQConfig(const UDQParams& params, const RestartIO::RstState& rst_state) : + UDQConfig(params) + { + for (const auto& rst_udq : rst_state.udqs) { + if (rst_udq.is_define()) { + KeywordLocation location("UDQ", "Restart file", 0); + this->add_define(rst_udq.name, location, {rst_udq.expression()}, rst_state.header.report_step); + } else + this->add_assign(rst_udq.name, rst_udq.assign_selector(), rst_udq.assign_value(), rst_state.header.report_step); + } + } + UDQConfig UDQConfig::serializeObject() { UDQConfig result; @@ -85,6 +97,15 @@ namespace Opm { assignment->second.add_record(selector, value, report_step); } + void UDQConfig::add_assign(const std::string& quantity, const std::unordered_set& selector, double value, std::size_t report_step) { + this->add_node(quantity, UDQAction::ASSIGN); + auto assignment = this->m_assignments.find(quantity); + if (assignment == this->m_assignments.end()) + this->m_assignments.insert( std::make_pair(quantity, UDQAssign(quantity, selector, value, report_step ))); + else + assignment->second.add_record(selector, value, report_step); + } + void UDQConfig::add_define(const std::string& quantity, const KeywordLocation& location, const std::vector& expression, std::size_t report_step) { this->add_node(quantity, UDQAction::DEFINE); @@ -114,7 +135,7 @@ namespace Opm { keyword. */ if (!this->has_keyword(keyword)) - this->add_assign(keyword, {}, 0, 0); + this->add_assign(keyword, std::vector{}, 0, 0); this->units[keyword] = unit; } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.cpp index 69a7346f0..27a32d690 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.cpp @@ -22,6 +22,7 @@ #include #include +#include namespace Opm { @@ -94,6 +95,39 @@ double get_wg(const std::unordered_mapwell_values[udq.name][wname] = value; + } + + if (udq.var_type == UDQVarType::GROUP_VAR) { + for (const auto& [gname, value] : udq.values()) + this->group_values[udq.name][gname] = value; + } + + const auto& field_value = udq.field_value(); + if (field_value.has_value()) + this->scalar_values[udq.name] = field_value.value(); + } else { + auto value = udq.assign_value(); + if (udq.var_type == UDQVarType::WELL_VAR) { + for (const auto& wname : udq.assign_selector()) + this->well_values[udq.name][wname] = value; + } + + if (udq.var_type == UDQVarType::GROUP_VAR) { + for (const auto& gname : udq.assign_selector()) + this->group_values[udq.name][gname] = value; + } + + if (udq.var_type == UDQVarType::FIELD_VAR) + this->scalar_values[udq.name] = value; + } + } +} double UDQState::undefined_value() const { return this->undef_value; diff --git a/tests/parser/UDQTests.cpp b/tests/parser/UDQTests.cpp index e8ad55ff6..8d19ffed7 100644 --- a/tests/parser/UDQTests.cpp +++ b/tests/parser/UDQTests.cpp @@ -1488,7 +1488,7 @@ BOOST_AUTO_TEST_CASE(UDQ_USAGE) { BOOST_CHECK_EQUAL( usage.IUAD_size(), 0U ); UDAValue uda1("WUX"); - conf.add_assign(uda1.get(), {}, 100, 0); + conf.add_assign(uda1.get(), std::vector{}, 100, 0); usage.update(conf, uda1, "W1", UDAControl::WCONPROD_ORAT); BOOST_CHECK_EQUAL( usage.IUAD_size(), 1U); diff --git a/tests/test_AggregateUDQData.cpp b/tests/test_AggregateUDQData.cpp index f0a7c57fc..d7a061a7f 100644 --- a/tests/test_AggregateUDQData.cpp +++ b/tests/test_AggregateUDQData.cpp @@ -103,10 +103,11 @@ Opm::UDQSet make_udq_set(const std::string& name, Opm::UDQVarType var_type, cons {"PROD1", "PROD2", "WINJ1", "WINJ2"}, {220, 221, 222, 223})); + // The WULPRL should really be an ASSIGN state.add_define(0, "WULPRL", make_udq_set("WULPRL", Opm::UDQVarType::WELL_VAR, {"PROD1", "PROD2", "WINJ1", "WINJ2"}, - {230, 231, 232, 233})); + {400, 400, 400, 400})); state.add_define(0, "WULPRU", make_udq_set("WULPRU", Opm::UDQVarType::WELL_VAR, @@ -130,10 +131,10 @@ Opm::UDQSet make_udq_set(const std::string& name, Opm::UDQVarType var_type, cons state.update_well_var("WINJ1", "WUOPRL", 212.); state.update_well_var("WINJ2", "WUOPRL", 213.); - state.update_well_var("PROD1", "WULPRL", 230.); - state.update_well_var("PROD2", "WULPRL", 231.); - state.update_well_var("WINJ1", "WULPRL", 232.); - state.update_well_var("WINJ2", "WULPRL", 233.); + state.update_well_var("PROD1", "WULPRL", 400.); + state.update_well_var("PROD2", "WULPRL", 400.); + state.update_well_var("WINJ1", "WULPRL", 400.); + state.update_well_var("WINJ2", "WULPRL", 400.); state.update_well_var("PROD1", "WUOPRU", 220.); state.update_well_var("PROD2", "WUOPRU", 221.); @@ -148,9 +149,19 @@ Opm::UDQSet make_udq_set(const std::string& name, Opm::UDQVarType var_type, cons state.update_well_var("PROD2", "WULPRU", 161.); state.update_well_var("WINJ1", "WULPRU", 162.); state.update_well_var("WINJ2", "WULPRU", 163.); - state.update("FULPR", 460.); + state.update_well_var("PROD1", "WOPR", 1.0); + state.update_well_var("PROD2", "WOPR", 1.0); + state.update_well_var("WINJ1", "WOPR", 0.0); + state.update_well_var("WINJ2", "WOPR", 0.0); + state.update_well_var("PROD1", "WLPR", 1.0); + state.update_well_var("PROD2", "WLPR", 1.0); + state.update_group_var("GRP1", "GOPR", 1.0); + state.update("FOPR", 145); + state.update("FLPR", 45); + state.update("FWPR", 450); + return state; } @@ -660,7 +671,7 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data) } -#if 0 + { /* 'DUDW ' 24 'DOUB' @@ -679,15 +690,15 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data) BOOST_CHECK_EQUAL(dUdw[start + 4] , -0.3E+21); // duDw NO. 1 start = 1*udqDims[8]; - BOOST_CHECK_EQUAL(dUdw[start + 0] , 230); // duDw NO. 1 - BOOST_CHECK_EQUAL(dUdw[start + 1] , 231); // duDw NO. 1 - BOOST_CHECK_EQUAL(dUdw[start + 2] , 232); // duDw NO. 1 - BOOST_CHECK_EQUAL(dUdw[start + 3] , 233); // duDw NO. 1 + BOOST_CHECK_EQUAL(dUdw[start + 0] , 400); // duDw NO. 1 + BOOST_CHECK_EQUAL(dUdw[start + 1] , 400); // duDw NO. 1 + BOOST_CHECK_EQUAL(dUdw[start + 2] , 400); // duDw NO. 1 + BOOST_CHECK_EQUAL(dUdw[start + 3] , 400); // duDw NO. 1 BOOST_CHECK_EQUAL(dUdw[start + 4] , -0.3E+21); // duDw NO. 1 } -#endif + { /* 'DUDG ' 5 'DOUB' @@ -750,7 +761,39 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data) } - BOOST_CHECK_EQUAL(rst_state.udqs[0].define.value(), "(WOPR PROD1 - 170) * 0.60"); + BOOST_CHECK_EQUAL(rst_state.udqs[0].expression(), "(WOPR PROD1 - 170) * 0.60"); + + + const auto& udq_params = es.runspec().udqParams(); + const auto& input_config = sched[1].udq(); + Opm::UDQConfig rst_config(udq_params, rst_state); + BOOST_CHECK_EQUAL(input_config.size(), rst_config.size()); + BOOST_CHECK_EQUAL(input_config.definitions().size(), rst_config.definitions().size()); + + const std::vector& wells = {"PROD1", "PROD2", "WINJ1", "WINJ2"}; + Opm::UDQState rst_udq_state(udq_params.undefinedValue()); + Opm::UDQFunctionTable udqft(udq_params); + Opm::UDQContext input_context(udqft, Opm::WellMatcher(wells), st, udq_state); + Opm::UDQContext rst_context(udqft, Opm::WellMatcher(wells), st, rst_udq_state); + + rst_udq_state.load_rst(rst_state); + for (const auto& input_def : input_config.definitions()) { + const auto& rst_def = rst_config.define( input_def.keyword() ); + + auto input_eval = input_def.eval(input_context); + auto rst_eval = rst_def.eval(rst_context); + + BOOST_CHECK(input_eval == rst_eval); + } + + for (const auto& input_assign : input_config.assignments()) { + const auto& rst_assign = rst_config.assign( input_assign.keyword() ); + + auto input_eval = input_assign.eval(wells); + auto rst_eval = rst_assign.eval(wells); + + BOOST_CHECK(input_eval == rst_eval); + } } }