19 #ifndef OPM_GROUPSTATEHELPER_HEADER_INCLUDED 20 #define OPM_GROUPSTATEHELPER_HEADER_INCLUDED 22 #include <opm/simulators/wells/rescoup/RescoupProxy.hpp> 24 #include <opm/common/TimingMacros.hpp> 25 #include <opm/input/eclipse/Schedule/ResCoup/GrupSlav.hpp> 26 #include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp> 27 #include <opm/input/eclipse/Schedule/Group/GPMaint.hpp> 28 #include <opm/input/eclipse/Schedule/Group/GSatProd.hpp> 29 #include <opm/input/eclipse/Schedule/Group/GuideRate.hpp> 30 #include <opm/input/eclipse/Schedule/Schedule.hpp> 31 #include <opm/input/eclipse/Schedule/ScheduleState.hpp> 32 #include <opm/input/eclipse/Schedule/SummaryState.hpp> 33 #include <opm/material/fluidsystems/PhaseUsageInfo.hpp> 34 #include <opm/simulators/utils/DeferredLogger.hpp> 35 #include <opm/simulators/utils/gatherDeferredLogger.hpp> 36 #include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp> 37 #include <opm/simulators/wells/GroupState.hpp> 38 #include <opm/simulators/wells/VFPProdProperties.hpp> 39 #include <opm/simulators/wells/WellState.hpp> 41 #include <opm/simulators/utils/ParallelCommunication.hpp> 49 #include <unordered_set> 55 template <
typename Scalar,
typename IndexTraits>
56 class GroupStateHelper
64 : groupStateHelper_ {groupStateHelper}
65 , previous_state_ptr_ {groupStateHelper_.well_state_}
68 groupStateHelper_.well_state_ = &well_state;
74 groupStateHelper_.well_state_ = previous_state_ptr_;
93 : group_state_helper_ {group_state_helper}
94 , previous_state_ptr_ {group_state_helper.group_state_}
97 group_state_helper_.group_state_ = &group_state;
103 group_state_helper_.group_state_ = previous_state_ptr_;
139 , previous_(helper.deferred_logger_)
140 , do_mpi_gather_(do_mpi_gather)
142 helper_->deferred_logger_ = &logger_;
148 if (do_mpi_gather_) {
153 if (helper_->terminalOutput()) {
158 if (helper_->terminalOutput()) {
164 helper_->deferred_logger_ = previous_;
176 : helper_(other.helper_)
177 , logger_(std::move(other.logger_))
178 , previous_(other.previous_)
179 , do_mpi_gather_(other.do_mpi_gather_)
183 helper_->deferred_logger_ = &logger_;
185 other.helper_ =
nullptr;
186 other.previous_ =
nullptr;
191 const GroupStateHelper* helper_{
nullptr};
192 DeferredLogger logger_;
193 DeferredLogger* previous_{
nullptr};
194 bool do_mpi_gather_{
true};
197 using GroupTarget =
typename SingleWellState<Scalar, IndexTraits>::GroupTarget;
199 GroupStateHelper(WellState<Scalar, IndexTraits>& well_state,
200 GroupState<Scalar>& group_state,
201 const Schedule& schedule,
202 const SummaryState& summary_state,
203 const GuideRate& guide_rate,
204 const PhaseUsageInfo<IndexTraits>& phase_usage_info,
205 const Parallel::Communication& comm,
206 bool terminal_output);
208 void accumulateGroupEfficiencyFactor(
const Group& group, Scalar& factor)
const;
210 std::pair<bool, Scalar> checkGroupConstraintsInj(
const std::string& name,
211 const std::string& parent,
214 const Phase injection_phase,
215 const Scalar efficiency_factor,
216 const std::vector<Scalar>& resv_coeff,
217 const bool check_guide_rate)
const;
219 std::pair<bool, Scalar> checkGroupConstraintsProd(
const std::string& name,
220 const std::string& parent,
223 const Scalar efficiency_factor,
224 const std::vector<Scalar>& resv_coeff,
225 const bool check_guide_rate)
const;
227 std::pair<Group::ProductionCMode, Scalar>
228 checkGroupProductionConstraints(
const Group& group)
const;
230 const Parallel::Communication& comm()
const {
return this->comm_; }
236 if (this->deferred_logger_ ==
nullptr) {
237 throw std::logic_error(
"DeferredLogger not set. Call pushLogger() first.");
239 return *this->deferred_logger_;
242 std::vector<Scalar> getGroupRatesAvailableForHigherLevelControl(
const Group& group,
const bool is_injector)
const;
244 Scalar getInjectionGroupTarget(
const Group& group,
245 const Phase& injection_phase,
246 const std::vector<Scalar>& resv_coeff)
const;
253 Scalar getProductionGroupTarget(
const Group& group)
const;
257 const Group::ProductionCMode cmode)
const;
264 std::pair<Scalar, Group::ProductionCMode>
265 getAutoChokeGroupProductionTargetRate(
const Group& bottom_group,
267 const std::vector<Scalar>& resv_coeff,
268 Scalar efficiencyFactor)
const;
270 GuideRate::RateVector getProductionGroupRateVector(
const std::string& group_name)
const;
272 std::optional<GroupTarget> getWellGroupTargetInjector(
const std::string& name,
273 const std::string& parent,
276 const Phase injection_phase,
277 const Scalar efficiency_factor,
278 const std::vector<Scalar>& resv_coeff)
const;
280 std::optional<GroupTarget> getWellGroupTargetProducer(
const std::string& name,
281 const std::string& parent,
284 const Scalar efficiency_factor,
285 const std::vector<Scalar>& resv_coeff)
const;
287 GuideRate::RateVector getWellRateVector(
const std::string& name)
const;
289 std::vector<std::string> groupChainTopBot(
const std::string& bottom,
const std::string& top)
const;
294 const std::string& always_included_child,
295 const bool is_production_group,
296 const Phase injection_phase)
const;
300 return *this->group_state_;
303 const GuideRate& guideRate()
const 305 return this->guide_rate_;
310 return this->well_state_->isRank0();
313 bool isReservoirCouplingMaster()
const {
return rescoup_.isMaster(); }
315 bool isReservoirCouplingMasterGroup(
const Group& group)
const {
return rescoup_.isMasterGroup(group.name()); }
317 bool isReservoirCouplingSlave()
const {
return rescoup_.isSlave(); }
319 bool isReservoirCouplingSlaveGroup(
const Group& group)
const {
return rescoup_.isSlaveGroup(group.name()); }
321 constexpr
int numPhases()
const {
322 return this->wellState().numPhases();
325 int phaseToActivePhaseIdx(
const Phase phase)
const;
327 const PhaseUsageInfo<IndexTraits>& phaseUsage()
const {
328 return this->phase_usage_info_;
331 GroupStateGuard pushGroupState(GroupState<Scalar>& group_state)
333 return GroupStateGuard(*
this, group_state);
349 ScopedLoggerGuard
pushLogger(
bool do_mpi_gather =
true)
const 351 return ScopedLoggerGuard(*
this, do_mpi_gather);
356 return WellStateGuard(*
this, well_state);
359 int reportStepIdx()
const 364 const Schedule& schedule()
const 366 return this->schedule_;
369 ReservoirCoupling::Proxy<Scalar>& rescoup() {
373 const ReservoirCoupling::Proxy<Scalar>& rescoup()
const {
377 ReservoirCouplingMaster<Scalar>& reservoirCouplingMaster() {
378 return rescoup_.master();
381 const ReservoirCouplingMaster<Scalar>& reservoirCouplingMaster()
const {
382 return rescoup_.master();
385 ReservoirCouplingSlave<Scalar>& reservoirCouplingSlave() {
386 return rescoup_.slave();
388 const ReservoirCouplingSlave<Scalar>& reservoirCouplingSlave()
const {
389 return rescoup_.slave();
392 #ifdef RESERVOIR_COUPLING_ENABLED 393 void setReservoirCouplingMaster(ReservoirCouplingMaster<Scalar>* master) {
394 rescoup_.setMaster(master);
396 void setReservoirCouplingSlave(ReservoirCouplingSlave<Scalar>* slave) {
397 rescoup_.setSlave(slave);
401 void setCmodeGroup(
const Group& group);
403 template <
class AverageRegionalPressureType>
405 setRegionAveragePressureCalculator(
const Group& group,
406 const FieldPropsManager& fp,
407 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>&
408 regional_average_pressure_calculator)
const;
410 void setReportStep(
int report_step)
412 report_step_ = report_step;
415 const SummaryState& summaryState()
const 417 return this->summary_state_;
420 Scalar sumSolventRates(
const Group& group,
const bool is_injector)
const;
422 Scalar sumWellResRates(
const Group& group,
const int phase_pos,
const bool injector)
const;
424 Scalar sumWellSurfaceRates(
const Group& group,
const int phase_pos,
const bool injector)
const;
426 Scalar sumWellPhaseRates(
bool res_rates,
430 const bool network =
false)
const;
432 bool terminalOutput()
const 434 return this->terminal_output_;
437 template <
class RegionalValues>
438 void updateGpMaintTargetForGroups(
const Group& group,
439 const RegionalValues& regional_values,
445 const Phase injection_phase);
447 void updateGroupProductionRates(
const Group& group);
449 void updateGroupTargetReduction(
const Group& group,
450 const bool is_injector);
452 void updateNetworkLeafNodeProductionRates();
467 void updateREINForGroups(
const Group& group,
bool sum_rank);
469 void updateReservoirRatesInjectionGroups(
const Group& group);
471 #ifdef RESERVOIR_COUPLING_ENABLED 472 void updateSlaveGroupCmodesFromMaster();
484 void updateState(WellState<Scalar, IndexTraits>& well_state, GroupState<Scalar>& group_state);
486 void updateSurfaceRatesInjectionGroups(
const Group& group);
488 void updateVREPForGroups(
const Group& group);
490 void updateWellRates(
const Group& group,
491 const WellState<Scalar, IndexTraits>& well_state_nupcol,
492 WellState<Scalar, IndexTraits>& well_state)
const;
494 const WellState<Scalar, IndexTraits>& wellState()
const 496 return *this->well_state_;
499 void updateWellRatesFromGroupTargetScale(
const Scalar scale,
502 WellState<Scalar, IndexTraits>& well_state)
const;
505 std::pair<std::optional<std::string>, Scalar>
507 const Group::ProductionCMode& offended_control)
const;
532 template<
typename ReductionLambda,
typename FractionLambda>
533 Scalar applyReductionsAndFractions_(
const std::vector<std::string>& chain,
535 Scalar current_rate_available,
536 std::size_t local_reduction_level,
537 bool is_production_group,
538 Phase injection_phase,
539 ReductionLambda&& local_reduction_lambda,
540 FractionLambda&& local_fraction_lambda,
541 bool do_addback)
const;
543 std::pair<Group::ProductionCMode, Scalar>
544 checkProductionRateConstraint_(
const Group& group,
545 Group::ProductionCMode cmode,
546 Group::ProductionCMode currentControl,
548 Scalar current_rate)
const;
557 std::unordered_set<std::string> collectTargetedProductionGroups_()
const;
569 Scalar computeAddbackEfficiency_(
const std::vector<std::string>& chain,
570 std::size_t local_reduction_level)
const;
572 std::string controlGroup_(
const Group& group)
const;
574 GuideRate::RateVector getGuideRateVector_(
const std::vector<Scalar>& rates)
const;
576 Scalar getInjectionGroupTargetForMode_(
const Group& group,
577 const Phase& injection_phase,
578 const std::vector<Scalar>& resv_coeff,
579 const Group::InjectionCMode cmode)
const;
591 std::size_t getLocalReductionLevel_(
const std::vector<std::string>& chain,
592 bool is_production_group,
593 Phase injection_phase)
const;
595 Scalar getProductionConstraintTarget_(
const Group& group,
596 Group::ProductionCMode cmode,
597 const Group::ProductionControls& controls)
const;
599 Scalar getProductionGroupTargetForMode_(
const Group& group,
const Group::ProductionCMode cmode)
const;
601 Scalar getSatelliteRate_(
const Group& group,
603 const bool res_rates,
604 const bool is_injector)
const;
609 bool isAutoChokeGroupUnderperforming_(
const Group& group)
const;
612 bool isInGroupChainTopBot_(
const std::string& bottom,
const std::string& top)
const;
614 bool isSatelliteGroup_(
const Group& group)
const;
616 Scalar satelliteInjectionRate_(
const ScheduleState& sched,
619 bool res_rates)
const;
621 Scalar satelliteProductionRate_(
const ScheduleState& sched,
623 const GSatProd::GSatProdGroupProp::Rate rate_comp,
624 bool res_rates)
const;
626 std::optional<GSatProd::GSatProdGroupProp::Rate> selectRateComponent_(
const int phase_pos)
const;
638 Scalar subtractOtherPhaseResvInjection_(
639 Phase injection_phase,
640 Scalar base_reservoir_rate,
641 const std::vector<Scalar>& group_injection_reservoir_rates)
const;
643 Scalar sumProductionRateForControlMode_(
const Group& group, Group::ProductionCMode cmode)
const;
645 int updateGroupControlledWellsRecursive_(
const std::string& group_name,
646 const bool is_production_group,
647 const Phase injection_phase);
649 void updateGroupTargetReductionRecursive_(
const Group& group,
650 const bool is_injector,
651 std::vector<Scalar>& group_target_reduction);
655 void validateInjectionTopupPhases_(
const Group& group)
const;
658 void validateInjectionTopupPhasesRecursive_(
const Group& group,
659 std::optional<Phase> inherited_topup_phase,
660 const std::string& inherited_topup_group)
const;
663 #ifdef RESERVOIR_COUPLING_ENABLED 664 ReservoirCoupling::Phase activePhaseIdxToRescoupPhase_(
int phase_pos)
const;
678 std::unordered_set<std::string> collectMasterGroupHierarchy_()
const;
693 Scalar getEffectiveProductionLimit_(
const std::string& gname,
694 Group::ProductionCMode rate_type,
695 Scalar slave_local_target)
const;
697 ReservoirCoupling::GrupSlav::FilterFlag getInjectionFilterFlag_(
const std::string& group_name,
698 const Phase injection_phase)
const;
700 ReservoirCoupling::GrupSlav::FilterFlag getProductionFilterFlag_(
const std::string& group_name,
701 const Group::ProductionCMode cmode)
const;
703 Scalar getReservoirCouplingMasterGroupRate_(
const Group& group,
705 const ReservoirCoupling::RateKind kind)
const;
706 #endif // RESERVOIR_COUPLING_ENABLED 708 const WellState<Scalar, IndexTraits>* well_state_ {
nullptr};
709 GroupState<Scalar>* group_state_ {
nullptr};
710 const Schedule& schedule_;
711 const SummaryState& summary_state_;
712 const GuideRate& guide_rate_;
715 mutable DeferredLogger* deferred_logger_ {
nullptr};
718 const PhaseUsageInfo<IndexTraits>& phase_usage_info_;
719 const Parallel::Communication& comm_;
720 bool terminal_output_ {
false};
721 int report_step_ {0};
722 ReservoirCoupling::Proxy<Scalar> rescoup_{};
734 template <
typename Scalar,
typename IndexTraits>
735 template <
class AverageRegionalPressureType>
737 GroupStateHelper<Scalar, IndexTraits>::setRegionAveragePressureCalculator(
739 const FieldPropsManager& fp,
740 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>& regional_average_pressure_calculator)
743 for (
const std::string& groupName : group.groups()) {
744 this->setRegionAveragePressureCalculator(this->schedule_.getGroup(groupName, this->report_step_),
746 regional_average_pressure_calculator);
748 const auto& gpm = group.gpmaint();
752 const auto& reg = gpm->region();
756 if (regional_average_pressure_calculator.count(reg->first) == 0) {
757 const std::string name = (reg->first.rfind(
"FIP", 0) == 0) ? reg->first :
"FIP" + reg->first;
758 const auto& fipnum = fp.get_int(name);
759 regional_average_pressure_calculator[reg->first]
760 = std::make_unique<AverageRegionalPressureType>(fipnum);
769 template <
typename Scalar,
typename IndexTraits>
770 template <
class RegionalValues>
772 GroupStateHelper<Scalar, IndexTraits>::updateGpMaintTargetForGroups(
const Group& group,
773 const RegionalValues& regional_values,
777 for (
const std::string& group_name : group.groups()) {
778 const Group& group_tmp = this->schedule_.getGroup(group_name, this->report_step_);
779 this->updateGpMaintTargetForGroups(group_tmp, regional_values, dt);
781 const auto& gpm = group.gpmaint();
785 const auto& region = gpm->region();
788 if (this->isReservoirCouplingMasterGroup(group)) {
799 "GPMAINT is not supported for reservoir coupling master groups.",
800 this->deferredLogger()
804 else if (this->isReservoirCouplingSlaveGroup(group)) {
809 "GPMAINT is not supported for reservoir coupling slave groups.",
810 this->deferredLogger()
814 const auto [name, number] = *region;
815 const Scalar error = gpm->pressure_target() - regional_values.at(name)->pressure(number);
816 Scalar current_rate = 0.0;
817 const auto& pu = this->phase_usage_info_;
818 bool injection =
true;
820 switch (gpm->flow_target()) {
821 case GPMaint::FlowTarget::RESV_PROD: {
822 current_rate = -this->groupState().injection_vrep_rate(group.name());
827 case GPMaint::FlowTarget::RESV_OINJ: {
828 if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
829 const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
830 current_rate = this->groupState().injection_reservoir_rates(group.name())[io];
834 case GPMaint::FlowTarget::RESV_WINJ: {
835 if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
836 const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
837 current_rate = this->groupState().injection_reservoir_rates(group.name())[iw];
841 case GPMaint::FlowTarget::RESV_GINJ: {
842 if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
843 const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
844 current_rate = this->groupState().injection_reservoir_rates(group.name())[ig];
848 case GPMaint::FlowTarget::SURF_OINJ: {
849 if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
850 const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
851 current_rate = this->groupState().injection_surface_rates(group.name())[io];
855 case GPMaint::FlowTarget::SURF_WINJ: {
856 if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
857 const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
858 current_rate = this->groupState().injection_surface_rates(group.name())[iw];
862 case GPMaint::FlowTarget::SURF_GINJ: {
863 if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
864 const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
865 current_rate = this->groupState().injection_surface_rates(group.name())[ig];
870 throw std::invalid_argument(
"Invalid Flow target type in GPMAINT");
872 auto& gpmaint_state = this->groupState().gpmaint(group.name());
875 bool activate = (injection && error > 0) || (!injection && error < 0);
878 rate = gpm->rate(gpmaint_state, current_rate, error, dt);
880 gpm->resetState(gpmaint_state);
882 this->groupState().update_gpmaint_target(group.name(), std::max(Scalar {0.0}, sign * rate));
887 #endif // OPM_GROUPSTATE_HELPER_HEADER_INCLUDED int updateGroupControlledWells(const bool is_production_group, const Phase injection_phase)
update the number of wells that are actively under group control for a given group with name given by...
Definition: GroupStateHelper.cpp:1175
ScopedLoggerGuard(const GroupStateHelper &helper, bool do_mpi_gather=true)
Constructor for scoped logger guard.
Definition: GroupStateHelper.hpp:137
RAII guard that owns a DeferredLogger and auto-gathers on destruction.
Definition: GroupStateHelper.hpp:129
int groupControlledWells(const std::string &group_name, const std::string &always_included_child, const bool is_production_group, const Phase injection_phase) const
returns the number of wells that are actively under group control for a given group with name given b...
Definition: GroupStateHelper.cpp:906
GuideRateModel::Target getInjectionGuideTargetMode(Phase injection_phase) const
Get the guide rate target mode for an injection phase.
Definition: GroupStateHelper.cpp:562
ScopedLoggerGuard pushLogger(bool do_mpi_gather=true) const
Push a new logger onto the stack with auto-cleanup on destruction.
Definition: GroupStateHelper.hpp:349
std::pair< std::optional< std::string >, Scalar > worstOffendingWell(const Group &group, const Group::ProductionCMode &offended_control) const
Returns the name of the worst offending well and its fraction (i.e. violated_phase / preferred_phase)...
Definition: GroupStateHelper.cpp:1534
Definition: GroupStateHelper.hpp:60
Definition: BlackoilWellModelConstraints.hpp:34
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Definition: BlackoilWellModelConstraints.hpp:37
Definition: DeferredLogger.hpp:56
void updateNONEProductionGroups()
Set production control to NONE for groups not targeting any well.
Definition: GroupStateHelper.cpp:1236
DeferredLogger & deferredLogger() const
Get the deferred logger.
Definition: GroupStateHelper.hpp:234
void logMessages()
Log all messages to the OpmLog backends, and clear the message container.
Definition: DeferredLogger.cpp:92
Opm::DeferredLogger gatherDeferredLogger(const Opm::DeferredLogger &local_deferredlogger, Opm::Parallel::Communication)
Create a global log combining local logs.
Definition: gatherDeferredLogger.cpp:168
Definition: GroupStateHelper.hpp:89
Scalar getProductionGroupTargetForMode(const Group &group, const Group::ProductionCMode cmode) const
Get the production target for a specific control mode (not necessarily the active one)...
Definition: GroupStateHelper.cpp:531
GuideRateModel::Target getProductionGuideTargetMode(const Group &group) const
Get the guide rate target mode for a production group.
Definition: GroupStateHelper.cpp:540
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition: TemperatureModel.hpp:61