Merge pull request #2714 from jalvestad/rstfieldctrl-r

Improve Eclipse-compatible restart file. Output correct Guiderate control and FIELD level control
This commit is contained in:
Bård Skaflestad 2021-09-29 17:07:08 +02:00 committed by GitHub
commit 7ecbf4725a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 151 additions and 94 deletions

View File

@ -81,6 +81,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
Water = 2, Water = 2,
Gas = 3, Gas = 3,
Liquid = 4, Liquid = 4,
Resv = 6, // need to be verified!!!
Potn = 7, Potn = 7,
Form = 8, Form = 8,
Comb = 9, Comb = 9,

View File

@ -16,6 +16,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <fmt/format.h>
#include <opm/output/eclipse/AggregateGroupData.hpp> #include <opm/output/eclipse/AggregateGroupData.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp> #include <opm/output/eclipse/WriteRestartHelpers.hpp>
@ -61,6 +62,38 @@ int nwgmax(const std::vector<int>& inteHead)
{ {
return inteHead[Opm::RestartIO::Helpers::VectorItems::NWGMAX]; return inteHead[Opm::RestartIO::Helpers::VectorItems::NWGMAX];
} }
namespace value = ::Opm::RestartIO::Helpers::VectorItems::IGroup::Value;
value::GuideRateMode GuideRateModeFromGuideRateProdTarget(Opm::Group::GuideRateProdTarget grpt) {
switch (grpt) {
case Opm::Group::GuideRateProdTarget::OIL:
return value::GuideRateMode::Oil;
case Opm::Group::GuideRateProdTarget::WAT:
return value::GuideRateMode::Water;
case Opm::Group::GuideRateProdTarget::GAS:
return value::GuideRateMode::Gas;
case Opm::Group::GuideRateProdTarget::LIQ:
return value::GuideRateMode::Liquid;
case Opm::Group::GuideRateProdTarget::RES:
return value::GuideRateMode::Resv;
case Opm::Group::GuideRateProdTarget::COMB:
return value::GuideRateMode::Comb;
case Opm::Group::GuideRateProdTarget::WGA:
return value::GuideRateMode::None;
case Opm::Group::GuideRateProdTarget::CVAL:
return value::GuideRateMode::None;
case Opm::Group::GuideRateProdTarget::INJV:
return value::GuideRateMode::None;
case Opm::Group::GuideRateProdTarget::POTN:
return value::GuideRateMode::Potn;
case Opm::Group::GuideRateProdTarget::FORM:
return value::GuideRateMode::Form;
case Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE:
return value::GuideRateMode::None;
default:
throw std::logic_error(fmt::format("Not recognized value: {} for GuideRateProdTarget", grpt));
}
}
template <typename GroupOp> template <typename GroupOp>
@ -211,11 +244,23 @@ std::optional<Opm::Group> controlGroup(const Opm::Schedule& sched,
const Opm::Group& group, const Opm::Group& group,
const std::size_t simStep) { const std::size_t simStep) {
auto current = group; auto current = group;
while (current.name() != "FIELD") { bool isField = false;
current = sched.getGroup(current.parent(), simStep); double cur_prod_ctrl= 0.;
auto cur_prod_ctrl = sumState.get_group_var(current.name(), "GMCTP", 0); while (!isField) {
if (cur_prod_ctrl > 0) if (current.name() != "FIELD") {
cur_prod_ctrl = sumState.get_group_var(current.name(), "GMCTP", 0);
} else {
cur_prod_ctrl = sumState.get("FMCTP", 0);
}
if (cur_prod_ctrl > 0) {
return current; return current;
}
if (current.name() != "FIELD") {
current = sched.getGroup(current.parent(), simStep);
}
else {
isField = true;
}
} }
return {}; return {};
} }
@ -224,23 +269,35 @@ std::optional<Opm::Group> controlGroup(const Opm::Schedule& sched,
std::optional<Opm::Group> injectionControlGroup(const Opm::Schedule& sched, std::optional<Opm::Group> injectionControlGroup(const Opm::Schedule& sched,
const Opm::SummaryState& sumState, const Opm::SummaryState& sumState,
const Opm::Group& group, const Opm::Group& group,
const std::string curInjCtrlKey, const std::string curGroupInjCtrlKey,
const std::string curFieldInjCtrlKey,
const size_t simStep) const size_t simStep)
// //
// returns group of higher (highest) level group with active control different from (NONE or FLD) // returns group of higher (highest) level group with active control different from (NONE or FLD)
// //
{ {
auto current = group; auto current = group;
while (current.name() != "FIELD" ) { bool isField = false;
current = sched.getGroup(current.parent(), simStep); double cur_inj_ctrl = 0.;
if (sumState.has_group_var(current.name(), curInjCtrlKey)) { while (!isField) {
auto cur_inj_ctrl = sumState.get_group_var(current.name(), curInjCtrlKey); if (current.name() != "FIELD") {
if (cur_inj_ctrl > 0) return current; cur_inj_ctrl = sumState.get_group_var(current.name(), curGroupInjCtrlKey, 0.);
} else { } else {
cur_inj_ctrl = sumState.get(curFieldInjCtrlKey, 0.);
}
if (cur_inj_ctrl > 0) {
return current;
}
#if ENABLE_GCNTL_DEBUG_OUTPUT #if ENABLE_GCNTL_DEBUG_OUTPUT
else {
std::cout << "Current injection group control: " << curInjCtrlKey std::cout << "Current injection group control: " << curInjCtrlKey
<< " is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl; << " is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl;
}
#endif // ENABLE_GCNTL_DEBUG_OUTPUT #endif // ENABLE_GCNTL_DEBUG_OUTPUT
if (current.name() != "FIELD") {
current = sched.getGroup(current.parent(), simStep);
} else {
isField = true;
} }
} }
return {}; return {};
@ -327,7 +384,7 @@ void productionGroup(const Opm::Schedule& sched,
const auto& cgroup = controlGroup(sched, sumState, group, simStep); const auto& cgroup = controlGroup(sched, sumState, group, simStep);
const auto& deck_cmode = group.prod_cmode(); const auto& deck_cmode = group.prod_cmode();
if (cgroup && (group.getGroupType() != Opm::Group::GroupType::NONE)) { if (cgroup && (cgroup->name() != group.name()) && (group.getGroupType() != Opm::Group::GroupType::NONE)) {
auto cgroup_control = (cgroup->name() == "FIELD") ? static_cast<int>(sumState.get("FMCTP", 0)) : static_cast<int>(sumState.get_group_var(cgroup->name(), "GMCTP", 0)); auto cgroup_control = (cgroup->name() == "FIELD") ? static_cast<int>(sumState.get("FMCTP", 0)) : static_cast<int>(sumState.get_group_var(cgroup->name(), "GMCTP", 0));
iGrp[nwgmax + IGroup::ProdActiveCMode] iGrp[nwgmax + IGroup::ProdActiveCMode]
= (prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE) ? cgroup_control : 0; = (prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE) ? cgroup_control : 0;
@ -341,7 +398,7 @@ void productionGroup(const Opm::Schedule& sched,
} }
iGrp[nwgmax + 9] = iGrp[nwgmax + IGroup::ProdActiveCMode]; iGrp[nwgmax + 9] = iGrp[nwgmax + IGroup::ProdActiveCMode];
iGrp[nwgmax + IGroup::GuideRateDef] = Value::GuideRateMode::None; iGrp[nwgmax + IGroup::GuideRateDef] = GuideRateModeFromGuideRateProdTarget(prod_guide_rate_def);
// Set iGrp for [nwgmax + IGroup::ExceedAction] // Set iGrp for [nwgmax + IGroup::ExceedAction]
/* /*
@ -381,7 +438,7 @@ void productionGroup(const Opm::Schedule& sched,
break; break;
case Opm::Group::ProductionCMode::FLD: case Opm::Group::ProductionCMode::FLD:
if (cgroup && (prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) { if (cgroup && (prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::GuideRateDef] = Value::GuideRateMode::Form; iGrp[nwgmax + IGroup::GuideRateDef] = GuideRateModeFromGuideRateProdTarget(prod_guide_rate_def);
} }
iGrp[nwgmax + IGroup::ExceedAction] = (p_exceed_act == Opm::Group::ExceedAction::NONE) ? 4 : 4; iGrp[nwgmax + IGroup::ExceedAction] = (p_exceed_act == Opm::Group::ExceedAction::NONE) ? 4 : 4;
break; break;
@ -392,7 +449,7 @@ void productionGroup(const Opm::Schedule& sched,
// Start branching for determining iGrp[nwgmax + IGroup::ProdHighLevCtrl] // Start branching for determining iGrp[nwgmax + IGroup::ProdHighLevCtrl]
// use default value if group is not available for group control // use default value if group is not available for group control
if (group.getGroupType() == Opm::Group::GroupType::NONE) { if (group.getGroupType() == Opm::Group::GroupType::NONE || group.getGroupType() == Opm::Group::GroupType::INJECTION) {
if (is_field) { if (is_field) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 0; iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 0;
} else { } else {
@ -402,36 +459,38 @@ void productionGroup(const Opm::Schedule& sched,
return; return;
} }
if (cgroup && cgroup->name() == "FIELD") if (group.name() == "FIELD" ) {
throw std::logic_error("Got cgroup == FIELD - uncertain logic");
// group is available for higher level control, but is currently constrained by own limits
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = -1;
if ((deck_cmode != Opm::Group::ProductionCMode::FLD) && !group.productionGroupControlAvailable()) {
//group is not free to respond to higher level control)
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 0; iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 0;
} else if (cgroup && ((active_cmode == Opm::Group::ProductionCMode::FLD) || (active_cmode == Opm::Group::ProductionCMode::NONE))) { } else {
//a higher level group control is active constraint // group is available for higher level control, but is currently constrained by own limits
if ((deck_cmode != Opm::Group::ProductionCMode::FLD) && (deck_cmode != Opm::Group::ProductionCMode::NONE)) { iGrp[nwgmax + IGroup::ProdHighLevCtrl] = -1;
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = cgroup->insert_index(); if ((deck_cmode != Opm::Group::ProductionCMode::FLD) && !group.productionGroupControlAvailable()) {
} else if ((deck_cmode == Opm::Group::ProductionCMode::FLD) && (prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) { //group is not free to respond to higher level control)
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = cgroup->insert_index(); iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 0;
} else if ((deck_cmode == Opm::Group::ProductionCMode::NONE) && group.productionGroupControlAvailable() && } else if (cgroup && ((active_cmode == Opm::Group::ProductionCMode::FLD) || (active_cmode == Opm::Group::ProductionCMode::NONE))) {
(prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) { //a higher level group control is active constraint
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = cgroup->insert_index(); if ((deck_cmode != Opm::Group::ProductionCMode::FLD) && (deck_cmode != Opm::Group::ProductionCMode::NONE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = cgroup->insert_index();
} else if ((deck_cmode == Opm::Group::ProductionCMode::FLD) && (prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = cgroup->insert_index();
} else if ((deck_cmode == Opm::Group::ProductionCMode::NONE) && group.productionGroupControlAvailable() &&
(prod_guide_rate_def != Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = cgroup->insert_index();
//group is directly under higher level controlGroup
} else if ((deck_cmode == Opm::Group::ProductionCMode::FLD) && (prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1;
} else if ((deck_cmode == Opm::Group::ProductionCMode::NONE) && group.productionGroupControlAvailable() &&
(prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1;
}
} else if (!cgroup && active_cmode == Opm::Group::ProductionCMode::NONE) {
//group is directly under higher level controlGroup //group is directly under higher level controlGroup
} else if ((deck_cmode == Opm::Group::ProductionCMode::FLD) && (prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) { if ((deck_cmode == Opm::Group::ProductionCMode::FLD) && (prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1; iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1;
} else if ((deck_cmode == Opm::Group::ProductionCMode::NONE) && group.productionGroupControlAvailable() && } else if ((deck_cmode == Opm::Group::ProductionCMode::NONE) && group.productionGroupControlAvailable() &&
(prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) { (prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1; iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1;
} }
} else if (!cgroup && active_cmode == Opm::Group::ProductionCMode::NONE) {
//group is directly under higher level controlGroup
if ((deck_cmode == Opm::Group::ProductionCMode::FLD) && (prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1;
} else if ((deck_cmode == Opm::Group::ProductionCMode::NONE) && group.productionGroupControlAvailable() &&
(prod_guide_rate_def == Opm::Group::GuideRateProdTarget::NO_GUIDE_RATE)) {
iGrp[nwgmax + IGroup::ProdHighLevCtrl] = 1;
} }
} }
} }
@ -444,7 +503,7 @@ std::tuple<int, int, int> injectionGroup(const Opm::Schedule& sched,
{ {
const bool is_field = group.name() == "FIELD"; const bool is_field = group.name() == "FIELD";
auto group_parent_list = groupParentSeqIndex(sched, group, simStep); auto group_parent_list = groupParentSeqIndex(sched, group, simStep);
int high_level_ctrl; int high_level_ctrl = 0;
int current_cmode = 0; int current_cmode = 0;
int gconinje_cmode = 0; int gconinje_cmode = 0;
@ -454,66 +513,60 @@ std::tuple<int, int, int> injectionGroup(const Opm::Schedule& sched,
// WATER INJECTION GROUP CONTROL // WATER INJECTION GROUP CONTROL
if (group.hasInjectionControl(phase)) { if (group.hasInjectionControl(phase)) {
if (is_field) { const auto& injection_controls = group.injectionControls(phase, sumState);
//set value for the group's availability for higher level control for injection const auto& guide_rate_def = injection_controls.guide_rate_def;
const auto& cur_inj_ctrl = group.name() == "FIELD" ? static_cast<int>(sumState.get(field_key, -1)) : static_cast<int>(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);
// group is available for higher level control, but is currently constrained by own limits
high_level_ctrl = -1;
if ((deck_cmode != Opm::Group::InjectionCMode::FLD) && !group_control_available) {
//group is not free to respond to higher level control)
high_level_ctrl = 0; high_level_ctrl = 0;
} else { }
const auto& injection_controls = group.injectionControls(phase, sumState); if (cgroup) {
const auto& guide_rate_def = injection_controls.guide_rate_def; if ((active_cmode == Opm::Group::InjectionCMode::FLD) || (active_cmode == Opm::Group::InjectionCMode::NONE)) {
const auto& cur_inj_ctrl = group.name() == "FIELD" ? static_cast<int>(sumState.get(field_key, -1)) : static_cast<int>(sumState.get_group_var(group.name(), group_key, -1)); //a higher level group control is active constraint
Opm::Group::InjectionCMode active_cmode = Opm::Group::InjectionCModeFromInt(cur_inj_ctrl); if ((deck_cmode != Opm::Group::InjectionCMode::FLD) && (deck_cmode != Opm::Group::InjectionCMode::NONE)) {
const auto& deck_cmode = (group.hasInjectionControl(phase)) high_level_ctrl = cgroup->insert_index();
? injection_controls.cmode : Opm::Group::InjectionCMode::NONE; } else {
const auto& cgroup = injectionControlGroup(sched, sumState, group, group_key, simStep); if (guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE) {
const auto& group_control_available = group.injectionGroupControlAvailable(phase); if (deck_cmode == Opm::Group::InjectionCMode::FLD) {
high_level_ctrl = 1;
// group is available for higher level control, but is currently constrained by own limits } else if ((deck_cmode == Opm::Group::InjectionCMode::NONE) && group_control_available) {
high_level_ctrl = -1; high_level_ctrl = 1;
if ((deck_cmode != Opm::Group::InjectionCMode::FLD) && !group_control_available) { }
//group is not free to respond to higher level control)
high_level_ctrl = 0;
}
if (cgroup) {
if ((active_cmode == Opm::Group::InjectionCMode::FLD) || (active_cmode == Opm::Group::InjectionCMode::NONE)) {
//a higher level group control is active constraint
if ((deck_cmode != Opm::Group::InjectionCMode::FLD) && (deck_cmode != Opm::Group::InjectionCMode::NONE)) {
high_level_ctrl = cgroup->insert_index();
} else { } else {
if (guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE) { if (deck_cmode == Opm::Group::InjectionCMode::FLD) {
if (deck_cmode == Opm::Group::InjectionCMode::FLD) { high_level_ctrl = cgroup->insert_index();
high_level_ctrl = 1; } else if ((deck_cmode == Opm::Group::InjectionCMode::NONE) && group_control_available) {
} else if ((deck_cmode == Opm::Group::InjectionCMode::NONE) && group_control_available) { high_level_ctrl = cgroup->insert_index();
high_level_ctrl = 1;
}
} else {
if (deck_cmode == Opm::Group::InjectionCMode::FLD) {
high_level_ctrl = cgroup->insert_index();
} else if ((deck_cmode == Opm::Group::InjectionCMode::NONE) && group_control_available) {
high_level_ctrl = cgroup->insert_index();
}
} }
} }
} }
} else { }
if ((active_cmode == Opm::Group::InjectionCMode::NONE) && (guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE)) { } else {
//group is directly under higher level controlGroup if ((active_cmode == Opm::Group::InjectionCMode::NONE) && (guide_rate_def == Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE)) {
if (deck_cmode == Opm::Group::InjectionCMode::FLD) { //group is directly under higher level controlGroup
high_level_ctrl = 1; if (deck_cmode == Opm::Group::InjectionCMode::FLD) {
} else if ((deck_cmode == Opm::Group::InjectionCMode::NONE) && group_control_available) { high_level_ctrl = 1;
high_level_ctrl = 1; } else if ((deck_cmode == Opm::Group::InjectionCMode::NONE) && group_control_available) {
} high_level_ctrl = 1;
} }
} }
}
gconinje_cmode = Opm::Group::InjectionCMode2Int(deck_cmode); gconinje_cmode = Opm::Group::InjectionCMode2Int(deck_cmode);
if (cgroup && (group.getGroupType() != Opm::Group::GroupType::NONE)) { if (cgroup && (cgroup->name() != group.name()) && (group.getGroupType() != Opm::Group::GroupType::NONE)) {
auto cgroup_control = (cgroup->name() == "FIELD") ? static_cast<int>(sumState.get(field_key, 0)) : static_cast<int>(sumState.get_group_var(cgroup->name(), group_key, 0)); auto cgroup_control = (cgroup->name() == "FIELD") ? static_cast<int>(sumState.get(field_key, 0)) : static_cast<int>(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 = (guide_rate_def != Opm::Group::GuideRateInjTarget::NO_GUIDE_RATE) ? cgroup_control : 0;
} else { } else {
current_cmode = cur_inj_ctrl; current_cmode = cur_inj_ctrl;
}
} }
} }
else { else {
@ -521,6 +574,9 @@ std::tuple<int, int, int> injectionGroup(const Opm::Schedule& sched,
high_level_ctrl = (groupCurrentlyInjectionControllable(sched, sumState, group, phase, simStep) ) ? 1 : -1; high_level_ctrl = (groupCurrentlyInjectionControllable(sched, sumState, group, phase, simStep) ) ? 1 : -1;
} }
// 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};
} }