opm-simulators
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 #include <opm/simulators/flow/BlackoilModelParameters.hpp>
29 #include <opm/simulators/wells/RuntimePerforation.hpp>
30 
31 #include <map>
32 #include <optional>
33 #include <string>
34 #include <vector>
35 
36 namespace Opm
37 {
38 
39 class DeferredLogger;
40 class GuideRate;
41 template<class Scalar> class ParallelWellInfo;
42 template<class Scalar> struct PerforationData;
43 class SummaryState;
44 template<typename Scalar, typename IndexTraits> class VFPProperties;
45 class WellTestState;
46 template<typename Scalar, typename IndexTraits> class WellState;
47 template<typename Scalar, typename IndexTraits> class SingleWellState;
48 class Group;
49 class Schedule;
50 template<typename IndexTraits> class PhaseUsageInfo;
51 
52 template<typename Scalar, typename IndexTraits>
53 class WellInterfaceGeneric {
54 public:
55  using ModelParameters = BlackoilModelParameters<Scalar>;
56 
57  using WellStateType = WellState<Scalar, IndexTraits>;
58 
59  WellInterfaceGeneric(const Well& well,
60  const ParallelWellInfo<Scalar>& parallel_well_info,
61  const int time_step,
62  const ModelParameters& param,
63  const int pvtRegionIdx,
64  const int num_conservation_quantities,
65  const int num_phases,
66  const int index_of_well,
67  const PhaseUsageInfo<IndexTraits>& phase_usage,
68  const std::vector<PerforationData<Scalar>>& perf_data);
69 
70  virtual ~WellInterfaceGeneric() = default;
71 
73  const std::vector<PerforationData<Scalar>>& perforationData() const;
74 
76  const std::string& name() const;
77 
79  bool isInjector() const;
80 
82  bool isProducer() const;
83 
85  const std::vector<int>& cells() const { return well_cells_; }
86 
88  int indexOfWell() const;
89 
90  void adaptRatesForVFP(std::vector<Scalar>& rates) const;
91 
92  const Well& wellEcl() const;
93  Well& wellEcl();
94  const PhaseUsageInfo<IndexTraits>& phaseUsage() const;
95 
97  bool underPredictionMode() const;
98 
99  // whether the well is operable
100  bool isOperableAndSolvable() const;
101  bool useVfpExplicit () const;
102  bool thpLimitViolatedButNotSwitched() const;
103 
104  void initCompletions();
105  void closeCompletions(const WellTestState& wellTestState);
106 
107  void setVFPProperties(const VFPProperties<Scalar, IndexTraits>* vfp_properties_arg);
108  void setPrevSurfaceRates(WellStateType& well_state,
109  const WellStateType& prev_well_state) const;
110  void setGuideRate(const GuideRate* guide_rate_arg);
111  void setWellEfficiencyFactor(const Scalar efficiency_factor);
112  void setRepRadiusPerfLength();
113  void setWsolvent(const Scalar wsolvent);
114  void setDynamicThpLimit(const Scalar thp_limit);
115  std::optional<Scalar> getDynamicThpLimit() const;
116  void setDynamicThpLimit(const std::optional<Scalar> thp_limit);
117  void updatePerforatedCell(std::vector<bool>& is_cell_perforated);
118 
120  bool wellHasTHPConstraints(const SummaryState& summaryState) const;
121 
122  void stopWell() { this->wellStatus_ = Well::Status::STOP; }
123  void openWell() { this->wellStatus_ = Well::Status::OPEN; }
124  Well::Status wellStatus() { return this->wellStatus_;}
125 
126  bool wellIsStopped() const { return this->wellStatus_ == Well::Status::STOP; }
127 
128  int currentStep() const { return this->current_step_; }
129 
130  int pvtRegionIdx() const { return pvtRegionIdx_; }
131 
132  const GuideRate* guideRate() const { return guide_rate_; }
133 
134  int numConservationQuantities() const { return num_conservation_quantities_; }
135 
136  int numPhases() const { return number_of_phases_; }
137 
138  int numLocalPerfs() const { return number_of_local_perforations_; }
139 
140  Scalar refDepth() const { return ref_depth_; }
141 
142  Scalar gravity() const { return gravity_; }
143 
144  const VFPProperties<Scalar, IndexTraits>* vfpProperties() const { return vfp_properties_; }
145 
146  const ParallelWellInfo<Scalar>& parallelWellInfo() const { return parallel_well_info_; }
147 
148  const std::vector<Scalar>& perfDepth() const { return perf_depth_; }
149 
150  std::vector<Scalar>& perfDepth() { return perf_depth_; }
151 
152  const std::vector<Scalar>& wellIndex() const { return well_index_; }
153 
154  const std::map<int,std::vector<int>>& getCompletions() const { return completions_; }
155 
156  Scalar getTHPConstraint(const SummaryState& summaryState) const;
157  Scalar getALQ(const WellStateType& well_state) const;
158  Scalar wsolvent() const;
159  Scalar rsRvInj() const;
160 
161  // at the beginning of the time step, we check what inj_multiplier from the previous running
162  void initInjMult(const std::vector<Scalar>& max_inj_mult);
163 
164  // update the InjMult information at the end of the time step, so it can be used for later.
165  void updateInjMult(std::vector<Scalar>& inj_multipliers,
166  DeferredLogger& deferred_logger) const;
167 
168  // Note:: for multisegment wells, bhp is actually segment pressure in practice based on observation
169  // it might change in the future
170  Scalar getInjMult(const int local_perf_index, const Scalar bhp, const Scalar perf_pres, DeferredLogger& dlogger) const;
171 
172  // whether a well is specified with a non-zero and valid VFP table number
173  bool isVFPActive(DeferredLogger& deferred_logger) const;
174 
175  void reportWellSwitching(const SingleWellState<Scalar, IndexTraits>& ws,
176  DeferredLogger& deferred_logger) const;
177 
178  bool changedToOpenThisStep() const { return this->changed_to_open_this_step_; }
179 
180  void updateWellTestState(const SingleWellState<Scalar, IndexTraits>& ws,
181  const double& simulationTime,
182  const bool& writeMessageToOPMLog,
183  const bool zero_group_target,
184  WellTestState& wellTestState,
185  DeferredLogger& deferred_logger) const;
186 
187  bool isPressureControlled(const WellStateType& well_state) const;
188 
189  Scalar wellEfficiencyFactor() const { return well_efficiency_factor_; }
190 
192  void updateFilterCakeMultipliers(const std::vector<Scalar>& inj_fc_multiplier)
193  {
194  inj_fc_multiplier_ = inj_fc_multiplier;
195  }
196 
197  void resetWellOperability();
198 
199  virtual std::vector<Scalar> getPrimaryVars() const
200  {
201  return {};
202  }
203 
204  virtual int setPrimaryVars(typename std::vector<Scalar>::const_iterator)
205  {
206  return 0;
207  }
208 
209  virtual Scalar connectionDensity(const int globalConnIdx,
210  const int openConnIdx) const = 0;
211 
212  void addPerforations(const std::vector<RuntimePerforation>& perfs);
213 
214 protected:
215  bool getAllowCrossFlow() const;
216 
217  Scalar wmicrobes_() const;
218  Scalar wfoam_() const;
219  Scalar woxygen_() const;
220  Scalar wpolymer_() const;
221  Scalar wsalt_() const;
222  Scalar wurea_() const;
223 
224  int polymerTable_() const;
225  int polymerInjTable_() const;
226  int polymerWaterTable_() const;
227 
228  bool wellUnderZeroRateTargetIndividual(const SummaryState& summary_state,
229  const WellState<Scalar, IndexTraits>& well_state) const;
230 
231  bool wellUnderGroupControl(const SingleWellState<Scalar, IndexTraits>& ws) const;
232 
233  std::pair<bool,bool>
234  computeWellPotentials(std::vector<Scalar>& well_potentials,
235  const WellStateType& well_state);
236 
237  void checkNegativeWellPotentials(std::vector<Scalar>& well_potentials,
238  const bool checkOperability,
239  DeferredLogger& deferred_logger);
240 
241  // Remove all other controls than THP and BHP
242  void onlyKeepBHPandTHPcontrols(const SummaryState& summary_state,
243  WellStateType& well_state,
244  Well::InjectionControls& inj_controls,
245  Well::ProductionControls& prod_controls) const;
246 
247  void resetDampening()
248  {
249  std::ranges::fill(this->inj_multiplier_damp_factor_, 1.0);
250  }
251 
252  // definition of the struct OperabilityStatus
254  {
255  bool isOperableAndSolvable() const
256  {
257  if (!operable_under_only_bhp_limit || !solvable || has_negative_potentials) {
258  return false;
259  }
260 
261  return isOperableUnderBHPLimit() || isOperableUnderTHPLimit();
262  }
263 
264  bool isOperableUnderBHPLimit() const
265  {
266  return operable_under_only_bhp_limit && obey_thp_limit_under_bhp_limit;
267  }
268 
269  bool isOperableUnderTHPLimit() const
270  {
271  return can_obtain_bhp_with_thp_limit && obey_bhp_limit_with_thp_limit;
272  }
273 
274  void resetOperability()
275  {
276  operable_under_only_bhp_limit = true;
277  obey_thp_limit_under_bhp_limit = true;
278  can_obtain_bhp_with_thp_limit = true;
279  obey_bhp_limit_with_thp_limit = true;
280  }
281 
282  // whether the well can be operated under bhp limit
283  // without considering other limits.
284  // if it is false, then the well is not operable for sure.
285  bool operable_under_only_bhp_limit = true;
286  // if the well can be operated under bhp limit, will it obey(not violate)
287  // the thp limit when operated under bhp limit
288  bool obey_thp_limit_under_bhp_limit = true;
289  // whether the well operate under the thp limit only
290  bool can_obtain_bhp_with_thp_limit = true;
291  // whether the well obey bhp limit when operated under thp limit
292  bool obey_bhp_limit_with_thp_limit = true;
293  // the well is solveable
294  bool solvable = true;
295  // the well have non positive potentials
296  bool has_negative_potentials = false;
297  //thp limit violated but not switched
298  mutable bool thp_limit_violated_but_not_switched = false;
299 
300  bool use_vfpexplicit = false;
301  };
302 
303  OperabilityStatus operability_status_;
304 
305  Well well_ecl_;
306 
307  const ParallelWellInfo<Scalar>& parallel_well_info_;
308  const int current_step_;
309  const ModelParameters& param_;
310 
311  // The pvt region of the well. We assume
312  // We assume a well to not penetrate more than one pvt region.
313  const int pvtRegionIdx_;
314 
315  const int num_conservation_quantities_;
316 
317  // number of phases
318  int number_of_phases_;
319 
320  // the index of well in Wells struct
321  int index_of_well_;
322 
323  const PhaseUsageInfo<IndexTraits>& phase_usage_;
324 
325  const std::vector<PerforationData<Scalar>>* perf_data_;
326 
327  // the vectors used to describe the inflow performance relationship (IPR)
328  // Q = IPR_A - BHP * IPR_B
329  // TODO: it minght need to go to WellInterface, let us implement it in StandardWell first
330  // it is only updated and used for producers for now
331  mutable std::vector<Scalar> ipr_a_;
332  mutable std::vector<Scalar> ipr_b_;
333 
334  // cell index for each well perforation
335  std::vector<int> well_cells_;
336 
337  // well index for each perforation
338  std::vector<Scalar> well_index_;
339 
340  // number of the perforations for this well on this process
341  int number_of_local_perforations_;
342 
343  // depth for each perforation
344  std::vector<Scalar> perf_depth_;
345 
346  // representative radius of the perforations, used in shear calculation
347  std::vector<Scalar> perf_rep_radius_;
348 
349  // length of the perforations, use in shear calculation
350  std::vector<Scalar> perf_length_;
351 
352  // well bore diameter
353  std::vector<Scalar> bore_diameters_;
354 
355  /*
356  * completions_ contains the mapping from completion id to connection indices
357  * {
358  * 2 : [ConnectionIndex, ConnectionIndex],
359  * 1 : [ConnectionIndex, ConnectionIndex, ConnectionIndex],
360  * 5 : [ConnectionIndex],
361  * 7 : [ConnectionIndex]
362  * ...
363  * }
364  * The integer IDs correspond to the COMPLETION id given by the COMPLUMP keyword.
365  * When there is no COMPLUMP keyword used, a default completion number will be assigned
366  * based on the order of the declaration of the connections.
367  * Since the connections not OPEN is not included in the Wells, so they will not be considered
368  * in this mapping relation.
369  */
370  std::map<int, std::vector<int>> completions_;
371 
372  // reference depth for the BHP
373  Scalar ref_depth_;
374 
375  // saturation table nubmer for each well perforation
376  std::vector<int> saturation_table_number_;
377 
378  Well::Status wellStatus_;
379 
380  Scalar gravity_;
381  Scalar wsolvent_;
382  std::optional<Scalar> dynamic_thp_limit_;
383 
384  // recording the multiplier calculate from the keyword WINJMULT during the time step
385  mutable std::vector<Scalar> inj_multiplier_;
386 
387  // the injection multiplier from the previous running, it is mostly used for CIRR mode
388  // which intends to keep the fracturing open
389  std::vector<Scalar> prev_inj_multiplier_;
390 
391  // WINJMULT multipliers for previous iteration (used for oscillation detection)
392  mutable std::vector<Scalar> inj_multiplier_previter_;
393  // WINJMULT dampening factors (used in case of oscillations)
394  mutable std::vector<Scalar> inj_multiplier_damp_factor_;
395 
396  // the multiplier due to injection filtration cake
397  std::vector<Scalar> inj_fc_multiplier_;
398 
399  Scalar well_efficiency_factor_;
400  const VFPProperties<Scalar, IndexTraits>* vfp_properties_;
401  const GuideRate* guide_rate_;
402 
403  std::vector<std::string> well_control_log_;
404 
405  bool changed_to_open_this_step_ = true;
406 };
407 
408 }
409 
410 #endif // OPM_WELLINTERFACE_GENERIC_HEADER_INCLUDED
const std::vector< PerforationData< Scalar > > & perforationData() const
Get the perforations of the well.
Definition: WellInterfaceGeneric.cpp:160
const std::vector< int > & cells() const
Well cells.
Definition: WellInterfaceGeneric.hpp:85
A thin wrapper class that holds one VFPProdProperties and one VFPInjProperties object.
Definition: BlackoilWellModelGeneric.hpp:74
Definition: WellInterfaceGeneric.hpp:253
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Solver parameters for the BlackoilModel.
Definition: BlackoilModelParameters.hpp:193
int indexOfWell() const
Index of well in the wells struct and wellState.
Definition: WellInterfaceGeneric.cpp:185
Class encapsulating some information about parallel wells.
Definition: MSWellHelpers.hpp:34
Definition: GasLiftGroupInfo.hpp:38
void updateFilterCakeMultipliers(const std::vector< Scalar > &inj_fc_multiplier)
Update filter cake multipliers.
Definition: WellInterfaceGeneric.hpp:192
const std::string & name() const
Well name.
Definition: WellInterfaceGeneric.cpp:167
bool isInjector() const
True if the well is an injector.
Definition: WellInterfaceGeneric.cpp:173
bool isProducer() const
True if the well is a producer.
Definition: WellInterfaceGeneric.cpp:179
bool wellHasTHPConstraints(const SummaryState &summaryState) const
Returns true if the well has one or more THP limits/constraints.
Definition: WellInterfaceGeneric.cpp:324
bool underPredictionMode() const
Returns true if the well is currently in prediction mode (i.e. not history mode). ...
Definition: WellInterfaceGeneric.cpp:371