From 134834cefaa7fbd18716810aea87cd24b38486b8 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Thu, 15 Oct 2020 09:11:17 +0200 Subject: [PATCH] Pass VFP ALQ type to enable unit conversion for ALQ values --- .../EclipseState/Schedule/Well/Well.hpp | 6 ++- .../EclipseState/Schedule/KeywordHandlers.cpp | 16 ++++++-- .../Well/WellProductionProperties.cpp | 40 +++++++++++-------- .../share/keywords/000_Eclipse100/W/WCONHIST | 2 +- tests/parser/GroupTests.cpp | 4 +- tests/parser/ScheduleTests.cpp | 2 - tests/parser/WellTests.cpp | 17 ++++---- 7 files changed, 53 insertions(+), 34 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp index 4362b991d..8d67bba6f 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -386,8 +387,8 @@ public: // this is used to check whether the specified control mode is an effective history matching production mode static bool effectiveHistoryProductionControl(ProducerCMode cmode); - void handleWCONPROD( const std::string& well, const DeckRecord& record); - void handleWCONHIST( const DeckRecord& record); + void handleWCONPROD( const std::optional& alq_type, const UnitSystem& unit_system, const std::string& well, const DeckRecord& record); + void handleWCONHIST( const std::optional& alq_type, const UnitSystem& unit_system, const DeckRecord& record); void handleWELTARG( WELTARGCMode cmode, const UDAValue& new_arg, double SiFactorP); void resetDefaultBHPLimit(); void clearControls(); @@ -425,6 +426,7 @@ public: void init_rates( const DeckRecord& record ); void init_history(const DeckRecord& record); + void init_vfp(const std::optional& alq_type, const UnitSystem& unit_system, const DeckRecord& record); WellProductionProperties(const DeckRecord& record); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index 9fc5a7e9c..16009bf3f 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -819,6 +819,7 @@ namespace { } void Schedule::handleWCONHIST(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { + const auto& unit_system = handlerContext.section.unitSystem(); for (const auto& record : handlerContext.keyword) { const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0); const auto well_names = this->wellNames(wellNamePattern, handlerContext.currentStep); @@ -830,12 +831,17 @@ namespace { for (const auto& well_name : well_names) { updateWellStatus( well_name , handlerContext.currentStep , status, false ); + const auto table_nr = record.getItem("VFP_TABLE").get< int >(0); + std::optional alq_type; auto& dynamic_state = this->wells_static.at(well_name); auto well2 = std::make_shared(*dynamic_state[handlerContext.currentStep]); const bool switching_from_injector = !well2->isProducer(); auto properties = std::make_shared(well2->getProductionProperties()); bool update_well = false; - properties->handleWCONHIST(record); + + if (table_nr != 0) + alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); + properties->handleWCONHIST(alq_type, unit_system, record); if (switching_from_injector) { properties->resetDefaultBHPLimit(); @@ -880,6 +886,7 @@ namespace { } void Schedule::handleWCONPROD(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { + const auto& unit_system = handlerContext.section.unitSystem(); for (const auto& record : handlerContext.keyword) { const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0); const auto well_names = this->wellNames(wellNamePattern, handlerContext.currentStep); @@ -890,7 +897,8 @@ namespace { for (const auto& well_name : well_names) { updateWellStatus(well_name, handlerContext.currentStep, status, false); - + const auto table_nr = record.getItem("VFP_TABLE").get< int >(0); + std::optional alq_type; auto& dynamic_state = this->wells_static.at(well_name); auto well2 = std::make_shared(*dynamic_state[handlerContext.currentStep]); const bool switching_from_injector = !well2->isProducer(); @@ -900,7 +908,9 @@ namespace { if (well2->isAvailableForGroupControl()) properties->addProductionControl(Well::ProducerCMode::GRUP); - properties->handleWCONPROD(well_name, record); + if (table_nr != 0) + alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); + properties->handleWCONPROD(alq_type, unit_system, well_name, record); if (switching_from_injector) properties->resetDefaultBHPLimit(); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp index 720bba2a3..2e9a2c05b 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "../eval_uda.hpp" @@ -89,6 +90,20 @@ namespace Opm { } + void Well::WellProductionProperties::init_vfp(const std::optional& alq_type, const UnitSystem& unit_system, const DeckRecord& record) { + if (alq_type) { + this->VFPTableNumber = record.getItem("VFP_TABLE").get(0); + double alq_input = record.getItem("ALQ").get(0); + const auto alq_dim = VFPProdTable::ALQDimension(*alq_type, unit_system); + this->ALQValue = alq_dim.convertRawToSi(alq_input); + } else { + const auto table_nr = record.getItem("VFP_TABLE").get< int >(0); + if (table_nr != 0) + throw std::logic_error("VFP table inconsistency - BUG"); + } + } + + void Well::WellProductionProperties::init_history(const DeckRecord& record) { this->predictionMode = false; @@ -135,25 +150,18 @@ namespace Opm { if (cmode == ProducerCMode::BHP) this->setBHPLimit(this->BHPH); - const auto vfp_table = record.getItem("VFP_TABLE").get< int >(0); - if (vfp_table != 0) - this->VFPTableNumber = vfp_table; - - auto alq_value = record.getItem("LIFT").get(0); //NOTE: Unit of ALQ is never touched - if (alq_value != 0.) - this->ALQValue = alq_value; } - void Well::WellProductionProperties::handleWCONPROD( const std::string& /* well */, const DeckRecord& record) +void Well::WellProductionProperties::handleWCONPROD(const std::optional& alq_type, const UnitSystem& unit_system, const std::string& /* well */, const DeckRecord& record) { this->predictionMode = true; + this->init_vfp(alq_type, unit_system, record); + this->init_rates(record); this->BHPTarget = record.getItem("BHP").get(0); this->THPTarget = record.getItem("THP").get(0); - this->ALQValue = record.getItem("ALQ").get< double >(0); //NOTE: Unit of ALQ is never touched - this->VFPTableNumber = record.getItem("VFP_TABLE").get< int >(0); this->LiquidRate = record.getItem("LRAT").get(0); this->ResVRate = record.getItem("RESV").get(0); @@ -164,8 +172,6 @@ namespace Opm { }; - this->init_rates(record); - for( const auto& cmode : modes ) { if( !record.getItem( cmode.first ).defaultApplied( 0 ) ) { @@ -197,9 +203,10 @@ namespace Opm { originate from the WCONHIST keyword. Predictions are handled with the default constructor and the handleWCONPROD() method. */ - void Well::WellProductionProperties::handleWCONHIST(const DeckRecord& record) +void Well::WellProductionProperties::handleWCONHIST(const std::optional& alq_type, const UnitSystem& unit_system, const DeckRecord& record) { this->init_rates(record); + this->init_vfp(alq_type, unit_system, record); this->LiquidRate = 0; this->ResVRate = 0; @@ -250,9 +257,10 @@ namespace Opm { this->THPTarget.update_value( new_arg ); this->addProductionControl( ProducerCMode::THP ); } - else if (cmode == WELTARGCMode::VFP) - this->VFPTableNumber = static_cast(new_arg.get()); - else if (cmode != WELTARGCMode::GUID) + else if (cmode == WELTARGCMode::VFP) { + OpmLog::warning("When using WELTARG to change VFP table it is assumed that ALQ type is the same for the new and old table"); + this->VFPTableNumber = static_cast( new_arg.get() ); + } else if (cmode != WELTARGCMode::GUID) throw std::invalid_argument("Invalid keyword (MODE) supplied"); } diff --git a/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WCONHIST b/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WCONHIST index c012f17e5..446bf4fbf 100644 --- a/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WCONHIST +++ b/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WCONHIST @@ -42,7 +42,7 @@ "comment": "The default is a state variable" }, { - "name": "LIFT", + "name": "ALQ", "value_type": "DOUBLE", "default": 0, "comment": "The default is a state variable" diff --git a/tests/parser/GroupTests.cpp b/tests/parser/GroupTests.cpp index 6c342c09d..8829d2318 100644 --- a/tests/parser/GroupTests.cpp +++ b/tests/parser/GroupTests.cpp @@ -161,8 +161,8 @@ BOOST_AUTO_TEST_CASE(createDeckWithWGRUPCONandWCONPROD) { "/\n" "WCONPROD\n" - " 'B-37T2' 'OPEN' 'GRUP' 1000 2* 2000.000 2* 1* 10 200000.000 5* / / \n" - " 'B-43A' 'OPEN' 'GRUP' 1200 2* 3000.000 2* 1* 11 0.000 5* / / \n" + " 'B-37T2' 'OPEN' 'GRUP' 1000 2* 2000.000 2* 1* 0 200000.000 5* / / \n" + " 'B-43A' 'OPEN' 'GRUP' 1200 2* 3000.000 2* 1* 0 0.000 5* / / \n" "/\n"; diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 585c74c59..b9ec05289 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -955,7 +955,6 @@ BOOST_AUTO_TEST_CASE(createDeckWithWeltArg) { " OP_1 RESV 1801.05 /\n" " OP_1 BHP 1900 /\n" " OP_1 THP 2000 /\n" - " OP_1 VFP 2100.09 /\n" " OP_1 GUID 2300.14 /\n" "/\n"; @@ -985,7 +984,6 @@ BOOST_AUTO_TEST_CASE(createDeckWithWeltArg) { BOOST_CHECK_EQUAL(prod_controls.resv_rate, 1801.05 * siFactorL); BOOST_CHECK_EQUAL(prod_controls.bhp_limit, 1900 * siFactorP); BOOST_CHECK_EQUAL(prod_controls.thp_limit, 2000 * siFactorP); - BOOST_CHECK_EQUAL(prod_controls.vfp_table_number, 2100); BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::RESV) ); diff --git a/tests/parser/WellTests.cpp b/tests/parser/WellTests.cpp index 916033f63..2b7d0be4e 100644 --- a/tests/parser/WellTests.cpp +++ b/tests/parser/WellTests.cpp @@ -19,6 +19,7 @@ #include #include +#include #define BOOST_TEST_MODULE WellTest #include @@ -493,13 +494,13 @@ namespace { } - Opm::Well::WellProductionProperties properties(const std::string& input) { + Opm::Well::WellProductionProperties properties(const std::string& input, std::optional alq_type = {}) { Opm::Parser parser; Opm::UnitSystem unit_system(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); auto deck = parser.parseString(input); const auto& record = deck.getKeyword("WCONHIST").getRecord(0); Opm::Well::WellProductionProperties hist(unit_system, "W"); - hist.handleWCONHIST(record); + hist.handleWCONHIST(alq_type, unit_system, record); return hist; @@ -545,14 +546,14 @@ namespace { } Opm::UnitSystem unit_system(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); - Opm::Well::WellProductionProperties properties(const std::string& input) + Opm::Well::WellProductionProperties properties(const std::string& input, std::optional alq_type = {}) { Opm::Parser parser; auto deck = parser.parseString(input); const auto& kwd = deck.getKeyword("WCONPROD"); const auto& record = kwd.getRecord(0); Opm::Well::WellProductionProperties pred(unit_system, "W"); - pred.handleWCONPROD("WELL", record); + pred.handleWCONPROD(alq_type, unit_system, "WELL", record); return pred; } @@ -657,7 +658,7 @@ BOOST_AUTO_TEST_CASE(WCH_Rates_NON_Defaulted_VFP) { Opm::SummaryState st(std::chrono::system_clock::now()); const Opm::Well::WellProductionProperties& p = - WCONHIST::properties(WCONHIST::all_defaulted_with_bhp_vfp_table()); + WCONHIST::properties(WCONHIST::all_defaulted_with_bhp_vfp_table(), VFPProdTable::ALQ_UNDEF); BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT)); BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT)); @@ -715,7 +716,7 @@ BOOST_AUTO_TEST_CASE(WCONPROD_ORAT_CMode) BOOST_AUTO_TEST_CASE(WCONPROD_THP_CMode) { const Opm::Well::WellProductionProperties& p = - WCONPROD::properties(WCONPROD::thp_CMODE()); + WCONPROD::properties(WCONPROD::thp_CMODE(), VFPProdTable::ALQ_UNDEF); BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::ORAT)); BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::WRAT)); @@ -737,7 +738,7 @@ BOOST_AUTO_TEST_CASE(WCONPROD_THP_CMode) BOOST_AUTO_TEST_CASE(WCONPROD_BHP_CMode) { const Opm::Well::WellProductionProperties& p = - WCONPROD::properties(WCONPROD::bhp_CMODE()); + WCONPROD::properties(WCONPROD::bhp_CMODE(), VFPProdTable::ALQ_UNDEF); BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::ORAT)); BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::WRAT)); @@ -1118,7 +1119,7 @@ DATES -- 2 / WCONPROD - 'P' 'OPEN' 'BHP' 1 2 3 2* 20. 10. 8 13 / + 'P' 'OPEN' 'BHP' 1 2 3 2* 20. 10. 0 13 / / WCONINJE