My Project
GasLiftSingleWell_impl.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 namespace Opm {
21 
22 template<typename TypeTag>
23 GasLiftSingleWell<TypeTag>::
24 GasLiftSingleWell(const StdWell &std_well,
25  const Simulator &ebos_simulator,
26  const SummaryState &summary_state,
27  DeferredLogger &deferred_logger,
28  WellState &well_state,
29  const GroupState &group_state,
30  GasLiftGroupInfo &group_info,
31  GLiftSyncGroups &sync_groups
32  )
33  // The parent class GasLiftSingleWellGeneric contains all stuff
34  // that is not dependent on TypeTag
35  : GasLiftSingleWellGeneric(
36  deferred_logger,
37  well_state,
38  group_state,
39  std_well.wellEcl(),
40  summary_state,
41  group_info,
42  ebos_simulator.vanguard().schedule(),
43  ebos_simulator.episodeIndex(),
44  sync_groups
45  )
46  , ebos_simulator_{ebos_simulator}
47  , std_well_{std_well}
48 {
49  const auto& gl_well = *gl_well_;
50  if(useFixedAlq_(gl_well)) {
51  updateWellStateAlqFixedValue_(gl_well);
52  this->optimize_ = false; // lift gas supply is fixed
53  }
54  else {
55  setAlqMaxRate_(gl_well);
56  this->optimize_ = true;
57  }
58 
59  const auto& pu = std_well_.phaseUsage();
60  this->oil_pos_ = pu.phase_pos[Oil];
61  this->gas_pos_ = pu.phase_pos[Gas];
62  this->water_pos_ = pu.phase_pos[Water];
63  // get the alq value used for this well for the previous iteration (a
64  // nonlinear iteration in assemble() in BlackoilWellModel).
65  // If gas lift optimization has not been applied to this well yet, the
66  // default value is used.
67  this->orig_alq_ = this->well_state_.getALQ(this->well_name_);
68  if(this->optimize_) {
69  setAlqMinRate_(gl_well);
70  // NOTE: According to item 4 in WLIFTOPT, this value does not
71  // have to be positive.
72  // TODO: Does it make sense to have a negative value?
73  this->alpha_w_ = gl_well.weight_factor();
74  if (this->alpha_w_ <= 0 ) {
75  displayWarning_("Nonpositive value for alpha_w ignored");
76  this->alpha_w_ = 1.0;
77  }
78 
79  // NOTE: According to item 6 in WLIFTOPT:
80  // "If this value is greater than zero, the incremental gas rate will influence
81  // the calculation of the incremental gradient and may be used
82  // to discourage the allocation of lift gas to wells which produce more gas."
83  // TODO: Does this mean that we should ignore this value if it
84  // is negative?
85  this->alpha_g_ = gl_well.inc_weight_factor();
86 
87  // TODO: adhoc value.. Should we keep max_iterations_ as a safety measure
88  // or does it not make sense to have it?
89  this->max_iterations_ = 1000;
90  }
91 }
92 
93 /****************************************
94  * Private methods in alphabetical order
95  ****************************************/
96 
97 template<typename TypeTag>
98 void
99 GasLiftSingleWell<TypeTag>::
100 computeWellRates_(
101  double bhp, std::vector<double> &potentials, bool debug_output) const
102 {
103  // NOTE: If we do not clear the potentials here, it will accumulate
104  // the new potentials to the old values..
105  std::fill(potentials.begin(), potentials.end(), 0.0);
106  this->std_well_.computeWellRatesWithBhp(
107  this->ebos_simulator_, bhp, potentials, this->deferred_logger_);
108  if (debug_output) {
109  const std::string msg = fmt::format("computed well potentials given bhp {}, "
110  "oil: {}, gas: {}, water: {}", bhp,
111  -potentials[this->oil_pos_], -potentials[this->gas_pos_],
112  -potentials[this->water_pos_]);
113  displayDebugMessage_(msg);
114  }
115 }
116 
117 template<typename TypeTag>
118 std::optional<double>
119 GasLiftSingleWell<TypeTag>::
120 computeBhpAtThpLimit_(double alq) const
121 {
122  auto bhp_at_thp_limit = this->std_well_.computeBhpAtThpLimitProdWithAlq(
123  this->ebos_simulator_,
124  this->summary_state_,
125  this->deferred_logger_,
126  alq);
127  if (bhp_at_thp_limit) {
128  if (*bhp_at_thp_limit < this->controls_.bhp_limit) {
129  const std::string msg = fmt::format(
130  "Computed bhp ({}) from thp limit is below bhp limit ({}), (ALQ = {})."
131  " Using bhp limit instead",
132  *bhp_at_thp_limit, this->controls_.bhp_limit, alq);
133  displayDebugMessage_(msg);
134  bhp_at_thp_limit = this->controls_.bhp_limit;
135  }
136  //bhp_at_thp_limit = std::max(*bhp_at_thp_limit, this->controls_.bhp_limit);
137  }
138  else {
139  const std::string msg = fmt::format(
140  "Failed in getting converged bhp potential from thp limit (ALQ = {})", alq);
141  displayDebugMessage_(msg);
142  }
143  return bhp_at_thp_limit;
144 }
145 
146 template<typename TypeTag>
147 void
148 GasLiftSingleWell<TypeTag>::
149 setAlqMaxRate_(const GasLiftOpt::Well &well)
150 {
151  auto& max_alq_optional = well.max_rate();
152  if (max_alq_optional) {
153  // NOTE: To prevent extrapolation of the VFP tables, any value
154  // entered here must not exceed the largest ALQ value in the well's VFP table.
155  this->max_alq_ = *max_alq_optional;
156  }
157  else { // i.e. WLIFTOPT, item 3 has been defaulted
158  // According to the manual for WLIFTOPT, item 3:
159  // The default value should be set to the largest ALQ
160  // value in the well's VFP table
161  const auto& table = std_well_.vfp_properties_->getProd()->getTable(
162  this->controls_.vfp_table_number);
163  const auto& alq_values = table.getALQAxis();
164  // Assume the alq_values are sorted in ascending order, so
165  // the last item should be the largest value:
166  this->max_alq_ = alq_values.back();
167  }
168 }
169 
170 }
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:26