From b2341a84d61e6c12f362cb0f4c45e5f4b555e286 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 9 Jun 2021 15:15:12 +0200 Subject: [PATCH] scale well rates after group switching --- .../wells/BlackoilWellModelGeneric.cpp | 77 ++++++++++++------ .../wells/BlackoilWellModelGeneric.hpp | 4 +- opm/simulators/wells/WellGroupHelpers.cpp | 80 ++++++++++++++++++- opm/simulators/wells/WellGroupHelpers.hpp | 8 ++ 4 files changed, 142 insertions(+), 27 deletions(-) diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index ac519656d..1115a27e0 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -398,15 +398,15 @@ checkGroupConstraints(const Group& group, if (!group.hasInjectionControl(phase)) { continue; } - Group::InjectionCMode newControl = checkGroupInjectionConstraints(group, reportStepIdx, phase); - if (newControl != Group::InjectionCMode::NONE) { + const auto& check = checkGroupInjectionConstraints(group, reportStepIdx, phase); + if (check.first != Group::InjectionCMode::NONE) { return true; } } } if (group.isProductionGroup()) { - Group::ProductionCMode newControl = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger); - if (newControl != Group::ProductionCMode::NONE) + const auto& check = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger); + if (check.first != Group::ProductionCMode::NONE) { return true; } @@ -420,7 +420,7 @@ checkGroupConstraints(const Group& group, return violated; } -Group::InjectionCMode +std::pair BlackoilWellModelGeneric:: checkGroupInjectionConstraints(const Group& group, const int reportStepIdx, @@ -452,7 +452,10 @@ checkGroupInjectionConstraints(const Group& group, current_rate = comm_.sum(current_rate); if (controls.surface_max_rate < current_rate) { - return Group::InjectionCMode::RATE; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.surface_max_rate / current_rate; + return std::make_pair(Group::InjectionCMode::RATE, scale); } } } @@ -466,7 +469,10 @@ checkGroupInjectionConstraints(const Group& group, current_rate = comm_.sum(current_rate); if (controls.resv_max_rate < current_rate) { - return Group::InjectionCMode::RESV; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.resv_max_rate / current_rate; + return std::make_pair(Group::InjectionCMode::RESV, scale); } } } @@ -488,7 +494,10 @@ checkGroupInjectionConstraints(const Group& group, current_rate = comm_.sum(current_rate); if (controls.target_reinj_fraction*production_Rate < current_rate) { - return Group::InjectionCMode::REIN; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.target_reinj_fraction*production_Rate / current_rate; + return std::make_pair(Group::InjectionCMode::REIN, scale); } } } @@ -514,14 +523,17 @@ checkGroupInjectionConstraints(const Group& group, total_rate = comm_.sum(total_rate); if (controls.target_void_fraction*voidage_rate < total_rate) { - return Group::InjectionCMode::VREP; + double scale = 1.0; + if (total_rate > 1e-12) + scale = controls.target_void_fraction*voidage_rate / total_rate; + return std::make_pair(Group::InjectionCMode::VREP, scale); } } } - return Group::InjectionCMode::NONE; + return std::make_pair(Group::InjectionCMode::NONE, 1.0); } -Group::ProductionCMode +std::pair BlackoilWellModelGeneric:: checkGroupProductionConstraints(const Group& group, const int reportStepIdx, @@ -543,7 +555,10 @@ checkGroupProductionConstraints(const Group& group, current_rate = comm_.sum(current_rate); if (controls.oil_target < current_rate ) { - return Group::ProductionCMode::ORAT; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.oil_target / current_rate; + return std::make_pair(Group::ProductionCMode::ORAT, scale); } } } @@ -560,7 +575,10 @@ checkGroupProductionConstraints(const Group& group, current_rate = comm_.sum(current_rate); if (controls.water_target < current_rate ) { - return Group::ProductionCMode::WRAT; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.water_target / current_rate; + return std::make_pair(Group::ProductionCMode::WRAT, scale); } } } @@ -574,7 +592,10 @@ checkGroupProductionConstraints(const Group& group, // sum over all nodes current_rate = comm_.sum(current_rate); if (controls.gas_target < current_rate ) { - return Group::ProductionCMode::GRAT; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.gas_target / current_rate; + return std::make_pair(Group::ProductionCMode::GRAT, scale); } } } @@ -590,7 +611,10 @@ checkGroupProductionConstraints(const Group& group, current_rate = comm_.sum(current_rate); if (controls.liquid_target < current_rate ) { - return Group::ProductionCMode::LRAT; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.liquid_target / current_rate; + return std::make_pair(Group::ProductionCMode::LRAT, scale); } } } @@ -612,7 +636,10 @@ checkGroupProductionConstraints(const Group& group, current_rate = comm_.sum(current_rate); if (controls.resv_target < current_rate ) { - return Group::ProductionCMode::RESV; + double scale = 1.0; + if (current_rate > 1e-12) + scale = controls.resv_target / current_rate; + return std::make_pair(Group::ProductionCMode::RESV, scale); } } } @@ -620,7 +647,7 @@ checkGroupProductionConstraints(const Group& group, { OPM_DEFLOG_THROW(std::runtime_error, "Group " + group.name() + "PRBL control for production groups not implemented", deferred_logger); } - return Group::ProductionCMode::NONE; + return std::make_pair(Group::ProductionCMode::NONE, 1.0); } void @@ -808,6 +835,7 @@ checkGroupHigherConstraints(const Group& group, if (changed.first) { switched_groups.insert(group.name()); actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, deferred_logger); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ true, this->groupState(), this->wellState()); } } } @@ -845,6 +873,7 @@ checkGroupHigherConstraints(const Group& group, switched_groups.insert(group.name()); const auto exceed_action = group.productionControls(summaryState_).exceed_action; actionOnBrokenConstraints(group, exceed_action, Group::ProductionCMode::FLD, deferred_logger); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); } } } @@ -870,21 +899,23 @@ updateGroupIndividualControl(const Group& group, if (!group.hasInjectionControl(phase)) { continue; } - Group::InjectionCMode newControl = checkGroupInjectionConstraints(group, reportStepIdx, phase); - if (newControl != Group::InjectionCMode::NONE) + const auto& changed = checkGroupInjectionConstraints(group, reportStepIdx, phase); + if (changed.first != Group::InjectionCMode::NONE) { switched_groups.insert(group.name()); - actionOnBrokenConstraints(group, newControl, phase, deferred_logger); + actionOnBrokenConstraints(group, changed.first, phase, deferred_logger); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); } } } if (!skip && group.isProductionGroup()) { - Group::ProductionCMode newControl = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger); + const auto& changed = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger); const auto controls = group.productionControls(summaryState_); - if (newControl != Group::ProductionCMode::NONE) + if (changed.first != Group::ProductionCMode::NONE) { switched_groups.insert(group.name()); - actionOnBrokenConstraints(group, controls.exceed_action, newControl, deferred_logger); + actionOnBrokenConstraints(group, controls.exceed_action, changed.first, deferred_logger); + WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState()); } } diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index 6e1d18a23..1a1dcde87 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -286,10 +286,10 @@ protected: const int reportStepIdx, DeferredLogger& deferred_logger) const; - Group::InjectionCMode checkGroupInjectionConstraints(const Group& group, + std::pair checkGroupInjectionConstraints(const Group& group, const int reportStepIdx, const Phase& phase) const; - Group::ProductionCMode checkGroupProductionConstraints(const Group& group, + std::pair checkGroupProductionConstraints(const Group& group, const int reportStepIdx, DeferredLogger& deferred_logger) const; diff --git a/opm/simulators/wells/WellGroupHelpers.cpp b/opm/simulators/wells/WellGroupHelpers.cpp index b2eac79ca..f48974d8b 100644 --- a/opm/simulators/wells/WellGroupHelpers.cpp +++ b/opm/simulators/wells/WellGroupHelpers.cpp @@ -423,6 +423,76 @@ namespace WellGroupHelpers group_state.update_production_reduction_rates(group.name(), groupTargetReduction); } + void updateWellRatesFromGroupTargetScale(const double scale, + const Group& group, + const Schedule& schedule, + const int reportStepIdx, + bool isInjector, + const GroupState& group_state, + WellState& wellState) { + for (const std::string& groupName : group.groups()) { + bool individual_control = false; + if (isInjector) { + const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS}; + for (Phase phase : all) { + const Group::InjectionCMode& currentGroupControl + = group_state.injection_control(groupName, phase); + individual_control = individual_control || (currentGroupControl != Group::InjectionCMode::FLD + && currentGroupControl != Group::InjectionCMode::NONE); + } + } else { + const Group::ProductionCMode& currentGroupControl = group_state.production_control(groupName); + individual_control = (currentGroupControl != Group::ProductionCMode::FLD + && currentGroupControl != Group::ProductionCMode::NONE); + } + if (!individual_control) { + const Group& groupTmp = schedule.getGroup(groupName, reportStepIdx); + updateWellRatesFromGroupTargetScale(scale, groupTmp, schedule, reportStepIdx, isInjector, group_state, wellState); + } + } + + const int np = wellState.numPhases(); + for (const std::string& wellName : group.wells()) { + const auto& wellTmp = schedule.getWell(wellName, reportStepIdx); + + if (wellTmp.isProducer() && isInjector) + continue; + + if (wellTmp.isInjector() && !isInjector) + continue; + + if (wellTmp.getStatus() == Well::Status::SHUT) + continue; + + const auto& end = wellState.wellMap().end(); + const auto& it = wellState.wellMap().find(wellName); + if (it == end) // the well is not found + continue; + + int well_index = it->second[0]; + + if (! wellState.wellIsOwned(well_index, wellName) ) // Only sum once + { + continue; + } + + // scale rates + if (isInjector) { + if (wellState.currentInjectionControl(well_index) == Well::InjectorCMode::GRUP) + for (int phase = 0; phase < np; phase++) { + wellState.wellRates(well_index)[phase] *= scale; + } + } else { + if (wellState.currentProductionControl(well_index) == Well::ProducerCMode::GRUP) + for (int phase = 0; phase < np; phase++) { + wellState.wellRates(well_index)[phase] *= scale; + } + } + } + + + } + void updateVREPForGroups(const Group& group, const Schedule& schedule, @@ -1100,7 +1170,10 @@ namespace WellGroupHelpers } // Avoid negative target rates comming from too large local reductions. const double target_rate = std::max(1e-12, target / efficiencyFactorInclGroup); - return std::make_pair(current_rate > target_rate, target_rate / current_rate); + double scale = 1.0; + if (current_rate > 1e-12) + scale = target_rate / current_rate; + return std::make_pair(current_rate > target_rate, scale); } std::pair checkGroupConstraintsInj(const std::string& name, @@ -1224,7 +1297,10 @@ namespace WellGroupHelpers } // Avoid negative target rates comming from too large local reductions. const double target_rate = std::max(1e-12, target / efficiencyFactorInclGroup); - return std::make_pair(current_rate > target_rate, target_rate / current_rate); + double scale = 1.0; + if (current_rate > 1e-12) + scale = target_rate / current_rate; + return std::make_pair(current_rate > target_rate, scale); } template diff --git a/opm/simulators/wells/WellGroupHelpers.hpp b/opm/simulators/wells/WellGroupHelpers.hpp index d723e57b7..a8f958857 100644 --- a/opm/simulators/wells/WellGroupHelpers.hpp +++ b/opm/simulators/wells/WellGroupHelpers.hpp @@ -158,6 +158,14 @@ namespace WellGroupHelpers WellState& wellState, GroupState& group_state); + void updateWellRatesFromGroupTargetScale(const double scale, + const Group& group, + const Schedule& schedule, + const int reportStepIdx, + bool isInjector, + const GroupState& group_state, + WellState& wellState); + void updateREINForGroups(const Group& group, const Schedule& schedule, const int reportStepIdx,