opm-common
Aquifer.hpp
1 /*
2  Copyright 2019 Statoil 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_OUTPUT_AQUIFER_HPP
21 #define OPM_OUTPUT_AQUIFER_HPP
22 
23 #include <cstddef>
24 #include <map>
25 #include <string>
26 #include <unordered_map>
27 #include <variant>
28 #include <vector>
29 
30 namespace Opm { namespace data {
31 
32  enum class AquiferType
33  {
34  Fetkovich, CarterTracy, ConstantFlux, Numerical,
35  };
36 
38  {
39  double initVolume{};
40  double prodIndex{};
41  double timeConstant{};
42 
43  bool operator==(const FetkovichData& other) const;
44 
45  // MessageBufferType API should be similar to Dune::MessageBufferIF
46  template <class MessageBufferType>
47  void write(MessageBufferType& buffer) const;
48 
49  // MessageBufferType API should be similar to Dune::MessageBufferIF
50  template <class MessageBufferType>
51  void read(MessageBufferType& buffer);
52 
53  template<class Serializer>
54  void serializeOp(Serializer& serializer)
55  {
56  serializer(initVolume);
57  serializer(prodIndex);
58  serializer(timeConstant);
59  }
60 
61  static FetkovichData serializationTestObject()
62  {
63  return FetkovichData{1.0, 2.0, 3.0};
64  }
65  };
66 
68  {
69  double timeConstant{};
70  double influxConstant{};
71  double waterDensity{};
72  double waterViscosity{};
73 
74  double dimensionless_time{};
75  double dimensionless_pressure{};
76 
77  bool operator==(const CarterTracyData& other) const;
78 
79  // MessageBufferType API should be similar to Dune::MessageBufferIF
80  template <class MessageBufferType>
81  void write(MessageBufferType& buffer) const;
82 
83  // MessageBufferType API should be similar to Dune::MessageBufferIF
84  template <class MessageBufferType>
85  void read(MessageBufferType& buffer);
86 
87  template<class Serializer>
88  void serializeOp(Serializer& serializer)
89  {
90  serializer(timeConstant);
91  serializer(influxConstant);
92  serializer(waterDensity);
93  serializer(waterViscosity);
94  serializer(dimensionless_time);
95  serializer(dimensionless_pressure);
96  }
97 
98  static CarterTracyData serializationTestObject()
99  {
100  return CarterTracyData{1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
101  }
102  };
103 
105  {
106  std::vector<double> initPressure{};
107 
108  bool operator==(const NumericAquiferData& other) const;
109 
110  // MessageBufferType API should be similar to Dune::MessageBufferIF
111  template <class MessageBufferType>
112  void write(MessageBufferType& buffer) const;
113 
114  // MessageBufferType API should be similar to Dune::MessageBufferIF
115  template <class MessageBufferType>
116  void read(MessageBufferType& buffer);
117 
118  template<class Serializer>
119  void serializeOp(Serializer& serializer)
120  {
121  serializer(initPressure);
122  }
123 
124  static NumericAquiferData serializationTestObject()
125  {
126  return NumericAquiferData{{1.0, 2.0, 3.0}};
127  }
128  };
129 
130  namespace detail {
131  template <AquiferType>
132  struct TypeMap;
133 
134  template <> struct TypeMap<AquiferType::CarterTracy>
135  {
137  };
138 
139  template <> struct TypeMap<AquiferType::Fetkovich>
140  {
141  using Alternative = FetkovichData;
142  };
143 
144  template <> struct TypeMap<AquiferType::Numerical>
145  {
147  };
148 
149  template <AquiferType t>
150  using TypeMap_t = typename TypeMap<t>::Alternative;
151  } // namespace detail
152 
154  {
155  private:
156  template <typename T>
157  bool is() const
158  {
159  return std::holds_alternative<T>(this->options_);
160  }
161 
162  template <typename T>
163  const T* get() const
164  {
165  return this->template is<T>()
166  ? &std::get<T>(this->options_)
167  : nullptr;
168  }
169 
170  template <typename T>
171  T* get()
172  {
173  return this->template is<T>()
174  ? &std::get<T>(this->options_)
175  : nullptr;
176  }
177 
178  public:
179  TypeSpecificData() = default;
180 
181  TypeSpecificData(const TypeSpecificData&) = default;
182  TypeSpecificData(TypeSpecificData&&) = default;
183 
184  TypeSpecificData& operator=(const TypeSpecificData&) = default;
185  TypeSpecificData& operator=(TypeSpecificData&&) = default;
186 
187  bool operator==(const TypeSpecificData& that) const
188  {
189  return std::visit(Equal{}, this->options_, that.options_);
190  }
191 
192  template <AquiferType t>
193  auto* create()
194  {
195  return &this->options_.emplace<detail::TypeMap_t<t>>();
196  }
197 
198  template <AquiferType t>
199  bool is() const
200  {
201  return this->template is<detail::TypeMap_t<t>>();
202  }
203 
204  template <AquiferType t>
205  auto const* get() const
206  {
207  return this->template get<detail::TypeMap_t<t>>();
208  }
209 
210  template <AquiferType t>
211  auto* getMutable()
212  {
213  return this->template get<detail::TypeMap_t<t>>();
214  }
215 
216  template <typename MessageBufferType>
217  void write(MessageBufferType& buffer) const
218  {
219  buffer.write(this->options_.index());
220  std::visit(Write<MessageBufferType>{buffer}, this->options_);
221  }
222 
223  template <typename MessageBufferType>
224  void read(MessageBufferType& buffer)
225  {
226  auto type = 0 * this->options_.index();
227  buffer.read(type);
228 
229  if (type < std::variant_size_v<Types>) {
230  this->create(type);
231 
232  std::visit(Read<MessageBufferType>{buffer}, this->options_);
233  }
234  }
235 
236  template<class Serializer>
237  void serializeOp(Serializer& serializer)
238  {
239  serializer(options_);
240  }
241 
242  private:
243  using Types = std::variant<std::monostate,
247 
248  struct Equal
249  {
250  template <typename T1, typename T2>
251  bool operator()(const T1&, const T2&) const
252  {
253  return false;
254  }
255 
256  template <typename T>
257  bool operator()(const T& e1, const T& e2) const
258  {
259  return e1 == e2;
260  }
261 
262  bool operator()(const std::monostate&,
263  const std::monostate&) const
264  {
265  return true;
266  }
267  };
268 
269  template <typename MessageBufferType>
270  class Read
271  {
272  public:
273  explicit Read(MessageBufferType& buffer)
274  : buffer_{ buffer }
275  {}
276 
277  template <typename T>
278  void operator()(T& alternative)
279  {
280  return alternative.read(this->buffer_);
281  }
282 
283  void operator()(std::monostate&)
284  {}
285 
286  private:
287  MessageBufferType& buffer_;
288  };
289 
290  template <typename MessageBufferType>
291  class Write
292  {
293  public:
294  explicit Write(MessageBufferType& buffer)
295  : buffer_{ buffer }
296  {}
297 
298  template <typename T>
299  void operator()(const T& alternative) const
300  {
301  return alternative.write(this->buffer_);
302  }
303 
304  void operator()(const std::monostate&) const
305  {}
306 
307  private:
308  MessageBufferType& buffer_;
309  };
310 
311  Types options_{};
312 
313  void create(const std::size_t option);
314  };
315 
316  struct AquiferData
317  {
318  int aquiferID = 0; //< One-based ID, range 1..NANAQ
319  double pressure = 0.0; //< Aquifer pressure
320  double fluxRate = 0.0; //< Aquifer influx rate (liquid aquifer)
321  double volume = 0.0; //< Produced liquid volume
322  double initPressure = 0.0; //< Aquifer's initial pressure
323  double datumDepth = 0.0; //< Aquifer's pressure reference depth
324 
325  TypeSpecificData typeData{};
326 
327  double get(const std::string& key) const;
328 
329  bool operator==(const AquiferData& other) const;
330 
331  // MessageBufferType API should be similar to Dune::MessageBufferIF
332  template <class MessageBufferType>
333  void write(MessageBufferType& buffer) const;
334 
335  // MessageBufferType API should be similar to Dune::MessageBufferIF
336  template <class MessageBufferType>
337  void read(MessageBufferType& buffer);
338 
339  template<class Serializer>
340  void serializeOp(Serializer& serializer)
341  {
342  serializer(aquiferID);
343  serializer(pressure);
344  serializer(fluxRate);
345  serializer(volume);
346  serializer(initPressure);
347  serializer(datumDepth);
348  serializer(typeData);
349  }
350 
351  static AquiferData serializationTestObjectF()
352  {
353  auto aquifer = AquiferData {1, 123.456, 56.78, 9.0e10, 290.0, 2515.5};
354  auto* aquFet = aquifer.typeData.create<AquiferType::Fetkovich>();
355  aquFet->initVolume = 1.23;
356  aquFet->prodIndex = 45.67;
357  aquFet->timeConstant = 890.123;
358 
359  return aquifer;
360  }
361 
362  static AquiferData serializationTestObjectC()
363  {
364  auto aquifer = AquiferData {2, 123.456, 56.78, 9.0e10, 290.0, 2515.5};
365  auto* aquCT = aquifer.typeData.create<AquiferType::CarterTracy>();
366 
367  aquCT->timeConstant = 987.65;
368  aquCT->influxConstant = 43.21;
369  aquCT->waterDensity = 1014.5;
370  aquCT->waterViscosity = 0.00318;
371  aquCT->dimensionless_time = 42.0;
372  aquCT->dimensionless_pressure = 2.34;
373 
374  return aquifer;
375  }
376 
377  static AquiferData serializationTestObjectN()
378  {
379  auto aquifer = AquiferData {3, 123.456, 56.78, 9.0e10, 290.0, 2515.5};
380  auto* aquNum = aquifer.typeData.create<AquiferType::Numerical>();
381 
382  aquNum->initPressure = {1.234, 2.345, 3.4, 9.876};
383 
384  return aquifer;
385  }
386 
387  private:
388  using GetSummaryValue = double (AquiferData::*)() const;
389  using SummaryValueDispatchTable = std::unordered_map<std::string, GetSummaryValue>;
390 
391  static SummaryValueDispatchTable summaryValueDispatchTable_;
392 
393  double aquiferFlowRate() const;
394  double aquiferPressure() const;
395  double aquiferTotalProduction() const;
396  double carterTracyDimensionlessTime() const;
397  double carterTracyDimensionlessPressure() const;
398  };
399 
400  // TODO: not sure what extension we will need
401  using Aquifers = std::map<int, AquiferData>;
402 
403  template <class MessageBufferType>
404  void FetkovichData::write(MessageBufferType& buffer) const
405  {
406  buffer.write(this->initVolume);
407  buffer.write(this->prodIndex);
408  buffer.write(this->timeConstant);
409  }
410 
411  template <class MessageBufferType>
412  void FetkovichData::read(MessageBufferType& buffer)
413  {
414  buffer.read(this->initVolume);
415  buffer.read(this->prodIndex);
416  buffer.read(this->timeConstant);
417  }
418 
419  template <class MessageBufferType>
420  void CarterTracyData::write(MessageBufferType& buffer) const
421  {
422  buffer.write(this->timeConstant);
423  buffer.write(this->influxConstant);
424  buffer.write(this->waterDensity);
425  buffer.write(this->waterViscosity);
426  buffer.write(this->dimensionless_time);
427  buffer.write(this->dimensionless_pressure);
428  }
429 
430  template <class MessageBufferType>
431  void CarterTracyData::read(MessageBufferType& buffer)
432  {
433  buffer.read(this->timeConstant);
434  buffer.read(this->influxConstant);
435  buffer.read(this->waterDensity);
436  buffer.read(this->waterViscosity);
437  buffer.read(this->dimensionless_time);
438  buffer.read(this->dimensionless_pressure);
439  }
440 
441  template <class MessageBufferType>
442  void NumericAquiferData::write(MessageBufferType& buffer) const
443  {
444  buffer.write(this->initPressure.size());
445 
446  for (const auto& pressure : this->initPressure) {
447  buffer.write(pressure);
448  }
449  }
450 
451  template <class MessageBufferType>
452  void NumericAquiferData::read(MessageBufferType& buffer)
453  {
454  decltype(this->initPressure.size()) size{};
455  buffer.read(size);
456 
457  this->initPressure.resize(size, 0.0);
458  for (auto& pressure : this->initPressure) {
459  buffer.read(pressure);
460  }
461  }
462 
463  template <class MessageBufferType>
464  void AquiferData::write(MessageBufferType& buffer) const
465  {
466  buffer.write(this->aquiferID);
467  buffer.write(this->pressure);
468  buffer.write(this->fluxRate);
469  buffer.write(this->volume);
470  buffer.write(this->initPressure);
471  buffer.write(this->datumDepth);
472 
473  this->typeData.write(buffer);
474  }
475 
476  template <class MessageBufferType>
477  void AquiferData::read(MessageBufferType& buffer)
478  {
479  buffer.read(this->aquiferID);
480  buffer.read(this->pressure);
481  buffer.read(this->fluxRate);
482  buffer.read(this->volume);
483  buffer.read(this->initPressure);
484  buffer.read(this->datumDepth);
485 
486  this->typeData.read(buffer);
487  }
488 }} // Opm::data
489 
490 #endif // OPM_OUTPUT_AQUIFER_HPP
Definition: Aquifer.hpp:67
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Definition: Aquifer.hpp:132
Definition: Aquifer.hpp:37
Definition: CriticalError.hpp:115
Definition: Aquifer.hpp:316
Definition: Aquifer.hpp:153
Definition: Aquifer.hpp:104
Class for (de-)serializing.
Definition: Serializer.hpp:94