diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp index a87c6dfb8..6a7c63af6 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp @@ -31,17 +31,18 @@ namespace Opm { class UDAValue; +class UDQConfig; class UDQActive { public: struct Record{ - std::size_t index; + std::size_t input_index; std::string udq; std::string wgname; UDAControl control; bool active; }; - int update(const UDAValue& uda, const std::string& wgname, UDAControl control); + int update(const UDQConfig& udq_config, const UDAValue& uda, const std::string& wgname, UDAControl control); std::size_t size() const; std::size_t use_count(const std::string& udq) const; @@ -53,7 +54,7 @@ public: std::vector::const_iterator end() const; private: std::string hash(const std::string& wgname, UDAControl control); - int add(const std::string& udq, const std::string& wgname, UDAControl control); + int add(const UDQConfig& udq_config, const std::string& udq, const std::string& wgname, UDAControl control); int drop(const std::string& wgname, UDAControl control); std::vector data; diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp index d84b06c96..888603d05 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp @@ -41,11 +41,15 @@ namespace Opm { class UDQConfig { public: explicit UDQConfig(const Deck& deck); + explicit UDQConfig(const UDQParams& params); const std::string& unit(const std::string& key) const; bool has_unit(const std::string& keyword) const; bool has_keyword(const std::string& keyword) const; void add_record(const DeckRecord& record); - void assign_unit(const std::string& keyword, const std::string& unit); + + void add_unit(const std::string& keyword, const std::string& unit); + void add_assign(const std::string& quantity, const std::vector& selector, double value); + void add_define(const std::string& quantity, const std::vector& expression); std::vector definitions() const; std::vector definitions(UDQVarType var_type) const; @@ -63,6 +67,8 @@ namespace Opm { const UDQParams& params() const; const UDQFunctionTable& function_table() const; private: + void add_node(const std::string& quantity, UDQAction action); + UDQParams udq_params; UDQFunctionTable udqft; diff --git a/src/opm/output/eclipse/AggregateUDQData.cpp b/src/opm/output/eclipse/AggregateUDQData.cpp index ae099a542..a5dc016cf 100644 --- a/src/opm/output/eclipse/AggregateUDQData.cpp +++ b/src/opm/output/eclipse/AggregateUDQData.cpp @@ -100,7 +100,7 @@ namespace { const auto& udq = udq_active[iactive]; iUad[0] = Opm::UDQ::uadCode(udq.control); - iUad[1] = udq.index; + iUad[1] = udq.input_index; // entry 3 - unknown meaning - value = 1 iUad[2] = 1; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index e4f613fc5..2ac986be9 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -799,7 +799,7 @@ namespace { } auto udq = std::make_shared(this->udqActive(currentStep)); - if (properties->updateUDQActive(*udq)) + if (properties->updateUDQActive(this->getUDQConfig(currentStep), *udq)) this->updateUDQActive(currentStep, udq); } } @@ -907,7 +907,7 @@ namespace { } auto udq = std::make_shared(this->udqActive(currentStep)); - if (injection->updateUDQActive(*udq)) + if (injection->updateUDQActive(this->getUDQConfig(currentStep), *udq)) this->updateUDQActive(currentStep, udq); } } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp index 70fe069bc..a79e5af91 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp @@ -19,6 +19,7 @@ #include #include +#include namespace Opm { @@ -35,11 +36,13 @@ std::string UDQActive::hash(const std::string& wgname, UDAControl control) { } -int UDQActive::add(const std::string& udq, const std::string& wgname, UDAControl control) { +int UDQActive::add(const UDQConfig& udq_config, const std::string& udq, const std::string& wgname, UDAControl control) { auto hash_key = this->hash(wgname, control); const auto iter = this->keys.find( hash_key ); if (iter == this->keys.end()) { - auto index = this->data.size(); + const auto& udq_input = udq_config[udq]; + auto index = udq_input.index.insert_index; + this->data.push_back( {index, udq, wgname, control, true} ); this->keys.insert( std::make_pair(hash_key, index) ); } else { @@ -76,9 +79,9 @@ int UDQActive::drop(const std::string& wgname, UDAControl control) { } -int UDQActive::update(const UDAValue& uda, const std::string& wgname, UDAControl control) { +int UDQActive::update(const UDQConfig& udq_config, const UDAValue& uda, const std::string& wgname, UDAControl control) { if (uda.is()) - return this->add(uda.get(), wgname, control); + return this->add(udq_config, uda.get(), wgname, control); else return this->drop(wgname, control); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp index a51b6b083..3729477fd 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp @@ -36,17 +36,66 @@ namespace Opm { } + UDQConfig::UDQConfig(const UDQParams& params) : + udq_params(params), + udqft(this->udq_params) + {} + + UDQConfig::UDQConfig(const Deck& deck) : udq_params(deck), udqft(this->udq_params) - { - } + {} + const UDQParams& UDQConfig::params() const { return this->udq_params; } + void UDQConfig::add_node( const std::string& quantity, UDQAction action) { + auto index_iter = this->input_index.find(quantity); + if (this->input_index.find(quantity) == this->input_index.end()) { + auto var_type = UDQ::varType(quantity); + auto insert_index = this->input_index.size(); + this->type_count[var_type] += 1; + this->input_index[quantity] = UDQIndex(insert_index, this->type_count[var_type], action); + } else + index_iter->second.action = action; + } + + void UDQConfig::add_assign(const std::string& quantity, const std::vector& selector, double value) { + 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 ))); + else + assignment->second.add_record(selector, value); + } + + + void UDQConfig::add_define(const std::string& quantity, const std::vector& expression) { + this->add_node(quantity, UDQAction::DEFINE); + auto defined_iter = this->m_definitions.find( quantity ); + if (defined_iter != this->m_definitions.end()) + this->m_definitions.erase( defined_iter ); + + this->m_definitions.insert( std::make_pair(quantity, UDQDefine(this->udq_params, quantity, expression))); + } + + + void UDQConfig::add_unit(const std::string& keyword, const std::string& quoted_unit) { + const std::string unit = strip_quotes(quoted_unit); + const auto pair_ptr = this->units.find(keyword); + if (pair_ptr != this->units.end()) { + if (pair_ptr->second != unit) + throw std::invalid_argument("Illegal to change unit of UDQ keyword runtime"); + + return; + } + this->units[keyword] = unit; + } + void UDQConfig::add_record(const DeckRecord& record) { auto action = UDQ::actionType(record.getItem("ACTION").get(0)); @@ -57,33 +106,15 @@ namespace Opm { throw std::invalid_argument("The UDQ action UPDATE is not yet implemented in opm/flow"); if (action == UDQAction::UNITS) - this->assign_unit( quantity, data[0] ); + this->add_unit( quantity, data[0] ); else { - auto index_iter = this->input_index.find(quantity); - if (this->input_index.find(quantity) == this->input_index.end()) { - auto var_type = UDQ::varType(quantity); - auto insert_index = this->input_index.size(); - this->type_count[var_type] += 1; - this->input_index[quantity] = UDQIndex(insert_index, this->type_count[var_type], action); - } else - index_iter->second.action = action; - - if (action == UDQAction::ASSIGN) { std::vector selector(data.begin(), data.end() - 1); double value = std::stod(data.back()); - 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 ))); - else - assignment->second.add_record(selector, value); - } else if (action == UDQAction::DEFINE) { - auto defined_iter = this->m_definitions.find( quantity ); - if (defined_iter != this->m_definitions.end()) - this->m_definitions.erase( defined_iter ); - - this->m_definitions.insert( std::make_pair(quantity, UDQDefine(this->udq_params, quantity, data))); - } else + this->add_assign(quantity, selector, value); + } else if (action == UDQAction::DEFINE) + this->add_define(quantity, data); + else throw std::runtime_error("Internal error - should not be here"); } } @@ -181,19 +212,6 @@ namespace Opm { return pair_ptr->second; } - - void UDQConfig::assign_unit(const std::string& keyword, const std::string& quoted_unit) { - const std::string unit = strip_quotes(quoted_unit); - const auto pair_ptr = this->units.find(keyword); - if (pair_ptr != this->units.end()) { - if (pair_ptr->second != unit) - throw std::invalid_argument("Illegal to change unit of UDQ keyword runtime"); - - return; - } - this->units[keyword] = unit; - } - bool UDQConfig::has_unit(const std::string& keyword) const { return (this->units.count(keyword) > 0); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp index da33b4ec7..07e974d8d 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp @@ -264,13 +264,13 @@ namespace Opm { return controls; } -bool WellInjectionProperties::updateUDQActive(UDQActive& active) const { + bool WellInjectionProperties::updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const { int update_count = 0; - update_count += active.update(this->surfaceInjectionRate, this->name, UDAControl::WCONINJE_RATE); - update_count += active.update(this->reservoirInjectionRate, this->name, UDAControl::WCONINJE_RESV); - update_count += active.update(this->BHPLimit, this->name, UDAControl::WCONINJE_BHP); - update_count += active.update(this->THPLimit, this->name, UDAControl::WCONINJE_THP); + update_count += active.update(udq_config, this->surfaceInjectionRate, this->name, UDAControl::WCONINJE_RATE); + update_count += active.update(udq_config, this->reservoirInjectionRate, this->name, UDAControl::WCONINJE_RESV); + update_count += active.update(udq_config, this->BHPLimit, this->name, UDAControl::WCONINJE_BHP); + update_count += active.update(udq_config, this->THPLimit, this->name, UDAControl::WCONINJE_THP); return (update_count > 0); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp index bb507c966..cc6817f3c 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp @@ -32,6 +32,7 @@ namespace Opm { class UnitSystem; class SummaryState; class UDQActive; + class UDQConfig; struct WellInjectionProperties { std::string name; @@ -76,7 +77,7 @@ namespace Opm { void setBHPLimit(const double limit); InjectionControls controls(const UnitSystem& unit_system, const SummaryState& st, double udq_default) const; - bool updateUDQActive(UDQActive& active) const; + bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const; }; std::ostream& operator<<( std::ostream&, const WellInjectionProperties& ); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp index 332272ce1..48f83e0fc 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp @@ -298,16 +298,16 @@ namespace Opm { return controls; } - bool WellProductionProperties::updateUDQActive(UDQActive& active) const { + bool WellProductionProperties::updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const { int update_count = 0; - update_count += active.update(this->OilRate, this->name, UDAControl::WCONPROD_ORAT); - update_count += active.update(this->WaterRate, this->name, UDAControl::WCONPROD_WRAT); - update_count += active.update(this->GasRate, this->name, UDAControl::WCONPROD_GRAT); - update_count += active.update(this->LiquidRate, this->name, UDAControl::WCONPROD_LRAT); - update_count += active.update(this->ResVRate, this->name, UDAControl::WCONPROD_RESV); - update_count += active.update(this->BHPLimit, this->name, UDAControl::WCONPROD_BHP); - update_count += active.update(this->THPLimit, this->name, UDAControl::WCONPROD_THP); + update_count += active.update(udq_config, this->OilRate, this->name, UDAControl::WCONPROD_ORAT); + update_count += active.update(udq_config, this->WaterRate, this->name, UDAControl::WCONPROD_WRAT); + update_count += active.update(udq_config, this->GasRate, this->name, UDAControl::WCONPROD_GRAT); + update_count += active.update(udq_config, this->LiquidRate, this->name, UDAControl::WCONPROD_LRAT); + update_count += active.update(udq_config, this->ResVRate, this->name, UDAControl::WCONPROD_RESV); + update_count += active.update(udq_config, this->BHPLimit, this->name, UDAControl::WCONPROD_BHP); + update_count += active.update(udq_config, this->THPLimit, this->name, UDAControl::WCONPROD_THP); return (update_count > 0); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp index a3e6510d6..52b031ccc 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp @@ -82,7 +82,7 @@ namespace Opm { void resetDefaultBHPLimit(); void clearControls(); ProductionControls controls(const SummaryState& st, double udq_default) const; - bool updateUDQActive(UDQActive& active) const; + bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const; private: int m_productionControls = 0; void init_rates( const DeckRecord& record ); diff --git a/tests/parser/UDQTests.cpp b/tests/parser/UDQTests.cpp index 288e2caa2..206d22154 100644 --- a/tests/parser/UDQTests.cpp +++ b/tests/parser/UDQTests.cpp @@ -1246,27 +1246,31 @@ UDQ BOOST_AUTO_TEST_CASE(UDQ_USAGE) { UDQActive usage; + UDQParams params; + UDQConfig conf(params); BOOST_CHECK_EQUAL( usage.size(), 0 ); BOOST_CHECK_EQUAL( usage.use_count("UDQ"), 0); - UDAValue uda1("UDQ"); - usage.update(uda1, "W1", UDAControl::WCONPROD_ORAT); - BOOST_CHECK_EQUAL( usage.size(), 1 ); - BOOST_CHECK_EQUAL( usage.use_count("UDQ"), 1); + UDAValue uda1("WUX"); + conf.add_assign(uda1.get(), {}, 100); - usage.update(uda1, "W1", UDAControl::WCONPROD_GRAT); + usage.update(conf, uda1, "W1", UDAControl::WCONPROD_ORAT); + BOOST_CHECK_EQUAL( usage.size(), 1 ); + BOOST_CHECK_EQUAL( usage.use_count("WUX"), 1); + + usage.update(conf, uda1, "W1", UDAControl::WCONPROD_GRAT); BOOST_CHECK_EQUAL( usage.size(), 2 ); - BOOST_CHECK_EQUAL( usage.use_count("UDQ"), 2); + BOOST_CHECK_EQUAL( usage.use_count("WUX"), 2); const auto& rec = usage.get("W1", UDAControl::WCONPROD_ORAT); BOOST_CHECK_EQUAL(rec.wgname, "W1"); - BOOST_CHECK_EQUAL(rec.udq, "UDQ"); + BOOST_CHECK_EQUAL(rec.udq, "WUX"); BOOST_CHECK(rec.control == UDAControl::WCONPROD_ORAT); std::size_t index = 0; for (const auto& record : usage) { - BOOST_CHECK_EQUAL(record.index, index); + BOOST_CHECK_EQUAL(record.input_index, 0); BOOST_CHECK_EQUAL(record.wgname, "W1"); BOOST_CHECK_EQUAL(record.active, true); @@ -1280,10 +1284,10 @@ BOOST_AUTO_TEST_CASE(UDQ_USAGE) { UDAValue uda2(100); - usage.update(uda2, "W1", UDAControl::WCONPROD_ORAT); + usage.update(conf, uda2, "W1", UDAControl::WCONPROD_ORAT); BOOST_CHECK_EQUAL(usage[0].active, false); BOOST_CHECK_EQUAL(usage[1].active, true); - BOOST_CHECK_EQUAL( usage.use_count("UDQ"), 1); + BOOST_CHECK_EQUAL( usage.use_count("WUX"), 1); } @@ -1309,10 +1313,10 @@ BOOST_AUTO_TEST_CASE(IntegrationTest) { BOOST_CHECK(active[2].udq == "WUOPRU"); BOOST_CHECK(active[3].udq == "WULPRU"); - BOOST_CHECK(active[0].index == 0); - BOOST_CHECK(active[1].index == 1); - BOOST_CHECK(active[2].index == 2); - BOOST_CHECK(active[3].index == 3); + BOOST_CHECK(active[0].input_index == 0); + BOOST_CHECK(active[1].input_index == 1); + BOOST_CHECK(active[2].input_index == 2); + BOOST_CHECK(active[3].input_index == 3); BOOST_CHECK(active[0].active == true); BOOST_CHECK(active[1].active == true); @@ -1344,10 +1348,10 @@ BOOST_AUTO_TEST_CASE(IntegrationTest) { BOOST_CHECK(active[2].udq == "WUOPRU"); BOOST_CHECK(active[3].udq == "WULPRU"); - BOOST_CHECK(active[0].index == 0); - BOOST_CHECK(active[1].index == 1); - BOOST_CHECK(active[2].index == 2); - BOOST_CHECK(active[3].index == 3); + BOOST_CHECK(active[0].input_index == 0); + BOOST_CHECK(active[1].input_index == 1); + BOOST_CHECK(active[2].input_index == 2); + BOOST_CHECK(active[3].input_index == 3); BOOST_CHECK(active[0].active == false); BOOST_CHECK(active[1].active == false); diff --git a/tests/test_UDQ_x.cpp b/tests/test_UDQ_x.cpp index cee354b0e..06c5bf426 100644 --- a/tests/test_UDQ_x.cpp +++ b/tests/test_UDQ_x.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include //#include //#include @@ -432,23 +434,26 @@ END return Opm::Parser{}.parseString(input); } - + Opm::UDQActive udq_active() { int update_count = 0; // construct record data for udq_active + Opm::UDQParams params; + Opm::UDQConfig conf(params); Opm::UDQActive udq_act; Opm::UDAValue uda1("WUOPRL"); - update_count += udq_act.update(uda1, "PROD1", Opm::UDAControl::WCONPROD_ORAT); + update_count += udq_act.update(conf, uda1, "PROD1", Opm::UDAControl::WCONPROD_ORAT); + Opm::UDAValue uda2("WULPRL"); - update_count += udq_act.update(uda2, "PROD1", Opm::UDAControl::WCONPROD_LRAT); + update_count += udq_act.update(conf, uda2, "PROD1", Opm::UDAControl::WCONPROD_LRAT); Opm::UDAValue uda3("WUOPRU"); - update_count += udq_act.update(uda3, "PROD2", Opm::UDAControl::WCONPROD_ORAT); + update_count += udq_act.update(conf, uda3, "PROD2", Opm::UDAControl::WCONPROD_ORAT); Opm::UDAValue uda4("WULPRU"); - update_count += udq_act.update(uda4, "PROD2", Opm::UDAControl::WCONPROD_LRAT); + update_count += udq_act.update(conf, uda4, "PROD2", Opm::UDAControl::WCONPROD_LRAT); for (auto it = udq_act.begin(); it != udq_act.end(); it++) { - auto ind = it->index; + auto ind = it->input_index; auto udq_key = it->udq; auto name = it->wgname; auto ctrl_type = it->control; @@ -488,8 +493,7 @@ BOOST_AUTO_TEST_CASE (Constructor) Opm::EclipseGrid grid = simCase.grid; const auto& ioConfig = es.getIOConfig(); const auto& restart = es.cfg().restart(); - Opm::UDQActive udq_act = udq_active(); - + */ // Report Step 1: 2008-10-10 --> 2011-01-20 const auto rptStep = std::size_t{1};