From a57374fae977b7b9ed4fefb46ff8f357f44d95d8 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Mon, 25 Oct 2021 15:35:30 +0200 Subject: [PATCH] Adjust reduction rate when well control is considered for GRUP The reduction rate is computed differently for cases without wells under GRUP For a well to check whether to switch to GRUP it needed to use the reduction rate that would have been computed if this particular well was under GRUP control and thus recompute the reduction rate without entering the no-grup path --- opm/simulators/wells/WellGroupHelpers.cpp | 114 +++++++++++++++++----- 1 file changed, 89 insertions(+), 25 deletions(-) diff --git a/opm/simulators/wells/WellGroupHelpers.cpp b/opm/simulators/wells/WellGroupHelpers.cpp index 5d584b733..9097d825a 100644 --- a/opm/simulators/wells/WellGroupHelpers.cpp +++ b/opm/simulators/wells/WellGroupHelpers.cpp @@ -1182,18 +1182,50 @@ namespace WellGroupHelpers // Add my reduction back at the level where it is included in the local reduction if (local_reduction_level == ii ) target += current_rate * efficiencyFactor; - } - if (ii < num_ancestors - 1) { - // Not final level. Add sub-level reduction back, if - // it was nonzero due to having no group-controlled - // wells. Note that we make this call without setting - // the current well to be always included, because we - // want to know the situation that applied to the - // calculation of reductions. - const int num_gr_ctrl = groupControlledWells(schedule, wellState, group_state, reportStepIdx, chain[ii + 1], "", /*is_producer*/true, /*injectionPhaseNotUsed*/Phase::OIL); - if (num_gr_ctrl == 0) { - if (guideRate->has(chain[ii + 1])) { - target += localReduction(chain[ii + 1]); + + for (size_t iii = ii + 1; iii < num_ancestors; ++iii) { + // Not final level. Add sub-level reduction back, if + // it was not under individual control and nonzero due to having no group-controlled + // wells. We may need to look several levels down the hierarchy to find groups without + // group control wells + const Group::ProductionCMode& subGroupControl = group_state.production_control(chain[iii]); + const bool individual_control = (subGroupControl != Group::ProductionCMode::FLD + && subGroupControl != Group::ProductionCMode::NONE); + // The sub group is on individual control. No adjustments needed. + if (individual_control) { + break; + } + + // Note that we make this call without setting + // the current well to be always included, because we + // want to know the situation that applied to the + // calculation of reductions. + const int num_gr_ctrl = groupControlledWells(schedule, + wellState, + group_state, + reportStepIdx, + chain[iii], + "", + /*is_producer*/ true, + /*injectionPhaseNotUsed*/ Phase::OIL); + if (num_gr_ctrl == 0) { + // We found a sub wells with no group controlled wells. We now need to adapt the reduction rate + // to reflect what would have happen if the current well under consideration would have been + // under group control. I.e. we first remove the efficient sub_rate from the reduction rate + // (since the reduction rate is removed already from the target we need to add it to the target) + const double sub_efficiency + = schedule.getGroup(chain[iii], reportStepIdx).getGroupEfficiencyFactor(); + const double sub_rate = tcalc.calcModeRateFromRates(group_state.production_rates(chain[iii])); + target += sub_efficiency * sub_rate; + // than we remove the local reduction from the target if it does not have a guide rate + if (!guideRate->has(chain[iii])) { + target -= sub_efficiency * localReduction(chain[iii]); + // this local reduction rate may also need adjustments since it may be computed based on the + // assumption that its subgroup dont have a group control wells. I.e we need to move down the + // hierarchy. + } else { + break; + } } } } @@ -1297,7 +1329,6 @@ namespace WellGroupHelpers local_reduction_level = ii; } } - double target = orig_target; for (size_t ii = 0; ii < num_ancestors; ++ii) { if ((ii == 0) || guideRate->has(chain[ii], injectionPhase)) { @@ -1309,18 +1340,51 @@ namespace WellGroupHelpers // Add my reduction back at the level where it is included in the local reduction if (local_reduction_level == ii ) target += current_rate * efficiencyFactor; - } - if (ii < num_ancestors - 1) { - // Not final level. Add sub-level reduction back, if - // it was nonzero due to having no group-controlled - // wells. Note that we make this call without setting - // the current well to be always included, because we - // want to know the situation that applied to the - // calculation of reductions. - const int num_gr_ctrl = groupControlledWells(schedule, wellState, group_state, reportStepIdx, chain[ii + 1], "", /*is_producer*/false, injectionPhase); - if (num_gr_ctrl == 0) { - if (guideRate->has(chain[ii + 1], injectionPhase)) { - target += localReduction(chain[ii + 1]); + + for (size_t iii = ii + 1; iii < num_ancestors; ++iii) { + // Not final level. Add sub-level reduction back, if + // it was not under individual control and nonzero due to having no group-controlled + // wells. We may need to look several levels down the hierarchy to find groups without + // group control wells + const Group::InjectionCMode& subGroupControl = group_state.injection_control(chain[iii], injectionPhase); + const bool individual_control = (subGroupControl != Group::InjectionCMode::FLD + && subGroupControl != Group::InjectionCMode::NONE); + // The sub group is on individual control. No adjustments needed. + if (individual_control) { + break; + } + + // Note that we make this call without setting + // the current well to be always included, because we + // want to know the situation that applied to the + // calculation of reductions. + const int num_gr_ctrl = groupControlledWells(schedule, + wellState, + group_state, + reportStepIdx, + chain[iii], + "", + /*is_producer*/ false, + injectionPhase); + if (num_gr_ctrl == 0) { + // We found a sub wells with no group controlled wells. We now need to adapt the reduction rate + // to reflect what would have happen if the well under consideration would have been + // under group control. I.e. we first remove the efficient sub_rate from the reduction rate + // (since the reduction rate is removed already from the target we need to add it to the target) + const double sub_efficiency + = schedule.getGroup(chain[iii], reportStepIdx).getGroupEfficiencyFactor(); + const double sub_rate + = tcalc.calcModeRateFromRates(group_state.injection_surface_rates(chain[iii])); + target += sub_efficiency * sub_rate; + // than we remove the local reduction from the target if it does not have a guide rate + if (!guideRate->has(chain[iii], injectionPhase)) { + target -= sub_efficiency * localReduction(chain[iii]); + // this local reduction rate may also need adjustments since it may be computed based on the + // assumption that its subgroup dont have group control wells. I.e we need to move down the + // hierarchy. + } else { + break; + } } } }