diff --git a/opm/output/eclipse/VectorItems/group.hpp b/opm/output/eclipse/VectorItems/group.hpp index 6daa8a740..3cd93cb7f 100644 --- a/opm/output/eclipse/VectorItems/group.hpp +++ b/opm/output/eclipse/VectorItems/group.hpp @@ -48,10 +48,12 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems waterResRateLimit = 16, // Group's water reservoir volume injection rate target/limit waterReinjectionLimit = 17, // Group's water reinjection fraction target/limit waterVoidageLimit = 18, // Group's water voidage injection fraction target/limit + waterGuideRate = 19, gasSurfRateLimit = 20, // Group's gas surface volume injection rate target/limit gasResRateLimit = 21, // Group's gas reservoir volume injection rate target/limit gasReinjectionLimit = 22, // Group's gas reinjection fraction target/limit gasVoidageLimit = 23, // Group's gas voidage injection fraction target/limit + gasGuideRate = 24, }; } // SGroup @@ -69,9 +71,11 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems WInjActiveCMode = 16, WInjHighLevCtrl = 17, GConInjeWInjCMode = 19, + GConInjeWaterGuideRateMode = 20, GInjActiveCMode = 21, GInjHighLevCtrl = 22, GConInjeGInjCMode = 24, + GConInjeGasGuideRateMode = 25, GroupType = 26, GroupLevel = 27, ParentGroup = 28, diff --git a/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp b/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp index 0aa113d5f..8983da591 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp @@ -125,6 +125,7 @@ enum class GuideRateInjTarget { }; static GuideRateInjTarget GuideRateInjTargetFromString( const std::string& stringValue ); static GuideRateInjTarget GuideRateInjTargetFromInt(int ecl_id); +static int GuideRateInjTargetToInt(GuideRateInjTarget target); struct GroupInjectionProperties { diff --git a/src/opm/output/eclipse/AggregateGroupData.cpp b/src/opm/output/eclipse/AggregateGroupData.cpp index 1488767fa..aa90fd9df 100644 --- a/src/opm/output/eclipse/AggregateGroupData.cpp +++ b/src/opm/output/eclipse/AggregateGroupData.cpp @@ -483,17 +483,18 @@ void productionGroup(const Opm::Schedule& sched, } } -std::tuple injectionGroup(const Opm::Schedule& sched, - const Opm::Group& group, - const std::size_t simStep, - const Opm::SummaryState& sumState, - const Opm::Phase phase) +std::tuple injectionGroup(const Opm::Schedule& sched, + const Opm::Group& group, + const std::size_t simStep, + const Opm::SummaryState& sumState, + const Opm::Phase phase) { const bool is_field = group.name() == "FIELD"; auto group_parent_list = groupParentSeqIndex(sched, group, simStep); int high_level_ctrl = 0; int current_cmode = 0; int gconinje_cmode = 0; + int guide_rate_def = 0; const std::string field_key = (phase == Opm::Phase::WATER) ? "FMCTW" : "FMCTG"; const std::string group_key = (phase == Opm::Phase::WATER) ? "GMCTW" : "GMCTG"; @@ -502,13 +503,13 @@ std::tuple injectionGroup(const Opm::Schedule& sched, if (group.hasInjectionControl(phase)) { const auto& injection_controls = group.injectionControls(phase, sumState); - const auto& guide_rate_def = injection_controls.guide_rate_def; const auto& cur_inj_ctrl = group.name() == "FIELD" ? static_cast(sumState.get(field_key, -1)) : static_cast(sumState.get_group_var(group.name(), group_key, -1)); Opm::Group::InjectionCMode active_cmode = Opm::Group::InjectionCModeFromInt(cur_inj_ctrl); const auto& deck_cmode = (group.hasInjectionControl(phase)) ? injection_controls.cmode : Opm::Group::InjectionCMode::NONE; const auto& cgroup = injectionControlGroup(sched, sumState, group, group_key, field_key, simStep); const auto& group_control_available = group.injectionGroupControlAvailable(phase); + const auto& deck_guide_rate_def = injection_controls.guide_rate_def; // group is available for higher level control, but is currently constrained by own limits high_level_ctrl = -1; @@ -523,7 +524,7 @@ std::tuple injectionGroup(const Opm::Schedule& sched, if ((deck_cmode != Opm::Group::InjectionCMode::FLD) && (deck_cmode != Opm::Group::InjectionCMode::NONE)) { high_level_ctrl = cgroup->insert_index(); } else { - if (guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE) { + if (deck_guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE) { if (deck_cmode == Opm::Group::InjectionCMode::FLD) { high_level_ctrl = 1; } else if ((deck_cmode == Opm::Group::InjectionCMode::NONE) && group_control_available) { @@ -539,7 +540,7 @@ std::tuple injectionGroup(const Opm::Schedule& sched, } } } else { - if ((active_cmode == Opm::Group::InjectionCMode::NONE) && (guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE)) { + if ((active_cmode == Opm::Group::InjectionCMode::NONE) && (deck_guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE)) { //group is directly under higher level controlGroup if (deck_cmode == Opm::Group::InjectionCMode::FLD) { high_level_ctrl = 1; @@ -549,10 +550,11 @@ std::tuple injectionGroup(const Opm::Schedule& sched, } } + guide_rate_def = Opm::Group::GuideRateInjTargetToInt(deck_guide_rate_def); gconinje_cmode = Opm::Group::InjectionCMode2Int(deck_cmode); if (cgroup && (cgroup->name() != group.name()) && (group.getGroupType() != Opm::Group::GroupType::NONE)) { auto cgroup_control = (cgroup->name() == "FIELD") ? static_cast(sumState.get(field_key, 0)) : static_cast(sumState.get_group_var(cgroup->name(), group_key, 0)); - current_cmode = (guide_rate_def != Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE) ? cgroup_control : 0; + current_cmode = (deck_guide_rate_def != Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE) ? cgroup_control : 0; } else { current_cmode = cur_inj_ctrl; } @@ -565,7 +567,7 @@ std::tuple injectionGroup(const Opm::Schedule& sched, // special treatment of group "FIELD" if (is_field) high_level_ctrl = 0; - return {high_level_ctrl, current_cmode, gconinje_cmode}; + return {high_level_ctrl, current_cmode, gconinje_cmode, guide_rate_def}; } @@ -602,16 +604,20 @@ void injectionGroup(const Opm::Schedule& sched, } { - auto [high_level_ctrl, active_cmode, gconinje_cmode] = injectionGroup(sched, group, simStep, sumState, Opm::Phase::WATER); - iGrp[nwgmax + IGroup::WInjHighLevCtrl] = high_level_ctrl; - iGrp[nwgmax + IGroup::WInjActiveCMode] = active_cmode; - iGrp[nwgmax + IGroup::GConInjeWInjCMode] = gconinje_cmode; + if (group.hasInjectionControl(Opm::Phase::WATER)) { + auto [high_level_ctrl, active_cmode, gconinje_cmode, guide_rate_def] = injectionGroup(sched, group, simStep, sumState, Opm::Phase::WATER); + iGrp[nwgmax + IGroup::WInjHighLevCtrl] = high_level_ctrl; + iGrp[nwgmax + IGroup::WInjActiveCMode] = active_cmode; + iGrp[nwgmax + IGroup::GConInjeWInjCMode] = gconinje_cmode; + iGrp[nwgmax + IGroup::GConInjeWaterGuideRateMode] = guide_rate_def; + } } { - auto [high_level_ctrl, active_cmode, gconinje_cmode] = injectionGroup(sched, group, simStep, sumState, Opm::Phase::GAS); + auto [high_level_ctrl, active_cmode, gconinje_cmode, guide_rate_def] = injectionGroup(sched, group, simStep, sumState, Opm::Phase::GAS); iGrp[nwgmax + IGroup::GInjHighLevCtrl] = high_level_ctrl; iGrp[nwgmax + IGroup::GInjActiveCMode] = active_cmode; iGrp[nwgmax + IGroup::GConInjeGInjCMode] = gconinje_cmode; + iGrp[nwgmax + IGroup::GConInjeGasGuideRateMode] = guide_rate_def; } } @@ -877,6 +883,8 @@ void staticContrib(const Opm::Group& group, sGrp[Isi::gasVoidageLimit] = inj_cntl.target_void_fraction; sGrp[68] = sGrp[Isi::gasVoidageLimit]; } + + sGrp[Isi::waterGuideRate] = inj_cntl.guide_rate; } if (group.hasInjectionControl(Opm::Phase::WATER)) { @@ -897,6 +905,8 @@ void staticContrib(const Opm::Group& group, sGrp[Isi::waterVoidageLimit] = inj_cntl.target_void_fraction; sGrp[64] = sGrp[Isi::waterVoidageLimit]; } + + sGrp[Isi::waterGuideRate] = inj_cntl.guide_rate; } if (group.hasInjectionControl(Opm::Phase::OIL)) { diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp index d2ba72ebe..70e11da94 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp @@ -1119,6 +1119,22 @@ Group::GuideRateInjTarget Group::GuideRateInjTargetFromString( const std::string return GuideRateInjTarget::NO_GUIDE_RATE; } +int Group::GuideRateInjTargetToInt(GuideRateInjTarget target) { + switch (target) { + case GuideRateInjTarget::RATE: + return 1; + case GuideRateInjTarget::RESV: + return 2; + case GuideRateInjTarget::VOID: + return 3; + case GuideRateInjTarget::NETV: + return 4; + default: + return 0; + } +} + + Group::GuideRateProdTarget Group::GuideRateProdTargetFromString( const std::string& stringValue ) { if (stringValue == "OIL") return GuideRateProdTarget::OIL; diff --git a/tests/test_AggregateGroupData.cpp b/tests/test_AggregateGroupData.cpp index e35025c5d..f5fded4ea 100644 --- a/tests/test_AggregateGroupData.cpp +++ b/tests/test_AggregateGroupData.cpp @@ -809,7 +809,7 @@ BOOST_AUTO_TEST_CASE (Declared_Group_Data_2) const auto& iGrp = agrpd.getIGroup(); BOOST_CHECK_EQUAL(iGrp[start + nwgmax + 5] , 2); // group available for higher level production control - BOOST_CHECK_EQUAL(iGrp[start + nwgmax + 17] , 1); // group available for higher level water injection control + BOOST_CHECK_EQUAL(iGrp[start + nwgmax + 17] , 0); // group available for higher level water injection control BOOST_CHECK_EQUAL(iGrp[start + nwgmax + 22] , -1); // group available for higher level gas injection control BOOST_CHECK_EQUAL(iGrp[start + nwgmax + 39] , 3); // groups sequence number in the external networt defined