opm-simulators
GenericThresholdPressure_impl.hpp
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
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 2 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  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
23 #ifndef OPM_GENERIC_THRESHOLD_PRESSURE_IMPL_HPP
24 #define OPM_GENERIC_THRESHOLD_PRESSURE_IMPL_HPP
25 
27 
28 #include <dune/grid/common/mcmgmapper.hh>
29 #include <dune/grid/common/rangegenerators.hh>
30 
31 #include <opm/common/ErrorMacros.hpp>
32 
33 #include <opm/input/eclipse/EclipseState/EclipseState.hpp>
34 #include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
35 #include <opm/input/eclipse/EclipseState/Tables/Eqldims.hpp>
36 #include <opm/input/eclipse/EclipseState/SimulationConfig/SimulationConfig.hpp>
37 #include <opm/input/eclipse/EclipseState/SimulationConfig/ThresholdPressure.hpp>
38 
39 #include <fmt/format.h>
40 
41 #include <algorithm>
42 #include <cstddef>
43 #include <limits>
44 #include <stdexcept>
45 
46 namespace Opm {
47 
48 template<class Grid, class GridView, class ElementMapper, class Scalar>
49 GenericThresholdPressure<Grid,GridView,ElementMapper,Scalar>::
50 GenericThresholdPressure(const CartesianIndexMapper& cartMapper,
51  const GridView& gridView,
52  const ElementMapper& elementMapper,
53  const EclipseState& eclState)
54  : cartMapper_(cartMapper)
55  , gridView_(gridView)
56  , elementMapper_(elementMapper)
57  , lookUpData_(gridView)
58  , lookUpCartesianData_(gridView, cartMapper_)
59  , eclState_(eclState)
60 {
61 }
62 
63 template<class Grid, class GridView, class ElementMapper,class Scalar>
64 Scalar GenericThresholdPressure<Grid,GridView,ElementMapper,Scalar>::
65 thresholdPressure(int elem1Idx, int elem2Idx) const
66 {
67  if (!enableThresholdPressure_)
68  return 0.0;
69 
70  // threshold pressure accross faults
71  if (!thpresftValues_.empty()) {
72 
73  int fault1Idx = lookUpCartesianData_(elem1Idx, cartElemFaultIdx_);
74  int fault2Idx = lookUpCartesianData_(elem2Idx, cartElemFaultIdx_);
75 
76  if (fault1Idx != -1 && fault1Idx == fault2Idx) {
77  // inside a fault there's no threshold pressure, even accross EQUIL
78  // regions.
79  return 0.0;
80  }
81  if (fault1Idx != fault2Idx) {
82  // TODO: which value if a cell is part of multiple faults? we take
83  // the maximum here.
84  Scalar val1 = (fault1Idx >= 0) ? thpresftValues_[fault1Idx] : 0.0;
85  Scalar val2 = (fault2Idx >= 0) ? thpresftValues_[fault2Idx] : 0.0;
86  return std::max(val1, val2);
87  }
88  }
89 
90  // threshold pressure accross EQUIL regions
91  auto equilRegion1Idx = elemEquilRegion_[elem1Idx];
92  auto equilRegion2Idx = elemEquilRegion_[elem2Idx];
93 
94  if (equilRegion1Idx == equilRegion2Idx) {
95  return 0.0;
96  }
97 
98  return thpres_[equilRegion1Idx*numEquilRegions_ + equilRegion2Idx];
99 }
100 
101 template<class Grid, class GridView, class ElementMapper, class Scalar>
104 {
105  const auto& simConfig = eclState_.getSimulationConfig();
106 
107  enableThresholdPressure_ = simConfig.useThresholdPressure();
108  if (!enableThresholdPressure_) {
109  return;
110  }
111 
112  numEquilRegions_ = eclState_.getTableManager().getEqldims().getNumEquilRegions();
113  const decltype(numEquilRegions_) maxRegions =
114  std::numeric_limits<std::decay_t<decltype(elemEquilRegion_[0])>>::max();
115 
116  if (numEquilRegions_ > maxRegions) {
117  // make sure that the index of an equilibration region can be stored
118  // in the vector
119  OPM_THROW(std::invalid_argument,
120  (fmt::format("The maximum number of supported "
121  "equilibration regions by OPM flow is {}, but "
122  "{} are used!",
123  maxRegions, numEquilRegions_)));
124  }
125 
126  if (numEquilRegions_ > 2048) {
127  // warn about performance
128  OpmLog::warning(fmt::format("Number of equilibration regions is {}, which is "
129  "rather large. Note, that this might "
130  "have a negative impact on performance "
131  "and memory consumption.", numEquilRegions_));
132  }
133 
134  // internalize the data specified using the EQLNUM keyword
135  elemEquilRegion_ = lookUpData_.
136  template assignFieldPropsIntOnLeaf<short unsigned int>(eclState_.fieldProps(),
137  "EQLNUM", true);
138 
139  /*
140  If this is a restart run the ThresholdPressure object will be active,
141  and already properly initialized with numerical values from the restart.
142  Done using GenericThresholdPressure::setFromRestart() in EclWriter::beginRestart().
143  */
144  if (simConfig.getThresholdPressure().restart()) {
145  return;
146  }
147 
148  // allocate the array which specifies the threshold pressures
149  thpres_.resize(numEquilRegions_*numEquilRegions_, 0.0);
150  thpresDefault_.resize(numEquilRegions_*numEquilRegions_, 0.0);
151 }
152 
153 template<class Grid, class GridView, class ElementMapper, class Scalar>
156 {
157  const SimulationConfig& simConfig = eclState_.getSimulationConfig();
158  const auto& thpres = simConfig.getThresholdPressure();
159 
160  // set the threshold pressures for all EQUIL region boundaries which have a
161  // intersection in the grid
162  for (const auto& elem : elements(gridView_, Dune::Partitions::interior)) {
163  for (const auto& intersection : intersections(gridView_, elem)) {
164  if (intersection.boundary()) {
165  continue; // ignore boundary intersections for now (TODO?)
166  }
167  else if (!intersection.neighbor()) { // processor boundary but not domain boundary
168  continue;
169  }
170 
171  const auto& inside = intersection.inside();
172  const auto& outside = intersection.outside();
173 
174  auto equilRegionInside = elemEquilRegion_[elementMapper_.index(inside)];
175  auto equilRegionOutside = elemEquilRegion_[elementMapper_.index(outside)];
176 
177  if (thpres.hasRegionBarrier(equilRegionInside + 1, equilRegionOutside + 1)) {
178  Scalar pth = 0.0;
179  if (thpres.hasThresholdPressure(equilRegionInside + 1, equilRegionOutside + 1)) {
180  // threshold pressure explicitly specified
181  pth = thpres.getThresholdPressure(equilRegionInside + 1, equilRegionOutside + 1);
182  }
183  else {
184  // take the threshold pressure from the initial condition
185  unsigned offset = equilRegionInside*numEquilRegions_ + equilRegionOutside;
186  pth = thpresDefault_[offset];
187  }
188 
189  unsigned offset1 = equilRegionInside*numEquilRegions_ + equilRegionOutside;
190  unsigned offset2 = equilRegionOutside*numEquilRegions_ + equilRegionInside;
191 
192  thpres_[offset1] = pth;
193  if (!thpres.irreversible()) {
194  thpres_[offset2] = pth;
195  }
196  }
197  }
198  }
199 
200  // apply threshold pressures across faults
201  if (thpres.ftSize() > 0) {
202  configureThpresft_();
203  }
204 }
205 
206 template<class Grid, class GridView, class ElementMapper, class Scalar>
207 void GenericThresholdPressure<Grid,GridView,ElementMapper,Scalar>::
208 configureThpresft_()
209 {
210  // retrieve the faults collection.
211  const FaultCollection& faults = eclState_.getFaults();
212  const SimulationConfig& simConfig = eclState_.getSimulationConfig();
213  const auto& thpres = simConfig.getThresholdPressure();
214 
215  // extract the multipliers
216  int numFaults = faults.size();
217  int numCartesianElem = eclState_.getInputGrid().getCartesianSize();
218  thpresftValues_.resize(numFaults, -1.0);
219  cartElemFaultIdx_.resize(numCartesianElem, -1);
220  for (std::size_t faultIdx = 0; faultIdx < faults.size(); ++faultIdx) {
221  const auto& fault = faults.getFault(faultIdx);
222  thpresftValues_[faultIdx] = thpres.getThresholdPressureFault(faultIdx);
223  for (const FaultFace& face : fault) {
224  // "face" is a misnomer because the object describes a set of cell
225  // indices, but we go with the conventions of the parser here...
226  for (std::size_t cartElemIdx : face) {
227  cartElemFaultIdx_[cartElemIdx] = faultIdx;
228  }
229  }
230  }
231 }
232 
233 template<class Grid, class GridView, class ElementMapper, class Scalar>
234 std::vector<Scalar>
235 GenericThresholdPressure<Grid,GridView,ElementMapper,Scalar>::
236 getRestartVector() const
237 {
238  if (!enableThresholdPressure_) {
239  return {};
240  }
241 
242  return this->thpres_;
243 }
244 
245 template<class Grid, class GridView, class ElementMapper, class Scalar>
246 bool
249 {
250  return this->enableThresholdPressure_;
251 }
252 
253 
254 template<class Grid, class GridView, class ElementMapper, class Scalar>
255 void
256 GenericThresholdPressure<Grid,GridView,ElementMapper,Scalar>::
257 logPressures()
258 {
259  if (!enableThresholdPressure_) {
260  return;
261  }
262 
263  auto lineFormat = [this](unsigned i, unsigned j, double val)
264  {
265  const auto& units = eclState_.getUnits();
266  return fmt::format("{:4}{:>6}{:23}{:>6}{:24}{:>11.07}{:7}{}\n",
267  " ", i,
268  " ", j,
269  " ", units.from_si(UnitSystem::measure::pressure, val),
270  " ", units.name(UnitSystem::measure::pressure));
271  };
272  auto lineFormatS = [](auto s1, auto s2, auto s3)
273  {
274  return fmt::format("{:4}{:^16}{:13}{:^9}{:21}{:^18}\n",
275  " ", s1, " ", s2, " ", s3);
276  };
277 
278  std::string str = "\nLIST OF ALL NON-ZERO THRESHOLD PRESSURES\n"
279  "----------------------------------------\n"
280  "\n";
281  str += lineFormatS("FLOW FROM REGION", "TO REGION", "THRESHOLD PRESSURE");
282  str += lineFormatS(std::string(16, '-'), std::string(9, '-'), std::string(18, '-'));
283  const auto& simConfig = eclState_.getSimulationConfig();
284  const auto& thpres = simConfig.getThresholdPressure();
285 
286  for (unsigned i = 1; i <= numEquilRegions_; ++i) {
287  for (unsigned j = (thpres.irreversible() ? 1 : i); j <= numEquilRegions_; ++j) {
288  if (thpres.hasRegionBarrier(i, j)) {
289  if (thpres.hasThresholdPressure(i, j)) {
290  str += lineFormat(i, j, thpres.getThresholdPressure(i, j));
291  }
292  else {
293  std::size_t idx = (i - 1) * numEquilRegions_ + (j - 1);
294  str += lineFormat(i, j, this->thpresDefault_[idx]);
295  }
296  }
297  }
298  }
299  str += lineFormatS(std::string(16, '-'), std::string(9, '-'), std::string(18, '-'));
300  OpmLog::note(str);
301 }
302 
303 } // namespace Opm
304 
305 #endif // OPM_GENERIC_THRESHOLD_PRESSURE_IMPL_HPP
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
Definition: GenericThresholdPressure.hpp:43