From c33b94ca3a200a88c5f8e092eb78cf1fc4f8adb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Tue, 13 Jun 2023 09:58:14 +0200 Subject: [PATCH 1/2] Default UDQ Assignments to All Wells in Model An assignment of the form ASSIGN WUPPERTAL 354.572 / should create a UDQ set of size equal to the number of wells in the model, not just the wells already flowing-especially if the assignment happens on the very first report step before any wells are flowing. --- msim/src/msim.cpp | 3 ++- opm/input/eclipse/Schedule/UDQ/UDQConfig.hpp | 9 ++++--- .../input/eclipse/Schedule/UDQ/UDQConfig.cpp | 16 ++++++++---- tests/parser/UDQTests.cpp | 26 +++++++++---------- tests/test_Restart.cpp | 6 ++++- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/msim/src/msim.cpp b/msim/src/msim.cpp index f7c152793..e32687846 100644 --- a/msim/src/msim.cpp +++ b/msim/src/msim.cpp @@ -127,7 +127,8 @@ void msim::run_step(WellTestState& wtest_state, UDQState& udq_state, data::Solut /* initial_inplace = */ {}, /* inplace = */ {}); - this->schedule.getUDQConfig( report_step ).eval(report_step, schedule.wellMatcher(report_step), this->st, udq_state); + this->schedule.getUDQConfig(report_step) + .eval(report_step, this->schedule, schedule.wellMatcher(report_step), this->st, udq_state); this->output(wtest_state, udq_state, diff --git a/opm/input/eclipse/Schedule/UDQ/UDQConfig.hpp b/opm/input/eclipse/Schedule/UDQ/UDQConfig.hpp index 18cb21294..ab579e438 100644 --- a/opm/input/eclipse/Schedule/UDQ/UDQConfig.hpp +++ b/opm/input/eclipse/Schedule/UDQ/UDQConfig.hpp @@ -40,9 +40,10 @@ namespace Opm { class DeckRecord; + class KeywordLocation; + class Schedule; class SummaryState; class UDQState; - class KeywordLocation; class WellMatcher; } // namespace Opm @@ -73,8 +74,8 @@ namespace Opm { 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_assign(std::size_t report_step, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const; - void eval(std::size_t report_step, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const; + void eval_assign(std::size_t report_step, const Schedule& sched, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const; + void eval(std::size_t report_step, const Schedule& sched, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const; const UDQDefine& define(const std::string& key) const; const UDQAssign& assign(const std::string& key) const; std::vector definitions() const; @@ -115,7 +116,7 @@ namespace Opm { private: void add_node(const std::string& quantity, UDQAction action); UDQAction action_type(const std::string& udq_key) const; - void eval_assign(std::size_t report_step, SummaryState& st, UDQState& udq_state, UDQContext& context) const; + void eval_assign(std::size_t report_step, const Schedule& sched, UDQState& udq_state, UDQContext& context) const; void eval_define(std::size_t report_step, UDQState& udq_state, UDQContext& context) const; UDQParams udq_params; diff --git a/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp b/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp index 2ac11d4e1..0b7bc6357 100644 --- a/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp +++ b/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -440,20 +441,23 @@ namespace Opm { } void UDQConfig::eval_assign(const std::size_t report_step, - SummaryState& st, + const Schedule& sched, UDQState& udq_state, UDQContext& context) const { + const auto wells = sched.wellNames(report_step); + const auto groups = sched.groupNames(report_step); + for (const auto& assign : this->assignments(UDQVarType::WELL_VAR)) { if (udq_state.assign(report_step, assign.keyword())) { - auto ws = assign.eval(st.wells()); + auto ws = assign.eval(wells); context.update_assign(report_step, assign.keyword(), ws); } } for (const auto& assign : this->assignments(UDQVarType::GROUP_VAR)) { if (udq_state.assign(report_step, assign.keyword())) { - auto ws = assign.eval(st.groups()); + auto ws = assign.eval(groups); context.update_assign(report_step, assign.keyword(), ws); } } @@ -505,22 +509,24 @@ namespace Opm { } void UDQConfig::eval(const std::size_t report_step, + const Schedule& sched, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const { UDQContext context(this->function_table(), wm, st, udq_state); - this->eval_assign(report_step, st, udq_state, context); + this->eval_assign(report_step, sched, udq_state, context); this->eval_define(report_step, udq_state, context); } void UDQConfig::eval_assign(const std::size_t report_step, + const Schedule& sched, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const { UDQContext context(this->function_table(), wm, st, udq_state); - this->eval_assign(report_step, st, udq_state, context); + this->eval_assign(report_step, sched, udq_state, context); } void UDQConfig::required_summary(std::unordered_set& summary_keys) const diff --git a/tests/parser/UDQTests.cpp b/tests/parser/UDQTests.cpp index 7eff16835..19080f6a7 100644 --- a/tests/parser/UDQTests.cpp +++ b/tests/parser/UDQTests.cpp @@ -1949,7 +1949,7 @@ UDQ SummaryState st(TimeService::now()); auto undefined_value = udq.params().undefinedValue(); UDQState udq_state(undefined_value); - udq.eval(0, {}, st, udq_state); + udq.eval(0, schedule, {}, st, udq_state); BOOST_CHECK_EQUAL( st.get("FU_UADD"), 12); // 10 + 2 @@ -1975,7 +1975,7 @@ DEFINE FU_PAR2 FU_PAR3 / auto undefined_value = udq.params().undefinedValue(); UDQState udq_state(undefined_value); st.update("FMWPR", 100); - udq.eval(0, {}, st, udq_state); + udq.eval(0, schedule, {}, st, udq_state); BOOST_CHECK_EQUAL(st.get("FU_PAR2"), 100); } @@ -1993,7 +1993,7 @@ DEFINE FU_PAR3 FU_PAR2 + 1/ SummaryState st(TimeService::now()); auto undefined_value = udq.params().undefinedValue(); UDQState udq_state(undefined_value); - udq.eval(0, {}, st, udq_state); + udq.eval(0, schedule, {}, st, udq_state); BOOST_CHECK_EQUAL(st.get("FU_PAR2"), undefined_value); BOOST_CHECK_EQUAL(st.get("FU_PAR3"), undefined_value); @@ -2103,7 +2103,7 @@ DEFINE WUGASRA 750000 - WGLIR '*' / NameOrder wo({"W1", "W2", "W3"}); WellMatcher wm(wo); - udq.eval(0, wm, st, udq_state); + udq.eval(0, schedule, wm, st, udq_state); { std::unordered_set required_keys; udq.required_summary(required_keys); @@ -2307,7 +2307,7 @@ DEFINE FU_VAR91 GOPR TEST / st.update_well_var("W3", "WGLIR", 3); st.update_group_var("TEST", "GOPR", 1); - udq.eval(0, {}, st, udq_state); + udq.eval(0, schedule, {}, st, udq_state); } BOOST_AUTO_TEST_CASE(UDQ_KEY_ERROR) { @@ -2326,7 +2326,7 @@ UDQ UDQState udq_state(undefined_value); SummaryState st(TimeService::now()); - BOOST_CHECK_THROW(udq.eval(0, {}, st, udq_state), std::exception); + BOOST_CHECK_THROW(udq.eval(0, schedule, {}, st, udq_state), std::exception); } BOOST_AUTO_TEST_CASE(UDQ_ASSIGN) { @@ -2351,7 +2351,7 @@ UDQ BOOST_CHECK(required_keys.empty()); } - udq.eval(0, {}, st, udq_state); + udq.eval(0, schedule, {}, st, udq_state); BOOST_CHECK_EQUAL(st.get("FU_VAR1"), 10); } @@ -2392,7 +2392,7 @@ TSTEP // Counting: 1,2,3,4,5 for (std::size_t report_step = 0; report_step < 5; report_step++) { const auto& udq = schedule.getUDQConfig(report_step); - udq.eval(report_step, schedule.wellMatcher(report_step), st, udq_state); + udq.eval(report_step, schedule, schedule.wellMatcher(report_step), st, udq_state); auto fu_var1 = st.get("FU_VAR1"); BOOST_CHECK_EQUAL(fu_var1, report_step + 1); } @@ -2400,7 +2400,7 @@ TSTEP // Reset to zero and count: 1,2,3,4,5 for (std::size_t report_step = 5; report_step < 10; report_step++) { const auto& udq = schedule.getUDQConfig(report_step); - udq.eval(report_step, schedule.wellMatcher(report_step), st, udq_state); + udq.eval(report_step, schedule, schedule.wellMatcher(report_step), st, udq_state); auto fu_var1 = st.get("FU_VAR1"); BOOST_CHECK_EQUAL(fu_var1, report_step - 4); } @@ -2408,7 +2408,7 @@ TSTEP // Reset to zero and stay there. for (std::size_t report_step = 10; report_step < 15; report_step++) { const auto& udq = schedule.getUDQConfig(report_step); - udq.eval(report_step, schedule.wellMatcher(report_step),st, udq_state); + udq.eval(report_step, schedule, schedule.wellMatcher(report_step),st, udq_state); auto fu_var1 = st.get("FU_VAR1"); BOOST_CHECK_EQUAL(fu_var1, 0); } @@ -2459,7 +2459,7 @@ UDQ SummaryState st(TimeService::now()); const auto& udq = schedule.getUDQConfig(0); - udq.eval(0, {}, st, udq_state); + udq.eval(0, schedule, {}, st, udq_state); auto fu_var1 = st.get("FU_VAR1"); auto fu_var2 = st.get("FU_VAR2"); auto fu_var3 = st.get("FU_VAR3"); @@ -2504,7 +2504,7 @@ UDQ st.update_well_var("P3", "WOPR", 3); st.update_well_var("P4", "WOPR", 4); - udq.eval(0, schedule.wellMatcher(0), st, udq_state); + udq.eval(0, schedule, schedule.wellMatcher(0), st, udq_state); auto fu_var1 = st.get("FU_VAR1"); auto fu_var2 = st.get("FU_VAR2"); auto fu_var3 = st.get("FU_VAR3"); @@ -2530,7 +2530,7 @@ UDQ UDQState udq_state(0); SummaryState st(TimeService::now()); const auto& udq = schedule.getUDQConfig(0); - udq.eval(0, schedule.wellMatcher(0), st, udq_state); + udq.eval(0, schedule, schedule.wellMatcher(0), st, udq_state); auto fu_var1 = st.get("FU_VAR1"); auto fu_var2 = st.get("FU_VAR2"); diff --git a/tests/test_Restart.cpp b/tests/test_Restart.cpp index 1f8420a12..640071705 100644 --- a/tests/test_Restart.cpp +++ b/tests/test_Restart.cpp @@ -419,7 +419,11 @@ RestartValue first_sim(const Setup& setup, Action::State& action_state, SummaryS const auto& udq = setup.schedule.getUDQConfig(report_step); RestartValue restart_value(sol, wells, groups, {}); - udq.eval(report_step, setup.schedule.wellMatcher(report_step), st, udq_state); + udq.eval(report_step, + setup.schedule, + setup.schedule.wellMatcher(report_step), + st, udq_state); + eclWriter.writeTimeStep( action_state, wtest_state, st, From 4c2617f537b5891ed0c7cca4df123182cd6ca407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Tue, 13 Jun 2023 10:06:25 +0200 Subject: [PATCH 2/2] Don't Run ASSIGN on Every Report Step Commit 5a060910a distinguished ASSIGN from DEFINE at the field level, but did not make the same distinction at the well or group levels. Passing 'report_step' instead of assign.report_step() as an argument to UDQState::assign() means we'd be running every ASSIGN operation on every report step which would reset the state. That's a bug if the model defines some sort of cumulative UDQ at the well or group levels. --- src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp b/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp index 0b7bc6357..db3960efa 100644 --- a/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp +++ b/src/opm/input/eclipse/Schedule/UDQ/UDQConfig.cpp @@ -449,14 +449,14 @@ namespace Opm { const auto groups = sched.groupNames(report_step); for (const auto& assign : this->assignments(UDQVarType::WELL_VAR)) { - if (udq_state.assign(report_step, assign.keyword())) { + if (udq_state.assign(assign.report_step(), assign.keyword())) { auto ws = assign.eval(wells); context.update_assign(report_step, assign.keyword(), ws); } } for (const auto& assign : this->assignments(UDQVarType::GROUP_VAR)) { - if (udq_state.assign(report_step, assign.keyword())) { + if (udq_state.assign(assign.report_step(), assign.keyword())) { auto ws = assign.eval(groups); context.update_assign(report_step, assign.keyword(), ws); }