diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp index 9e7a2c237..d38279f8b 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp @@ -65,6 +65,7 @@ namespace Opm { void eval(std::size_t report_step, 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; std::vector definitions(UDQVarType var_type) const; std::vector input() const; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp index dd1eba5c5..5d31d001c 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp @@ -159,6 +159,10 @@ namespace Opm { } } + const UDQAssign& UDQConfig::assign(const std::string& key) const { + return this->m_assignments.at(key); + } + const UDQDefine& UDQConfig::define(const std::string& key) const { return this->m_definitions.at(key); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.cpp index 9f03dba16..4574b539c 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.cpp @@ -478,37 +478,59 @@ UDQScalar operator/(double lhs, const UDQScalar& rhs) { namespace { +bool is_scalar(const UDQSet& udq_set) { + if (udq_set.var_type() == UDQVarType::SCALAR) + return true; + + if (udq_set.var_type() == UDQVarType::FIELD_VAR) + return true; + + return false; +} + + /* If one result set is scalar and the other represents a set of wells/groups, the scalar result is promoted to a set of the right type. -*/ -UDQSet udq_cast(const UDQSet& lhs, const UDQSet& rhs) -{ - if (lhs.size() != rhs.size()) { - if (lhs.var_type() != UDQVarType::SCALAR) { - auto msg = fmt::format("Type/size mismatch when combining UDQs {}(size={}, type={}) and {}(size={}, type={})", - lhs.name(), lhs.size(), lhs.var_type(), - rhs.name(), rhs.size(), rhs.var_type()); - throw std::logic_error(msg); - } + This function is quite subconcious about FIELD / SCALAR. +*/ +std::pair udq_cast(const UDQSet& lhs, const UDQSet& rhs) +{ + if (lhs.var_type() == rhs.var_type()) + return std::make_pair(lhs,rhs); + + if (lhs.size() == rhs.size()) + return std::make_pair(lhs,rhs); + + if (is_scalar(lhs)) { if (rhs.var_type() == UDQVarType::WELL_VAR) - return UDQSet::wells(lhs.name(), rhs.wgnames(), lhs[0].get()); + return std::make_pair(UDQSet::wells(lhs.name(), rhs.wgnames(), lhs[0].get()), rhs); if (rhs.var_type() == UDQVarType::GROUP_VAR) - return UDQSet::groups(lhs.name(), rhs.wgnames(), lhs[0].get()); + return std::make_pair(UDQSet::groups(lhs.name(), rhs.wgnames(), lhs[0].get()), rhs); + } - throw std::logic_error("Don't have a clue"); - } else - return lhs; + if (is_scalar(rhs)) { + if (lhs.var_type() == UDQVarType::WELL_VAR) + return std::make_pair(lhs, UDQSet::wells(rhs.name(), lhs.wgnames(), rhs[0].get())); + + if (lhs.var_type() == UDQVarType::GROUP_VAR) + return std::make_pair(lhs, UDQSet::groups(rhs.name(), lhs.wgnames(), rhs[0].get())); + } + + auto msg = fmt::format("Type/size mismatch when combining UDQs {}(size={}, type={}) and {}(size={}, type={})", + lhs.name(), lhs.size(), lhs.var_type(), + rhs.name(), rhs.size(), rhs.var_type()); + throw std::logic_error(msg); } } UDQSet operator+(const UDQSet&lhs, const UDQSet& rhs) { - UDQSet sum = udq_cast(lhs, rhs); - sum += rhs; - return sum; + auto [left,right] = udq_cast(lhs, rhs); + left += right; + return left; } UDQSet operator+(const UDQSet&lhs, double rhs) { @@ -524,9 +546,9 @@ UDQSet operator+(double lhs, const UDQSet& rhs) { } UDQSet operator-(const UDQSet&lhs, const UDQSet& rhs) { - UDQSet diff = udq_cast(lhs, rhs); - diff -= rhs; - return diff; + auto [left,right] = udq_cast(lhs, rhs); + left -= right; + return left; } UDQSet operator-(const UDQSet&lhs, double rhs) { @@ -542,9 +564,9 @@ UDQSet operator-(double lhs, const UDQSet& rhs) { } UDQSet operator*(const UDQSet&lhs, const UDQSet& rhs) { - UDQSet prod = udq_cast(lhs, rhs); - prod *= rhs; - return prod; + auto [left,right] = udq_cast(lhs, rhs); + left *= right; + return left; } UDQSet operator*(const UDQSet&lhs, double rhs) { @@ -560,9 +582,9 @@ UDQSet operator*(double lhs, const UDQSet& rhs) { } UDQSet operator/(const UDQSet&lhs, const UDQSet& rhs) { - UDQSet frac = udq_cast(lhs, rhs); - frac /= rhs; - return frac; + auto [left,right] = udq_cast(lhs, rhs); + left /= right; + return left; } UDQSet operator/(const UDQSet&lhs, double rhs) { diff --git a/tests/parser/UDQTests.cpp b/tests/parser/UDQTests.cpp index e0a419c60..f7b0cbc31 100644 --- a/tests/parser/UDQTests.cpp +++ b/tests/parser/UDQTests.cpp @@ -2484,3 +2484,48 @@ TSTEP BOOST_CHECK( !udq_state.define(def.keyword(), def.status())); } } + +BOOST_AUTO_TEST_CASE(UDQ_TYPE_CAST) { + + std::string valid = R"( +SCHEDULE + +UDQ + ASSIGN FUBHPP1 100 / +/ + +TSTEP +10 / + +UDQ + DEFINE FU_TIME TIME / + DEFINE WUDELTA WBHP '*' - FUBHPP1 / + DEFINE WU_TEST WUBHPINI '*' - (WGPR '*')/2000.0 / + +/ + +)"; + + + + auto schedule = make_schedule(valid); + UDQState udq_state(0); + SummaryState st(std::chrono::system_clock::now()); + UDQFunctionTable udqft; + UDQContext context(udqft, WellMatcher({"W1", "W2", "W3"}), st, udq_state); + st.update_well_var("W1", "WBHP", 400); + st.update_well_var("W2", "WBHP", 300); + st.update_well_var("W3", "WBHP", 200); + + const auto& udq = schedule.getUDQConfig(1); + { + const auto& ass = udq.assign("FUBHPP1"); + context.update_assign(1, "FUBHPP1", ass.eval()); + } + const auto& def = udq.define("WUDELTA"); + auto res = def.eval(context); + + BOOST_CHECK_EQUAL(res["W1"].get(), 300); + BOOST_CHECK_EQUAL(res["W2"].get(), 200); + BOOST_CHECK_EQUAL(res["W3"].get(), 100); +}