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