GroupStateHelper.hpp
Go to the documentation of this file.
1/*
2 Copyright 2025 Equinor ASA
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef OPM_GROUPSTATEHELPER_HEADER_INCLUDED
20#define OPM_GROUPSTATEHELPER_HEADER_INCLUDED
21
23
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>
40
42
43#include <algorithm>
44#include <map>
45#include <memory>
46#include <optional>
47#include <stdexcept>
48#include <string>
49#include <unordered_set>
50#include <vector>
51
52namespace Opm
53{
54template <typename Scalar, typename IndexTraits>
56{
57public:
58 // RAII guard for temporarily setting wellstate pointer
60 {
61 public:
63 : groupStateHelper_ {groupStateHelper}
64 , previous_state_ptr_ {groupStateHelper_.well_state_}
65 {
66 // Set the new state directly
67 groupStateHelper_.well_state_ = &well_state;
68 }
69
71 {
72 // Restore the previous state
73 groupStateHelper_.well_state_ = previous_state_ptr_;
74 }
75
76 // Delete copy and move operations
81
82 private:
83 GroupStateHelper& groupStateHelper_;
84 const WellState<Scalar, IndexTraits>* previous_state_ptr_;
85 };
86
87 // RAII guard for temporarily setting groupstate pointer
89 {
90 public:
91 GroupStateGuard(GroupStateHelper& group_state_helper, GroupState<Scalar>& group_state)
92 : group_state_helper_ {group_state_helper}
93 , previous_state_ptr_ {group_state_helper.group_state_}
94 {
95 // Set the new state directly
96 group_state_helper_.group_state_ = &group_state;
97 }
98
100 {
101 // Restore the previous state
102 group_state_helper_.group_state_ = previous_state_ptr_;
103 }
104
105 // Delete copy and move operations
110
111 private:
112 GroupStateHelper& group_state_helper_;
113 GroupState<Scalar>* previous_state_ptr_ {nullptr};
114 };
115
129 {
130 public:
136 explicit ScopedLoggerGuard(const GroupStateHelper& helper, bool do_mpi_gather = true)
137 : helper_(&helper)
138 , previous_(helper.deferred_logger_)
139 , do_mpi_gather_(do_mpi_gather)
140 {
141 helper_->deferred_logger_ = &logger_;
142 }
143
145 {
146 if (helper_) {
147 if (do_mpi_gather_) {
148 // 1. Gather messages across MPI ranks
149 DeferredLogger global = gatherDeferredLogger(logger_, helper_->comm());
150
151 // 2. Log on rank 0 (if terminal_output enabled)
152 if (helper_->terminalOutput()) {
153 global.logMessages();
154 }
155 } else {
156 // Just log locally without MPI gather
157 if (helper_->terminalOutput()) {
158 logger_.logMessages();
159 }
160 }
161
162 // 3. Restore previous logger
163 helper_->deferred_logger_ = previous_;
164 }
165 }
166
167 // Delete copy operations and move assignment
171
172 // Move constructor required for pushLogger() return-by-value (must be
173 // available even if elided by RVO)
175 : helper_(other.helper_)
176 , logger_(std::move(other.logger_))
177 , previous_(other.previous_)
178 , do_mpi_gather_(other.do_mpi_gather_)
179 {
180 // Update the helper's pointer to our moved logger
181 if (helper_) {
182 helper_->deferred_logger_ = &logger_;
183 }
184 other.helper_ = nullptr;
185 other.previous_ = nullptr;
186 }
187
188 private:
189 // Pointer (not reference) to allow nulling in move constructor
190 const GroupStateHelper* helper_{nullptr};
191 DeferredLogger logger_; // Owned logger
192 DeferredLogger* previous_{nullptr}; // For restore
193 bool do_mpi_gather_{true}; // Whether to gather messages across MPI ranks
194 };
195
197
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,
205 bool terminal_output);
206
207 void accumulateGroupEfficiencyFactor(const Group& group, Scalar& factor) const;
208
209 std::pair<bool, Scalar> checkGroupConstraintsInj(const std::string& name,
210 const std::string& parent,
211 const Group& group,
212 const Scalar* rates,
213 const Phase injection_phase,
214 const Scalar efficiency_factor,
215 const std::vector<Scalar>& resv_coeff,
216 const bool check_guide_rate) const;
217
218 std::pair<bool, Scalar> checkGroupConstraintsProd(const std::string& name,
219 const std::string& parent,
220 const Group& group,
221 const Scalar* rates,
222 const Scalar efficiency_factor,
223 const std::vector<Scalar>& resv_coeff,
224 const bool check_guide_rate) const;
225
226 std::pair<Group::ProductionCMode, Scalar>
227 checkGroupProductionConstraints(const Group& group) const;
228
229 const Parallel::Communication& comm() const { return this->comm_; }
230
234 {
235 if (this->deferred_logger_ == nullptr) {
236 throw std::logic_error("DeferredLogger not set. Call pushLogger() first.");
237 }
238 return *this->deferred_logger_;
239 }
240
241 std::vector<Scalar> getGroupRatesAvailableForHigherLevelControl(const Group& group, const bool is_injector) const;
242
243 Scalar getInjectionGroupTarget(const Group& group,
244 const Phase& injection_phase,
245 const std::vector<Scalar>& resv_coeff) const;
246
250 GuideRateModel::Target getInjectionGuideTargetMode(Phase injection_phase) const;
251
252 Scalar getProductionGroupTarget(const Group& group) const;
253
255 Scalar getProductionGroupTargetForMode(const Group& group,
256 const Group::ProductionCMode cmode) const;
257
261 GuideRateModel::Target getProductionGuideTargetMode(const Group& group) const;
262
263 GuideRateModel::Target
264 getProductionGuideTargetModeFromControlMode(const Group::ProductionCMode cmode) const;
265
266 std::pair<Scalar, Group::ProductionCMode>
267 getAutoChokeGroupProductionTargetRate(const Group& bottom_group,
268 const Group& group,
269 const std::vector<Scalar>& resv_coeff,
270 Scalar efficiencyFactor) const;
271
272 GuideRate::RateVector getProductionGroupRateVector(const std::string& group_name) const;
273
274 std::optional<GroupTarget> getWellGroupTargetInjector(const std::string& name,
275 const std::string& parent,
276 const Group& group,
277 const Scalar* rates,
278 const Phase injection_phase,
279 const Scalar efficiency_factor,
280 const std::vector<Scalar>& resv_coeff) const;
281
282 std::optional<GroupTarget> getWellGroupTargetProducer(const std::string& name,
283 const std::string& parent,
284 const Group& group,
285 const Scalar* rates,
286 const Scalar efficiency_factor,
287 const std::vector<Scalar>& resv_coeff,
288 std::optional<Group::ProductionCMode> target_cmode = std::nullopt) const;
289
290 GuideRate::RateVector getWellRateVector(const std::string& name) const;
291
292 std::vector<std::string> groupChainTopBot(const std::string& bottom, const std::string& top) const;
293
296 int groupControlledWells(const std::string& group_name,
297 const std::string& always_included_child,
298 const bool is_production_group,
299 const Phase injection_phase) const;
300
302 {
303 return *this->group_state_;
304 }
305
306 const GuideRate& guideRate() const
307 {
308 return this->guide_rate_;
309 }
310
320 bool isMasterGroupEligibleForGuideRate(const std::string& group_name) const;
321
331 bool isMasterGroupEligibleForInjectionGuideRate(const std::string& group_name,
332 Phase injection_phase) const;
333
334 bool isRank0() const
335 {
336 return this->well_state_->isRank0();
337 }
338
339 bool isReservoirCouplingMaster() const { return rescoup_.isMaster(); }
340
341 bool isReservoirCouplingMasterGroup(const Group& group) const { return rescoup_.isMasterGroup(group.name()); }
342
343 bool isReservoirCouplingSlave() const { return rescoup_.isSlave(); }
344
345 bool isReservoirCouplingSlaveGroup(const Group& group) const { return rescoup_.isSlaveGroup(group.name()); }
346
347 constexpr int numPhases() const {
348 return this->wellState().numPhases();
349 }
350
351 int phaseToActivePhaseIdx(const Phase phase) const;
352
354 return this->phase_usage_info_;
355 }
356
358 {
359 return GroupStateGuard(*this, group_state);
360 }
361
375 ScopedLoggerGuard pushLogger(bool do_mpi_gather = true) const
376 {
377 return ScopedLoggerGuard(*this, do_mpi_gather);
378 }
379
381 {
382 return WellStateGuard(*this, well_state);
383 }
384
385 int reportStepIdx() const
386 {
387 return report_step_;
388 }
389
390 const Schedule& schedule() const
391 {
392 return this->schedule_;
393 }
394
396 return rescoup_;
397 }
398
400 return rescoup_;
401 }
402
404 return rescoup_.master();
405 }
406
408 return rescoup_.master();
409 }
410
412 return rescoup_.slave();
413 }
415 return rescoup_.slave();
416 }
417
418#ifdef RESERVOIR_COUPLING_ENABLED
419 void setReservoirCouplingMaster(ReservoirCouplingMaster<Scalar>* master) {
420 rescoup_.setMaster(master);
421 }
422 void setReservoirCouplingSlave(ReservoirCouplingSlave<Scalar>* slave) {
423 rescoup_.setSlave(slave);
424 }
425#endif
426
427 void setCmodeGroup(const Group& group);
428
429 template <class AverageRegionalPressureType>
430 void
432 const FieldPropsManager& fp,
433 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>&
434 regional_average_pressure_calculator) const;
435
436 void setReportStep(int report_step)
437 {
438 report_step_ = report_step;
439 }
440
441 const SummaryState& summaryState() const
442 {
443 return this->summary_state_;
444 }
445
446 Scalar sumSolventRates(const Group& group, const bool is_injector) const;
447
448 Scalar sumWellResRates(const Group& group, const int phase_pos, const bool injector) const;
449
450 Scalar sumWellSurfaceRates(const Group& group, const int phase_pos, const bool injector) const;
451
452 Scalar sumWellPhaseRates(bool res_rates,
453 const Group& group,
454 const int phase_pos,
455 const bool injector,
456 const bool network = false) const;
457
458 bool terminalOutput() const
459 {
460 return this->terminal_output_;
461 }
462
463 template <class RegionalValues>
464 void updateGpMaintTargetForGroups(const Group& group,
465 const RegionalValues& regional_values,
466 const double dt);
467
470 int updateGroupControlledWells(const bool is_production_group,
471 const Phase injection_phase);
472
473 void updateGroupProductionRates(const Group& group);
474
475 void updatePreviousGroupProductionRates(const Group& group);
476
477 void updateGroupTargetReduction(const Group& group,
478 const bool is_injector);
479
481
494
495 void updateREINForGroups(const Group& group, bool sum_rank);
496
497 void updateReservoirRatesInjectionGroups(const Group& group);
498
499#ifdef RESERVOIR_COUPLING_ENABLED
509 void updateSlaveGroupCmodesFromMaster();
510#endif
511
513
514 void updateSurfaceRatesInjectionGroups(const Group& group);
515
516 void updateVREPForGroups(const Group& group);
517
518 void updateWellRates(const Group& group,
519 const WellState<Scalar, IndexTraits>& well_state_nupcol,
520 WellState<Scalar, IndexTraits>& well_state) const;
521
523 {
524 return *this->well_state_;
525 }
526
527 void updateWellRatesFromGroupTargetScale(const Scalar scale,
528 const Group& group,
529 bool is_injector,
530 WellState<Scalar, IndexTraits>& well_state) const;
531
548 Scalar wellRateContributionToGroup(const std::string& well_name,
549 const int phase_pos,
550 const bool res_rates,
551 const bool is_injector,
552 const bool network = false) const;
553
555 std::pair<std::optional<std::string>, Scalar>
556 worstOffendingWell(const Group& group,
557 const Group::ProductionCMode& offended_control) const;
558
559private:
560
582 template<typename ReductionLambda, typename FractionLambda>
583 Scalar applyReductionsAndFractions_(const std::vector<std::string>& chain,
584 Scalar orig_target,
585 Scalar current_rate_available,
586 std::size_t local_reduction_level,
587 bool is_production_group,
588 Phase injection_phase,
589 ReductionLambda&& local_reduction_lambda,
590 FractionLambda&& local_fraction_lambda,
591 bool do_addback) const;
592
593 std::pair<Group::ProductionCMode, Scalar>
594 checkProductionRateConstraint_(const Group& group,
595 Group::ProductionCMode cmode,
596 Group::ProductionCMode currentControl,
597 Scalar target,
598 Scalar current_rate) const;
599
607 std::unordered_set<std::string> collectTargetedProductionGroups_() const;
608
619 Scalar computeAddbackEfficiency_(const std::vector<std::string>& chain,
620 std::size_t local_reduction_level) const;
621
622 std::string controlGroup_(const Group& group) const;
623
624 GuideRate::RateVector getGuideRateVector_(const std::vector<Scalar>& rates) const;
625
626 Scalar getInjectionGroupTargetForMode_(const Group& group,
627 const Phase& injection_phase,
628 const std::vector<Scalar>& resv_coeff,
629 const Group::InjectionCMode cmode) const;
630
641 std::size_t getLocalReductionLevel_(const std::vector<std::string>& chain,
642 bool is_production_group,
643 Phase injection_phase) const;
644
645 Scalar getProductionConstraintTarget_(const Group& group,
646 Group::ProductionCMode cmode,
647 const Group::ProductionControls& controls) const;
648
649 Scalar getProductionGroupTargetForMode_(const Group& group, const Group::ProductionCMode cmode) const;
650
651 Scalar getSatelliteRate_(const Group& group,
652 const int phase_pos,
653 const bool res_rates,
654 const bool is_injector) const;
655
659 bool isAutoChokeGroupUnderperforming_(const Group& group) const;
660
662 bool isInGroupChainTopBot_(const std::string& bottom, const std::string& top) const;
663
664 bool isSatelliteGroup_(const Group& group) const;
665
666 Scalar satelliteInjectionRate_(const ScheduleState& sched,
667 const Group& group,
668 const int phase_pos,
669 bool res_rates) const;
670
671 Scalar satelliteProductionRate_(const ScheduleState& sched,
672 const Group& group,
673 const GSatProd::Rate rate_comp,
674 bool res_rates) const;
675
676 std::optional<GSatProd::Rate> selectRateComponent_(const int phase_pos) const;
677
688 Scalar subtractOtherPhaseResvInjection_(
689 Phase injection_phase,
690 Scalar base_reservoir_rate,
691 const std::vector<Scalar>& group_injection_reservoir_rates) const;
692
693 Scalar sumProductionRateForControlMode_(const Group& group, Group::ProductionCMode cmode) const;
694
695 int updateGroupControlledWellsRecursive_(const std::string& group_name,
696 const bool is_production_group,
697 const Phase injection_phase);
698
699 void updateGroupTargetReductionRecursive_(const Group& group,
700 const bool is_injector,
701 std::vector<Scalar>& group_target_reduction);
702
703 // Validate that GCONINJE top-up phases (RESV/VREP) are consistent
704 // across the group hierarchy. Called once from setCmodeGroup() for FIELD.
705 void validateInjectionTopupPhases_(const Group& group) const;
706
707 // Recursive helper for validateInjectionTopupPhases_()
708 void validateInjectionTopupPhasesRecursive_(const Group& group,
709 std::optional<Phase> inherited_topup_phase,
710 const std::string& inherited_topup_group) const;
711
712 // --- Reservoir coupling private methods ---
713#ifdef RESERVOIR_COUPLING_ENABLED
718 ReservoirCoupling::Phase activePhaseIdxToRescoupPhase_(int phase_pos) const;
719
728 std::unordered_set<std::string> collectMasterGroupHierarchy_() const;
729
753 int getMasterGroupEffectiveGCW_(const std::string& group_name,
754 bool is_production_group,
755 Phase injection_phase) const;
756
770 Scalar getEffectiveProductionLimit_(const std::string& gname,
771 Group::ProductionCMode rate_type,
772 Scalar slave_local_target) const;
773
774 ReservoirCoupling::GrupSlav::FilterFlag getInjectionFilterFlag_(const std::string& group_name,
775 const Phase injection_phase) const;
776
777 ReservoirCoupling::GrupSlav::FilterFlag getProductionFilterFlag_(const std::string& group_name,
778 const Group::ProductionCMode cmode) const;
779
780 Scalar getReservoirCouplingMasterGroupRate_(const Group& group,
781 const int phase_pos,
782 const ReservoirCoupling::RateKind kind) const;
783#endif // RESERVOIR_COUPLING_ENABLED
784
785 const WellState<Scalar, IndexTraits>* well_state_ {nullptr};
786 GroupState<Scalar>* group_state_ {nullptr};
787 const Schedule& schedule_;
788 const SummaryState& summary_state_;
789 const GuideRate& guide_rate_;
790 // NOTE: The deferred logger does not change the object "meaningful" state, so it should be ok to
791 // make it mutable and store a pointer to it here.
792 mutable DeferredLogger* deferred_logger_ {nullptr};
793 // NOTE: The phase usage info seems to be read-only throughout the simulation, so it should be safe
794 // to store a reference to it here.
795 const PhaseUsageInfo<IndexTraits>& phase_usage_info_;
796 const Parallel::Communication& comm_;
797 bool terminal_output_ {false};
798 int report_step_ {0};
799 ReservoirCoupling::Proxy<Scalar> rescoup_{};
800};
801
802// -----------------------------------------------------------------------------
803// Template member function implementations
804// -----------------------------------------------------------------------------
805
806// NOTE: This template member function is defined here in the header because the
807// AverageRegionalPressureType type parameter depends on derived class types that are
808// not available when GroupStateHelper.cpp is compiled. Template functions
809// must be visible at their instantiation point.
810// See GroupStateHelper.cpp for detailed rationale.
811template <typename Scalar, typename IndexTraits>
812template <class AverageRegionalPressureType>
813void
815 const Group& group,
816 const FieldPropsManager& fp,
817 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>& regional_average_pressure_calculator)
818 const
819{
820 for (const std::string& groupName : group.groups()) {
821 this->setRegionAveragePressureCalculator(this->schedule_.getGroup(groupName, this->report_step_),
822 fp,
823 regional_average_pressure_calculator);
824 }
825 const auto& gpm = group.gpmaint();
826 if (!gpm)
827 return;
828
829 const auto& reg = gpm->region();
830 if (!reg)
831 return;
832
833 if (regional_average_pressure_calculator.count(reg->first) == 0) {
834 const std::string name = (reg->first.rfind("FIP", 0) == 0) ? reg->first : "FIP" + reg->first;
835 const auto& fipnum = fp.get_int(name);
836 regional_average_pressure_calculator[reg->first]
837 = std::make_unique<AverageRegionalPressureType>(fipnum);
838 }
839}
840
841// NOTE: This template member function is defined in the header because the
842// RegionalValues type parameter depends on derived class types that are
843// not available when GroupStateHelper.cpp is compiled. Template functions
844// must be visible at their instantiation point.
845// See GroupStateHelper.cpp for detailed rationale.
846template <typename Scalar, typename IndexTraits>
847template <class RegionalValues>
848void
850 const RegionalValues& regional_values,
851 const double dt)
852{
853 OPM_TIMEFUNCTION();
854 for (const std::string& group_name : group.groups()) {
855 const Group& group_tmp = this->schedule_.getGroup(group_name, this->report_step_);
856 this->updateGpMaintTargetForGroups(group_tmp, regional_values, dt);
857 }
858 const auto& gpm = group.gpmaint();
859 if (!gpm)
860 return;
861
862 const auto& region = gpm->region();
863 if (!region)
864 return;
865 if (this->isReservoirCouplingMasterGroup(group)) {
866 // GPMAINT is not supported for reservoir coupling master groups since master groups do not have
867 // subordinate wells in the master reservoir, so the slaves cannot influence the master reservoir's
868 // average pressure.
869 // Even specifying GPMAINT on a group superior to the master group might not make sense, since if the
870 // superior target is distributed down to the master group with guide rate fractions, adjusting
871 // the master group's target (that is sent to the slave) could only indirectly influence the master
872 // reservoir's average pressure by affecting the guide rate fractions distributed to actual wells
873 // in the master reservoir.
875 std::runtime_error,
876 "GPMAINT is not supported for reservoir coupling master groups.",
877 this->deferredLogger()
878 );
879 return;
880 }
881 else if (this->isReservoirCouplingSlaveGroup(group)) {
882 // GPMAINT is not supported for reservoir coupling slave groups since their targets will be overridden
883 // by the corresponding master group's target anyway.
885 std::runtime_error,
886 "GPMAINT is not supported for reservoir coupling slave groups.",
887 this->deferredLogger()
888 );
889 return;
890 }
891 const auto [name, number] = *region;
892 const Scalar error = gpm->pressure_target() - regional_values.at(name)->pressure(number);
893 Scalar current_rate = 0.0;
894 const auto& pu = this->phase_usage_info_;
895 bool injection = true;
896 Scalar sign = 1.0;
897 switch (gpm->flow_target()) {
898 case GPMaint::FlowTarget::RESV_PROD: {
899 current_rate = -this->groupState().injection_vrep_rate(group.name());
900 injection = false;
901 sign = -1.0;
902 break;
903 }
904 case GPMaint::FlowTarget::RESV_OINJ: {
905 if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
906 const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
907 current_rate = this->groupState().injection_reservoir_rates(group.name())[io];
908 }
909 break;
910 }
911 case GPMaint::FlowTarget::RESV_WINJ: {
912 if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
913 const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
914 current_rate = this->groupState().injection_reservoir_rates(group.name())[iw];
915 }
916 break;
917 }
918 case GPMaint::FlowTarget::RESV_GINJ: {
919 if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
920 const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
921 current_rate = this->groupState().injection_reservoir_rates(group.name())[ig];
922 }
923 break;
924 }
925 case GPMaint::FlowTarget::SURF_OINJ: {
926 if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
927 const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
928 current_rate = this->groupState().injection_surface_rates(group.name())[io];
929 }
930 break;
931 }
932 case GPMaint::FlowTarget::SURF_WINJ: {
933 if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
934 const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
935 current_rate = this->groupState().injection_surface_rates(group.name())[iw];
936 }
937 break;
938 }
939 case GPMaint::FlowTarget::SURF_GINJ: {
940 if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
941 const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
942 current_rate = this->groupState().injection_surface_rates(group.name())[ig];
943 }
944 break;
945 }
946 default:
947 throw std::invalid_argument("Invalid Flow target type in GPMAINT");
948 }
949 auto& gpmaint_state = this->groupState().gpmaint(group.name());
950 // we only activate gpmaint if pressure is lower than the target regional pressure for injectors
951 // (i.e. error > 0) and higher for producers.
952 bool activate = (injection && error > 0) || (!injection && error < 0);
953 Scalar rate = 0.0;
954 if (activate) {
955 rate = gpm->rate(gpmaint_state, current_rate, error, dt);
956 } else {
957 gpm->resetState(gpmaint_state);
958 }
959 this->groupState().update_gpmaint_target(group.name(), std::max(Scalar {0.0}, sign * rate));
960}
961
962} // namespace Opm
963
964#endif // OPM_GROUPSTATE_HELPER_HEADER_INCLUDED
#define OPM_DEFLOG_THROW(Exception, message, deferred_logger)
Definition: DeferredLoggingErrorHelpers.hpp:47
Definition: DeferredLogger.hpp:57
Definition: GroupStateHelper.hpp:89
GroupStateGuard(GroupStateGuard &&)=delete
GroupStateGuard & operator=(GroupStateGuard &&)=delete
GroupStateGuard(GroupStateHelper &group_state_helper, GroupState< Scalar > &group_state)
Definition: GroupStateHelper.hpp:91
GroupStateGuard(const GroupStateGuard &)=delete
~GroupStateGuard()
Definition: GroupStateHelper.hpp:99
GroupStateGuard & operator=(const GroupStateGuard &)=delete
RAII guard that owns a DeferredLogger and auto-gathers on destruction.
Definition: GroupStateHelper.hpp:129
ScopedLoggerGuard & operator=(const ScopedLoggerGuard &)=delete
ScopedLoggerGuard(ScopedLoggerGuard &&other) noexcept
Definition: GroupStateHelper.hpp:174
ScopedLoggerGuard(const ScopedLoggerGuard &)=delete
ScopedLoggerGuard(const GroupStateHelper &helper, bool do_mpi_gather=true)
Constructor for scoped logger guard.
Definition: GroupStateHelper.hpp:136
~ScopedLoggerGuard()
Definition: GroupStateHelper.hpp:144
ScopedLoggerGuard & operator=(ScopedLoggerGuard &&)=delete
Definition: GroupStateHelper.hpp:60
WellStateGuard(WellStateGuard &&)=delete
WellStateGuard(const WellStateGuard &)=delete
~WellStateGuard()
Definition: GroupStateHelper.hpp:70
WellStateGuard & operator=(const WellStateGuard &)=delete
WellStateGuard & operator=(WellStateGuard &&)=delete
WellStateGuard(GroupStateHelper &groupStateHelper, WellState< Scalar, IndexTraits > &well_state)
Definition: GroupStateHelper.hpp:62
Definition: GroupStateHelper.hpp:56
void updateWellRatesFromGroupTargetScale(const Scalar scale, const Group &group, bool is_injector, WellState< Scalar, IndexTraits > &well_state) const
std::pair< Scalar, Group::ProductionCMode > getAutoChokeGroupProductionTargetRate(const Group &bottom_group, const Group &group, const std::vector< Scalar > &resv_coeff, Scalar efficiencyFactor) const
GuideRateModel::Target getProductionGuideTargetModeFromControlMode(const Group::ProductionCMode cmode) const
void setRegionAveragePressureCalculator(const Group &group, const FieldPropsManager &fp, std::map< std::string, std::unique_ptr< AverageRegionalPressureType > > &regional_average_pressure_calculator) const
Definition: GroupStateHelper.hpp:814
void setCmodeGroup(const Group &group)
std::vector< std::string > groupChainTopBot(const std::string &bottom, const std::string &top) const
void updateVREPForGroups(const Group &group)
void updateWellRates(const Group &group, const WellState< Scalar, IndexTraits > &well_state_nupcol, WellState< Scalar, IndexTraits > &well_state) const
ReservoirCouplingMaster< Scalar > & reservoirCouplingMaster()
Definition: GroupStateHelper.hpp:403
GroupState< Scalar > & groupState() const
Definition: GroupStateHelper.hpp:301
Scalar sumWellResRates(const Group &group, const int phase_pos, const bool injector) const
void accumulateGroupEfficiencyFactor(const Group &group, Scalar &factor) const
int groupControlledWells(const std::string &group_name, const std::string &always_included_child, const bool is_production_group, const Phase injection_phase) const
const PhaseUsageInfo< IndexTraits > & phaseUsage() const
Definition: GroupStateHelper.hpp:353
const ReservoirCouplingMaster< Scalar > & reservoirCouplingMaster() const
Definition: GroupStateHelper.hpp:407
const SummaryState & summaryState() const
Definition: GroupStateHelper.hpp:441
const GuideRate & guideRate() const
Definition: GroupStateHelper.hpp:306
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)
ReservoirCoupling::Proxy< Scalar > & rescoup()
Definition: GroupStateHelper.hpp:395
void updateReservoirRatesInjectionGroups(const Group &group)
void updatePreviousGroupProductionRates(const Group &group)
bool isReservoirCouplingSlaveGroup(const Group &group) const
Definition: GroupStateHelper.hpp:345
const WellState< Scalar, IndexTraits > & wellState() const
Definition: GroupStateHelper.hpp:522
constexpr int numPhases() const
Definition: GroupStateHelper.hpp:347
GuideRate::RateVector getWellRateVector(const std::string &name) const
ScopedLoggerGuard pushLogger(bool do_mpi_gather=true) const
Push a new logger onto the stack with auto-cleanup on destruction.
Definition: GroupStateHelper.hpp:375
const Parallel::Communication & comm() const
Definition: GroupStateHelper.hpp:229
GuideRateModel::Target getInjectionGuideTargetMode(Phase injection_phase) const
Get the guide rate target mode for an injection phase.
bool isRank0() const
Definition: GroupStateHelper.hpp:334
std::pair< Group::ProductionCMode, Scalar > checkGroupProductionConstraints(const Group &group) const
Scalar sumSolventRates(const Group &group, const bool is_injector) const
const Schedule & schedule() const
Definition: GroupStateHelper.hpp:390
void updateGroupTargetReduction(const Group &group, const bool is_injector)
bool isMasterGroupEligibleForInjectionGuideRate(const std::string &group_name, Phase injection_phase) const
Whether a reservoir-coupling master group is eligible to participate in its parent's injection guide-...
GuideRate::RateVector getProductionGroupRateVector(const std::string &group_name) const
void updateGroupProductionRates(const Group &group)
bool terminalOutput() const
Definition: GroupStateHelper.hpp:458
typename SingleWellState< Scalar, IndexTraits >::GroupTarget GroupTarget
Definition: GroupStateHelper.hpp:196
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...
void updateGpMaintTargetForGroups(const Group &group, const RegionalValues &regional_values, const double dt)
Definition: GroupStateHelper.hpp:849
int phaseToActivePhaseIdx(const Phase phase) const
std::pair< bool, Scalar > checkGroupConstraintsProd(const std::string &name, const std::string &parent, const Group &group, const Scalar *rates, const Scalar efficiency_factor, const std::vector< Scalar > &resv_coeff, const bool check_guide_rate) const
DeferredLogger & deferredLogger() const
Get the deferred logger.
Definition: GroupStateHelper.hpp:233
Scalar sumWellSurfaceRates(const Group &group, const int phase_pos, const bool injector) const
Scalar wellRateContributionToGroup(const std::string &well_name, const int phase_pos, const bool res_rates, const bool is_injector, const bool network=false) const
The contribution of a single well to a group rate sum.
void updateNetworkLeafNodeRates()
int reportStepIdx() const
Definition: GroupStateHelper.hpp:385
void setReportStep(int report_step)
Definition: GroupStateHelper.hpp:436
int updateGroupControlledWells(const bool is_production_group, const Phase injection_phase)
void updateState(WellState< Scalar, IndexTraits > &well_state, GroupState< Scalar > &group_state)
std::vector< Scalar > getGroupRatesAvailableForHigherLevelControl(const Group &group, const bool is_injector) const
bool isReservoirCouplingMasterGroup(const Group &group) const
Definition: GroupStateHelper.hpp:341
const ReservoirCoupling::Proxy< Scalar > & rescoup() const
Definition: GroupStateHelper.hpp:399
bool isReservoirCouplingMaster() const
Definition: GroupStateHelper.hpp:339
const ReservoirCouplingSlave< Scalar > & reservoirCouplingSlave() const
Definition: GroupStateHelper.hpp:414
Scalar getProductionGroupTargetForMode(const Group &group, const Group::ProductionCMode cmode) const
Get the production target for a specific control mode (not necessarily the active one).
WellStateGuard pushWellState(WellState< Scalar, IndexTraits > &well_state)
Definition: GroupStateHelper.hpp:380
Scalar getInjectionGroupTarget(const Group &group, const Phase &injection_phase, const std::vector< Scalar > &resv_coeff) const
GroupStateGuard pushGroupState(GroupState< Scalar > &group_state)
Definition: GroupStateHelper.hpp:357
ReservoirCouplingSlave< Scalar > & reservoirCouplingSlave()
Definition: GroupStateHelper.hpp:411
Scalar sumWellPhaseRates(bool res_rates, const Group &group, const int phase_pos, const bool injector, const bool network=false) const
std::optional< GroupTarget > getWellGroupTargetProducer(const std::string &name, const std::string &parent, const Group &group, const Scalar *rates, const Scalar efficiency_factor, const std::vector< Scalar > &resv_coeff, std::optional< Group::ProductionCMode > target_cmode=std::nullopt) const
void updateREINForGroups(const Group &group, bool sum_rank)
bool isReservoirCouplingSlave() const
Definition: GroupStateHelper.hpp:343
GuideRateModel::Target getProductionGuideTargetMode(const Group &group) const
Get the guide rate target mode for a production group.
void updateNONEProductionGroups()
Set production control to NONE for groups not targeting any well.
Scalar getProductionGroupTarget(const Group &group) const
std::pair< bool, Scalar > checkGroupConstraintsInj(const std::string &name, const std::string &parent, const Group &group, const Scalar *rates, const Phase injection_phase, const Scalar efficiency_factor, const std::vector< Scalar > &resv_coeff, const bool check_guide_rate) const
std::optional< GroupTarget > getWellGroupTargetInjector(const std::string &name, const std::string &parent, const Group &group, const Scalar *rates, const Phase injection_phase, const Scalar efficiency_factor, const std::vector< Scalar > &resv_coeff) const
GroupStateHelper(WellState< Scalar, IndexTraits > &well_state, GroupState< Scalar > &group_state, const Schedule &schedule, const SummaryState &summary_state, const GuideRate &guide_rate, const PhaseUsageInfo< IndexTraits > &phase_usage_info, const Parallel::Communication &comm, bool terminal_output)
void updateSurfaceRatesInjectionGroups(const Group &group)
Definition: GroupState.hpp:42
Definition: GasLiftGroupInfo.hpp:38
Thin proxy for reservoir coupling master/slave pointers.
Definition: RescoupProxy.hpp:54
Definition: ReservoirCouplingMaster.hpp:42
Definition: ReservoirCouplingSlave.hpp:40
Definition: WellState.hpp:68
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
RateKind
Selects which kind of rate to retrieve from slave group data.
Definition: ReservoirCoupling.hpp:195
Phase
Phase indices for reservoir coupling, we currently only support black-oil phases (oil,...
Definition: ReservoirCoupling.hpp:183
Definition: blackoilbioeffectsmodules.hh:45
Opm::DeferredLogger gatherDeferredLogger(const Opm::DeferredLogger &local_deferredlogger, Parallel::Communication communicator)
Create a global log combining local logs.
Definition: SingleWellState.hpp:130