diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 874c68adc..936859ebc 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -501,6 +501,7 @@ namespace Opm // Keyword Handlers void handlePYACTION (std::shared_ptr python, const std::string& input_path, const DeckKeyword&, std::size_t currentStep); void handleGCONPROD(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors); + void handleGCONINJE(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors); void handleGLIFTOPT(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors); // Normal keyword handlers -- in KeywordHandlers.cpp diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.cpp index 0d22d0de3..719f5ece0 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.cpp @@ -33,7 +33,7 @@ namespace Action { bool ActionX::valid_keyword(const std::string& keyword) { - static std::unordered_set actionx_allowed_list = {"EXIT", "GCONPROD", "GLIFTOPT", "WELSPECS","WELOPEN", "UDQ"}; + static std::unordered_set actionx_allowed_list = {"EXIT", "GCONINJE", "GCONPROD", "GLIFTOPT", "WELSPECS","WELOPEN", "UDQ"}; return (actionx_allowed_list.find(keyword) != actionx_allowed_list.end()); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index 299038d01..fd3d14380 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -267,11 +267,17 @@ namespace { } void Schedule::handleGCONINJE(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { - for (const auto& record : handlerContext.keyword) { + auto current_step = handlerContext.currentStep; + const auto& keyword = handlerContext.keyword; + this->handleGCONINJE(keyword, current_step, parseContext, errors); + } + + void Schedule::handleGCONINJE(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors) { + for (const auto& record : keyword) { const std::string& groupNamePattern = record.getItem("GROUP").getTrimmedString(0); const auto group_names = this->groupNames(groupNamePattern); if (group_names.empty()) - invalidNamePattern(groupNamePattern, handlerContext.currentStep, parseContext, errors, handlerContext.keyword); + invalidNamePattern(groupNamePattern, current_step, parseContext, errors, keyword); const Group::InjectionCMode controlMode = Group::InjectionCModeFromString(record.getItem("CONTROL_MODE").getTrimmedString(0)); const Phase phase = get_phase( record.getItem("PHASE").getTrimmedString(0)); @@ -283,7 +289,7 @@ namespace { for (const auto& group_name : group_names) { const bool availableForGroupControl = is_free && (group_name != "FIELD"); - auto group_ptr = std::make_shared(this->getGroup(group_name, handlerContext.currentStep)); + auto group_ptr = std::make_shared(this->getGroup(group_name, current_step)); Group::GroupInjectionProperties injection; injection.phase = phase; injection.cmode = controlMode; @@ -313,9 +319,9 @@ namespace { injection.voidage_group = record.getItem("VOIDAGE_GROUP").getTrimmedString(0); if (group_ptr->updateInjection(injection)) { - this->updateGroup(std::move(group_ptr), handlerContext.currentStep); - m_events.addEvent( ScheduleEvents::GROUP_INJECTION_UPDATE , handlerContext.currentStep); - this->addWellGroupEvent(group_name, ScheduleEvents::GROUP_INJECTION_UPDATE, handlerContext.currentStep); + this->updateGroup(std::move(group_ptr), current_step); + m_events.addEvent( ScheduleEvents::GROUP_INJECTION_UPDATE , current_step); + this->addWellGroupEvent(group_name, ScheduleEvents::GROUP_INJECTION_UPDATE, current_step); } } } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index f0cee5da1..9a02f2448 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -1515,6 +1515,9 @@ private: if (keyword.name() == "UDQ") this->updateUDQ(keyword, reportStep); + if (keyword.name() == "GCONINJE") + this->handleGCONINJE(keyword, reportStep, parseContext, errors); + if (keyword.name() == "GCONPROD") this->handleGCONPROD(keyword, reportStep, parseContext, errors); diff --git a/tests/parser/ACTIONX.cpp b/tests/parser/ACTIONX.cpp index 6a7e041a2..11a24ec9e 100644 --- a/tests/parser/ACTIONX.cpp +++ b/tests/parser/ACTIONX.cpp @@ -932,19 +932,24 @@ ENDACTIO -BOOST_AUTO_TEST_CASE(Action_GCONPROD) { +BOOST_AUTO_TEST_CASE(Action_GCON) { const auto deck_string = std::string{ R"( SCHEDULE WELSPECS 'PROD1' 'G1' 1 1 10 'OIL' / + 'INJ1' 'G1' 1 1 10 'WAT' / / GCONPROD 'G1' 'ORAT' 100 / / +GCONINJE +'G1' 'WATER' 'RATE' 1000 / +/ + ACTIONX 'A' / WWCT 'OPX' > 0.75 AND / @@ -955,6 +960,10 @@ GCONPROD 'G1' 'ORAT' 200 / / +GCONINJE +'G1' 'WATER' 'RATE' 5000 / +/ + ENDACTIO TSTEP @@ -970,6 +979,9 @@ TSTEP const auto& group = sched.getGroup("G1", 0); const auto& prod = group.productionControls(st); BOOST_CHECK_CLOSE( prod.oil_target , unit_system.to_si(UnitSystem::measure::liquid_surface_rate, 100), 1e-5 ); + + const auto& inj = group.injectionControls(Phase::WATER, st); + BOOST_CHECK_CLOSE( inj.surface_max_rate, unit_system.to_si(UnitSystem::measure::liquid_surface_rate, 1000), 1e-5 ); } Action::Result action_result(true); @@ -979,9 +991,13 @@ TSTEP const auto& group = sched.getGroup("G1", 1); const auto& prod = group.productionControls(st); BOOST_CHECK_CLOSE( prod.oil_target , unit_system.to_si(UnitSystem::measure::liquid_surface_rate, 200), 1e-5 ); + + const auto& inj = group.injectionControls(Phase::WATER, st); + BOOST_CHECK_CLOSE( inj.surface_max_rate, unit_system.to_si(UnitSystem::measure::liquid_surface_rate, 5000), 1e-5 ); } } + BOOST_AUTO_TEST_CASE(GASLIFT_OPT_DECK) { const auto input = R"(-- Turns on gas lift optimization RUNSPEC