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> 54 template <
typename Scalar,
typename IndexTraits>
55 class GroupStateHelper
63 : groupStateHelper_ {groupStateHelper}
64 , previous_state_ptr_ {groupStateHelper_.well_state_}
67 groupStateHelper_.well_state_ = &well_state;
73 groupStateHelper_.well_state_ = previous_state_ptr_;
92 : group_state_helper_ {group_state_helper}
93 , previous_state_ptr_ {group_state_helper.group_state_}
96 group_state_helper_.group_state_ = &group_state;
102 group_state_helper_.group_state_ = previous_state_ptr_;
138 , previous_(helper.deferred_logger_)
139 , do_mpi_gather_(do_mpi_gather)
141 helper_->deferred_logger_ = &logger_;
147 if (do_mpi_gather_) {
152 if (helper_->terminalOutput()) {
157 if (helper_->terminalOutput()) {
163 helper_->deferred_logger_ = previous_;
175 : helper_(other.helper_)
176 , logger_(std::move(other.logger_))
177 , previous_(other.previous_)
178 , do_mpi_gather_(other.do_mpi_gather_)
182 helper_->deferred_logger_ = &logger_;
184 other.helper_ =
nullptr;
185 other.previous_ =
nullptr;
190 const GroupStateHelper* helper_{
nullptr};
191 DeferredLogger logger_;
192 DeferredLogger* previous_{
nullptr};
193 bool do_mpi_gather_{
true};
196 using GroupTarget =
typename SingleWellState<Scalar, IndexTraits>::GroupTarget;
198 GroupStateHelper(WellState<Scalar, IndexTraits>& well_state,
199 GroupState<Scalar>& group_state,
200 const Schedule& schedule,
201 const SummaryState& summary_state,
202 const GuideRate& guide_rate,
203 const PhaseUsageInfo<IndexTraits>& phase_usage_info,
204 const Parallel::Communication& comm,
205 bool terminal_output);
207 void accumulateGroupEfficiencyFactor(
const Group& group, Scalar& factor)
const;
209 std::pair<bool, Scalar> checkGroupConstraintsInj(
const std::string& name,
210 const std::string& parent,
213 const Phase injection_phase,
214 const Scalar efficiency_factor,
215 const std::vector<Scalar>& resv_coeff,
216 const bool check_guide_rate)
const;
218 std::pair<bool, Scalar> checkGroupConstraintsProd(
const std::string& name,
219 const std::string& parent,
222 const Scalar efficiency_factor,
223 const std::vector<Scalar>& resv_coeff,
224 const bool check_guide_rate)
const;
226 std::pair<Group::ProductionCMode, Scalar>
227 checkGroupProductionConstraints(
const Group& group)
const;
229 const Parallel::Communication& comm()
const {
return this->comm_; }
235 if (this->deferred_logger_ ==
nullptr) {
236 throw std::logic_error(
"DeferredLogger not set. Call pushLogger() first.");
238 return *this->deferred_logger_;
241 std::vector<Scalar> getGroupRatesAvailableForHigherLevelControl(
const Group& group,
const bool is_injector)
const;
243 Scalar getInjectionGroupTarget(
const Group& group,
244 const Phase& injection_phase,
245 const std::vector<Scalar>& resv_coeff)
const;
252 Scalar getProductionGroupTarget(
const Group& group)
const;
256 const Group::ProductionCMode cmode)
const;
263 GuideRateModel::Target
264 getProductionGuideTargetModeFromControlMode(
const Group::ProductionCMode cmode)
const;
266 std::pair<Scalar, Group::ProductionCMode>
267 getAutoChokeGroupProductionTargetRate(
const Group& bottom_group,
269 const std::vector<Scalar>& resv_coeff,
270 Scalar efficiencyFactor)
const;
272 GuideRate::RateVector getProductionGroupRateVector(
const std::string& group_name)
const;
274 std::optional<GroupTarget> getWellGroupTargetInjector(
const std::string& name,
275 const std::string& parent,
278 const Phase injection_phase,
279 const Scalar efficiency_factor,
280 const std::vector<Scalar>& resv_coeff)
const;
282 std::optional<GroupTarget> getWellGroupTargetProducer(
const std::string& name,
283 const std::string& parent,
286 const Scalar efficiency_factor,
287 const std::vector<Scalar>& resv_coeff,
288 std::optional<Group::ProductionCMode> target_cmode = std::nullopt)
const;
290 GuideRate::RateVector getWellRateVector(
const std::string& name)
const;
292 std::vector<std::string> groupChainTopBot(
const std::string& bottom,
const std::string& top)
const;
297 const std::string& always_included_child,
298 const bool is_production_group,
299 const Phase injection_phase)
const;
303 return *this->group_state_;
306 const GuideRate& guideRate()
const 308 return this->guide_rate_;
324 return this->well_state_->isRank0();
327 bool isReservoirCouplingMaster()
const {
return rescoup_.isMaster(); }
329 bool isReservoirCouplingMasterGroup(
const Group& group)
const {
return rescoup_.isMasterGroup(group.name()); }
331 bool isReservoirCouplingSlave()
const {
return rescoup_.isSlave(); }
333 bool isReservoirCouplingSlaveGroup(
const Group& group)
const {
return rescoup_.isSlaveGroup(group.name()); }
335 constexpr
int numPhases()
const {
336 return this->wellState().numPhases();
339 int phaseToActivePhaseIdx(
const Phase phase)
const;
341 const PhaseUsageInfo<IndexTraits>& phaseUsage()
const {
342 return this->phase_usage_info_;
345 GroupStateGuard pushGroupState(GroupState<Scalar>& group_state)
347 return GroupStateGuard(*
this, group_state);
363 ScopedLoggerGuard
pushLogger(
bool do_mpi_gather =
true)
const 365 return ScopedLoggerGuard(*
this, do_mpi_gather);
370 return WellStateGuard(*
this, well_state);
373 int reportStepIdx()
const 378 const Schedule& schedule()
const 380 return this->schedule_;
383 ReservoirCoupling::Proxy<Scalar>& rescoup() {
387 const ReservoirCoupling::Proxy<Scalar>& rescoup()
const {
391 ReservoirCouplingMaster<Scalar>& reservoirCouplingMaster() {
392 return rescoup_.master();
395 const ReservoirCouplingMaster<Scalar>& reservoirCouplingMaster()
const {
396 return rescoup_.master();
399 ReservoirCouplingSlave<Scalar>& reservoirCouplingSlave() {
400 return rescoup_.slave();
402 const ReservoirCouplingSlave<Scalar>& reservoirCouplingSlave()
const {
403 return rescoup_.slave();
406 #ifdef RESERVOIR_COUPLING_ENABLED 407 void setReservoirCouplingMaster(ReservoirCouplingMaster<Scalar>* master) {
408 rescoup_.setMaster(master);
410 void setReservoirCouplingSlave(ReservoirCouplingSlave<Scalar>* slave) {
411 rescoup_.setSlave(slave);
415 void setCmodeGroup(
const Group& group);
417 template <
class AverageRegionalPressureType>
419 setRegionAveragePressureCalculator(
const Group& group,
420 const FieldPropsManager& fp,
421 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>&
422 regional_average_pressure_calculator)
const;
424 void setReportStep(
int report_step)
426 report_step_ = report_step;
429 const SummaryState& summaryState()
const 431 return this->summary_state_;
434 Scalar sumSolventRates(
const Group& group,
const bool is_injector)
const;
436 Scalar sumWellResRates(
const Group& group,
const int phase_pos,
const bool injector)
const;
438 Scalar sumWellSurfaceRates(
const Group& group,
const int phase_pos,
const bool injector)
const;
440 Scalar sumWellPhaseRates(
bool res_rates,
444 const bool network =
false)
const;
446 bool terminalOutput()
const 448 return this->terminal_output_;
451 template <
class RegionalValues>
452 void updateGpMaintTargetForGroups(
const Group& group,
453 const RegionalValues& regional_values,
459 const Phase injection_phase);
461 void updateGroupProductionRates(
const Group& group);
463 void updatePreviousGroupProductionRates(
const Group& group);
465 void updateGroupTargetReduction(
const Group& group,
466 const bool is_injector);
468 void updateNetworkLeafNodeRates();
483 void updateREINForGroups(
const Group& group,
bool sum_rank);
485 void updateReservoirRatesInjectionGroups(
const Group& group);
487 #ifdef RESERVOIR_COUPLING_ENABLED 488 void updateSlaveGroupCmodesFromMaster();
500 void updateState(WellState<Scalar, IndexTraits>& well_state, GroupState<Scalar>& group_state);
502 void updateSurfaceRatesInjectionGroups(
const Group& group);
504 void updateVREPForGroups(
const Group& group);
506 void updateWellRates(
const Group& group,
507 const WellState<Scalar, IndexTraits>& well_state_nupcol,
508 WellState<Scalar, IndexTraits>& well_state)
const;
510 const WellState<Scalar, IndexTraits>& wellState()
const 512 return *this->well_state_;
515 void updateWellRatesFromGroupTargetScale(
const Scalar scale,
518 WellState<Scalar, IndexTraits>& well_state)
const;
521 std::pair<std::optional<std::string>, Scalar>
523 const Group::ProductionCMode& offended_control)
const;
548 template<
typename ReductionLambda,
typename FractionLambda>
549 Scalar applyReductionsAndFractions_(
const std::vector<std::string>& chain,
551 Scalar current_rate_available,
552 std::size_t local_reduction_level,
553 bool is_production_group,
554 Phase injection_phase,
555 ReductionLambda&& local_reduction_lambda,
556 FractionLambda&& local_fraction_lambda,
557 bool do_addback)
const;
559 std::pair<Group::ProductionCMode, Scalar>
560 checkProductionRateConstraint_(
const Group& group,
561 Group::ProductionCMode cmode,
562 Group::ProductionCMode currentControl,
564 Scalar current_rate)
const;
573 std::unordered_set<std::string> collectTargetedProductionGroups_()
const;
585 Scalar computeAddbackEfficiency_(
const std::vector<std::string>& chain,
586 std::size_t local_reduction_level)
const;
588 std::string controlGroup_(
const Group& group)
const;
590 GuideRate::RateVector getGuideRateVector_(
const std::vector<Scalar>& rates)
const;
592 Scalar getInjectionGroupTargetForMode_(
const Group& group,
593 const Phase& injection_phase,
594 const std::vector<Scalar>& resv_coeff,
595 const Group::InjectionCMode cmode)
const;
607 std::size_t getLocalReductionLevel_(
const std::vector<std::string>& chain,
608 bool is_production_group,
609 Phase injection_phase)
const;
611 Scalar getProductionConstraintTarget_(
const Group& group,
612 Group::ProductionCMode cmode,
613 const Group::ProductionControls& controls)
const;
615 Scalar getProductionGroupTargetForMode_(
const Group& group,
const Group::ProductionCMode cmode)
const;
617 Scalar getSatelliteRate_(
const Group& group,
619 const bool res_rates,
620 const bool is_injector)
const;
625 bool isAutoChokeGroupUnderperforming_(
const Group& group)
const;
628 bool isInGroupChainTopBot_(
const std::string& bottom,
const std::string& top)
const;
630 bool isSatelliteGroup_(
const Group& group)
const;
632 Scalar satelliteInjectionRate_(
const ScheduleState& sched,
635 bool res_rates)
const;
637 Scalar satelliteProductionRate_(
const ScheduleState& sched,
639 const GSatProd::GSatProdGroupProp::Rate rate_comp,
640 bool res_rates)
const;
642 std::optional<GSatProd::GSatProdGroupProp::Rate> selectRateComponent_(
const int phase_pos)
const;
654 Scalar subtractOtherPhaseResvInjection_(
655 Phase injection_phase,
656 Scalar base_reservoir_rate,
657 const std::vector<Scalar>& group_injection_reservoir_rates)
const;
659 Scalar sumProductionRateForControlMode_(
const Group& group, Group::ProductionCMode cmode)
const;
661 int updateGroupControlledWellsRecursive_(
const std::string& group_name,
662 const bool is_production_group,
663 const Phase injection_phase);
665 void updateGroupTargetReductionRecursive_(
const Group& group,
666 const bool is_injector,
667 std::vector<Scalar>& group_target_reduction);
671 void validateInjectionTopupPhases_(
const Group& group)
const;
674 void validateInjectionTopupPhasesRecursive_(
const Group& group,
675 std::optional<Phase> inherited_topup_phase,
676 const std::string& inherited_topup_group)
const;
679 #ifdef RESERVOIR_COUPLING_ENABLED 680 ReservoirCoupling::Phase activePhaseIdxToRescoupPhase_(
int phase_pos)
const;
694 std::unordered_set<std::string> collectMasterGroupHierarchy_()
const;
714 int getMasterGroupEffectiveGCW_(
const std::string& group_name,
715 bool is_production_group)
const;
730 Scalar getEffectiveProductionLimit_(
const std::string& gname,
731 Group::ProductionCMode rate_type,
732 Scalar slave_local_target)
const;
734 ReservoirCoupling::GrupSlav::FilterFlag getInjectionFilterFlag_(
const std::string& group_name,
735 const Phase injection_phase)
const;
737 ReservoirCoupling::GrupSlav::FilterFlag getProductionFilterFlag_(
const std::string& group_name,
738 const Group::ProductionCMode cmode)
const;
740 Scalar getReservoirCouplingMasterGroupRate_(
const Group& group,
742 const ReservoirCoupling::RateKind kind)
const;
743 #endif // RESERVOIR_COUPLING_ENABLED 745 const WellState<Scalar, IndexTraits>* well_state_ {
nullptr};
746 GroupState<Scalar>* group_state_ {
nullptr};
747 const Schedule& schedule_;
748 const SummaryState& summary_state_;
749 const GuideRate& guide_rate_;
752 mutable DeferredLogger* deferred_logger_ {
nullptr};
755 const PhaseUsageInfo<IndexTraits>& phase_usage_info_;
756 const Parallel::Communication& comm_;
757 bool terminal_output_ {
false};
758 int report_step_ {0};
759 ReservoirCoupling::Proxy<Scalar> rescoup_{};
771 template <
typename Scalar,
typename IndexTraits>
772 template <
class AverageRegionalPressureType>
774 GroupStateHelper<Scalar, IndexTraits>::setRegionAveragePressureCalculator(
776 const FieldPropsManager& fp,
777 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>& regional_average_pressure_calculator)
780 for (
const std::string& groupName : group.groups()) {
781 this->setRegionAveragePressureCalculator(this->schedule_.getGroup(groupName, this->report_step_),
783 regional_average_pressure_calculator);
785 const auto& gpm = group.gpmaint();
789 const auto& reg = gpm->region();
793 if (regional_average_pressure_calculator.count(reg->first) == 0) {
794 const std::string name = (reg->first.rfind(
"FIP", 0) == 0) ? reg->first :
"FIP" + reg->first;
795 const auto& fipnum = fp.get_int(name);
796 regional_average_pressure_calculator[reg->first]
797 = std::make_unique<AverageRegionalPressureType>(fipnum);
806 template <
typename Scalar,
typename IndexTraits>
807 template <
class RegionalValues>
809 GroupStateHelper<Scalar, IndexTraits>::updateGpMaintTargetForGroups(
const Group& group,
810 const RegionalValues& regional_values,
814 for (
const std::string& group_name : group.groups()) {
815 const Group& group_tmp = this->schedule_.getGroup(group_name, this->report_step_);
816 this->updateGpMaintTargetForGroups(group_tmp, regional_values, dt);
818 const auto& gpm = group.gpmaint();
822 const auto& region = gpm->region();
825 if (this->isReservoirCouplingMasterGroup(group)) {
836 "GPMAINT is not supported for reservoir coupling master groups.",
837 this->deferredLogger()
841 else if (this->isReservoirCouplingSlaveGroup(group)) {
846 "GPMAINT is not supported for reservoir coupling slave groups.",
847 this->deferredLogger()
851 const auto [name, number] = *region;
852 const Scalar error = gpm->pressure_target() - regional_values.at(name)->pressure(number);
853 Scalar current_rate = 0.0;
854 const auto& pu = this->phase_usage_info_;
855 bool injection =
true;
857 switch (gpm->flow_target()) {
858 case GPMaint::FlowTarget::RESV_PROD: {
859 current_rate = -this->groupState().injection_vrep_rate(group.name());
864 case GPMaint::FlowTarget::RESV_OINJ: {
865 if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
866 const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
867 current_rate = this->groupState().injection_reservoir_rates(group.name())[io];
871 case GPMaint::FlowTarget::RESV_WINJ: {
872 if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
873 const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
874 current_rate = this->groupState().injection_reservoir_rates(group.name())[iw];
878 case GPMaint::FlowTarget::RESV_GINJ: {
879 if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
880 const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
881 current_rate = this->groupState().injection_reservoir_rates(group.name())[ig];
885 case GPMaint::FlowTarget::SURF_OINJ: {
886 if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
887 const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
888 current_rate = this->groupState().injection_surface_rates(group.name())[io];
892 case GPMaint::FlowTarget::SURF_WINJ: {
893 if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
894 const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
895 current_rate = this->groupState().injection_surface_rates(group.name())[iw];
899 case GPMaint::FlowTarget::SURF_GINJ: {
900 if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
901 const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
902 current_rate = this->groupState().injection_surface_rates(group.name())[ig];
907 throw std::invalid_argument(
"Invalid Flow target type in GPMAINT");
909 auto& gpmaint_state = this->groupState().gpmaint(group.name());
912 bool activate = (injection && error > 0) || (!injection && error < 0);
915 rate = gpm->rate(gpmaint_state, current_rate, error, dt);
917 gpm->resetState(gpmaint_state);
919 this->groupState().update_gpmaint_target(group.name(), std::max(Scalar {0.0}, sign * rate));
924 #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:1236
ScopedLoggerGuard(const GroupStateHelper &helper, bool do_mpi_gather=true)
Constructor for scoped logger guard.
Definition: GroupStateHelper.hpp:136
RAII guard that owns a DeferredLogger and auto-gathers on destruction.
Definition: GroupStateHelper.hpp:128
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:956
GuideRateModel::Target getInjectionGuideTargetMode(Phase injection_phase) const
Get the guide rate target mode for an injection phase.
Definition: GroupStateHelper.cpp:577
ScopedLoggerGuard pushLogger(bool do_mpi_gather=true) const
Push a new logger onto the stack with auto-cleanup on destruction.
Definition: GroupStateHelper.hpp:363
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:1619
Definition: GroupStateHelper.hpp:59
Definition: BlackoilWellModelConstraints.hpp:34
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
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:1321
DeferredLogger & deferredLogger() const
Get the deferred logger.
Definition: GroupStateHelper.hpp:233
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:205
Definition: GroupStateHelper.hpp:88
bool isMasterGroupEligibleForGuideRate(const std::string &group_name) const
Whether a reservoir-coupling master group is eligible to participate in its parent's guide-rate distr...
Definition: GroupStateHelper.cpp:977
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:538
GuideRateModel::Target getProductionGuideTargetMode(const Group &group) const
Get the guide rate target mode for a production group.
Definition: GroupStateHelper.cpp:547
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition: TemperatureModel.hpp:65