My Project
GasLiftSingleWellGeneric.hpp
1 /*
2  Copyright 2020 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_GASLIFT_SINGLE_WELL_GENERIC_HEADER_INCLUDED
21 #define OPM_GASLIFT_SINGLE_WELL_GENERIC_HEADER_INCLUDED
22 
23 #include <dune/common/version.hh>
24 #include <dune/common/parallel/mpihelper.hh>
25 
26 #include <opm/core/props/BlackoilPhases.hpp>
27 
28 #include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
29 #include <opm/input/eclipse/Schedule/Well/Well.hpp>
30 #include <opm/simulators/wells/GasLiftGroupInfo.hpp>
31 #include <opm/simulators/wells/GasLiftCommon.hpp>
32 
33 #include <functional>
34 #include <optional>
35 #include <string>
36 #include <tuple>
37 #include <vector>
38 #include <utility>
39 
40 namespace Opm
41 {
42 
43 class DeferredLogger;
44 class GasLiftWellState;
45 class Schedule;
46 class SummaryState;
47 class WellInterfaceGeneric;
48 class WellState;
49 class GroupState;
50 
52 {
53 protected:
54  static constexpr int Water = BlackoilPhases::Aqua;
55  static constexpr int Oil = BlackoilPhases::Liquid;
56  static constexpr int Gas = BlackoilPhases::Vapour;
57  static constexpr int NUM_PHASES = 3;
58  static constexpr double ALQ_EPSILON = 1e-8;
59 
60 public:
61  using GLiftSyncGroups = std::set<int>;
62  using Rate = GasLiftGroupInfo::Rate;
63  struct GradInfo
64  {
65  GradInfo() { }
66 
67  GradInfo(double grad_, double new_oil_rate_, bool oil_is_limited_,
68  double new_gas_rate_, bool gas_is_limited_,
69  double new_water_rate_, bool water_is_limited_,
70  double alq_, bool alq_is_limited_) :
71  grad{grad_},
72  new_oil_rate{new_oil_rate_},
73  oil_is_limited{oil_is_limited_},
74  new_gas_rate{new_gas_rate_},
75  gas_is_limited{gas_is_limited_},
76  new_water_rate{new_water_rate_},
77  water_is_limited{water_is_limited_},
78  alq{alq_},
79  alq_is_limited{alq_is_limited_} {}
80  double grad;
81  double new_oil_rate;
82  bool oil_is_limited;
83  double new_gas_rate;
84  bool gas_is_limited;
85  double new_water_rate;
86  bool water_is_limited;
87  double alq;
88  bool alq_is_limited;
89  };
90 
91  virtual ~GasLiftSingleWellGeneric() = default;
92 
93  const std::string& name() const { return well_name_; }
94 
95  std::optional<GradInfo> calcIncOrDecGradient(double oil_rate, double gas_rate,
96  double alq, bool increase) const;
97 
98  std::unique_ptr<GasLiftWellState> runOptimize(const int iteration_idx);
99 
100  virtual const WellInterfaceGeneric& getWell() const = 0;
101 
102 protected:
104  DeferredLogger& deferred_logger,
105  WellState& well_state,
106  const GroupState& group_state,
107  const Well& ecl_well,
108  const SummaryState& summary_state,
109  GasLiftGroupInfo& group_info,
110  const PhaseUsage& phase_usage,
111  const Schedule& schedule,
112  const int report_step_idx,
113  GLiftSyncGroups& sync_groups,
114  const Parallel::Communication& comm,
115  bool glift_debug
116  );
117 
118  struct LimitedRates;
119  struct BasicRates
120  {
121  BasicRates(const BasicRates& rates) :
122  oil{rates.oil},
123  gas{rates.gas},
124  water{rates.water},
125  bhp_is_limited{rates.bhp_is_limited}
126  {}
127  BasicRates(double oil_, double gas_, double water_, bool bhp_is_limited_) :
128  oil{oil_},
129  gas{gas_},
130  water{water_},
131  bhp_is_limited{bhp_is_limited_}
132  {}
133  BasicRates& operator=(const BasicRates& rates) {
134  oil = rates.oil;
135  gas = rates.gas;
136  water = rates.water;
137  bhp_is_limited = rates.bhp_is_limited;
138  return *this;
139  }
140  // This copy constructor cannot be defined inline here since LimitedRates
141  // has not been defined yet (it is defined below). Instead it is defined in
142  // in the .cpp file
143  BasicRates(const LimitedRates& rates);
144  double operator[](Rate rate_type) const {
145  switch (rate_type) {
146  case Rate::oil:
147  return this->oil;
148  case Rate::gas:
149  return this->gas;
150  case Rate::water:
151  return this->water;
152  case Rate::liquid:
153  return this->oil + this->water;
154  default:
155  throw std::runtime_error("This should not happen");
156  }
157  }
158 
159  double oil, gas, water;
160  bool bhp_is_limited;
161  };
162 
163  struct LimitedRates : public BasicRates
164  {
165  enum class LimitType {well, group, none};
166  LimitedRates(
167  double oil_, double gas_, double water_,
168  bool oil_is_limited_, bool gas_is_limited_,
169  bool water_is_limited_, bool bhp_is_limited_,
170  std::optional<Rate> oil_limiting_target_,
171  std::optional<Rate> water_limiting_target_
172  ) :
173  BasicRates(oil_, gas_, water_, bhp_is_limited_),
174  oil_is_limited{oil_is_limited_},
175  gas_is_limited{gas_is_limited_},
176  water_is_limited{water_is_limited_},
177  oil_limiting_target{oil_limiting_target_},
178  water_limiting_target{water_limiting_target_}
179  {
180  set_initial_limit_type_();
181  }
182 
183  LimitedRates(
184  const BasicRates& rates,
185  bool oil_is_limited_, bool gas_is_limited_,
186  bool water_is_limited_
187  ) :
188  BasicRates(rates),
189  oil_is_limited{oil_is_limited_},
190  gas_is_limited{gas_is_limited_},
191  water_is_limited{water_is_limited_}
192  {
193  set_initial_limit_type_();
194  }
195 
196  bool limited() const {
197  return oil_is_limited || gas_is_limited || water_is_limited;
198  }
199  // For a given ALQ value, were the rates limited due to group targets
200  // or due to well targets?
201  LimitType limit_type;
202  bool oil_is_limited;
203  bool gas_is_limited;
204  bool water_is_limited;
205  std::optional<Rate> oil_limiting_target;
206  std::optional<Rate> water_limiting_target;
207  private:
208  void set_initial_limit_type_() {
209  limit_type = limited() ? LimitType::well : LimitType::none;
210  }
211  };
212 
214  {
215  OptimizeState( GasLiftSingleWellGeneric& parent_, bool increase_ ) :
216  parent{parent_},
217  increase{increase_},
218  it{0},
219  stop_iteration{false},
220  bhp{-1}
221  {}
222 
223  GasLiftSingleWellGeneric& parent;
224  bool increase;
225  int it;
226  bool stop_iteration;
227  double bhp;
228 
229  std::pair<std::optional<double>,bool> addOrSubtractAlqIncrement(double alq);
230  double calcEcoGradient(double oil_rate, double new_oil_rate,
231  double gas_rate, double new_gas_rate);
232  bool checkAlqOutsideLimits(double alq, double oil_rate);
233  bool checkEcoGradient(double gradient);
234  bool checkOilRateExceedsTarget(double oil_rate);
235  bool checkRatesViolated(const LimitedRates& rates) const;
236  void debugShowIterationInfo(double alq);
237  double getBhpWithLimit();
238  void warn_(std::string msg) {parent.displayWarning_(msg);}
239  };
240  bool checkGroupALQrateExceeded(double delta_alq) const;
241  bool checkGroupTotalRateExceeded(double delta_alq, double delta_gas_rate) const;
242 
243  std::pair<std::optional<double>, bool> addOrSubtractAlqIncrement_(
244  double alq, bool increase) const;
245  double calcEcoGradient_(double oil_rate, double new_oil_rate,
246  double gas_rate, double new_gas_rate, bool increase) const;
247  bool checkALQequal_(double alq1, double alq2) const;
248  bool checkGroupTargetsViolated(
249  const BasicRates& rates, const BasicRates& new_rates) const;
250  bool checkInitialALQmodified_(double alq, double initial_alq) const;
251  virtual bool checkThpControl_() const = 0;
252  virtual std::optional<double> computeBhpAtThpLimit_(double alq) const = 0;
253  std::pair<std::optional<double>,double> computeConvergedBhpAtThpLimitByMaybeIncreasingALQ_() const;
254  std::pair<std::optional<BasicRates>,double> computeInitialWellRates_() const;
255  std::optional<LimitedRates> computeLimitedWellRatesWithALQ_(double alq) const;
256  virtual BasicRates computeWellRates_(double bhp, bool bhp_is_limited, bool debug_output = true) const = 0;
257  std::optional<BasicRates> computeWellRatesWithALQ_(double alq) const;
258  void debugCheckNegativeGradient_(double grad, double alq, double new_alq,
259  double oil_rate, double new_oil_rate,
260  double gas_rate, double new_gas_rate,
261  bool increase) const;
262  void debugPrintWellStateRates() const;
263  void debugShowAlqIncreaseDecreaseCounts_();
264  void debugShowBhpAlqTable_();
265  void debugShowLimitingTargets_(const LimitedRates& rates) const;
266  void debugShowProducerControlMode() const;
267  void debugShowStartIteration_(double alq, bool increase, double oil_rate);
268  void debugShowTargets_();
269  void displayDebugMessage_(const std::string& msg) const override;
270  void displayWarning_(const std::string& warning);
271  std::pair<double, bool> getBhpWithLimit_(double bhp) const;
272  std::pair<double, bool> getGasRateWithLimit_(
273  const BasicRates& rates) const;
274  std::pair<double, bool> getGasRateWithGroupLimit_(
275  double new_gas_rate, double gas_rate) const;
276  std::pair<std::optional<LimitedRates>,double> getInitialRatesWithLimit_() const;
277  LimitedRates getLimitedRatesFromRates_(const BasicRates& rates) const;
278  std::tuple<double,double,bool,bool> getLiquidRateWithGroupLimit_(
279  const double new_oil_rate, const double oil_rate,
280  const double new_water_rate, const double water_rate) const;
281  std::pair<double, bool> getOilRateWithGroupLimit_(
282  double new_oil_rate, double oil_rate) const;
283  std::pair<double, bool> getOilRateWithLimit_(const BasicRates& rates) const;
284  std::pair<double, std::optional<Rate>> getOilRateWithLimit2_(
285  const BasicRates& rates) const;
286  double getProductionTarget_(Rate rate) const;
287  double getRate_(Rate rate_type, const BasicRates& rates) const;
288  std::pair<double, std::optional<Rate>> getRateWithLimit_(
289  Rate rate_type, const BasicRates& rates) const;
290  std::tuple<double, const std::string*, double> getRateWithGroupLimit_(
291  Rate rate_type, const double new_rate, const double old_rate) const;
292  std::pair<double, bool> getWaterRateWithGroupLimit_(
293  double new_water_rate, double water_rate) const;
294  std::pair<double, bool> getWaterRateWithLimit_(const BasicRates& rates) const;
295  std::pair<double, std::optional<Rate>> getWaterRateWithLimit2_(
296  const BasicRates& rates) const;
297  BasicRates getWellStateRates_() const;
298  bool hasProductionControl_(Rate rate) const;
299  std::pair<LimitedRates, double> increaseALQtoPositiveOilRate_(
300  double alq, const LimitedRates& orig_rates) const;
301  std::pair<LimitedRates, double> increaseALQtoMinALQ_(
302  double alq, const LimitedRates& orig_rates) const;
303  void logSuccess_(double alq,
304  const int iteration_idx);
305  std::pair<LimitedRates, double> maybeAdjustALQbeforeOptimizeLoop_(
306  const LimitedRates& rates, double alq, bool increase) const;
307  std::pair<LimitedRates, double> reduceALQtoGroupAlqLimits_(
308  double alq, const LimitedRates& rates) const;
309  std::pair<LimitedRates, double> reduceALQtoGroupTarget(
310  double alq, const LimitedRates& rates) const;
311  std::pair<LimitedRates, double> reduceALQtoWellTarget_(
312  double alq, const LimitedRates& rates) const;
313  std::unique_ptr<GasLiftWellState> runOptimize1_();
314  std::unique_ptr<GasLiftWellState> runOptimize2_();
315  std::unique_ptr<GasLiftWellState> runOptimizeLoop_(bool increase);
316  void setAlqMinRate_(const GasLiftOpt::Well& well);
317  std::unique_ptr<GasLiftWellState> tryIncreaseLiftGas_();
318  std::unique_ptr<GasLiftWellState> tryDecreaseLiftGas_();
319  void updateGroupRates_(
320  const LimitedRates& rates,
321  const LimitedRates& new_rates,
322  double delta_alq) const;
323  LimitedRates updateRatesToGroupLimits_(
324  const BasicRates& rates, const LimitedRates& new_rates) const;
325  void updateWellStateAlqFixedValue_(const GasLiftOpt::Well& well);
326  bool useFixedAlq_(const GasLiftOpt::Well& well);
327  void debugInfoGroupRatesExceedTarget(
328  Rate rate_type, const std::string& gr_name, double rate, double target) const;
329  void warnMaxIterationsExceeded_();
330 
331  const GroupState& group_state_;
332  const Well& ecl_well_;
333  const SummaryState& summary_state_;
334  GasLiftGroupInfo& group_info_;
335  const PhaseUsage& phase_usage_;
336  GLiftSyncGroups& sync_groups_;
337  const Well::ProductionControls controls_;
338 
339  double increment_;
340  double max_alq_;
341  double min_alq_;
342  double orig_alq_;
343 
344  double alpha_w_;
345  double alpha_g_;
346  double eco_grad_;
347 
348  int gas_pos_;
349  int oil_pos_;
350  int water_pos_;
351 
352  int max_iterations_;
353 
354  std::string well_name_;
355 
356  const GasLiftOpt::Well* gl_well_;
357 
358  bool optimize_;
359  bool debug_limit_increase_decrease_;
360  bool debug_abort_if_decrease_and_oil_is_limited_ = false;
361  bool debug_abort_if_increase_and_gas_is_limited_ = false;
362 };
363 
364 } // namespace Opm
365 
366 #endif // OPM_GASLIFT_SINGLE_WELL_GENERIC_HEADER_INCLUDED
Definition: DeferredLogger.hpp:57
Definition: GasLiftCommon.hpp:32
Definition: GasLiftGroupInfo.hpp:47
Definition: GasLiftSingleWellGeneric.hpp:52
Definition: GroupState.hpp:34
Definition: WellInterfaceGeneric.hpp:51
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition: WellState.hpp:56
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27
Definition: GasLiftSingleWellGeneric.hpp:120
Definition: GasLiftSingleWellGeneric.hpp:64
Definition: GasLiftSingleWellGeneric.hpp:164
Definition: GasLiftSingleWellGeneric.hpp:214
Definition: BlackoilPhases.hpp:46