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  Copyright (C) 2008-2013 by Andreas Lauser
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
25 #ifndef OPM_ECL_DEFAULT_MATERIAL_HPP
26 #define OPM_ECL_DEFAULT_MATERIAL_HPP
27 
29 
32 
33 #include <opm/common/Exceptions.hpp>
34 #include <opm/common/ErrorMacros.hpp>
35 
36 #include <algorithm>
37 
38 namespace Opm {
39 
53 template <class TraitsT,
54  class GasOilMaterialLawT,
55  class OilWaterMaterialLawT,
56  class ParamsT = EclDefaultMaterialParams<TraitsT,
57  typename GasOilMaterialLawT::Params,
58  typename OilWaterMaterialLawT::Params> >
59 class EclDefaultMaterial : public TraitsT
60 {
61 public:
62  typedef GasOilMaterialLawT GasOilMaterialLaw;
63  typedef OilWaterMaterialLawT OilWaterMaterialLaw;
64 
65  // some safety checks
66  static_assert(TraitsT::numPhases == 3,
67  "The number of phases considered by this capillary pressure "
68  "law is always three!");
69  static_assert(GasOilMaterialLaw::numPhases == 2,
70  "The number of phases considered by the gas-oil capillary "
71  "pressure law must be two!");
72  static_assert(OilWaterMaterialLaw::numPhases == 2,
73  "The number of phases considered by the oil-water capillary "
74  "pressure law must be two!");
75  static_assert(std::is_same<typename GasOilMaterialLaw::Scalar,
76  typename OilWaterMaterialLaw::Scalar>::value,
77  "The two two-phase capillary pressure laws must use the same "
78  "type of floating point values.");
79 
80  static_assert(GasOilMaterialLaw::implementsTwoPhaseSatApi,
81  "The gas-oil material law must implement the two-phase saturation "
82  "only API to for the default Ecl capillary pressure law!");
83  static_assert(OilWaterMaterialLaw::implementsTwoPhaseSatApi,
84  "The oil-water material law must implement the two-phase saturation "
85  "only API to for the default Ecl capillary pressure law!");
86 
87  typedef TraitsT Traits;
88  typedef ParamsT Params;
89  typedef typename Traits::Scalar Scalar;
90 
91  static const int numPhases = 3;
92  static const int waterPhaseIdx = Traits::wettingPhaseIdx;
93  static const int oilPhaseIdx = Traits::nonWettingPhaseIdx;
94  static const int gasPhaseIdx = Traits::gasPhaseIdx;
95 
98  static const bool implementsTwoPhaseApi = false;
99 
102  static const bool implementsTwoPhaseSatApi = false;
103 
106  static const bool isSaturationDependent = true;
107 
110  static const bool isPressureDependent = false;
111 
114  static const bool isTemperatureDependent = false;
115 
118  static const bool isCompositionDependent = false;
119 
134  template <class ContainerT, class FluidState>
135  static void capillaryPressures(ContainerT &values,
136  const Params &params,
137  const FluidState &state)
138  {
139  typedef typename std::remove_reference<decltype(values[0])>::type Evaluation;
140  values[gasPhaseIdx] = pcgn<FluidState, Evaluation>(params, state);
141  values[oilPhaseIdx] = 0;
142  values[waterPhaseIdx] = - pcnw<FluidState, Evaluation>(params, state);
143 
144  Valgrind::CheckDefined(values[gasPhaseIdx]);
145  Valgrind::CheckDefined(values[oilPhaseIdx]);
146  Valgrind::CheckDefined(values[waterPhaseIdx]);
147  }
148 
158  template <class FluidState, class Evaluation = typename FluidState::Scalar>
159  static Evaluation pcgn(const Params &params,
160  const FluidState &fs)
161  {
163 
164  const auto& Sw = 1.0 - FsToolbox::template toLhs<Evaluation>(fs.saturation(gasPhaseIdx));
165  return GasOilMaterialLaw::twoPhaseSatPcnw(params.gasOilParams(), Sw);
166  }
167 
177  template <class FluidState, class Evaluation = typename FluidState::Scalar>
178  static Evaluation pcnw(const Params &params,
179  const FluidState &fs)
180  {
181  typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
182 
183  const auto& Sw = FsToolbox::template toLhs<Evaluation>(fs.saturation(waterPhaseIdx));
184  return OilWaterMaterialLaw::twoPhaseSatPcnw(params.oilWaterParams(), Sw);
185  }
186 
190  template <class ContainerT, class FluidState>
191  static void saturations(ContainerT& /*values*/,
192  const Params& /*params*/,
193  const FluidState& /*fluidState*/)
194  {
195  OPM_THROW(std::logic_error, "Not implemented: saturations()");
196  }
197 
201  template <class FluidState, class Evaluation = typename FluidState::Scalar>
202  static Evaluation Sg(const Params& /*params*/,
203  const FluidState& /*fluidState*/)
204  {
205  OPM_THROW(std::logic_error, "Not implemented: Sg()");
206  }
207 
211  template <class FluidState, class Evaluation = typename FluidState::Scalar>
212  static Evaluation Sn(const Params& /*params*/,
213  const FluidState& /*fluidState*/)
214  {
215  OPM_THROW(std::logic_error, "Not implemented: Sn()");
216  }
217 
221  template <class FluidState, class Evaluation = typename FluidState::Scalar>
222  static Evaluation Sw(const Params& /*params*/,
223  const FluidState& /*fluidState*/)
224  {
225  OPM_THROW(std::logic_error, "Not implemented: Sw()");
226  }
227 
243  template <class ContainerT, class FluidState>
244  static void relativePermeabilities(ContainerT &values,
245  const Params &params,
246  const FluidState &fluidState)
247  {
248  typedef typename std::remove_reference<decltype(values[0])>::type Evaluation;
249 
250  values[waterPhaseIdx] = krw<FluidState, Evaluation>(params, fluidState);
251  values[oilPhaseIdx] = krn<FluidState, Evaluation>(params, fluidState);
252  values[gasPhaseIdx] = krg<FluidState, Evaluation>(params, fluidState);
253  }
254 
258  template <class FluidState, class Evaluation = typename FluidState::Scalar>
259  static Evaluation krg(const Params &params,
260  const FluidState &fluidState)
261  {
262  typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
263 
264  const Evaluation& Sw = 1 - FsToolbox::template toLhs<Evaluation>(fluidState.saturation(gasPhaseIdx));
265  return GasOilMaterialLaw::twoPhaseSatKrn(params.gasOilParams(), Sw);
266  }
267 
271  template <class FluidState, class Evaluation = typename FluidState::Scalar>
272  static Evaluation krw(const Params &params,
273  const FluidState &fluidState)
274  {
275  typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
276 
277  const Evaluation& Sw = FsToolbox::template toLhs<Evaluation>(fluidState.saturation(waterPhaseIdx));
278  return OilWaterMaterialLaw::twoPhaseSatKrw(params.oilWaterParams(), Sw);
279  }
280 
284  template <class FluidState, class Evaluation = typename FluidState::Scalar>
285  static Evaluation krn(const Params &params,
286  const FluidState &fluidState)
287  {
288  typedef MathToolbox<Evaluation> Toolbox;
289  typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
290 
291  Scalar Swco = params.Swl();
292 
293  Evaluation Sw =
294  Toolbox::max(Evaluation(Swco),
295  FsToolbox::template toLhs<Evaluation>(fluidState.saturation(waterPhaseIdx)));
296  Evaluation Sg = FsToolbox::template toLhs<Evaluation>(fluidState.saturation(gasPhaseIdx));
297 
298  Evaluation Sw_ow = Sg + Sw;
299  Evaluation So_go = 1.0 - Sw_ow;
300  const Evaluation& kro_ow = OilWaterMaterialLaw::twoPhaseSatKrn(params.oilWaterParams(), Sw_ow);
301  const Evaluation& kro_go = GasOilMaterialLaw::twoPhaseSatKrw(params.gasOilParams(), So_go);
302 
303  // avoid the division by zero: chose a regularized kro which is used if Sw - Swco
304  // < epsilon/2 and interpolate between the oridinary and the regularized kro between
305  // epsilon and epsilon/2
306  const Scalar epsilon = 1e-5;
307  if (Toolbox::value(Sw_ow) - Swco < epsilon) {
308  Evaluation kro2 = (kro_ow + kro_go)/2;;
309  if (Toolbox::value(Sw_ow) - Swco > epsilon/2) {
310  Evaluation kro1 = (Sg*kro_go + (Sw - Swco)*kro_ow)/(Sw_ow - Swco);
311  Evaluation alpha = (epsilon - (Sw_ow - Swco))/(epsilon/2);
312  return kro2*alpha + kro1*(1 - alpha);
313  }
314 
315  return kro2;
316  }
317  else
318  return (Sg*kro_go + (Sw - Swco)*kro_ow)/(Sw_ow - Swco);
319  }
320 
328  template <class FluidState>
329  static void updateHysteresis(Params &params, const FluidState &fluidState)
330  {
331  typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
332 
333  Scalar Sw = FsToolbox::value(fluidState.saturation(waterPhaseIdx));
334  Scalar So = FsToolbox::value(fluidState.saturation(oilPhaseIdx));
335  Scalar Sg = FsToolbox::value(fluidState.saturation(gasPhaseIdx));
336 
337  if (params.inconsistentHysteresisUpdate()) {
338  Sg = std::min(Scalar(1.0), std::max(Scalar(0.0), Sg));
339  // NOTE: the saturations which are passed to update the hysteresis curves are
340  // inconsistent with the ones used to calculate the relative permabilities. We do
341  // it like this anyway because (a) the saturation functions of opm-core do it
342  // this way (b) the simulations seem to converge better (which is not too much
343  // surprising actually, because the time step does not start on a kink in the
344  // solution) and (c) the Eclipse 100 simulator may do the same.
345  //
346  // Though be aware that from a physical perspective this is definitively
347  // incorrect!
348  params.oilWaterParams().update(/*pcSw=*/1 - So, /*krwSw=*/1 - So, /*krn_Sw=*/1 - So);
349  params.gasOilParams().update(/*pcSw=*/1 - Sg, /*krwSw=*/1 - Sg, /*krn_Sw=*/1 - Sg);
350  }
351  else {
352  Scalar Swco = params.Swl();
353  Sw = std::min(Scalar(1.0), std::max(Scalar(0.0), Sw));
354  Sg = std::min(Scalar(1.0), std::max(Scalar(0.0), Sg));
355 
356  Scalar Sw_ow = Sg + std::max(Swco, Sw);
357  Scalar So_go = 1 + Sw_ow;
358 
359  params.oilWaterParams().update(/*pcSw=*/Sw, /*krwSw=*/1 - Sg, /*krnSw=*/Sw_ow);
360  params.gasOilParams().update(/*pcSw=*/1 - Sg, /*krwSw=*/So_go, /*krnSw=*/1 - Sg);
361  }
362  }
363 };
364 } // namespace Opm
365 
366 #endif
GasOilMaterialLawT GasOilMaterialLaw
Definition: EclDefaultMaterial.hpp:62
bool CheckDefined(const T &value OPM_UNUSED)
Make valgrind complain if any of the memory occupied by an object is undefined.
Definition: Valgrind.hpp:74
Definition: MathToolbox.hpp:39
Definition: Air_Mesitylene.hpp:31
Default implementation for the parameters required by the default three-phase capillary pressure mode...
Some templates to wrap the valgrind client request macros.
Evaluation< Scalar, VarSetTag, numVars > max(const Evaluation< Scalar, VarSetTag, numVars > &x1, const Evaluation< Scalar, VarSetTag, numVars > &x2)
Definition: Math.hpp:114
Implements the default three phase capillary pressure law used by the ECLipse simulator.
Definition: EclDefaultMaterial.hpp:59
Evaluation< Scalar, VarSetTag, numVars > min(const Evaluation< Scalar, VarSetTag, numVars > &x1, const Evaluation< Scalar, VarSetTag, numVars > &x2)
Definition: Math.hpp:61
OilWaterMaterialLawT OilWaterMaterialLaw
Definition: EclDefaultMaterial.hpp:63
A traits class which provides basic mathematical functions for arbitrary scalar floating point values...