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  bool checkThpControl_() const;
252  virtual std::optional<double> computeBhpAtThpLimit_(double alq) const = 0;
253  std::optional<BasicRates> computeInitialWellRates_() const;
254  std::optional<LimitedRates> computeLimitedWellRatesWithALQ_(double alq) const;
255  virtual BasicRates computeWellRates_(double bhp, bool bhp_is_limited, bool debug_output = true) const = 0;
256  std::optional<BasicRates> computeWellRatesWithALQ_(double alq) const;
257  void debugCheckNegativeGradient_(double grad, double alq, double new_alq,
258  double oil_rate, double new_oil_rate,
259  double gas_rate, double new_gas_rate,
260  bool increase) const;
261  void debugPrintWellStateRates() const;
262  void debugShowAlqIncreaseDecreaseCounts_();
263  void debugShowBhpAlqTable_();
264  void debugShowLimitingTargets_(const LimitedRates& rates) const;
265  void debugShowProducerControlMode() const;
266  void debugShowStartIteration_(double alq, bool increase, double oil_rate);
267  void debugShowTargets_();
268  void displayDebugMessage_(const std::string& msg) const override;
269  void displayWarning_(const std::string& warning);
270  std::pair<double, bool> getBhpWithLimit_(double bhp) const;
271  std::pair<double, bool> getGasRateWithLimit_(
272  const BasicRates& rates) const;
273  std::pair<double, bool> getGasRateWithGroupLimit_(
274  double new_gas_rate, double gas_rate) const;
275  std::optional<LimitedRates> getInitialRatesWithLimit_() const;
276  LimitedRates getLimitedRatesFromRates_(const BasicRates& rates) const;
277  std::tuple<double,double,bool,bool> getLiquidRateWithGroupLimit_(
278  const double new_oil_rate, const double oil_rate,
279  const double new_water_rate, const double water_rate) const;
280  std::pair<double, bool> getOilRateWithGroupLimit_(
281  double new_oil_rate, double oil_rate) const;
282  std::pair<double, bool> getOilRateWithLimit_(const BasicRates& rates) const;
283  std::pair<double, std::optional<Rate>> getOilRateWithLimit2_(
284  const BasicRates& rates) const;
285  double getProductionTarget_(Rate rate) const;
286  double getRate_(Rate rate_type, const BasicRates& rates) const;
287  std::pair<double, std::optional<Rate>> getRateWithLimit_(
288  Rate rate_type, const BasicRates& rates) const;
289  std::tuple<double, const std::string*, double> getRateWithGroupLimit_(
290  Rate rate_type, const double new_rate, const double old_rate) const;
291  std::pair<double, bool> getWaterRateWithGroupLimit_(
292  double new_water_rate, double water_rate) const;
293  std::pair<double, bool> getWaterRateWithLimit_(const BasicRates& rates) const;
294  std::pair<double, std::optional<Rate>> getWaterRateWithLimit2_(
295  const BasicRates& rates) const;
296  BasicRates getWellStateRates_() const;
297  bool hasProductionControl_(Rate rate) const;
298  std::pair<LimitedRates, double> increaseALQtoPositiveOilRate_(
299  double alq, const LimitedRates& orig_rates) const;
300  std::pair<LimitedRates, double> increaseALQtoMinALQ_(
301  double alq, const LimitedRates& orig_rates) const;
302  void logSuccess_(double alq,
303  const int iteration_idx);
304  std::pair<LimitedRates, double> maybeAdjustALQbeforeOptimizeLoop_(
305  const LimitedRates& rates, double alq, bool increase) const;
306  std::pair<LimitedRates, double> reduceALQtoGroupAlqLimits_(
307  double alq, const LimitedRates& rates) const;
308  std::pair<LimitedRates, double> reduceALQtoGroupTarget(
309  double alq, const LimitedRates& rates) const;
310  std::pair<LimitedRates, double> reduceALQtoWellTarget_(
311  double alq, const LimitedRates& rates) const;
312  std::unique_ptr<GasLiftWellState> runOptimize1_();
313  std::unique_ptr<GasLiftWellState> runOptimize2_();
314  std::unique_ptr<GasLiftWellState> runOptimizeLoop_(bool increase);
315  void setAlqMinRate_(const GasLiftOpt::Well& well);
316  std::unique_ptr<GasLiftWellState> tryIncreaseLiftGas_();
317  std::unique_ptr<GasLiftWellState> tryDecreaseLiftGas_();
318  void updateGroupRates_(
319  const LimitedRates& rates,
320  const LimitedRates& new_rates,
321  double delta_alq) const;
322  LimitedRates updateRatesToGroupLimits_(
323  const BasicRates& rates, const LimitedRates& new_rates) const;
324  void updateWellStateAlqFixedValue_(const GasLiftOpt::Well& well);
325  bool useFixedAlq_(const GasLiftOpt::Well& well);
326  void debugInfoGroupRatesExceedTarget(
327  Rate rate_type, const std::string& gr_name, double rate, double target) const;
328  void warnMaxIterationsExceeded_();
329 
330  const GroupState& group_state_;
331  const Well& ecl_well_;
332  const SummaryState& summary_state_;
333  GasLiftGroupInfo& group_info_;
334  const PhaseUsage& phase_usage_;
335  GLiftSyncGroups& sync_groups_;
336  const Well::ProductionControls controls_;
337 
338  double increment_;
339  double max_alq_;
340  double min_alq_;
341  double orig_alq_;
342 
343  double alpha_w_;
344  double alpha_g_;
345  double eco_grad_;
346 
347  int gas_pos_;
348  int oil_pos_;
349  int water_pos_;
350 
351  int max_iterations_;
352 
353  std::string well_name_;
354 
355  const GasLiftOpt::Well* gl_well_;
356 
357  bool optimize_;
358  bool debug_limit_increase_decrease_;
359  bool debug_abort_if_decrease_and_oil_is_limited_ = false;
360  bool debug_abort_if_increase_and_gas_is_limited_ = false;
361 };
362 
363 } // namespace Opm
364 
365 #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