opm-simulators
AquiferConstantFlux.hpp
1 /*
2  Copyright (C) 2023 Equinor
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_AQUIFERCONSTANTFLUX_HPP
21 #define OPM_AQUIFERCONSTANTFLUX_HPP
22 
23 #include <opm/simulators/aquifers/AquiferInterface.hpp>
24 
25 #include <opm/input/eclipse/EclipseState/Aquifer/Aquancon.hpp>
26 #include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
27 
28 #include <opm/material/common/MathToolbox.hpp>
29 #include <opm/material/densead/Evaluation.hpp>
30 
31 #include <cassert>
32 #include <numeric>
33 #include <vector>
34 
35 namespace Opm {
36 
37 template<typename TypeTag>
38 class AquiferConstantFlux : public AquiferInterface<TypeTag>
39 {
40 public:
45  using BlackoilIndices = GetPropType<TypeTag, Properties::Indices>;
47 
48  static constexpr int numEq = BlackoilIndices::numEq;
50  AquiferConstantFlux(const std::vector<Aquancon::AquancCell>& connections,
51  const Simulator& simulator,
52  const SingleAquiferFlux& aquifer)
53  : AquiferInterface<TypeTag>(aquifer.id, simulator)
54  , connections_ (connections)
55  , aquifer_data_ (aquifer)
56  , connection_flux_ (connections_.size(), Eval{0})
57  {
58  this->total_face_area_ = this->initializeConnections();
59  }
60 
61  static AquiferConstantFlux serializationTestObject(const Simulator& simulator)
62  {
63  AquiferConstantFlux<TypeTag> result({}, simulator, {});
64  result.cumulative_flux_ = 1.0;
65 
66  return result;
67  }
68 
69  void computeFaceAreaFraction(const std::vector<Scalar>& total_face_area) override
70  {
71  assert (total_face_area.size() >= static_cast<typename std::vector<Scalar>::size_type>(this->aquiferID()));
72 
73  this->area_fraction_ = this->totalFaceArea()
74  / total_face_area[this->aquiferID() - 1];
75  }
76 
77  Scalar totalFaceArea() const override
78  {
79  return this->total_face_area_;
80  }
81 
82  void updateAquifer(const SingleAquiferFlux& aquifer)
83  {
84  aquifer_data_ = aquifer;
85  }
86 
87  void initFromRestart(const data::Aquifers& aquiferSoln) override
88  {
89  auto xaqPos = aquiferSoln.find(this->aquiferID());
90  if (xaqPos == aquiferSoln.end()) {
91  return;
92  }
93 
94  this->cumulative_flux_ = this->area_fraction_ * xaqPos->second.volume;
95  }
96 
97  void initialSolutionApplied() override
98  {}
99 
100  void beginTimeStep() override
101  {}
102 
103  void endTimeStep() override
104  {
105  this->flux_rate_ = this->totalFluxRate();
106  this->cumulative_flux_ +=
107  this->flux_rate_ * this->simulator_.timeStepSize();
108  }
109 
110  data::AquiferData aquiferData() const override
111  {
112  data::AquiferData data;
113 
114  data.aquiferID = this->aquifer_data_.id;
115 
116  // Pressure for constant flux aquifer is 0
117  data.pressure = 0.0;
118  data.fluxRate = this->totalFluxRate();
119 
120  data.volume = this->cumulative_flux_;
121 
122  // not totally sure whether initPressure matters
123  data.initPressure = 0.0;
124 
125  return data;
126  }
127 
128  void addToSource(RateVector& rates,
129  const unsigned cellIdx,
130  [[maybe_unused]] const unsigned timeIdx) override
131  {
132  const int idx = this->cellToConnectionIdx_[cellIdx];
133  if (idx < 0) {
134  return;
135  }
136 
137  const auto& model = this->simulator_.model();
138 
139  const auto fw = this->aquifer_data_.flux;
140 
141  this->connection_flux_[idx] = fw * this->connections_[idx].effective_facearea;
142 
143  rates[BlackoilIndices::conti0EqIdx + compIdx_()]
144  += this->connection_flux_[idx] / model.dofTotalVolume(cellIdx);
145  }
146 
147  template<class Serializer>
148  void serializeOp(Serializer& serializer)
149  {
150  serializer(cumulative_flux_);
151  }
152 
153  bool operator==(const AquiferConstantFlux& rhs) const
154  {
155  return this->cumulative_flux_ == rhs.cumulative_flux_;
156  }
157 
158 private:
159  const std::vector<Aquancon::AquancCell>& connections_;
160 
161  SingleAquiferFlux aquifer_data_;
162  std::vector<Eval> connection_flux_{};
163  std::vector<int> cellToConnectionIdx_{};
164  Scalar flux_rate_{};
165  Scalar cumulative_flux_{};
166  Scalar total_face_area_{0.0};
167  Scalar area_fraction_{1.0};
168 
169  Scalar initializeConnections()
170  {
171  auto connected_face_area = 0.0;
172 
173  this->cellToConnectionIdx_
174  .resize(this->simulator_.gridView().size(/*codim=*/0), -1);
175 
176  for (std::size_t idx = 0; idx < this->connections_.size(); ++idx) {
177  const auto global_index = this->connections_[idx].global_index;
178  const int cell_index = this->simulator_.vanguard()
179  .compressedIndexForInterior(global_index);
180 
181  if (cell_index < 0) {
182  continue;
183  }
184 
185  this->cellToConnectionIdx_[cell_index] = idx;
186 
187  connected_face_area += this->connections_[idx].effective_facearea;
188  }
189 
190  // TODO: At the moment, we are using the effective_facearea from the
191  // parser. Should we update the facearea here if the grid changed
192  // during the preprocessing?
193 
194  return connected_face_area;
195  }
196 
197  Scalar computeFaceAreaFraction(const Scalar connected_face_area) const
198  {
199  const auto tot_face_area = this->simulator_.vanguard()
200  .grid().comm().sum(connected_face_area);
201 
202  return (tot_face_area > 0.0)
203  ? connected_face_area / tot_face_area
204  : 0.0;
205  }
206 
207  // TODO: this is a function from AquiferAnalytical
208  int compIdx_() const
209  {
210  if (this->co2store_or_h2store_())
211  return FluidSystem::oilCompIdx;
212 
213  return FluidSystem::waterCompIdx;
214  }
215 
216  Scalar totalFluxRate() const
217  {
218  return std::accumulate(this->connection_flux_.begin(),
219  this->connection_flux_.end(), 0.0,
220  [](const Scalar rate, const auto& q)
221  {
222  return rate + getValue(q);
223  });
224  }
225 };
226 
227 } // namespace Opm
228 
229 #endif //OPM_AQUIFERCONSTANTFLUX_HPP
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(...))
Definition: propertysystem.hh:233
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Definition: AquiferInterface.hpp:34
Definition: AquiferConstantFlux.hpp:38