opm-simulators
WellState.hpp
1 /*
2  Copyright 2014 SINTEF ICT, Applied Mathematics.
3  Copyright 2017 IRIS AS
4 
5  This file is part of the Open Porous Media project (OPM).
6 
7  OPM is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  OPM is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with OPM. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
22 #define OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
23 
24 #include <dune/common/version.hh>
25 #include <dune/common/parallel/mpihelper.hh>
26 
27 #include <opm/common/ErrorMacros.hpp>
28 
29 #include <opm/material/fluidsystems/PhaseUsageInfo.hpp>
30 
31 #include <opm/input/eclipse/Schedule/Events.hpp>
32 
33 #include <opm/output/data/Wells.hpp>
34 
35 #include <opm/simulators/wells/GlobalWellInfo.hpp>
36 #include <opm/simulators/wells/PerfData.hpp>
37 #include <opm/simulators/wells/SegmentState.hpp>
38 #include <opm/simulators/wells/SingleWellState.hpp>
39 #include <opm/simulators/wells/WellContainer.hpp>
40 
41 #include <opm/simulators/utils/ParallelCommunication.hpp>
42 
43 #include <algorithm>
44 #include <cstddef>
45 #include <cstdint>
46 #include <functional>
47 #include <map>
48 #include <optional>
49 #include <string>
50 #include <utility>
51 #include <vector>
52 
53 namespace Opm
54 {
55 
56 template<class Scalar> class ParallelWellInfo;
57 template<class Scalar> struct PerforationData;
58 template<class Scalar> class ConnFracStatistics;
59 class Schedule;
60 enum class WellStatus : std::uint8_t;
61 
64 template<typename Scalar, typename IndexTraits>
65 class WellState
66 {
67 public:
68  struct RsConstInfo
69  {
70  RsConstInfo() = default;
71  RsConstInfo(const bool en, const Scalar val)
72  : enabled { en }
73  , value { val }
74  {}
75 
76  // True when RSCONST-based reporting should be applied.
77  bool enabled {false};
78 
79  // Constant Rs value (surface gas volume per surface oil volume).
80  Scalar value {};
81  };
82 
83  static const std::uint64_t event_mask = ScheduleEvents::WELL_STATUS_CHANGE
84  | ScheduleEvents::PRODUCTION_UPDATE
85  | ScheduleEvents::INJECTION_UPDATE;
86 
87  // TODO: same definition with WellInterface, eventually they should go to a common header file.
88 
89  // TODO: trying to PhasedIdx to make it more explicit as phase index, will evaluate how it goes.
90  // TODO: eventually, we should distinguish phase index and component index
91  static const int waterPhaseIdx = IndexTraits::waterPhaseIdx;
92  static const int oilPhaseIdx = IndexTraits::oilPhaseIdx;
93  static const int gasPhaseIdx = IndexTraits::gasPhaseIdx;
94 
95  // Only usable for testing purposes
96  explicit WellState(const ParallelWellInfo<Scalar>& pinfo);
97 
98  explicit WellState(const PhaseUsageInfo<IndexTraits>& pu)
99  : phaseUsageInfo_(pu)
100  {}
101 
102  static WellState serializationTestObject(const ParallelWellInfo<Scalar>& pinfo);
103 
104  std::size_t size() const
105  {
106  return this->wells_.size();
107  }
108 
109  std::vector<std::string> wells() const
110  {
111  return this->wells_.wells();
112  }
113 
114  int numWells() const
115  {
116  return this->size();
117  }
118 
119  // TODO: temporary naming during development, will change to phaseUsage() later
120  const PhaseUsageInfo<IndexTraits>& phaseUsageInfo() const
121  {
122  return this->phaseUsageInfo_;
123  }
124 
125  const ParallelWellInfo<Scalar>& parallelWellInfo(std::size_t well_index) const;
126 
130  void init(const std::vector<Scalar>& cellPressures,
131  const std::vector<Scalar>& cellTemperatures,
132  const Schedule& schedule,
133  const std::vector<Well>& wells_ecl,
134  const std::vector<std::reference_wrapper<ParallelWellInfo<Scalar>>>& parallel_well_info,
135  const int report_step,
136  const WellState* prevState,
137  const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
138  const SummaryState& summary_state,
139  const bool enableDistributedWells);
140 
141  void resize(const std::vector<Well>& wells_ecl,
142  const std::vector<std::reference_wrapper<ParallelWellInfo<Scalar>>>& parallel_well_info,
143  const Schedule& schedule,
144  const bool handle_ms_well,
145  const std::size_t numCells,
146  const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
147  const SummaryState& summary_state,
148  const bool enable_distributed_wells);
149 
150  void setCurrentWellRates(const std::string& wellName,
151  const std::vector<Scalar>& new_rates)
152  {
153  auto& [owner, rates] = this->well_rates.at(wellName);
154  if (owner)
155  rates = new_rates;
156  }
157 
158  const std::vector<Scalar>& currentWellRates(const std::string& wellName) const;
159 
160  bool hasWellRates(const std::string& wellName) const
161  {
162  return this->well_rates.find(wellName) != this->well_rates.end();
163  }
164 
165  void clearWellRates()
166  {
167  this->well_rates.clear();
168  }
169 
170  void gatherVectorsOnRoot(const std::vector<data::Connection>& from_connections,
171  std::vector<data::Connection>& to_connections,
172  const Parallel::Communication& comm) const;
173 
174  data::Wells
175  report(const int* globalCellIdxMap,
176  const std::function<bool(const int)>& wasDynamicallyClosed,
177  const RsConstInfo& rsConst = RsConstInfo{}) const;
178 
179  void reportConnections(std::vector<data::Connection>& connections,
180  std::size_t well_index,
181  const int* globalCellIdxMap) const;
182 
184  void initWellStateMSWell(const std::vector<Well>& wells_ecl,
185  const WellState* prev_well_state);
186 
187  static void calculateSegmentRates(const ParallelWellInfo<Scalar>& pw_info,
188  const std::vector<std::vector<int>>& segment_inlets,
189  const std::vector<std::vector<int>>& segment_perforations,
190  const std::vector<Scalar>& perforation_rates,
191  const int np,
192  const int segment,
193  std::vector<Scalar>& segment_rates);
194 
195 
196  void communicateGroupRates(const Parallel::Communication& comm);
197 
198  void updateGlobalIsGrup(const Parallel::Communication& comm,
199  const std::vector<WellStatus>& well_status);
200  void updateEfficiencyScalingFactor(const std::string& wellName,
201  const Scalar value);
202 
203  bool isInjectionGrup(const std::string& name) const
204  {
205  return this->global_well_info.value().in_injecting_group(name);
206  }
207 
208  bool isProductionGrup(const std::string& name) const
209  {
210  return this->global_well_info.value().in_producing_group(name);
211  }
212 
213  bool isOpen(const std::string& name) const
214  {
215  return this->global_well_info.value().is_open(name);
216  }
217 
218  Scalar getGlobalEfficiencyScalingFactor(const std::string& name) const
219  {
220  return this->global_well_info.value().efficiency_scaling_factor(name);
221  }
222 
223  // If the ALQ has changed since the previous time step,
224  // reset current_alq and update default_alq. ALQ is used for
225  // constant lift gas injection and for gas lift optimization
226  // (THP controlled wells).
227  void updateWellsDefaultALQ(const Schedule& schedule,
228  const int report_step,
229  const SummaryState& summary_state);
230 
231  void gliftTimeStepInit()
232  {
233  for (size_t i = 0; i < this->size(); ++i) {
234  this->wells_[i].alq_state.reset_count();
235  }
236  }
237 
238 
239  int wellNameToGlobalIdx(const std::string& name)
240  {
241  return this->global_well_info.value().well_index(name);
242  }
243 
244  std::string globalIdxToWellName(const int index)
245  {
246  return this->global_well_info.value().well_name(index);
247  }
248 
249  bool wellIsOwned(std::size_t well_index,
250  const std::string& wellName) const;
251 
252  bool wellIsOwned(const std::string& wellName) const;
253 
254  bool isRank0() const {
255  return this->global_well_info.value().isRank0();
256  }
257 
258  void updateStatus(int well_index, WellStatus status);
259 
260  void openWell(int well_index);
261  void shutWell(int well_index);
262  void stopWell(int well_index);
263 
265  constexpr int numPhases() const
266  {
267  return phaseUsageInfo_.numActivePhases();
268  }
269 
271  std::vector<Scalar>& wellRates(std::size_t well_index)
272  { return this->wells_[well_index].surface_rates; }
273  const std::vector<Scalar>& wellRates(std::size_t well_index) const
274  { return this->wells_[well_index].surface_rates; }
275 
276  const std::string& name(std::size_t well_index) const
277  {
278  return this->wells_.well_name(well_index);
279  }
280 
281  std::optional<std::size_t> index(const std::string& well_name) const
282  {
283  return this->wells_.well_index(well_name);
284  }
285 
286  const SingleWellState<Scalar, IndexTraits>& operator[](std::size_t well_index) const
287  {
288  return this->wells_[well_index];
289  }
290 
291  const SingleWellState<Scalar, IndexTraits>& operator[](const std::string& well_name) const
292  {
293  return this->wells_[well_name];
294  }
295 
296  SingleWellState<Scalar, IndexTraits>& operator[](std::size_t well_index)
297  {
298  return this->wells_[well_index];
299  }
300 
301  SingleWellState<Scalar, IndexTraits>& operator[](const std::string& well_name)
302  {
303  return this->wells_[well_name];
304  }
305 
306  const SingleWellState<Scalar, IndexTraits>& well(std::size_t well_index) const
307  {
308  return this->operator[](well_index);
309  }
310 
311  const SingleWellState<Scalar, IndexTraits>& well(const std::string& well_name) const
312  {
313  return this->operator[](well_name);
314  }
315 
316  SingleWellState<Scalar, IndexTraits>& well(std::size_t well_index)
317  {
318  return this->operator[](well_index);
319  }
320 
321  SingleWellState<Scalar, IndexTraits>& well(const std::string& well_name)
322  {
323  return this->operator[](well_name);
324  }
325 
326  bool has(const std::string& well_name) const
327  {
328  return this->wells_.has(well_name);
329  }
330 
331  bool operator==(const WellState&) const;
332 
333  template<class Serializer>
334  void serializeOp(Serializer& serializer)
335  {
336  serializer(well_rates);
337  if (serializer.isSerializing()) {
338  serializer(wells_.size());
339  } else {
340  std::size_t size = 0;
341  serializer(size);
342  if (size != wells_.size()) {
343  OPM_THROW(std::runtime_error, "Error deserializing WellState: size mismatch");
344  }
345  }
346  for (auto& w : wells_) {
347  serializer(w);
348  }
349  serializer(permanently_inactive_well_names_);
350  }
351 
352  bool is_permanently_inactive_well(const std::string& wname) const {
353  return std::ranges::find(this->permanently_inactive_well_names_, wname) !=
354  this->permanently_inactive_well_names_.end();
355  }
356 
357 private:
358  bool enableDistributedWells_ = false;
359 
360  PhaseUsageInfo<IndexTraits> phaseUsageInfo_;
361 
362  // The wells_ variable is essentially a map of all the wells on the current
363  // process. Observe that since a well can be split over several processes a
364  // well might appear in the WellContainer on different processes.
365  WellContainer<SingleWellState<Scalar, IndexTraits>> wells_;
366 
367  // The members global_well_info and well_rates are map like
368  // structures which will have entries for *all* the wells in the system.
369 
370  // Use of std::optional<> here is a technical crutch, the
371  // WellStateFullyImplicitBlackoil class should be default constructible,
372  // whereas the GlobalWellInfo is not.
373  std::optional<GlobalWellInfo<Scalar>> global_well_info;
374 
375  // The well_rates variable is defined for all wells on all processors. The
376  // bool in the value pair is whether the current process owns the well or
377  // not.
378  std::map<std::string, std::pair<bool, std::vector<Scalar>>> well_rates;
379 
380  // Keep track of permanently inactive well names
381  std::vector<std::string> permanently_inactive_well_names_;
382 
383  data::Segment
384  reportSegmentResults(const int well_id,
385  const int seg_ix,
386  const int seg_no) const;
387 
388 
394  void base_init(const std::vector<Scalar>& cellPressures,
395  const std::vector<Scalar>& cellTemperatures,
396  const std::vector<Well>& wells_ecl,
397  const std::vector<std::reference_wrapper<ParallelWellInfo<Scalar>>>& parallel_well_info,
398  const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
399  const SummaryState& summary_state);
400 
401  void initSingleWell(const std::vector<Scalar>& cellPressures,
402  const std::vector<Scalar>& cellTemperatures,
403  const Well& well,
404  const std::vector<PerforationData<Scalar>>& well_perf_data,
405  const ParallelWellInfo<Scalar>& well_info,
406  const SummaryState& summary_state);
407 
408  void initSingleProducer(const Well& well,
409  const ParallelWellInfo<Scalar>& well_info,
410  Scalar pressure_first_connection,
411  const std::vector<PerforationData<Scalar>>& well_perf_data,
412  const SummaryState& summary_state);
413 
414  void initSingleInjector(const Well& well,
415  const ParallelWellInfo<Scalar>& well_info,
416  Scalar pressure_first_connection,
417  Scalar temperature_first_connection,
418  const std::vector<PerforationData<Scalar>>& well_perf_data,
419  const SummaryState& summary_state);
420 
421  static void calculateSegmentRatesBeforeSum(const ParallelWellInfo<Scalar>& pw_info,
422  const std::vector<std::vector<int>>& segment_inlets,
423  const std::vector<std::vector<int>>& segment_perforations,
424  const std::vector<Scalar>& perforation_rates,
425  const int np,
426  const int segment,
427  std::vector<Scalar>& segment_rates);
428 
429  void reportConnectionFactors(const std::size_t well_index,
430  std::vector<data::Connection>& connections) const;
431 
432  void reportConnectionPressuresAndRates(const std::size_t well_index,
433  std::vector<data::Connection>& connections) const;
434 
435  void reportConnectionFilterCake(const std::size_t well_index,
436  std::vector<data::Connection>& connections) const;
437 
438  void reportFractureStatistics(const std::vector<ConnFracStatistics<Scalar>>& stats,
439  std::vector<data::Connection>& connections) const;
440 };
441 
442 } // namespace Opm
443 
444 // TODO: we are missing pu, while it was not there in the first place
445 #endif // OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
std::vector< Scalar > & wellRates(std::size_t well_index)
One rate per well and phase.
Definition: WellState.hpp:271
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Definition: WellState.hpp:68
Class encapsulating some information about parallel wells.
Definition: MSWellHelpers.hpp:34
Definition: GasLiftGroupInfo.hpp:38
constexpr int numPhases() const
The number of phases present.
Definition: WellState.hpp:265
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition: TemperatureModel.hpp:61