My Project
WellInterfaceGeneric.hpp
1 /*
2  Copyright 2017 SINTEF Digital, Mathematics and Cybernetics.
3  Copyright 2017 Statoil ASA.
4  Copyright 2017 IRIS
5  Copyright 2019 Norce
6 
7  This file is part of the Open Porous Media project (OPM).
8 
9  OPM is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OPM is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OPM. If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 
24 #ifndef OPM_WELLINTERFACE_GENERIC_HEADER_INCLUDED
25 #define OPM_WELLINTERFACE_GENERIC_HEADER_INCLUDED
26 
27 #include <opm/input/eclipse/Schedule/Well/Well.hpp>
28 
29 #include <map>
30 #include <optional>
31 #include <string>
32 #include <vector>
33 
34 namespace Opm
35 {
36 
37 class DeferredLogger;
38 class GuideRate;
39 class ParallelWellInfo;
40 struct PerforationData;
41 struct PhaseUsage;
42 class SummaryState;
43 class VFPProperties;
44 class WellTestState;
45 class WellState;
46 class SingleWellState;
47 class GroupState;
48 class Group;
49 class Schedule;
50 
52 public:
53 
54  WellInterfaceGeneric(const Well& well,
55  const ParallelWellInfo& parallel_well_info,
56  const int time_step,
57  const int pvtRegionIdx,
58  const int num_components,
59  const int num_phases,
60  const int index_of_well,
61  const std::vector<PerforationData>& perf_data);
62 
64  const std::vector<PerforationData>& perforationData() const;
65 
67  const std::string& name() const;
68 
70  bool isInjector() const;
71 
73  bool isProducer() const;
74 
76  const std::vector<int>& cells() const { return well_cells_; }
77 
79  int indexOfWell() const;
80 
81  void adaptRatesForVFP(std::vector<double>& rates) const;
82 
83  const Well& wellEcl() const;
84  const PhaseUsage& phaseUsage() const;
85 
87  bool underPredictionMode() const;
88 
89  // whether the well is operable
90  bool isOperableAndSolvable() const;
91 
92  void initCompletions();
93  void closeCompletions(const WellTestState& wellTestState);
94 
95  void setVFPProperties(const VFPProperties* vfp_properties_arg);
96  void setGuideRate(const GuideRate* guide_rate_arg);
97  void setWellEfficiencyFactor(const double efficiency_factor);
98  void setRepRadiusPerfLength();
99  void setWsolvent(const double wsolvent);
100  void setDynamicThpLimit(const double thp_limit);
101  void updatePerforatedCell(std::vector<bool>& is_cell_perforated);
102 
104  bool wellHasTHPConstraints(const SummaryState& summaryState) const;
105 
106  void stopWell() {
107  this->wellStatus_ = Well::Status::STOP;
108  }
109 
110  void openWell() {
111  this->wellStatus_ = Well::Status::OPEN;
112  }
113 
114  bool wellIsStopped() const {
115  return this->wellStatus_ == Well::Status::STOP;
116  }
117 
118  int currentStep() const {
119  return this->current_step_;
120  }
121 
122  int pvtRegionIdx() const {
123  return pvtRegionIdx_;
124  }
125 
126  const GuideRate* guideRate() const {
127  return guide_rate_;
128  }
129 
130  int numComponents() const {
131  return num_components_;
132  }
133 
134  int numPhases() const {
135  return number_of_phases_;
136  }
137 
138  int numPerfs() const {
139  return number_of_perforations_;
140  }
141 
142  double refDepth() const {
143  return ref_depth_;
144  }
145 
146  double gravity() const {
147  return gravity_;
148  }
149 
150  const VFPProperties* vfpProperties() const {
151  return vfp_properties_;
152  }
153 
154  const ParallelWellInfo& parallelWellInfo() const {
155  return parallel_well_info_;
156  }
157 
158  const std::vector<double>& perfDepth() const {
159  return perf_depth_;
160  }
161 
162  std::vector<double>& perfDepth() {
163  return perf_depth_;
164  }
165 
166  const std::vector<double>& wellIndex() const {
167  return well_index_;
168  }
169 
170  double getTHPConstraint(const SummaryState& summaryState) const;
171  double getALQ(const WellState& well_state) const;
172  double wsolvent() const;
173 
174  // whether a well is specified with a non-zero and valid VFP table number
175  bool isVFPActive(DeferredLogger& deferred_logger) const;
176 
177  void reportWellSwitching(const SingleWellState& ws, DeferredLogger& deferred_logger) const;
178 
179  bool changedToOpenThisStep() const {
180  return this->changed_to_open_this_step_;
181  }
182  std::optional<double> computeBhpAtThpLimitProdCommon(const std::function<std::vector<double>(const double)>& frates,
183  const SummaryState& summary_state,
184  const double maxPerfPress,
185  const double rho,
186  const double alq_value,
187  DeferredLogger& deferred_logger
188  ) const;
189 
190 
191 
192 protected:
193  bool getAllowCrossFlow() const;
194  double mostStrictBhpFromBhpLimits(const SummaryState& summaryState) const;
195  void updateWellTestStatePhysical(const double simulation_time,
196  const bool write_message_to_opmlog,
197  WellTestState& well_test_state,
198  DeferredLogger& deferred_logger) const;
199 
200  std::optional<double> bhpMax(const std::function<double(const double)>& fflo,
201  const double bhp_limit,
202  const double maxPerfPress,
203  const double vfp_flo_front,
204  DeferredLogger& deferred_logger) const;
205 
206  std::optional<double> computeBhpAtThpLimitCommon(
207  const std::function<std::vector<double>(const double)>& frates,
208  const std::function<double(const std::vector<double>)>& fbhp,
209  const std::array<double, 2>& range,
210  DeferredLogger& deferred_logger) const;
211 
212 
213  bool bruteForceBracket(const std::function<double(const double)>& eq,
214  const std::array<double, 2>& range,
215  double& low, double& high,
216  DeferredLogger& deferred_logger) const;
217 
218  bool bisectBracket(const std::function<double(const double)>& eq,
219  const std::array<double, 2>& range,
220  double& low, double& high,
221  std::optional<double>& approximate_solution,
222  DeferredLogger& deferred_logger) const;
223 
224 
225  // definition of the struct OperabilityStatus
227  bool isOperableAndSolvable() const {
228  if (!operable_under_only_bhp_limit || !solvable || has_negative_potentials) {
229  return false;
230  } else {
231  return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) );
232  }
233  }
234 
235  bool isOperableUnderBHPLimit() const {
236  return operable_under_only_bhp_limit && obey_thp_limit_under_bhp_limit;
237  }
238 
239  bool isOperableUnderTHPLimit() const {
240  return can_obtain_bhp_with_thp_limit && obey_bhp_limit_with_thp_limit;
241  }
242 
243  void resetOperability() {
244  operable_under_only_bhp_limit = true;
245  obey_thp_limit_under_bhp_limit = true;
246  can_obtain_bhp_with_thp_limit = true;
247  obey_bhp_limit_with_thp_limit = true;
248  }
249 
250  // whether the well can be operated under bhp limit
251  // without considering other limits.
252  // if it is false, then the well is not operable for sure.
253  bool operable_under_only_bhp_limit = true;
254  // if the well can be operated under bhp limit, will it obey(not violate)
255  // the thp limit when operated under bhp limit
256  bool obey_thp_limit_under_bhp_limit = true;
257  // whether the well operate under the thp limit only
258  bool can_obtain_bhp_with_thp_limit = true;
259  // whether the well obey bhp limit when operated under thp limit
260  bool obey_bhp_limit_with_thp_limit = true;
261  // the well is solveable
262  bool solvable = true;
263  // the well have non positive potentials
264  bool has_negative_potentials = false;
265  //thp limit violated but not switched
266  mutable bool thp_limit_violated_but_not_switched = false;
267  };
268 
269  OperabilityStatus operability_status_;
270 
271  Well well_ecl_;
272 
273  const ParallelWellInfo& parallel_well_info_;
274  const int current_step_;
275 
276  // The pvt region of the well. We assume
277  // We assume a well to not penetrate more than one pvt region.
278  const int pvtRegionIdx_;
279 
280  const int num_components_;
281 
282  // number of phases
283  int number_of_phases_;
284 
285  // the index of well in Wells struct
286  int index_of_well_;
287 
288  const std::vector<PerforationData>* perf_data_;
289 
290  // the vectors used to describe the inflow performance relationship (IPR)
291  // Q = IPR_A - BHP * IPR_B
292  // TODO: it minght need to go to WellInterface, let us implement it in StandardWell first
293  // it is only updated and used for producers for now
294  mutable std::vector<double> ipr_a_;
295  mutable std::vector<double> ipr_b_;
296 
297  // cell index for each well perforation
298  std::vector<int> well_cells_;
299 
300  // well index for each perforation
301  std::vector<double> well_index_;
302 
303  // number of the perforations for this well
304  int number_of_perforations_;
305 
306  // depth for each perforation
307  std::vector<double> perf_depth_;
308 
309  // representative radius of the perforations, used in shear calculation
310  std::vector<double> perf_rep_radius_;
311 
312  // length of the perforations, use in shear calculation
313  std::vector<double> perf_length_;
314 
315  // well bore diameter
316  std::vector<double> bore_diameters_;
317 
318  /*
319  * completions_ contains the mapping from completion id to connection indices
320  * {
321  * 2 : [ConnectionIndex, ConnectionIndex],
322  * 1 : [ConnectionIndex, ConnectionIndex, ConnectionIndex],
323  * 5 : [ConnectionIndex],
324  * 7 : [ConnectionIndex]
325  * ...
326  * }
327  * The integer IDs correspond to the COMPLETION id given by the COMPLUMP keyword.
328  * When there is no COMPLUMP keyword used, a default completion number will be assigned
329  * based on the order of the declaration of the connections.
330  * Since the connections not OPEN is not included in the Wells, so they will not be considered
331  * in this mapping relation.
332  */
333  std::map<int, std::vector<int>> completions_;
334 
335  // reference depth for the BHP
336  double ref_depth_;
337 
338  // saturation table nubmer for each well perforation
339  std::vector<int> saturation_table_number_;
340 
341  Well::Status wellStatus_;
342 
343  const PhaseUsage* phase_usage_;
344 
345  double gravity_;
346  double wsolvent_;
347  std::optional<double> dynamic_thp_limit_;
348 
349  double well_efficiency_factor_;
350  const VFPProperties* vfp_properties_;
351  const GuideRate* guide_rate_;
352 
353  std::vector< std::string> well_control_log_;
354 
355  bool changed_to_open_this_step_ = false;
356 };
357 
358 }
359 
360 #endif // OPM_WELLINTERFACE_HEADER_INCLUDED
Class encapsulating some information about parallel wells.
Definition: ParallelWellInfo.hpp:252
A thin wrapper class that holds one VFPProdProperties and one VFPInjProperties object.
Definition: VFPProperties.hpp:37
Definition: WellInterfaceGeneric.hpp:51
bool wellHasTHPConstraints(const SummaryState &summaryState) const
Returns true if the well has one or more THP limits/constraints.
Definition: WellInterfaceGeneric.cpp:176
int indexOfWell() const
Index of well in the wells struct and wellState.
Definition: WellInterfaceGeneric.cpp:149
const std::string & name() const
Well name.
Definition: WellInterfaceGeneric.cpp:134
const std::vector< int > & cells() const
Well cells.
Definition: WellInterfaceGeneric.hpp:76
bool underPredictionMode() const
Returns true if the well is currently in prediction mode (i.e. not history mode).
Definition: WellInterfaceGeneric.cpp:231
bool isProducer() const
True if the well is a producer.
Definition: WellInterfaceGeneric.cpp:144
bool isInjector() const
True if the well is an injector.
Definition: WellInterfaceGeneric.cpp:139
const std::vector< PerforationData > & perforationData() const
Get the perforations of the well.
Definition: WellInterfaceGeneric.cpp:129
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27
Definition: BlackoilPhases.hpp:46
Definition: WellInterfaceGeneric.hpp:226