opm-simulators
AquiferFetkovich.hpp
1 /*
2 Copyright 2017 TNO - Heat Transfer & Fluid Dynamics, Modelling & Optimization of the Subsurface
3 Copyright 2017 Statoil ASA.
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_AQUIFETP_HEADER_INCLUDED
22 #define OPM_AQUIFETP_HEADER_INCLUDED
23 
24 #include <opm/simulators/aquifers/AquiferAnalytical.hpp>
25 
26 #include <opm/input/eclipse/EclipseState/Aquifer/Aquifetp.hpp>
27 
28 #include <opm/output/data/Aquifer.hpp>
29 
30 #include <stdexcept>
31 #include <vector>
32 
33 namespace Opm
34 {
35 
36 template <typename TypeTag>
37 class AquiferFetkovich : public AquiferAnalytical<TypeTag>
38 {
39 
40 public:
42 
43  using typename Base::BlackoilIndices;
44  using typename Base::ElementContext;
45  using typename Base::Eval;
46  using typename Base::FluidState;
47  using typename Base::FluidSystem;
48  using typename Base::IntensiveQuantities;
49  using typename Base::RateVector;
50  using typename Base::Scalar;
51  using typename Base::Simulator;
52  using typename Base::ElementMapper;
53 
54  AquiferFetkovich(const std::vector<Aquancon::AquancCell>& connections,
55  const Simulator& simulator,
56  const Aquifetp::AQUFETP_data& aqufetp_data)
57  : Base(aqufetp_data.aquiferID, connections, simulator)
58  , aqufetp_data_(aqufetp_data)
59  {
60  }
61 
62  static AquiferFetkovich serializationTestObject(const Simulator& simulator)
63  {
64  AquiferFetkovich result({}, simulator, {});
65 
66  result.pressure_previous_ = {1.0, 2.0, 3.0};
67  result.pressure_current_ = {4.0, 5.0};
68  result.Qai_ = {{6.0}};
69  result.rhow_ = 7.0;
70  result.W_flux_ = 8.0;
71  result.aquifer_pressure_ = 9.0;
72 
73  return result;
74  }
75 
76  void endTimeStep() override
77  {
78  for (const auto& q : this->Qai_) {
79  this->W_flux_ += q * this->simulator_.timeStepSize();
80  }
81  aquifer_pressure_ = aquiferPressure();
82  }
83 
84  data::AquiferData aquiferData() const override
85  {
86  // TODO: how to unify the two functions?
87  auto data = data::AquiferData{};
88 
89  data.aquiferID = this->aquiferID();
90  data.pressure = this->aquifer_pressure_;
91  data.fluxRate = std::accumulate(this->Qai_.begin(), this->Qai_.end(), 0.0,
92  [](const double flux, const auto& q) -> double
93  {
94  return flux + q.value();
95  });
96  data.volume = this->W_flux_.value();
97  data.initPressure = this->pa0_;
98 
99  auto* aquFet = data.typeData.template create<data::AquiferType::Fetkovich>();
100  aquFet->initVolume = this->aqufetp_data_.initial_watvolume;
101  aquFet->prodIndex = this->aqufetp_data_.prod_index;
102  aquFet->timeConstant = this->aqufetp_data_.timeConstant();
103 
104  return data;
105  }
106 
107  template<class Serializer>
108  void serializeOp(Serializer& serializer)
109  {
110  serializer(static_cast<Base&>(*this));
111  serializer(aquifer_pressure_);
112  }
113 
114  bool operator==(const AquiferFetkovich& rhs) const
115  {
116  return static_cast<const Base&>(*this) == rhs &&
117  this->aquifer_pressure_ == rhs.aquifer_pressure_;
118  }
119 
120 protected:
121  // Aquifer Fetkovich Specific Variables
122  Aquifetp::AQUFETP_data aqufetp_data_;
123  Scalar aquifer_pressure_; // aquifer
124 
125  void assignRestartData(const data::AquiferData& xaq) override
126  {
127  if (! xaq.typeData.is<data::AquiferType::Fetkovich>()) {
128  throw std::invalid_argument {
129  "Analytic aquifer data for unexpected aquifer "
130  "type passed to Fetkovich aquifer"
131  };
132  }
133 
134  this->aquifer_pressure_ = xaq.pressure;
135  this->rhow_ = this->aqufetp_data_.waterDensity();
136  }
137 
138  inline Eval dpai(int idx)
139  {
140  const auto gdz =
141  this->gravity_() * (this->cell_depth_[idx] - this->aquiferDepth());
142 
143  return this->aquifer_pressure_ + this->rhow_*gdz
144  - this->pressure_current_.at(idx);
145  }
146 
147  // This function implements Eq 5.12 of the EclipseTechnicalDescription
148  inline Scalar aquiferPressure()
149  {
150  Scalar Flux = this->W_flux_.value();
151 
152  const auto& comm = this->simulator_.vanguard().grid().comm();
153  comm.sum(&Flux, 1);
154 
155  const auto denom =
156  this->aqufetp_data_.total_compr * this->aqufetp_data_.initial_watvolume;
157 
158  return this->pa0_ - (Flux / denom);
159  }
160 
161  inline void calculateAquiferConstants() override
162  {
163  this->Tc_ = this->aqufetp_data_.timeConstant();
164  }
165 
166  // This function implements Eq 5.14 of the EclipseTechnicalDescription
167  inline void calculateInflowRate(int idx, const Simulator& simulator) override
168  {
169  const Scalar td_Tc_ = simulator.timeStepSize() / this->Tc_;
170  const Scalar coef = (1 - exp(-td_Tc_)) / td_Tc_;
171 
172  this->Qai_.at(idx) = coef * this->alphai_[idx] *
173  this->aqufetp_data_.prod_index * dpai(idx);
174  }
175 
176  inline void calculateAquiferCondition() override
177  {
178  if (this->solution_set_from_restart_) {
179  return;
180  }
181 
182  if (! this->aqufetp_data_.initial_pressure.has_value()) {
183  this->aqufetp_data_.initial_pressure =
184  this->calculateReservoirEquilibrium();
185 
186  const auto& tables = this->simulator_.vanguard()
187  .eclState().getTableManager();
188 
189  this->aqufetp_data_.finishInitialisation(tables);
190  }
191 
192  this->rhow_ = this->aqufetp_data_.waterDensity();
193  this->pa0_ = this->aqufetp_data_.initial_pressure.value();
194  if (this->aqufetp_data_.initial_temperature.has_value())
195  this->Ta0_ = this->aqufetp_data_.initial_temperature.value();
196  this->aquifer_pressure_ = this->pa0_;
197  }
198 
199  virtual Scalar aquiferDepth() const override
200  {
201  return this->aqufetp_data_.datum_depth;
202  }
203 }; // Class AquiferFetkovich
204 
205 } // namespace Opm
206 
207 #endif
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Definition: AquiferFetkovich.hpp:37
Definition: AquiferAnalytical.hpp:56