opm-common
PiecewiseLinearTwoPhaseMaterial.hpp
Go to the documentation of this file.
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 */
27 #ifndef OPM_PIECEWISE_LINEAR_TWO_PHASE_MATERIAL_HPP
28 #define OPM_PIECEWISE_LINEAR_TWO_PHASE_MATERIAL_HPP
29 
31 
32 #include <opm/common/TimingMacros.hpp>
34 
35 #include <opm/common/utility/gpuDecorators.hpp>
36 
37 #include <cstddef>
38 #include <stdexcept>
39 #include <type_traits>
40 
41 namespace Opm {
52 template <class TraitsT, class ParamsT = PiecewiseLinearTwoPhaseMaterialParams<TraitsT> >
53 class PiecewiseLinearTwoPhaseMaterial : public TraitsT
54 {
55  using ValueVector = typename ParamsT::ValueVector;
56 
57 public:
59  using Traits = TraitsT;
60 
62  using Params = ParamsT;
63 
65  using Scalar = typename Traits::Scalar;
66 
68  static constexpr int numPhases = Traits::numPhases;
69  static_assert(numPhases == 2,
70  "The piecewise linear two-phase capillary pressure law only"
71  "applies to the case of two fluid phases");
72 
75  static constexpr bool implementsTwoPhaseApi = true;
76 
79  static constexpr bool implementsTwoPhaseSatApi = true;
80 
83  static constexpr bool isSaturationDependent = true;
84 
87  static constexpr bool isPressureDependent = false;
88 
91  static constexpr bool isTemperatureDependent = false;
92 
95  static constexpr bool isCompositionDependent = false;
96 
100  template <class Container, class FluidState>
101  OPM_HOST_DEVICE static void capillaryPressures(Container& values, const Params& params, const FluidState& fs)
102  {
103  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
104  using Evaluation = typename std::remove_reference<decltype(values[0])>::type;
105 
106  values[Traits::wettingPhaseIdx] = 0.0; // reference phase
107  values[Traits::nonWettingPhaseIdx] = pcnw<FluidState, Evaluation>(params, fs);
108  }
109 
114  template <class Container, class FluidState>
115  OPM_HOST_DEVICE static void saturations(Container& /* values */, const Params& /* params */, const FluidState& /* fs */)
116  { throw std::logic_error("Not implemented: saturations()"); }
117 
121  template <class Container, class FluidState>
122  OPM_HOST_DEVICE static void relativePermeabilities(Container& values, const Params& params, const FluidState& fs)
123  {
124  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
125  using Evaluation = typename std::remove_reference<decltype(values[0])>::type;
126 
127  values[Traits::wettingPhaseIdx] = krw<FluidState, Evaluation>(params, fs);
128  values[Traits::nonWettingPhaseIdx] = krn<FluidState, Evaluation>(params, fs);
129  }
130 
134  template <class FluidState, class Evaluation = typename FluidState::ValueType>
135  OPM_HOST_DEVICE static Evaluation pcnw(const Params& params, const FluidState& fs)
136  {
137  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
138  const auto& Sw =
139  decay<Evaluation>(fs.saturation(Traits::wettingPhaseIdx));
140 
141  return twoPhaseSatPcnw(params, Sw);
142  }
143 
147  template <class Evaluation>
148  OPM_HOST_DEVICE static Evaluation twoPhaseSatPcnw(const Params& params, const Evaluation& Sw)
149  {
150  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
151  return eval_(params.SwPcwnSamples(), params.pcwnSamples(), Sw);
152  }
153 
154  template <class Evaluation>
155  static Evaluation twoPhaseSatPcnwInv(const Params& params, const Evaluation& pcnw)
156  { return eval_(params.pcwnSamples(), params.SwPcwnSamples(), pcnw); }
157 
161  template <class FluidState, class Evaluation = typename FluidState::ValueType>
162  OPM_HOST_DEVICE static Evaluation Sw(const Params& /* params */, const FluidState& /* fs */)
163  { throw std::logic_error("Not implemented: Sw()"); }
164 
165  template <class Evaluation>
166  OPM_HOST_DEVICE static Evaluation twoPhaseSatSw(const Params& /* params */, const Evaluation& /* pC */)
167  { throw std::logic_error("Not implemented: twoPhaseSatSw()"); }
168 
173  template <class FluidState, class Evaluation = typename FluidState::ValueType>
174  OPM_HOST_DEVICE static Evaluation Sn(const Params& params, const FluidState& fs)
175  { return 1 - Sw<FluidState, Scalar>(params, fs); }
176 
177  template <class Evaluation>
178  OPM_HOST_DEVICE static Evaluation twoPhaseSatSn(const Params& params, const Evaluation& pC)
179  { return 1 - twoPhaseSatSw(params, pC); }
180 
185  template <class FluidState, class Evaluation = typename FluidState::ValueType>
186  OPM_HOST_DEVICE static Evaluation krw(const Params& params, const FluidState& fs)
187  {
188  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
189  const auto& sw =
190  decay<Evaluation>(fs.saturation(Traits::wettingPhaseIdx));
191 
192  return twoPhaseSatKrw(params, sw);
193  }
194 
195  template <class Evaluation>
196  OPM_HOST_DEVICE static Evaluation twoPhaseSatKrw(const Params& params, const Evaluation& Sw)
197  {
198  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
199  return eval_(params.SwKrwSamples(), params.krwSamples(), Sw);
200  }
201 
202  template <class Evaluation>
203  OPM_HOST_DEVICE static Evaluation twoPhaseSatKrwInv(const Params& params, const Evaluation& krw)
204  {
205  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
206  return eval_(params.krwSamples(), params.SwKrwSamples(), krw);
207  }
208 
213  template <class FluidState, class Evaluation = typename FluidState::ValueType>
214  OPM_HOST_DEVICE static Evaluation krn(const Params& params, const FluidState& fs)
215  {
216  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
217  const auto& sw =
218  decay<Evaluation>(fs.saturation(Traits::wettingPhaseIdx));
219 
220  return twoPhaseSatKrn(params, sw);
221  }
222 
223  template <class Evaluation>
224  OPM_HOST_DEVICE static Evaluation twoPhaseSatKrn(const Params& params, const Evaluation& Sw)
225  {
226  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
227  return eval_(params.SwKrnSamples(), params.krnSamples(), Sw);
228  }
229 
230  template <class Evaluation>
231  OPM_HOST_DEVICE static Evaluation twoPhaseSatKrnInv(const Params& params, const Evaluation& krn)
232  { return eval_(params.krnSamples(), params.SwKrnSamples(), krn); }
233 
234  template <class Evaluation>
235  OPM_HOST_DEVICE static std::size_t findSegmentIndex(const ValueVector& xValues, const Evaluation& x){
236  return findSegmentIndex_(xValues, scalarValue(x));
237  }
238 
239  template <class Evaluation>
240  OPM_HOST_DEVICE static std::size_t findSegmentIndexDescending(const ValueVector& xValues, const Evaluation& x){
241  return findSegmentIndexDescending_(xValues, scalarValue(x));
242  }
243 
244  template <class Evaluation>
245  OPM_HOST_DEVICE static Evaluation eval(const ValueVector& xValues, const ValueVector& yValues, const Evaluation& x, unsigned segIdx){
246  Scalar x0 = xValues[segIdx];
247  Scalar x1 = xValues[segIdx + 1];
248 
249  Scalar y0 = yValues[segIdx];
250  Scalar y1 = yValues[segIdx + 1];
251 
252  Scalar m = (y1 - y0)/(x1 - x0);
253 
254  return y0 + (x - x0)*m;
255  }
256 
257 private:
258  template <class Evaluation>
259  OPM_HOST_DEVICE static Evaluation eval_(const ValueVector& xValues,
260  const ValueVector& yValues,
261  const Evaluation& x)
262  {
263  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
264  if (xValues.front() < xValues.back())
265  return evalAscending_(xValues, yValues, x);
266  return evalDescending_(xValues, yValues, x);
267  }
268 
269  template <class Evaluation>
270  OPM_HOST_DEVICE static Evaluation evalAscending_(const ValueVector& xValues,
271  const ValueVector& yValues,
272  const Evaluation& x)
273  {
274  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
275  if (x <= xValues.front())
276  return yValues.front();
277  if (x >= xValues.back())
278  return yValues.back();
279 
280  std::size_t segIdx = findSegmentIndex_(xValues, scalarValue(x));
281 
282  return eval(xValues, yValues, x, segIdx);
283  }
284 
285  template <class Evaluation>
286  OPM_HOST_DEVICE static Evaluation evalDescending_(const ValueVector& xValues,
287  const ValueVector& yValues,
288  const Evaluation& x)
289  {
290  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
291  if (x >= xValues.front())
292  return yValues.front();
293  if (x <= xValues.back())
294  return yValues.back();
295 
296  std::size_t segIdx = findSegmentIndexDescending_(xValues, scalarValue(x));
297 
298  return eval(xValues, yValues, x, segIdx);
299  }
300 
301  template <class Evaluation>
302  OPM_HOST_DEVICE static Evaluation evalDeriv_(const ValueVector& xValues,
303  const ValueVector& yValues,
304  const Evaluation& x)
305  {
306  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
307  if (x <= xValues.front())
308  return 0.0;
309  if (x >= xValues.back())
310  return 0.0;
311 
312  std::size_t segIdx = findSegmentIndex_(xValues, scalarValue(x));
313 
314  Scalar x0 = xValues[segIdx];
315  Scalar x1 = xValues[segIdx + 1];
316 
317  Scalar y0 = yValues[segIdx];
318  Scalar y1 = yValues[segIdx + 1];
319 
320  return (y1 - y0)/(x1 - x0);
321  }
322  template<class ScalarT>
323  OPM_HOST_DEVICE static std::size_t findSegmentIndex_(const ValueVector& xValues, const ScalarT& x)
324  {
325  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
326  assert(xValues.size() > 1); // we need at least two sampling points!
327  std::size_t n = xValues.size() - 1;
328  if (xValues.back() <= x)
329  return n - 1;
330  else if (x <= xValues.front())
331  return 0;
332 
333  // bisection
334  std::size_t lowIdx = 0, highIdx = n;
335  while (lowIdx + 1 < highIdx) {
336  std::size_t curIdx = (lowIdx + highIdx)/2;
337  if (xValues[curIdx] < x)
338  lowIdx = curIdx;
339  else
340  highIdx = curIdx;
341  }
342 
343  return lowIdx;
344  }
345 
346  OPM_HOST_DEVICE static std::size_t findSegmentIndexDescending_(const ValueVector& xValues, Scalar x)
347  {
348  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
349  assert(xValues.size() > 1); // we need at least two sampling points!
350  std::size_t n = xValues.size() - 1;
351  if (x <= xValues.back())
352  return n;
353  else if (xValues.front() <= x)
354  return 0;
355 
356  // bisection
357  std::size_t lowIdx = 0, highIdx = n;
358  while (lowIdx + 1 < highIdx) {
359  std::size_t curIdx = (lowIdx + highIdx)/2;
360  if (xValues[curIdx] >= x)
361  lowIdx = curIdx;
362  else
363  highIdx = curIdx;
364  }
365 
366  return lowIdx;
367  }
368 };
369 
370 } // namespace Opm
371 
372 #endif
static OPM_HOST_DEVICE void saturations(Container &, const Params &, const FluidState &)
The saturations of the fluid phases starting from their pressure differences.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:115
static constexpr bool isTemperatureDependent
Specify whether the quantities defined by this material law are temperature dependent.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:91
A traits class which provides basic mathematical functions for arbitrary scalar floating point values...
static constexpr bool isSaturationDependent
Specify whether the quantities defined by this material law are saturation dependent.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:83
static constexpr bool implementsTwoPhaseApi
Specify whether this material law implements the two-phase convenience API.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:75
static OPM_HOST_DEVICE void relativePermeabilities(Container &values, const Params &params, const FluidState &fs)
The relative permeabilities.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:122
typename Traits::Scalar Scalar
The type of the scalar values for this law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:65
ParamsT Params
The type of the parameter objects for this law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:62
static constexpr bool implementsTwoPhaseSatApi
Specify whether this material law implements the two-phase convenience API which only depends on the ...
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:79
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Implementation of a tabulated, piecewise linear capillary pressure law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:53
static OPM_HOST_DEVICE void capillaryPressures(Container &values, const Params &params, const FluidState &fs)
The capillary pressure-saturation curve.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:101
TraitsT Traits
The traits class for this material law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:59
Specification of the material parameters for a two-phase material law which uses a table and piecewis...
static OPM_HOST_DEVICE Evaluation krn(const Params &params, const FluidState &fs)
The relative permeability for the non-wetting phase of the porous medium.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:214
static OPM_HOST_DEVICE Evaluation krw(const Params &params, const FluidState &fs)
The relative permeability for the wetting phase of the porous medium.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:186
static OPM_HOST_DEVICE Evaluation Sw(const Params &, const FluidState &)
The saturation-capillary pressure curve.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:162
static OPM_HOST_DEVICE Evaluation twoPhaseSatPcnw(const Params &params, const Evaluation &Sw)
The saturation-capillary pressure curve.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:148
static constexpr bool isCompositionDependent
Specify whether the quantities defined by this material law are dependent on the phase composition...
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:95
static OPM_HOST_DEVICE Evaluation pcnw(const Params &params, const FluidState &fs)
The capillary pressure-saturation curve.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:135
static OPM_HOST_DEVICE Evaluation Sn(const Params &params, const FluidState &fs)
Calculate the non-wetting phase saturations depending on the phase pressures.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:174
static constexpr bool isPressureDependent
Specify whether the quantities defined by this material law are dependent on the absolute pressure...
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:87
static constexpr int numPhases
The number of fluid phases.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:68