opm-common
EclDefaultMaterial.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_ECL_DEFAULT_MATERIAL_HPP
28 #define OPM_ECL_DEFAULT_MATERIAL_HPP
29 
30 #include <opm/common/TimingMacros.hpp>
31 
32 #include <opm/common/utility/gpuDecorators.hpp>
36 
37 #include <algorithm>
38 #include <stdexcept>
39 #include <type_traits>
40 
41 namespace Opm {
42 
56 template <class TraitsT,
57  class GasOilMaterialLawT,
58  class OilWaterMaterialLawT,
59  class ParamsT = EclDefaultMaterialParams<TraitsT,
60  typename GasOilMaterialLawT::Params,
61  typename OilWaterMaterialLawT::Params> >
62 class EclDefaultMaterial : public TraitsT
63 {
64 public:
65  using GasOilMaterialLaw = GasOilMaterialLawT;
66  using OilWaterMaterialLaw = OilWaterMaterialLawT;
67 
68  // some safety checks
69  static_assert(TraitsT::numPhases == 3,
70  "The number of phases considered by this capillary pressure "
71  "law is always three!");
72  static_assert(GasOilMaterialLaw::numPhases == 2,
73  "The number of phases considered by the gas-oil capillary "
74  "pressure law must be two!");
75  static_assert(OilWaterMaterialLaw::numPhases == 2,
76  "The number of phases considered by the oil-water capillary "
77  "pressure law must be two!");
78  static_assert(std::is_same<typename GasOilMaterialLaw::Scalar,
79  typename OilWaterMaterialLaw::Scalar>::value,
80  "The two two-phase capillary pressure laws must use the same "
81  "type of floating point values.");
82 
83  static_assert(GasOilMaterialLaw::implementsTwoPhaseSatApi,
84  "The gas-oil material law must implement the two-phase saturation "
85  "only API to for the default Ecl capillary pressure law!");
86  static_assert(OilWaterMaterialLaw::implementsTwoPhaseSatApi,
87  "The oil-water material law must implement the two-phase saturation "
88  "only API to for the default Ecl capillary pressure law!");
89 
90  using Traits = TraitsT;
91  using Params = ParamsT;
92  using Scalar = typename Traits::Scalar;
93 
94  static constexpr int numPhases = 3;
95  static constexpr int waterPhaseIdx = Traits::wettingPhaseIdx;
96  static constexpr int oilPhaseIdx = Traits::nonWettingPhaseIdx;
97  static constexpr int gasPhaseIdx = Traits::gasPhaseIdx;
98 
101  static constexpr bool implementsTwoPhaseApi = false;
102 
105  static constexpr bool implementsTwoPhaseSatApi = false;
106 
109  static constexpr bool isSaturationDependent = true;
110 
113  static constexpr bool isPressureDependent = false;
114 
117  static constexpr bool isTemperatureDependent = false;
118 
121  static constexpr bool isCompositionDependent = false;
122 
137  template <class ContainerT, class FluidState, class ...Args>
138  OPM_HOST_DEVICE static void capillaryPressures(ContainerT& values,
139  const Params& params,
140  const FluidState& state)
141  {
142  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
143  using Evaluation = typename std::remove_reference<decltype(values[0])>::type;
144  values[gasPhaseIdx] = pcgn<FluidState, Evaluation, Args...>(params, state);
145  values[oilPhaseIdx] = 0;
146  values[waterPhaseIdx] = - pcnw<FluidState, Evaluation, Args...>(params, state);
147 
148  Valgrind::CheckDefined(values[gasPhaseIdx]);
149  Valgrind::CheckDefined(values[oilPhaseIdx]);
150  Valgrind::CheckDefined(values[waterPhaseIdx]);
151  }
152 
153  /*
154  * Hysteresis parameters for oil-water
155  * @see EclHysteresisTwoPhaseLawParams::soMax(...)
156  * @see EclHysteresisTwoPhaseLawParams::swMax(...)
157  * @see EclHysteresisTwoPhaseLawParams::swMin(...)
158  * \param params Parameters
159  */
160  static void oilWaterHysteresisParams(Scalar& soMax,
161  Scalar& swMax,
162  Scalar& swMin,
163  const Params& params)
164  {
165  if constexpr (Traits::enableHysteresis) {
166  soMax = 1.0 - params.oilWaterParams().krnSwMdc();
167  swMax = params.oilWaterParams().krwSwMdc();
168  swMin = params.oilWaterParams().pcSwMdc();
169  Valgrind::CheckDefined(soMax);
170  Valgrind::CheckDefined(swMax);
171  Valgrind::CheckDefined(swMin);
172  }
173  }
174 
175  /*
176  * Hysteresis parameters for oil-water
177  * @see EclHysteresisTwoPhaseLawParams::soMax(...)
178  * @see EclHysteresisTwoPhaseLawParams::swMax(...)
179  * @see EclHysteresisTwoPhaseLawParams::swMin(...)
180  * \param params Parameters
181  */
182  static void setOilWaterHysteresisParams(const Scalar& soMax,
183  const Scalar& swMax,
184  const Scalar& swMin,
185  Params& params)
186  {
187  if constexpr (Traits::enableHysteresis) {
188  params.oilWaterParams().update(swMin, swMax, 1.0 - soMax);
189  }
190  }
191 
192  /*
193  * Hysteresis parameters for gas-oil
194  * @see EclHysteresisTwoPhaseLawParams::sgMax(...)
195  * @see EclHysteresisTwoPhaseLawParams::shMax(...)
196  * @see EclHysteresisTwoPhaseLawParams::soMin(...)
197  * \param params Parameters
198  */
199  static void gasOilHysteresisParams(Scalar& sgMax,
200  Scalar& shMax,
201  Scalar& soMin,
202  const Params& params)
203  {
204  if constexpr (Traits::enableHysteresis) {
205  const auto Swco = params.Swl();
206  sgMax = 1.0 - params.gasOilParams().krnSwMdc() - Swco;
207  shMax = params.gasOilParams().krwSwMdc();
208  soMin = params.gasOilParams().pcSwMdc();
209  Valgrind::CheckDefined(sgMax);
210  Valgrind::CheckDefined(shMax);
211  Valgrind::CheckDefined(soMin);
212  }
213  }
214 
215  /*
216  * Hysteresis parameters for gas-oil
217  * @see EclHysteresisTwoPhaseLawParams::sgMax(...)
218  * @see EclHysteresisTwoPhaseLawParams::shMax(...)
219  * @see EclHysteresisTwoPhaseLawParams::soMin(...)
220  * \param params Parameters
221  */
222  static void setGasOilHysteresisParams(const Scalar& sgMax,
223  const Scalar& shMax,
224  const Scalar& soMin,
225  Params& params)
226  {
227  if constexpr (Traits::enableHysteresis) {
228  const auto Swco = params.Swl();
229  params.gasOilParams().update(soMin, shMax, 1.0 - sgMax - Swco);
230  }
231  }
232 
233  static Scalar trappedGasSaturation(const Params& params, bool maximumTrapping)
234  {
235  const auto Swco = params.Swl();
236  return params.gasOilParams().SnTrapped(maximumTrapping) - Swco;
237  }
238 
239  static Scalar trappedOilSaturation(const Params& params, bool maximumTrapping)
240  {
241  return params.oilWaterParams().SnTrapped(maximumTrapping) + params.gasOilParams().SwTrapped();
242  }
243 
244  static Scalar trappedWaterSaturation(const Params& params)
245  {
246  return params.oilWaterParams().SwTrapped();
247  }
248 
249  static Scalar strandedGasSaturation(const Params& params, Scalar Sg, Scalar Kg)
250  {
251  const auto Swco = params.Swl();
252  return params.gasOilParams().SnStranded(Sg, Kg) - Swco;
253  }
254 
264  template <class FluidState, class Evaluation, class ...Args>
265  OPM_HOST_DEVICE static Evaluation pcgn(const Params& params,
266  const FluidState& fs)
267  {
268  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
269  // Maximum attainable oil saturation is 1-SWL.
270  const auto Sw = 1.0 - params.Swl() - decay<Evaluation>(fs.saturation(gasPhaseIdx));
271  return GasOilMaterialLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.gasOilParams(), Sw);
272  }
273 
283  template <class FluidState, class Evaluation, class ...Args>
284  OPM_HOST_DEVICE static Evaluation pcnw(const Params& params,
285  const FluidState& fs)
286  {
287  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
288  const auto Sw = decay<Evaluation>(fs.saturation(waterPhaseIdx));
289  return OilWaterMaterialLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.oilWaterParams(), Sw);
290  }
291 
295  template <class ContainerT, class FluidState>
296  static void saturations(ContainerT& /*values*/,
297  const Params& /*params*/,
298  const FluidState& /*fluidState*/)
299  {
300  throw std::logic_error("Not implemented: saturations()");
301  }
302 
306  template <class FluidState, class Evaluation = typename FluidState::ValueType>
307  static Evaluation Sg(const Params& /*params*/,
308  const FluidState& /*fluidState*/)
309  {
310  throw std::logic_error("Not implemented: Sg()");
311  }
312 
316  template <class FluidState, class Evaluation = typename FluidState::ValueType>
317  static Evaluation Sn(const Params& /*params*/,
318  const FluidState& /*fluidState*/)
319  {
320  throw std::logic_error("Not implemented: Sn()");
321  }
322 
326  template <class FluidState, class Evaluation = typename FluidState::ValueType>
327  static Evaluation Sw(const Params& /*params*/,
328  const FluidState& /*fluidState*/)
329  {
330  throw std::logic_error("Not implemented: Sw()");
331  }
332 
348  template <class ContainerT, class FluidState, class ...Args>
349  OPM_HOST_DEVICE static void relativePermeabilities(ContainerT& values,
350  const Params& params,
351  const FluidState& fluidState)
352  {
353  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
354  using Evaluation = typename std::remove_reference<decltype(values[0])>::type;
355 
356  values[waterPhaseIdx] = krw<FluidState, Evaluation, Args...>(params, fluidState);
357  values[oilPhaseIdx] = krn<FluidState, Evaluation, Args...>(params, fluidState);
358  values[gasPhaseIdx] = krg<FluidState, Evaluation, Args...>(params, fluidState);
359  }
360 
364  template <class FluidState, class Evaluation, class ...Args>
365  OPM_HOST_DEVICE static Evaluation krg(const Params& params,
366  const FluidState& fluidState)
367  {
368  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
369  // Maximum attainable oil saturation is 1-SWL.
370  const Evaluation sw = 1.0 - params.Swl() - decay<Evaluation>(fluidState.saturation(gasPhaseIdx));
371  return GasOilMaterialLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.gasOilParams(), sw);
372  }
373 
377  template <class FluidState, class Evaluation, class ...Args>
378  OPM_HOST_DEVICE static Evaluation krw(const Params& params,
379  const FluidState& fluidState)
380  {
381  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
382  const Evaluation sw = decay<Evaluation>(fluidState.saturation(waterPhaseIdx));
383  return OilWaterMaterialLaw::template twoPhaseSatKrw<Evaluation, Args...>(params.oilWaterParams(), sw);
384  }
385 
389  template <class FluidState, class Evaluation, class ...Args>
390  OPM_HOST_DEVICE static Evaluation krn(const Params& params,
391  const FluidState& fluidState)
392  {
393  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
394  const Scalar Swco = params.Swl();
395 
396  const Evaluation sw =
397  max(Evaluation(Swco),
398  decay<Evaluation>(fluidState.saturation(waterPhaseIdx)));
399 
400  const Evaluation sg = decay<Evaluation>(fluidState.saturation(gasPhaseIdx));
401 
402  const Evaluation Sw_ow = sg + sw;
403  const Evaluation kro_ow = relpermOilInOilWaterSystem<Evaluation, FluidState, Args...>(params, fluidState);
404  const Evaluation kro_go = relpermOilInOilGasSystem<Evaluation, FluidState, Args...>(params, fluidState);
405 
406  // avoid the division by zero: chose a regularized kro which is used if Sw - Swco
407  // < epsilon/2 and interpolate between the oridinary and the regularized kro between
408  // epsilon and epsilon/2
409  constexpr const Scalar epsilon = 1e-5;
410  if (scalarValue(Sw_ow) - Swco < epsilon) {
411  const Evaluation kro2 = (kro_ow + kro_go)/2;
412  if (scalarValue(Sw_ow) - Swco > epsilon/2) {
413  const Evaluation kro1 = (sg * kro_go + (sw - Swco) * kro_ow) / (Sw_ow - Swco);
414  const Evaluation alpha = (epsilon - (Sw_ow - Swco)) / (epsilon / 2);
415 
416  return kro2 * alpha + kro1 * (1 - alpha);
417  }
418 
419  return kro2;
420  }
421 
422  return (sg * kro_go + (sw - Swco) * kro_ow) / (Sw_ow - Swco);
423  }
424 
428  template <class Evaluation, class FluidState, class ...Args>
429  OPM_HOST_DEVICE static Evaluation relpermOilInOilGasSystem(const Params& params,
430  const FluidState& fluidState)
431  {
432  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
433  const Evaluation sw =
434  max(Evaluation{ params.Swl() },
435  decay<Evaluation>(fluidState.saturation(waterPhaseIdx)));
436 
437  const Evaluation sg = decay<Evaluation>(fluidState.saturation(gasPhaseIdx));
438  const Evaluation So_go = 1.0 - (sg + sw);
439 
440  return GasOilMaterialLaw::template twoPhaseSatKrw<Evaluation, Args...>(params.gasOilParams(), So_go);
441  }
442 
446  template <class Evaluation, class FluidState, class ...Args>
447  OPM_HOST_DEVICE static Evaluation relpermOilInOilWaterSystem(const Params& params,
448  const FluidState& fluidState)
449  {
450  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
451  const Evaluation sw =
452  max(Evaluation{ params.Swl() },
453  decay<Evaluation>(fluidState.saturation(waterPhaseIdx)));
454 
455  const Evaluation sg = decay<Evaluation>(fluidState.saturation(gasPhaseIdx));
456  const Evaluation Sw_ow = sg + sw;
457 
458  return OilWaterMaterialLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.oilWaterParams(), Sw_ow);
459  }
460 
468  template <class FluidState>
469  static bool updateHysteresis(Params& params, const FluidState& fluidState)
470  {
471  if constexpr (Traits::enableHysteresis) {
472  const Scalar Swco = params.Swl();
473  const Scalar sw = clampSaturation(fluidState, waterPhaseIdx);
474  const Scalar So = clampSaturation(fluidState, oilPhaseIdx);
475  const Scalar sg = clampSaturation(fluidState, gasPhaseIdx);
476  bool owChanged = params.oilWaterParams().update(/*pcSw=*/sw, /*krwSw=*/sw, /*krnSw=*/1 - So);
477  bool gochanged = params.gasOilParams().update(/*pcSw=*/So,
478  /*krwSw=*/So,
479  /*krnSw=*/1.0 - Swco - sg);
480  return owChanged || gochanged;
481  } else {
482  return false;
483  }
484  }
485 
486  template <class FluidState>
487  static Scalar clampSaturation(const FluidState& fluidState, const int phaseIndex)
488  {
489  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
490  const auto sat = scalarValue(fluidState.saturation(phaseIndex));
491  return std::clamp(sat, Scalar{0.0}, Scalar{1.0});
492  }
493 };
494 
495 } // namespace Opm
496 
497 #endif
static constexpr bool isTemperatureDependent
Specify whether the quantities defined by this material law are temperature dependent.
Definition: EclDefaultMaterial.hpp:117
static OPM_HOST_DEVICE Evaluation relpermOilInOilGasSystem(const Params &params, const FluidState &fluidState)
The relative permeability of oil in oil/gas system.
Definition: EclDefaultMaterial.hpp:429
A traits class which provides basic mathematical functions for arbitrary scalar floating point values...
static OPM_HOST_DEVICE Evaluation krg(const Params &params, const FluidState &fluidState)
The relative permeability of the gas phase.
Definition: EclDefaultMaterial.hpp:365
static Evaluation Sg(const Params &, const FluidState &)
The saturation of the gas phase.
Definition: EclDefaultMaterial.hpp:307
static constexpr bool isCompositionDependent
Specify whether the quantities defined by this material law are dependent on the phase composition...
Definition: EclDefaultMaterial.hpp:121
static OPM_HOST_DEVICE Evaluation krn(const Params &params, const FluidState &fluidState)
The relative permeability of the non-wetting (i.e., oil) phase.
Definition: EclDefaultMaterial.hpp:390
Default implementation for the parameters required by the default three-phase capillary pressure mode...
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
static OPM_HOST_DEVICE void relativePermeabilities(ContainerT &values, const Params &params, const FluidState &fluidState)
The relative permeability of all phases.
Definition: EclDefaultMaterial.hpp:349
static constexpr bool isPressureDependent
Specify whether the quantities defined by this material law are dependent on the absolute pressure...
Definition: EclDefaultMaterial.hpp:113
static OPM_HOST_DEVICE Evaluation relpermOilInOilWaterSystem(const Params &params, const FluidState &fluidState)
The relative permeability of oil in oil/water system.
Definition: EclDefaultMaterial.hpp:447
static void saturations(ContainerT &, const Params &, const FluidState &)
The inverse of the capillary pressure.
Definition: EclDefaultMaterial.hpp:296
static constexpr bool implementsTwoPhaseSatApi
Specify whether this material law implements the two-phase convenience API which only depends on the ...
Definition: EclDefaultMaterial.hpp:105
static OPM_HOST_DEVICE void capillaryPressures(ContainerT &values, const Params &params, const FluidState &state)
Implements the default three phase capillary pressure law used by the ECLipse simulator.
Definition: EclDefaultMaterial.hpp:138
static bool updateHysteresis(Params &params, const FluidState &fluidState)
Update the hysteresis parameters after a time step.
Definition: EclDefaultMaterial.hpp:469
static OPM_HOST_DEVICE Evaluation krw(const Params &params, const FluidState &fluidState)
The relative permeability of the wetting phase.
Definition: EclDefaultMaterial.hpp:378
static Evaluation Sn(const Params &, const FluidState &)
The saturation of the non-wetting (i.e., oil) phase.
Definition: EclDefaultMaterial.hpp:317
static constexpr bool implementsTwoPhaseApi
Specify whether this material law implements the two-phase convenience API.
Definition: EclDefaultMaterial.hpp:101
static Evaluation Sw(const Params &, const FluidState &)
The saturation of the wetting (i.e., water) phase.
Definition: EclDefaultMaterial.hpp:327
static constexpr bool isSaturationDependent
Specify whether the quantities defined by this material law are saturation dependent.
Definition: EclDefaultMaterial.hpp:109
static OPM_HOST_DEVICE Evaluation pcnw(const Params &params, const FluidState &fs)
Capillary pressure between the non-wetting liquid (i.e., oil) and the wetting liquid (i...
Definition: EclDefaultMaterial.hpp:284
Some templates to wrap the valgrind client request macros.
Implements the default three phase capillary pressure law used by the ECLipse simulator.
Definition: EclDefaultMaterial.hpp:62
static OPM_HOST_DEVICE Evaluation pcgn(const Params &params, const FluidState &fs)
Capillary pressure between the gas and the non-wetting liquid (i.e., oil) phase.
Definition: EclDefaultMaterial.hpp:265