fluid-matrix interactions: remove "3p" folder

because fluid-matrix interactions have been independent of the number
of phases for a while. The only law left in this folder (implementing
the Parker-van Genuchten law) has been moved one folder up and been
cleaned up considerably.
This commit is contained in:
Andreas Lauser
2014-03-27 16:12:18 +01:00
parent a532d0ed6a
commit 49ec85abab
5 changed files with 539 additions and 586 deletions

View File

@@ -1,380 +0,0 @@
/*
Copyright (C) 2008-2013 by Andreas Lauser
Copyright (C) 2012 by Holger Class
Copyright (C) 2012 by Vishal Jambhekar
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
* \copydoc Opm::ThreePParkerVanGenuchten
*/
#ifndef OPM_3P_PARKER_VAN_GENUCHTEN_HPP
#define OPM_3P_PARKER_VAN_GENUCHTEN_HPP
#include "3pParkerVanGenuchtenParams.hpp"
#include <algorithm>
namespace Opm {
/*!
* \ingroup FluidMatrixInteractions
*
* \brief Implementation of van Genuchten's capillary pressure <->
* saturation relation.
*
* \sa VanGenuchten, VanGenuchtenThreephase
*/
template <class ScalarT, class ParamsT = ParkerVanGen3PParams<ScalarT> >
class ThreePParkerVanGenuchten
{
public:
typedef ParamsT Params;
typedef typename Params::Scalar Scalar;
/*!
* \brief The capillary pressure-saturation curve.
*
*/
static Scalar pC(const Params &params, Scalar Sw)
{
OPM_THROW(std::logic_error, "Not implemented: Capillary pressures for three phases is not so simple! Use pCGN, pCNW, and pcGW");
}
static Scalar pCGW(const Params &params, Scalar Sw)
{
/*
Sw = wetting phase saturation, or,
sum of wetting phase saturations
alpha : VanGenuchten-alpha
this function is copied from MUFTE/pml/constrel3p3cni.c */
Scalar r,Se,x,vg_m;
Scalar pc,pc_prime,Se_regu;
Scalar PC_VG_REG = 0.01;
Se = (Sw-params.Swr())/(1.-params.Sgr());
/* Snr = 0.0; test version */
/* regularization */
if (Se<0.0) Se=0.0;
if (Se>1.0) Se=1.0;
vg_m = 1.-1./params.vgN();
if (Se>PC_VG_REG && Se<1-PC_VG_REG)
{
r = std::pow(Se,-1/vg_m);
x = r-1;
vg_m = 1-vg_m;
x = std::pow(x,vg_m);
r = x/params.vgAlpha();
return(r);
}
else
{
/* value and derivative at regularization point */
if (Se<=PC_VG_REG) Se_regu = PC_VG_REG; else Se_regu = 1-PC_VG_REG;
pc = std::pow(std::pow(Se_regu,-1/vg_m)-1,1/params.vgN())/params.vgAlpha();
pc_prime = std::pow(std::pow(Se_regu,-1/vg_m)-1,1/params.vgN()-1)*std::pow(Se_regu,-1/vg_m-1)*(-1/vg_m)/params.vgAlpha()/(1-params.Sgr()-params.Swr())/params.vgN();
/* evaluate tangential */
r = (Se-Se_regu)*pc_prime+pc;
return(r/params.betaGW());
}
}
static Scalar pCNW(const Params &params, Scalar Sw)
{
/*
Sw = wetting phase saturation, or,
sum of wetting phase saturations
alpha : VanGenuchten-alpha
this function is just copied from MUFTE/pml/constrel3p3cni.c */
Scalar r,Se,x,vg_m;
Scalar pc,pc_prime,Se_regu;
Scalar PC_VG_REG = 0.01;
Se = (Sw-params.Swr())/(1.-params.Snr());
/* Snr = 0.0; test version */
/* regularization */
if (Se<0.0) Se=0.0;
if (Se>1.0) Se=1.0;
vg_m = 1.-1./params.vgN();
if (Se>PC_VG_REG && Se<1-PC_VG_REG)
{
r = std::pow(Se,-1/vg_m);
x = r-1;
vg_m = 1-vg_m;
x = std::pow(x,vg_m);
r = x/params.vgAlpha();
return(r);
}
else
{
/* value and derivative at regularization point */
if (Se<=PC_VG_REG) Se_regu = PC_VG_REG; else Se_regu = 1-PC_VG_REG;
pc = std::pow(std::pow(Se_regu,-1/vg_m)-1,1/params.vgN())/params.vgAlpha();
pc_prime = std::pow(std::pow(Se_regu,-1/vg_m)-1,1/params.vgN()-1)*std::pow(Se_regu,-1/vg_m-1)*(-1/vg_m)/params.vgAlpha()/(1-params.Snr()-params.Swr())/params.vgN();
/* evaluate tangential */
r = (Se-Se_regu)*pc_prime+pc;
return(r/params.betaNW());
}
}
static Scalar pCGN(const Params &params, Scalar St)
{
/*
St = sum of wetting (liquid) phase saturations
alpha : VanGenuchten-alpha
this function is just copied from MUFTE/pml/constrel3p3cni.c */
Scalar r,Se,x,vg_m;
Scalar pc,pc_prime,Se_regu;
Scalar PC_VG_REG = 0.01;
Se = (St-params.Swrx())/(1.-params.Swrx());
/* Snr = 0.0; test version */
/* regularization */
if (Se<0.0) Se=0.0;
if (Se>1.0) Se=1.0;
vg_m = 1.-1./params.vgN();
if (Se>PC_VG_REG && Se<1-PC_VG_REG)
{
r = std::pow(Se,-1/vg_m);
x = r-1;
vg_m = 1-vg_m;
x = std::pow(x,vg_m);
r = x/params.vgAlpha();
return(r);
}
else
{
/* value and derivative at regularization point */
if (Se<=PC_VG_REG) Se_regu = PC_VG_REG; else Se_regu = 1-PC_VG_REG;
pc = std::pow(std::pow(Se_regu,-1/vg_m)-1,1/params.vgN())/params.vgAlpha();
pc_prime = std::pow(std::pow(Se_regu,-1/vg_m)-1,1/params.vgN()-1)*std::pow(Se_regu,-1/vg_m-1)*(-1/vg_m)/params.vgAlpha()/(1-params.Sgr()-params.Swrx())/params.vgN();
/* evaluate tangential */
r = (Se-Se_regu)*pc_prime+pc;
return(r/params.betaGN());
}
}
static Scalar pCAlpha(const Params &params, Scalar Sn)
{
/* continuous transition to zero */
Scalar alpha,Sne;
Sne=Sn;
/* regularization */
if (Sne<=0.001) Sne=0.0;
if (Sne>=1.0) Sne=1.0;
if (Sne>params.Snr()) alpha = 1.0;
else
{
if (params.Snr()>=0.001) alpha = Sne/params.Snr();
else alpha = 0.0;
}
return(alpha);
}
/*!
* \brief The saturation-capillary pressure curve.
*
*/
static Scalar Sw(const Params &params, Scalar pC)
{
OPM_THROW(std::logic_error, "Not implemented: Sw(pc) for three phases not implemented! Do it yourself!");
}
/*!
* \brief Returns the partial derivative of the capillary
* pressure to the effective saturation.
*
*/
static Scalar dpC_dSw(const Params &params, Scalar Sw)
{
OPM_THROW(std::logic_error, "Not implemented: dpC/dSw for three phases not implemented! Do it yourself!");
}
/*!
* \brief Returns the partial derivative of the effective
* saturation to the capillary pressure.
*/
static Scalar dSw_dpC(const Params &params, Scalar pC)
{
OPM_THROW(std::logic_error, "Not implemented: dSw/dpC for three phases not implemented! Do it yourself!");
}
/*!
* \brief The relative permeability for the wetting phase of
* the medium implied by van Genuchten's
* parameterization.
*
* The permeability of water in a 3p system equals the standard 2p description.
* (see p61. in "Comparison of the Three-Phase Oil Relative Permeability Models"
* MOJDEH DELSHAD and GARY A. POPE, Transport in Porous Media 4 (1989), 59-83.)
*
* \param Sn saturation of the NAPL phase.
* \param Sg saturation of the gas phase.
* \param saturation saturation of the water phase.
* \param params Array of parameters.
*/
static Scalar krw(const Params &params, Scalar saturation, Scalar Sn, Scalar Sg)
{
//transformation to effective saturation
Scalar Se = (saturation - params.Swr()) / (1-params.Swr());
/* regularization */
if(Se > 1.0) return 1.;
if(Se < 0.0) return 0.;
Scalar r = 1. - std::pow(1 - std::pow(Se, 1/params.vgM()), params.vgM());
return std::sqrt(Se)*r*r;
}
/*!
* \brief The relative permeability for the non-wetting phase
* after the Model of Parker et al. (1987).
*
* See model 7 in "Comparison of the Three-Phase Oil Relative Permeability Models"
* MOJDEH DELSHAD and GARY A. POPE, Transport in Porous Media 4 (1989), 59-83.
* or more comprehensive in
* "Estimation of primary drainage three-phase relative permeability for organic
* liquid transport in the vadose zone", Leonardo I. Oliveira, Avery H. Demond,
* Journal of Contaminant Hydrology 66 (2003), 261-285
*
*
* \param Sw saturation of the water phase.
* \param Sg saturation of the gas phase.
* \param saturation saturation of the NAPL phase.
* \param params Array of parameters.
*/
static Scalar krn(const Params &params, Scalar Sw, Scalar saturation, Scalar Sg)
{
Scalar Swe = std::min((Sw - params.Swr()) / (1 - params.Swr()), 1.);
Scalar Ste = std::min((Sw + saturation - params.Swr()) / (1 - params.Swr()), 1.);
// regularization
if(Swe <= 0.0) Swe = 0.;
if(Ste <= 0.0) Ste = 0.;
if(Ste - Swe <= 0.0) return 0.;
Scalar krn_;
krn_ = std::pow(1 - std::pow(Swe, 1/params.vgM()), params.vgM());
krn_ -= std::pow(1 - std::pow(Ste, 1/params.vgM()), params.vgM());
krn_ *= krn_;
if (params.krRegardsSnr())
{
// regard Snr in the permeability of the n-phase, see Helmig1997
Scalar resIncluded = std::max(std::min((saturation - params.Snr()/ (1-params.Swr())), 1.), 0.);
krn_ *= std::sqrt(resIncluded );
}
else
krn_ *= std::sqrt(saturation / (1 - params.Swr())); // Hint: (Ste - Swe) = Sn / (1-Srw)
return krn_;
}
/*!
* \brief The relative permeability for the non-wetting phase
* of the medium implied by van Genuchten's
* parameterization.
*
* The permeability of gas in a 3p system equals the standard 2p description.
* (see p61. in "Comparison of the Three-Phase Oil Relative Permeability Models"
* MOJDEH DELSHAD and GARY A. POPE, Transport in Porous Media 4 (1989), 59-83.)
*
* \param Sw saturation of the water phase.
* \param Sn saturation of the NAPL phase.
* \param saturation saturation of the gas phase.
* \param params Array of parameters.
*/
static Scalar krg(const Params &params, Scalar Sw, Scalar Sn, Scalar saturation)
{
// Se = (Sw+Sn - Sgr)/(1-Sgr)
Scalar Se = std::min(((1-saturation) - params.Sgr()) / (1 - params.Sgr()), 1.);
/* regularization */
if(Se > 1.0) return 0.0;
if(Se < 0.0) return 1.0;
Scalar scalFact = 1.;
if (saturation<=0.1)
{
scalFact = (saturation - params.Sgr())/(0.1 - params.Sgr());
if (scalFact < 0.) scalFact = 0.;
}
Scalar result = scalFact * std::pow(1 - Se, 1.0/3.) * std::pow(1 - std::pow(Se, 1/params.vgM()), 2*params.vgM());
return result;
}
/*!
* \brief The relative permeability for a phase.
* \param Sw saturation of the water phase.
* \param Sg saturation of the gas phase.
* \param Sn saturation of the NAPL phase.
* \param params Array of parameters.
* \param phase indicator, The saturation of all phases.
*/
static Scalar kr(const Params &params, const int phase, const Scalar Sw, const Scalar Sn, const Scalar Sg)
{
switch (phase)
{
case 0:
return krw(params, Sw, Sn, Sg);
break;
case 1:
return krn(params, Sw, Sn, Sg);
break;
case 2:
return krg(params, Sw, Sn, Sg);
break;
}
return 0;
}
/*
* \brief the basis for calculating adsorbed NAPL in storage term
* \param bulk density of porous medium, adsorption coefficient
*/
static Scalar bulkDensTimesAdsorpCoeff (const Params &params)
{
return params.rhoBulk() * params.KdNAPL();
}
};
} // namespace Opm
#endif

View File

@@ -1,105 +0,0 @@
/*
Copyright (C) 2009-2013 by Andreas Lauser
Copyright (C) 2012 by Bernd Flemisch
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
* \copydoc Opm::ThreePAdapter
*/
#ifndef OPM_3P_ADAPTER_HPP
#define OPM_3P_ADAPTER_HPP
#include <opm/core/utility/ErrorMacros.hpp>
#include <opm/core/utility/Exceptions.hpp>
#include <opm/material/Valgrind.hpp>
#include <algorithm>
namespace Opm {
/*!
* \ingroup FluidMatrixInteractions
*
* \brief Makes the three-phase capillary pressure-saturation relations
* available under the M-phase API for material laws.
*/
template <int wPhaseIdx, int nPhaseIdx, int gPhaseIdx, class ThreePLaw>
class ThreePAdapter
{
public:
typedef typename ThreePLaw::Params Params;
typedef typename ThreePLaw::Scalar Scalar;
enum { numPhases = 3 };
/*!
* \brief The capillary pressure-saturation curve.
*/
template <class ContainerT, class FluidState>
static void capillaryPressures(ContainerT &values,
const Params &params,
const FluidState &fluidState)
{
Scalar p_cgw = ThreePLaw::pCGW(params, fluidState.saturation(wPhaseIdx));
Scalar p_cnw = ThreePLaw::pCNW(params, fluidState.saturation(wPhaseIdx));
Scalar p_cgn = ThreePLaw::pCGN(params,
fluidState.saturation(wPhaseIdx)
+ fluidState.saturation(nPhaseIdx));
Scalar p_cAlpha = ThreePLaw::pCAlpha(params,
fluidState.saturation(nPhaseIdx));
Scalar p_cnw1 = 0.0;
Valgrind::CheckDefined(p_cgw);
Valgrind::CheckDefined(p_cnw);
Valgrind::CheckDefined(p_cgn);
Valgrind::CheckDefined(p_cAlpha);
values[gPhaseIdx] = 0;
values[nPhaseIdx] = - (p_cAlpha*p_cgn + (1 - p_cAlpha)*(p_cgw - p_cnw1));
values[wPhaseIdx] = values[nPhaseIdx] - (p_cAlpha*p_cnw + (1 - p_cAlpha)*p_cnw1);
}
static Scalar pCGW(const Params &params, Scalar Sw)
{ return ThreePLaw::pCGW(params, Sw); }
/*!
* \brief The inverse of the capillary pressure-saturation curve.
*/
template <class ContainerT, class FluidState>
static void saturations(ContainerT &values,
const Params &params,
const FluidState &fluidState)
{ OPM_THROW(std::runtime_error, "Not implemented: Inverse capillary pressure curves"); }
/*!
* \brief The relative permeability of all phases.
*/
template <class ContainerT, class FluidState>
static void relativePermeabilities(ContainerT &values,
const Params &params,
const FluidState &fluidState)
{
Scalar Sw = fluidState.saturation(wPhaseIdx);
Scalar Sn = fluidState.saturation(nPhaseIdx);
Scalar Sg = fluidState.saturation(gPhaseIdx);
values[wPhaseIdx] = ThreePLaw::krw(params, Sw, Sn, Sg);
values[nPhaseIdx] = ThreePLaw::krn(params, Sw, Sn, Sg);
values[gPhaseIdx] = ThreePLaw::krg(params, Sw, Sn, Sg);
}
};
} // namespace Opm
#endif

View File

@@ -0,0 +1,485 @@
/*
Copyright (C) 2008-2013 by Andreas Lauser
Copyright (C) 2012 by Holger Class
Copyright (C) 2012 by Vishal Jambhekar
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
* \copydoc Opm::ThreePhaseParkerVanGenuchten
*/
#ifndef OPM_THREE_PHASE_PARKER_VAN_GENUCHTEN_HPP
#define OPM_THREE_PHASE_PARKER_VAN_GENUCHTEN_HPP
#include "ThreePhaseParkerVanGenuchtenParams.hpp"
#include <algorithm>
namespace Opm {
/*!
* \ingroup FluidMatrixInteractions
*
* \brief Implementation of three-phase capillary pressure and
* relative permeability relations proposed by Parker and van
* Genuchten.
*
* Reference: J.B. Kool, J.C. Parker, M.Th. van Genuchten: Parameter
* Estimation for Unsaturated Flow and Transport Models -- A Review;
* Journal of Hydrology, 91 (1987) 255-293
*/
template <class TraitsT,
class ParamsT = ThreePhaseParkerVanGenuchtenParams<TraitsT> >
class ThreePhaseParkerVanGenuchten
{
public:
static_assert(TraitsT::numPhases == 3,
"The number of phases considered by this capillary pressure "
"law is always three!");
typedef TraitsT Traits;
typedef ParamsT Params;
typedef typename Traits::Scalar Scalar;
static const int numPhases = 3;
static const int wPhaseIdx = Traits::wPhaseIdx;
static const int nPhaseIdx = Traits::nPhaseIdx;
static const int gPhaseIdx = Traits::gPhaseIdx;
//! Specify whether this material law implements the two-phase
//! convenience API
static const bool implementsTwoPhaseApi = false;
//! Specify whether this material law implements the two-phase
//! convenience API which only depends on the phase saturations
static const bool implementsTwoPhaseSatApi = false;
//! Specify whether the quantities defined by this material law
//! are saturation dependent
static const bool isSaturationDependent = true;
//! Specify whether the quantities defined by this material law
//! are dependent on the absolute pressure
static const bool isPressureDependent = false;
//! Specify whether the quantities defined by this material law
//! are temperature dependent
static const bool isTemperatureDependent = false;
//! Specify whether the quantities defined by this material law
//! are dependent on the phase composition
static const bool isCompositionDependent = false;
/*!
* \brief Implements the three phase capillary pressure law
* proposed by Parker and van Genuchten.
*
* This material law is valid for three fluid phases and only
* depends on the saturations.
*
* \param values Container for the return values
* \param params Parameters
* \param state The fluid state
*/
template <class ContainerT, class FluidState>
static void capillaryPressures(ContainerT &values,
const Params &params,
const FluidState &fluidState)
{
values[gPhaseIdx] = pcgn(params, fluidState);
values[nPhaseIdx] = 0;
values[wPhaseIdx] = - pcnw(params, fluidState);
}
/*!
* \brief Capillary pressure between the gas and the non-wetting
* liquid (i.e., oil) phase.
*
* This is defined as
* \f[
* p_{c,gn} = p_g - p_n
* \f]
*/
template <class FluidState>
static Scalar pcgn(const Params &params,
const FluidState &fluidState)
{
Scalar PC_VG_REG = 0.01;
// sum of liquid saturations
Scalar St =
fluidState.saturation(wPhaseIdx)
+ fluidState.saturation(nPhaseIdx);
Scalar Se = (St - params.Swrx())/(1. - params.Swrx());
// regularization
if (Se < 0.0)
Se=0.0;
if (Se > 1.0)
Se=1.0;
if (Se>PC_VG_REG && Se<1-PC_VG_REG)
{
Scalar x = std::pow(Se,-1/params.vgM()) - 1;
return std::pow(x, 1 - params.vgM())/params.vgAlpha();
}
// value and derivative at regularization point
Scalar Se_regu;
if (Se<=PC_VG_REG)
Se_regu = PC_VG_REG;
else
Se_regu = 1-PC_VG_REG;
Scalar x = std::pow(Se_regu,-1/params.vgM())-1;
Scalar pc = std::pow(x, 1/params.vgN())/params.vgAlpha();
Scalar pc_prime =
std::pow(x, 1/params.vgN()-1)
* std::pow(Se_regu,-1/params.vgM()-1)
/ (-params.vgM())
/ params.vgAlpha()
/ (1 - params.Sgr() - params.Swrx())
/ params.vgN();
// evaluate tangential
return ((Se-Se_regu)*pc_prime + pc)/params.betaGN();
}
/*!
* \brief Capillary pressure between the non-wetting liquid (i.e.,
* oil) and the wetting liquid (i.e., water) phase.
*
* This is defined as
* \f[
* p_{c,nw} = p_n - p_w
* \f]
*/
template <class FluidState>
static Scalar pcnw(const Params &params,
const FluidState &fluidState)
{
Scalar Sw = fluidState.saturation(wPhaseIdx);
Scalar Se = (Sw-params.Swr())/(1.-params.Snr());
Scalar PC_VG_REG = 0.01;
// regularization
if (Se<0.0)
Se=0.0;
if (Se>1.0)
Se=1.0;
if (Se>PC_VG_REG && Se<1-PC_VG_REG) {
Scalar x = std::pow(Se,-1/params.vgM()) - 1.0;
x = std::pow(x, 1 - params.vgM());
return x/params.vgAlpha();
}
// value and derivative at regularization point
Scalar Se_regu;
if (Se<=PC_VG_REG)
Se_regu = PC_VG_REG;
else
Se_regu = 1.0 - PC_VG_REG;
Scalar x = std::pow(Se_regu,-1/params.vgM())-1;
Scalar pc = std::pow(x, 1/params.vgN())/params.vgAlpha();
Scalar pc_prime =
std::pow(x,1/params.vgN()-1)
* std::pow(Se_regu, -1.0/params.vgM() - 1)
/ (-params.vgM())
/ params.vgAlpha()
/ (1-params.Snr()-params.Swr())
/ params.vgN();
// evaluate tangential
return ((Se-Se_regu)*pc_prime + pc)/params.betaNW();
}
/*!
* \brief The saturation-capillary pressure curve.
*
*/
template <class ContainerT, class FluidState>
static void saturations(ContainerT &values,
const Params &params,
const FluidState &fluidState)
{ OPM_THROW(std::logic_error, "Not implemented: inverse capillary pressures"); }
/*!
* \brief The saturation of the gas phase.
*/
template <class FluidState>
static Scalar Sg(const Params &params,
const FluidState &fluidState)
{ OPM_THROW(std::logic_error, "Not implemented: Sg()"); }
/*!
* \brief The saturation of the non-wetting (i.e., oil) phase.
*/
template <class FluidState>
static Scalar Sn(const Params &params,
const FluidState &fluidState)
{ OPM_THROW(std::logic_error, "Not implemented: Sn()"); }
/*!
* \brief The saturation of the wetting (i.e., water) phase.
*/
template <class FluidState>
static Scalar Sw(const Params &params,
const FluidState &fluidState)
{ OPM_THROW(std::logic_error, "Not implemented: Sw()"); }
/*!
* \brief The relative permeability of all phases.
*/
template <class ContainerT, class FluidState>
static void relativePermeabilities(ContainerT &values,
const Params &params,
const FluidState &fluidState)
{
values[wPhaseIdx] = krw(params, fluidState);
values[nPhaseIdx] = krn(params, fluidState);
values[gPhaseIdx] = krg(params, fluidState);
}
/*!
* \brief The relative permeability for the wetting phase of the
* medium implied by van Genuchten's parameterization.
*
* The permeability of water in a 3p system equals the standard 2p description.
* (see p61. in "Comparison of the Three-Phase Oil Relative Permeability Models"
* MOJDEH DELSHAD and GARY A. POPE, Transport in Porous Media 4 (1989), 59-83.)
*/
template <class FluidState>
static Scalar krw(const Params &params,
const FluidState &fluidState)
{
// transformation to effective saturation
Scalar Se = (fluidState.saturation(wPhaseIdx) - params.Swr()) / (1-params.Swr());
// regularization
if(Se > 1.0) return 1.;
if(Se < 0.0) return 0.;
Scalar r = 1. - std::pow(1 - std::pow(Se, 1/params.vgM()), params.vgM());
return std::sqrt(Se)*r*r;
}
/*!
* \brief The relative permeability for the non-wetting phase
* due to the model of Parker et al. (1987).
*
* See model 7 of "Comparison of the Three-Phase Oil Relative
* Permeability Models" M. Delshad and G. A. Pope, Transport in
* Porous Media 4 (1989), 59-83; or -- more comprehensively --
* "Estimation of primary drainage three-phase relative
* permeability for organic liquid transport in the vadose zone",
* L. I. Oliveira, A. H. Demond, Journal of Contaminant Hydrology
* 66 (2003), 261-285
*/
template <class FluidState>
static Scalar krn(const Params &params,
const FluidState &fluidState)
{
Scalar Sn = fluidState.saturation(nPhaseIdx);
Scalar Sw = fluidState.saturation(wPhaseIdx);
Scalar Swe = std::min((Sw - params.Swr()) / (1 - params.Swr()), 1.);
Scalar Ste = std::min((Sw + Sn - params.Swr()) / (1 - params.Swr()), 1.);
// regularization
if(Swe <= 0.0) Swe = 0.;
if(Ste <= 0.0) Ste = 0.;
if(Ste - Swe <= 0.0) return 0.;
Scalar krn_;
krn_ = std::pow(1 - std::pow(Swe, 1/params.vgM()), params.vgM());
krn_ -= std::pow(1 - std::pow(Ste, 1/params.vgM()), params.vgM());
krn_ *= krn_;
if (params.krRegardsSnr())
{
// regard Snr in the permeability of the non-wetting
// phase, see Helmig1997
Scalar resIncluded =
std::max(std::min(Sw - params.Snr() / (1-params.Swr()), 1.0),
0.0);
krn_ *= std::sqrt(resIncluded );
}
else
krn_ *= std::sqrt(Sn / (1 - params.Swr()));
return krn_;
}
/*!
* \brief The relative permeability for the non-wetting phase
* of the medium implied by van Genuchten's
* parameterization.
*
* The permeability of gas in a three-phase system equals the
* standard two-phase description. (see p61. of "Comparison of the
* Three-Phase Oil Relative Permeability Models" M. Delshad and
* G. A. Pope, Transport in Porous Media 4 (1989), 59-83.)
*/
template <class FluidState>
static Scalar krg(const Params &params,
const FluidState &fluidState)
{
Scalar Sg = fluidState.saturation(gPhaseIdx);
Scalar Se = std::min(((1-Sg) - params.Sgr()) / (1 - params.Sgr()), 1.);
// regularization
if(Se > 1.0)
return 0.0;
if(Se < 0.0)
return 1.0;
Scalar scaleFactor = 1.;
if (Sg<=0.1) {
scaleFactor = (Sg - params.Sgr())/(0.1 - params.Sgr());
if (scaleFactor < 0.)
scaleFactor = 0.;
}
return scaleFactor
* std::pow(1 - Se, 1.0/3.)
* std::pow(1 - std::pow(Se, 1/params.vgM()), 2*params.vgM());
}
/*!
* \brief The derivative of all capillary pressures in regard to
* a given phase saturation.
*/
template <class ContainerT, class FluidState>
static void dCapillaryPressures_dSaturation(ContainerT &values,
const Params &params,
const FluidState &state,
int satPhaseIdx)
{
OPM_THROW(std::logic_error,
"Not implemented: dCapillaryPressures_dSaturation()");
}
/*!
* \brief The derivative of all capillary pressures in regard to
* a given phase pressure.
*/
template <class ContainerT, class FluidState>
static void dCapillaryPressures_dPressure(ContainerT &values,
const Params &params,
const FluidState &state,
int pPhaseIdx)
{
// -> not pressure dependent
for (int pcPhaseIdx = 0; pcPhaseIdx < numPhases; ++pcPhaseIdx)
values[pcPhaseIdx] = 0.0;
}
/*!
* \brief The derivative of all capillary pressures in regard to
* temperature.
*/
template <class ContainerT, class FluidState>
static void dCapillaryPressures_dTemperature(ContainerT &values,
const Params &params,
const FluidState &state)
{
// -> not temperature dependent
for (int pcPhaseIdx = 0; pcPhaseIdx < numPhases; ++pcPhaseIdx)
values[pcPhaseIdx] = 0.0;
}
/*!
* \brief The derivative of all capillary pressures in regard to
* a given mole fraction of a component in a phase.
*/
template <class ContainerT, class FluidState>
static void dCapillaryPressures_dMoleFraction(ContainerT &values,
const Params &params,
const FluidState &state,
int phaseIdx,
int compIdx)
{
// -> not composition dependent
for (int pcPhaseIdx = 0; pcPhaseIdx < numPhases; ++pcPhaseIdx)
values[pcPhaseIdx] = 0.0;
}
/*!
* \brief The derivative of all relative permeabilities in regard to
* a given phase saturation.
*/
template <class ContainerT, class FluidState>
static void dRelativePermeabilities_dSaturation(ContainerT &values,
const Params &params,
const FluidState &state,
int satPhaseIdx)
{
OPM_THROW(std::logic_error,
"Not implemented: dRelativePermeabilities_dSaturation()");
}
/*!
* \brief The derivative of all relative permeabilities in regard to
* a given phase pressure.
*/
template <class ContainerT, class FluidState>
static void dRelativePermeabilities_dPressure(ContainerT &values,
const Params &params,
const FluidState &state,
int pPhaseIdx)
{
// -> not pressure dependent
for (int krPhaseIdx = 0; krPhaseIdx < numPhases; ++krPhaseIdx)
values[krPhaseIdx] = 0.0;
}
/*!
* \brief The derivative of all relative permeabilities in regard to
* temperature.
*/
template <class ContainerT, class FluidState>
static void dRelativePermeabilities_dTemperature(ContainerT &values,
const Params &params,
const FluidState &state)
{
// -> not temperature dependent
for (int krPhaseIdx = 0; krPhaseIdx < numPhases; ++krPhaseIdx)
values[krPhaseIdx] = 0.0;
}
/*!
* \brief The derivative of all relative permeabilities in regard to
* a given mole fraction of a component in a phase.
*/
template <class ContainerT, class FluidState>
static void dRelativePermeabilities_dMoleFraction(ContainerT &values,
const Params &params,
const FluidState &state,
int phaseIdx,
int compIdx)
{
// -> not composition dependent
for (int krPhaseIdx = 0; krPhaseIdx < numPhases; ++krPhaseIdx)
values[krPhaseIdx] = 0.0;
}
};
} // namespace Opm
#endif

View File

@@ -19,10 +19,10 @@
*/
/*!
* \file
* \copydoc Opm::ParkerVanGen3PParams
* \copydoc Opm::ThreePhaseParkerVanGenuchtenParams
*/
#ifndef OPM_3P_PARKER_VAN_GENUCHTEN_PARAMS_HPP
#define OPM_3P_PARKER_VAN_GENUCHTEN_PARAMS_HPP
#ifndef OPM_THREE_PHASE_PARKER_VAN_GENUCHTEN_PARAMS_HPP
#define OPM_THREE_PHASE_PARKER_VAN_GENUCHTEN_PARAMS_HPP
#include <dune/common/fvector.hh>
@@ -42,29 +42,31 @@ namespace Opm {
* includes the residual saturations, as their handling is very
* model-specific.
*/
template<class ScalarT>
class ParkerVanGen3PParams
template<class TraitsT>
class ThreePhaseParkerVanGenuchtenParams
{
public:
typedef ScalarT Scalar;
typedef TraitsT Traits;
typedef typename Traits::Scalar Scalar;
ParkerVanGen3PParams()
{betaGW_ = betaNW_ = betaGN_ = 1.;}
ParkerVanGen3PParams(Scalar vgAlpha, Scalar vgN, Scalar KdNAPL, Scalar rhoBulk, Dune::FieldVector<Scalar, 4> residualSaturation, Scalar betaNW = 1., Scalar betaGN = 1., Scalar betaGW = 1., bool regardSnr=false)
ThreePhaseParkerVanGenuchtenParams()
{
setVgAlpha(vgAlpha);
setVgN(vgN);
setSwr(residualSaturation[0]);
setSnr(residualSaturation[1]);
setSgr(residualSaturation[2]);
setSwrx(residualSaturation[3]);
setkrRegardsSnr(regardSnr);
setKdNAPL(KdNAPL);
setBetaNW(betaNW);
setBetaGN(betaGN);
setBetaGW(betaGW);
setRhoBulk(rhoBulk);
betaNW_ = 1.0;
betaGN_ = 1.0;
#ifndef NDEBUG
finalized_ = false;
#endif
}
/*!
* \brief Finish the initialization of the parameter object.
*/
void finalize()
{
#ifndef NDEBUG
finalized_ = true;
#endif
}
/*!
@@ -72,7 +74,7 @@ public:
* curve.
*/
Scalar vgAlpha() const
{ return vgAlpha_; }
{ assertFinalized_(); return vgAlpha_; }
/*!
* \brief Set the \f$\alpha\f$ shape parameter of van Genuchten's
@@ -86,7 +88,7 @@ public:
* curve.
*/
Scalar vgM() const
{ return vgM_; }
{ assertFinalized_(); return vgM_; }
/*!
* \brief Set the \f$m\f$ shape parameter of van Genuchten's
@@ -102,7 +104,7 @@ public:
* curve.
*/
Scalar vgN() const
{ return vgN_; }
{ assertFinalized_(); return vgN_; }
/*!
* \brief Set the \f$n\f$ shape parameter of van Genuchten's
@@ -113,42 +115,11 @@ public:
void setVgN(Scalar n)
{ vgN_ = n; vgM_ = 1 - 1/vgN_; }
/*!
* \brief Return the residual saturation.
*/
Scalar satResidual(int phaseIdx) const
{
switch (phaseIdx)
{
case 0:
return Swr_;
break;
case 1:
return Snr_;
break;
case 2:
return Sgr_;
break;
};
OPM_THROW(std::logic_error, "Invalid phase index " << phaseIdx);
}
/*!
* \brief Set all residual saturations.
*/
void setResiduals(Dune::FieldVector<Scalar, 3> residualSaturation)
{
setSwr(residualSaturation[0]);
setSnr(residualSaturation[1]);
setSgr(residualSaturation[2]);
}
/*!
* \brief Return the residual wetting saturation.
*/
Scalar Swr() const
{ return Swr_; }
{ assertFinalized_(); return Swr_; }
/*!
* \brief Set the residual wetting saturation.
@@ -160,7 +131,7 @@ public:
* \brief Return the residual non-wetting saturation.
*/
Scalar Snr() const
{ return Snr_; }
{ assertFinalized_(); return Snr_; }
/*!
* \brief Set the residual non-wetting saturation.
@@ -172,7 +143,7 @@ public:
* \brief Return the residual gas saturation.
*/
Scalar Sgr() const
{ return Sgr_; }
{ assertFinalized_(); return Sgr_; }
/*!
* \brief Set the residual gas saturation.
@@ -181,7 +152,7 @@ public:
{ Sgr_ = input; }
Scalar Swrx() const
{ return Swrx_; }
{ assertFinalized_(); return Swrx_; }
/*!
* \brief Set the residual gas saturation.
@@ -198,20 +169,14 @@ public:
void setBetaGN(Scalar input)
{ betaGN_ = input; }
void setBetaGW(Scalar input)
{ betaGW_ = input; }
/*!
* \brief Return the values for the beta scaling parameters of capillary pressure between the phases
*/
Scalar betaNW() const
{ return betaNW_; }
{ assertFinalized_(); return betaNW_; }
Scalar betaGN() const
{ return betaGN_; }
Scalar betaGW() const
{ return betaGW_; }
{ assertFinalized_(); return betaGN_; }
/*!
* \brief defines if residual n-phase saturation should be regarded in its relative permeability.
@@ -222,32 +187,7 @@ public:
* \brief Calls if residual n-phase saturation should be regarded in its relative permeability.
*/
bool krRegardsSnr() const
{ return krRegardsSnr_; }
/*!
* \brief Return the bulk density of the porous medium
*/
Scalar rhoBulk() const
{ return rhoBulk_; }
/*!
* \brief Set the bulk density of the porous medium
*/
void setRhoBulk(Scalar input)
{ rhoBulk_ = input; }
/*!
* \brief Return the adsorption coefficient
*/
Scalar KdNAPL() const
{ return KdNAPL_; }
/*!
* \brief Set the adsorption coefficient
*/
void setKdNAPL(Scalar input)
{ KdNAPL_ = input; }
{ assertFinalized_(); return krRegardsSnr_; }
void checkDefined() const
{
@@ -258,26 +198,32 @@ public:
Valgrind::CheckDefined(Snr_);
Valgrind::CheckDefined(Sgr_);
Valgrind::CheckDefined(Swrx_);
Valgrind::CheckDefined(KdNAPL_);
Valgrind::CheckDefined(rhoBulk_);
Valgrind::CheckDefined(betaNW_);
Valgrind::CheckDefined(betaGN_);
Valgrind::CheckDefined(krRegardsSnr_);
}
private:
#ifndef NDEBUG
void assertFinalized_() const
{ assert(finalized_); }
bool finalized_;
#else
void assertFinalized_() const
{ }
#endif
Scalar vgAlpha_;
Scalar vgM_;
Scalar vgN_;
Scalar Swr_;
Scalar Snr_;
Scalar Sgr_;
Scalar Swrx_; /* (Sw+Sn)_r */
Scalar KdNAPL_;
Scalar rhoBulk_;
Scalar Swrx_; // Swr + Snr
Scalar betaNW_;
Scalar betaGN_;
Scalar betaGW_;
bool krRegardsSnr_ ;
};

View File

@@ -36,6 +36,7 @@
#include <opm/material/fluidmatrixinteractions/EffToAbsLaw.hpp>
#include <opm/material/fluidmatrixinteractions/EclDefaultMaterial.hpp>
#include <opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterial.hpp>
#include <opm/material/fluidmatrixinteractions/ThreePhaseParkerVanGenuchten.hpp>
// include the helper classes to construct traits
#include <opm/material/fluidmatrixinteractions/MaterialTraits.hpp>
@@ -305,6 +306,12 @@ int main(int argc, char **argv)
testThreePhaseApi<MaterialLaw, ThreePhaseFluidState>();
//testThreePhaseSatApi<MaterialLaw, ThreePhaseFluidState>();
}
{
typedef Opm::ThreePhaseParkerVanGenuchten<ThreePhaseTraits> MaterialLaw;
testGenericApi<MaterialLaw, ThreePhaseFluidState>();
testThreePhaseApi<MaterialLaw, ThreePhaseFluidState>();
//testThreePhaseSatApi<MaterialLaw, ThreePhaseFluidState>();
}
{
typedef Opm::NullMaterial<TwoPhaseTraits> MaterialLaw;
testGenericApi<MaterialLaw, TwoPhaseFluidState>();