opm-simulators
GroupConstraintCalculator.hpp
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 
20 #ifndef OPM_GROUP_CONSTRAINT_CALCULATOR_HPP
21 #define OPM_GROUP_CONSTRAINT_CALCULATOR_HPP
22 #include <opm/common/ErrorMacros.hpp>
23 #include <opm/input/eclipse/EclipseState/Phase.hpp>
24 #include <opm/input/eclipse/Schedule/Schedule.hpp>
25 #include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
26 #include <opm/input/eclipse/Schedule/Group/Group.hpp>
27 #include <opm/simulators/flow/rescoup/ReservoirCoupling.hpp>
28 #include <opm/simulators/flow/rescoup/ReservoirCouplingMaster.hpp>
29 #include <opm/simulators/utils/DeferredLogger.hpp>
30 #include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
31 #include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
32 #include <opm/simulators/wells/FractionCalculator.hpp>
33 #include <opm/simulators/wells/GroupState.hpp>
34 #include <opm/simulators/wells/TargetCalculator.hpp>
35 #include <opm/simulators/wells/GroupStateHelper.hpp>
36 #include <opm/simulators/wells/WellState.hpp>
37 
38 #include <variant>
39 #include <optional>
40 #include <vector>
41 #include <string>
42 
43 namespace Opm {
44 
54 template<class Scalar, class IndexTraits>
56 public:
62  using ControlMode = std::variant<
63  std::monostate,
64  Group::InjectionCMode,
65  Group::ProductionCMode
66  >;
71 
73  enum class ConstraintType {
74  Target,
75  Limit
76  };
78  struct ConstraintInfo {
79  Scalar constraint; // Target or limit value
80  ControlMode cmode;
81  };
84  Scalar constraint; // Target or limit value
85  Group::ProductionCMode cmode;
86  };
89  Scalar constraint; // Target
90  Group::InjectionCMode cmode;
91  };
106  Scalar active_target;
107  Group::ProductionCMode active_cmode;
108  Scalar oil_limit = -1;
109  Scalar water_limit = -1;
110  Scalar gas_limit = -1;
111  Scalar liquid_limit = -1;
112  Scalar resv_limit = -1;
113  };
114 
126  public:
127  using TargetCalculatorType = std::variant<std::monostate, TargetCalculator, InjectionTargetCalculator>;
129  GroupConstraintCalculator& calculator,
130  const Group& original_group, // the bottom group we want to calculate the target for
131  std::optional<ReservoirCoupling::Phase> injection_phase = std::nullopt
132  );
136  GroupConstraintCalculator& calculator,
137  const Group& original_group,
138  Group::ProductionCMode explicit_cmode
139  );
140  std::optional<ConstraintInfo> calculateGroupConstraint();
141  ConstraintType constraintType() const { return this->constraint_type_; }
142  DeferredLogger& deferredLogger() { return this->parent_calculator_.deferredLogger(); }
143  // Const overload: allows logging from const methods.
144  DeferredLogger& deferredLogger() const { return this->parent_calculator_.deferredLogger(); }
145  int fipnum() const { return this->parent_calculator_.fipnum(); }
146  const GConSale& gconsale() const {
147  return this->schedule()[this->reportStepIdx()].gconsale();
148  }
149  const GroupState<Scalar>& groupState() const { return this->parent_calculator_.groupState(); }
150  TargetCalculatorType getInjectionTargetCalculator(const Group& group);
151  TargetCalculatorType getProductionTargetCalculator(const Group& group) const;
152  TargetCalculatorType getTargetCalculator(const Group& group);
153  std::optional<ConstraintInfo> getGroupConstraintNoGuideRate(const Group& group);
154  std::optional<Group::ProductionCMode> getProdCmode(const Group& group) const;
155  Group::ProductionCMode getProdCmode() const;
156  const GuideRate& guideRate() const { return this->parent_calculator_.guideRate(); }
157  bool hasGuideRate(const Group& group) const { return this->hasGuideRate(group.name()); }
158  bool hasGuideRate(const std::string& name) const {
159  if (this->isInjectionConstraint()) {
160  return this->guideRate().has(name, this->injectionPhase_());
161  }
162  return this->guideRate().has(name);
163  }
164  bool hasHigherLevelControlOrNoLimit(const Group& group);
165  Phase injectionPhase_() const;
166  bool isInjectionConstraint() const { return this->injection_phase_.has_value(); }
167  bool isProductionConstraint() const { return !this->injection_phase_.has_value(); }
168  const Group& originalGroup() const { return this->original_group_; }
169  const PhaseUsageInfo<IndexTraits>& phaseUsage() const { return this->parent_calculator_.phaseUsage(); }
170  int pvtreg() const { return this->parent_calculator_.pvtreg(); }
171  int reportStepIdx() const { return this->parent_calculator_.reportStepIdx(); }
172  const std::vector<Scalar>& resvCoeffsInj() const { return this->parent_calculator_.resvCoeffsInj(); }
173  const std::vector<Scalar>& resvCoeffsProd() const { return this->resv_coeffs_prod_; }
174  const Schedule& schedule() const { return this->parent_calculator_.schedule(); }
175  const SummaryState& summaryState() const { return this->parent_calculator_.summaryState(); }
176  const BlackoilWellModelGeneric<Scalar, IndexTraits>& wellModel() const {
177  return this->parent_calculator_.wellModel();
178  }
179  const WellState<Scalar, IndexTraits>& wellState() const { return this->parent_calculator_.wellState(); }
180  const GroupStateHelperType& groupStateHelper() const { return this->parent_calculator_.groupStateHelper(); }
181  private:
184  const Group& original_group,
185  std::optional<ReservoirCoupling::Phase> injection_phase, // Only used for injectors
186  std::optional<Group::ProductionCMode> production_cmode,
187  ConstraintType constraint_type
188  );
189  std::optional<ConstraintInfo> calculateGroupConstraintRecursive_(
190  const Group& group, const Scalar efficiency_factor);
191  const Group& parentGroup(const Group& group) const {
192  return this->schedule().getGroup(group.parent(), this->reportStepIdx());
193  }
194  bool parentGroupControlAvailable_(const Group& group);
195  Phase reservoirCouplingToOpmPhase_(ReservoirCoupling::Phase reservoir_coupling_phase) const;
196 
197  GroupConstraintCalculator& parent_calculator_;
198  const Group& original_group_; // The bottom group we want to calculate the target for
199  std::optional<ReservoirCoupling::Phase> injection_phase_;
200  ControlMode control_mode_;
201  ConstraintType constraint_type_;
202  std::vector<Scalar> resv_coeffs_prod_;
203  };
204 
215  public:
216  using TargetCalculatorType = std::variant<std::monostate, TargetCalculator, InjectionTargetCalculator>;
217 
218  constexpr static Scalar TARGET_RATE_TOLERANCE = 1e-12;
219 
221  GeneralCalculator& parent_calculator,
222  const Group& top_group,
223  const Group& bottom_group,
224  Scalar efficiency_factor
225  );
226 
227  std::optional<ConstraintInfo> calculateGroupConstraint();
228  ConstraintType constraintType() const { return this->parent_calculator_.constraintType(); }
229  DeferredLogger& deferredLogger() { return this->parent_calculator_.deferredLogger(); }
230  // Const overload: allows logging from const methods (logical constness for external logger).
231  DeferredLogger& deferredLogger() const { return this->parent_calculator_.deferredLogger(); }
232  Group::ProductionCMode getProdCmode() const { return this->parent_calculator_.getProdCmode(); }
233  std::optional<Group::ProductionCMode> getProdCmode(const Group& group) const {
234  return this->parent_calculator_.getProdCmode(group);
235  }
236  const GroupState<Scalar>& groupState() const { return this->parent_calculator_.groupState(); }
237  const GuideRate& guideRate() const { return this->parent_calculator_.guideRate(); }
238  bool isInjectionConstraint() const { return this->parent_calculator_.isInjectionConstraint(); }
239  bool isProductionConstraint() const { return this->parent_calculator_.isProductionConstraint(); }
240  const PhaseUsageInfo<IndexTraits>& phaseUsage() const { return this->parent_calculator_.phaseUsage(); }
241  int reportStepIdx() const { return this->parent_calculator_.reportStepIdx(); }
242  const std::vector<Scalar>& resvCoeffsInj() const { return this->parent_calculator_.resvCoeffsInj(); }
243  const std::vector<Scalar>& resvCoeffsProd() const { return this->parent_calculator_.resvCoeffsProd(); }
244  const Schedule& schedule() const { return this->parent_calculator_.schedule(); }
245  const SummaryState& summaryState() const { return this->parent_calculator_.summaryState(); }
246  const WellState<Scalar, IndexTraits>& wellState() const { return this->parent_calculator_.wellState(); }
247  const GroupStateHelperType& groupStateHelper() const { return this->parent_calculator_.groupStateHelper(); }
248 
249  private:
250  bool bottomGroupHasIndividualControl_();
251  Scalar computeAddbackEfficiency_(const std::vector<std::string>& chain,
252  const std::size_t local_reduction_level) const;
253  Scalar getBottomGroupCurrentRateAvailable_() const;
254  std::vector<std::string> getGroupChainTopBot_() const;
255  std::size_t getLocalReductionLevel_(const std::vector<std::string>& chain);
256  TargetCalculatorType getProductionTargetCalculator_(const Group& group) const {
257  return this->parent_calculator_.getProductionTargetCalculator(group); }
258  TargetCalculatorType getInjectionTargetCalculator_(const Group& group) const {
259  return this->parent_calculator_.getInjectionTargetCalculator(group); }
260  TargetCalculatorType getInjectionTargetCalculator(const Group& group) const;
261  TargetCalculatorType getProductionTargetCalculator(const Group& group) const;
268  Scalar getSlaveGroupReservoirRate_(const Group& master_group);
269  std::optional<ConstraintInfo> getGroupConstraintNoGuideRate_(const Group& group) const {
270  return this->parent_calculator_.getGroupConstraintNoGuideRate(group);
271  }
272  ControlMode getToplevelControlMode_() const;
273  Scalar getTopLevelTargetOrLimit_();
274  bool hasHigherLevelControlOrNoLimit(const Group& group) {
275  return this->parent_calculator_.hasHigherLevelControlOrNoLimit(group);
276  }
277  bool hasFLDControl_(const Group& group) const;
278  bool hasGuideRate_(const std::string& name) const {
279  return this->parent_calculator_.hasGuideRate(name);
280  }
281  void initForInjector_();
282  void initForProducer_();
283  Phase injectionPhase_() const { return this->parent_calculator_.injectionPhase_(); }
284  bool isProducerAndRESVControl_(const Group& group) const;
285  Scalar localFraction_(const std::string& group_name);
286  Scalar localReduction_(const std::string& group_name);
287 
288  GeneralCalculator& parent_calculator_;
289  const Group& top_group_;
290  const Group& bottom_group_;
291  // Accumulated efficiency factor along the chain from top to bottom, excluding the top group.
292  Scalar chain_efficiency_factor_;
293  // Active calculator used for distributing the target along the chain:
294  // either production TargetCalculator or InjectionTargetCalculator.
295  std::variant<std::monostate, TargetCalculator, InjectionTargetCalculator> target_calculator_;
296  // Since FractionCalculator does not have a default constructor, we use std::optional
297  // to conditionally initialize it based on whether we are dealing with an injector or producer.
298  std::optional<FractionCalculator> fraction_calculator_;
299  };
300 
306  const GroupStateHelperType& group_state_helper
307  );
308  DeferredLogger& deferredLogger() { return this->group_state_helper_.deferredLogger(); }
309  // Const overload: allows logging from const methods.
310  DeferredLogger& deferredLogger() const { return this->group_state_helper_.deferredLogger(); }
311  int fipnum() const { return this->fipnum_; }
313  std::optional<InjectionConstraintInfo> groupInjectionTarget(
314  const Group& group, ReservoirCoupling::Phase injection_phase
315  );
317  std::optional<ProductionConstraintInfo> groupProductionTarget(const Group& group);
321  std::optional<ProductionConstraintResult> groupProductionConstraints(const Group& group);
322  const GroupState<Scalar>& groupState() const { return this->group_state_; }
323  const GuideRate& guideRate() const { return this->guide_rate_; }
324  const PhaseUsageInfo<IndexTraits>& phaseUsage() const { return this->phase_usage_; }
325  int pvtreg() const { return this->pvtreg_; }
326  int reportStepIdx() const { return this->report_step_idx_; }
327  const std::vector<Scalar>& resvCoeffsInj() const { return this->resv_coeffs_inj_; }
328  const Schedule& schedule() const { return this->schedule_; }
329  const SummaryState& summaryState() const { return this->summary_state_; }
330  const BlackoilWellModelGeneric<Scalar, IndexTraits>& wellModel() const { return this->well_model_; }
331  const WellState<Scalar, IndexTraits>& wellState() const { return this->well_state_; }
332  const GroupStateHelperType& groupStateHelper() const { return this->group_state_helper_; }
333 private:
334  const BlackoilWellModelGeneric<Scalar, IndexTraits>& well_model_;
335  const GroupStateHelperType& group_state_helper_;
336  const WellState<Scalar, IndexTraits >& well_state_;
337  const GroupState<Scalar>& group_state_;
338  const Schedule& schedule_;
339  const SummaryState& summary_state_;
340  const PhaseUsageInfo<IndexTraits>& phase_usage_;
341  const GuideRate& guide_rate_;
342  int report_step_idx_;
343  std::vector<Scalar> resv_coeff_;
344  int fipnum_; // FIP region for the groups
345  int pvtreg_; // PVT region for the groups
346  std::vector<Scalar> resv_coeffs_inj_;
347 };
348 
349 } // namespace Opm
350 
351 #endif // OPM_GROUP_CONSTRAINT_CALCULATOR_HPP
Class for handling the blackoil well model.
Definition: ActionHandler.hpp:39
Definition: FractionCalculator.hpp:39
Distribute a top-level constraint (target or limit) down to the requested group.
Definition: GroupConstraintCalculator.hpp:214
Result for a production constraint with its production control mode.
Definition: GroupConstraintCalculator.hpp:83
Definition: BlackoilWellModelConstraints.hpp:34
Generic result for a computed constraint and its control mode.
Definition: GroupConstraintCalculator.hpp:78
std::variant< std::monostate, Group::InjectionCMode, Group::ProductionCMode > ControlMode
Union of control-mode types used by group constraint calculations.
Definition: GroupConstraintCalculator.hpp:66
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Definition: BlackoilWellModelConstraints.hpp:37
Per-rate-type production constraints info for a group.
Definition: GroupConstraintCalculator.hpp:105
GroupConstraintCalculator(const BlackoilWellModelGeneric< Scalar, IndexTraits > &well_model, const GroupStateHelperType &group_state_helper)
Construct a calculator bound to one report step and simulator state.
Definition: GroupConstraintCalculator.cpp:34
Based on a group control mode, extract or calculate rates, and provide other conveniences.
Definition: TargetCalculator.hpp:71
Definition: DeferredLogger.hpp:56
Based on a group control mode, extract or calculate rates, and provide other conveniences.
Definition: TargetCalculator.hpp:38
std::optional< ProductionConstraintInfo > groupProductionTarget(const Group &group)
Compute production target for group.
Definition: GroupConstraintCalculator.cpp:78
Definition: GasLiftGroupInfo.hpp:38
DeferredLogger & deferredLogger() const
Get the deferred logger.
Definition: GroupStateHelper.hpp:234
std::optional< InjectionConstraintInfo > groupInjectionTarget(const Group &group, ReservoirCoupling::Phase injection_phase)
Compute injection target for group in the given injection phase.
Definition: GroupConstraintCalculator.cpp:59
Result for an injection constraint with its injection control mode.
Definition: GroupConstraintCalculator.hpp:88
Calculate group-level constraints for production and injection.
Definition: GroupConstraintCalculator.hpp:55
ConstraintType
Type of constraint to calculate: target or limit.
Definition: GroupConstraintCalculator.hpp:73
Shared logic for injector and producer paths.
Definition: GroupConstraintCalculator.hpp:125
std::optional< ProductionConstraintResult > groupProductionConstraints(const Group &group)
Compute per-rate-type production constraints for a group.
Definition: GroupConstraintCalculator.cpp:96
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition: TemperatureModel.hpp:61