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; + } } } }