From 0df3a96fa6e3195cb27b3448b8bd1612b631127c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 22 Apr 2020 11:16:20 +0200 Subject: [PATCH] Fix how group rate reductions work. --- .../wells/BlackoilWellModel_impl.hpp | 4 +-- opm/simulators/wells/WellGroupHelpers.cpp | 35 +++++++++++++++---- opm/simulators/wells/WellGroupHelpers.hpp | 1 + opm/simulators/wells/WellInterface_impl.hpp | 9 +++-- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index 4c5250d8c..335053ffe 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -1233,9 +1233,9 @@ namespace Opm { // the group target reduction rates needs to be update since wells may have swicthed to/from GRUP control // Currently the group target reduction does not honor NUPCOL. TODO: is that true? std::vector groupTargetReduction(numPhases(), 0.0); - WellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ false, phase_usage_, well_state_nupcol_, well_state_, groupTargetReduction); + WellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ false, phase_usage_, *guideRate_, well_state_nupcol_, well_state_, groupTargetReduction); std::vector groupTargetReductionInj(numPhases(), 0.0); - WellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ true, phase_usage_, well_state_nupcol_, well_state_, groupTargetReductionInj); + WellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ true, phase_usage_, *guideRate_, well_state_nupcol_, well_state_, groupTargetReductionInj); const double simulationTime = ebosSimulator_.time(); std::vector pot(numPhases(), 0.0); diff --git a/opm/simulators/wells/WellGroupHelpers.cpp b/opm/simulators/wells/WellGroupHelpers.cpp index 08c7ce9dd..df03d8d13 100644 --- a/opm/simulators/wells/WellGroupHelpers.cpp +++ b/opm/simulators/wells/WellGroupHelpers.cpp @@ -194,6 +194,7 @@ namespace WellGroupHelpers const int reportStepIdx, const bool isInjector, const PhaseUsage& pu, + const GuideRate& guide_rate, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState, std::vector& groupTargetReduction) @@ -202,8 +203,15 @@ namespace WellGroupHelpers for (const std::string& subGroupName : group.groups()) { std::vector subGroupTargetReduction(np, 0.0); const Group& subGroup = schedule.getGroup(subGroupName, reportStepIdx); - updateGroupTargetReduction( - subGroup, schedule, reportStepIdx, isInjector, pu, wellStateNupcol, wellState, subGroupTargetReduction); + updateGroupTargetReduction(subGroup, + schedule, + reportStepIdx, + isInjector, + pu, + guide_rate, + wellStateNupcol, + wellState, + subGroupTargetReduction); // accumulate group contribution from sub group if (isInjector) { @@ -243,13 +251,21 @@ namespace WellGroupHelpers += sumWellRates(subGroup, schedule, wellStateNupcol, reportStepIdx, phase, isInjector); } } else { - // or accumulate directly from the wells if controled from its parents - for (int phase = 0; phase < np; phase++) { - // groupTargetReduction[phase] += subGroupTargetReduction[phase]; + // The subgroup may participate in group control. + if (!guide_rate.has(subGroupName)) { + // Accumulate from this subgroup only if no group guide rate is set for it. + for (int phase = 0; phase < np; phase++) { + groupTargetReduction[phase] += subGroupTargetReduction[phase]; + } } } } } + + + + + for (const std::string& wellName : group.wells()) { const auto& wellTmp = schedule.getWell(wellName, reportStepIdx); @@ -762,7 +778,7 @@ namespace WellGroupHelpers // We are a group, with default guide rate. // Compute guide rate by accumulating our children's guide rates. const Group& group = schedule_.getGroup(name, report_step_); - return guideRateSum(group, always_included_child, true); + return guideRateSum(group, always_included_child, false); } } else { // No group-controlled subordinate wells. @@ -1135,7 +1151,12 @@ namespace WellGroupHelpers const size_t num_ancestors = chain.size() - 1; double target = orig_target; for (size_t ii = 0; ii < num_ancestors; ++ii) { - target -= localReduction(chain[ii]); + if ((ii == 0) || guideRate->has(chain[ii])) { + // Apply local reductions only at the control level + // (top) and for levels where we have a specified + // group guide rate. + target -= localReduction(chain[ii]); + } if (ii == num_ancestors - 1) { // Final level. Add my reduction back. target += current_rate * efficiencyFactor; diff --git a/opm/simulators/wells/WellGroupHelpers.hpp b/opm/simulators/wells/WellGroupHelpers.hpp index 6140d85a1..f73b75f54 100644 --- a/opm/simulators/wells/WellGroupHelpers.hpp +++ b/opm/simulators/wells/WellGroupHelpers.hpp @@ -86,6 +86,7 @@ namespace WellGroupHelpers const int reportStepIdx, const bool isInjector, const PhaseUsage& pu, + const GuideRate& guide_rate, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState, std::vector& groupTargetReduction); diff --git a/opm/simulators/wells/WellInterface_impl.hpp b/opm/simulators/wells/WellInterface_impl.hpp index f5d18dbc1..c81fd57be 100644 --- a/opm/simulators/wells/WellInterface_impl.hpp +++ b/opm/simulators/wells/WellInterface_impl.hpp @@ -2270,10 +2270,15 @@ namespace Opm const size_t num_ancestors = chain.size() - 1; double target = orig_target; for (size_t ii = 0; ii < num_ancestors; ++ii) { - target -= localReduction(chain[ii]); + if ((ii == 0) || guide_rate_->has(chain[ii])) { + // Apply local reductions only at the control level + // (top) and for levels where we have a specified + // group guide rate. + target -= localReduction(chain[ii]); + } target *= localFraction(chain[ii+1]); } - // Avoid negative target rates comming from too large local reductions. + // Avoid negative target rates coming from too large local reductions. const double target_rate = std::max(0.0, target / efficiencyFactor); const auto current_rate = -tcalc.calcModeRateFromRates(rates); // Switch sign since 'rates' are negative for producers. control_eq = current_rate - target_rate;