// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- // vi: set et ts=4 sw=4 sts=4: /***************************************************************************** * See the file COPYING for full copying permissions. * * * * This program 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. * * * * This program 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 this program. If not, see . * *****************************************************************************/ /*! * \file * * \brief Implementation of van Genuchten's capillary pressure-saturation relation. * */ #ifndef PARKERVANGEN_3P_HH #define PARKERVANGEN_3P_HH #include "parkervangen3pparams.hh" #include namespace Dumux { /*! * \ingroup material * * \brief Implementation of van Genuchten's capillary pressure <-> * saturation relation. This class bundles the "raw" curves * as static members and doesn't concern itself converting * absolute to effective saturations and vince versa. * * \sa VanGenuchten, VanGenuchtenThreephase */ template > class ParkerVanGen3P { public: typedef ParamsT Params; typedef typename Params::Scalar Scalar; /*! * \brief The capillary pressure-saturation curve. * \param params Array of parameters * \param sw wetting phase saturation * */ static Scalar pc(const Params ¶ms, Scalar sw) { DUNE_THROW(Dune::NotImplemented, "Capillary pressures for three phases is not so simple! Use pcgn, pcnw, and pcgw"); } /*! * \brief The capillary pressure-saturation curve copied from MUFTE/pml/constrel3p3cni.c * \param params Array of parameters * \param sw wetting phase saturation or sum of wetting phase saturations * */ static Scalar pcgw(const Params ¶ms, 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 that is why variable names do not yet fulfill Dumux rules, TODO Change */ Scalar r,se,x,vgm; Scalar pc,pcPrime,seRegu; Scalar pcvgReg = 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; vgm = 1.-1./params.vgn(); if (se>pcvgReg && se<1-pcvgReg) { r = std::pow(se,-1/vgm); x = r-1; vgm = 1-vgm; x = std::pow(x,vgm); r = x/params.vgAlpha(); return(r); } else { /* value and derivative at regularization point */ if (se<=pcvgReg) seRegu = pcvgReg; else seRegu = 1-pcvgReg; pc = std::pow(std::pow(seRegu,-1/vgm)-1,1/params.vgn())/params.vgAlpha(); pcPrime = std::pow(std::pow(seRegu,-1/vgm)-1,1/params.vgn()-1)*std::pow(seRegu,-1/vgm-1) *(-1/vgm)/params.vgAlpha()/(1-params.sgr()-params.swr())/params.vgn(); /* evaluate tangential */ r = (se-seRegu)*pcPrime+pc; return(r/params.betaGw()); } } /*! * \brief The capillary pressure-saturation curve copied from MUFTE/pml/constrel3p3cni.c * \param params Array of parameters * \param sw wetting phase saturation or sum of wetting phase saturations */ static Scalar pcnw(const Params ¶ms, 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 that is why variable names do not yet fulfill Dumux rules, TODO Change */ Scalar r,se,x,vgm; Scalar pc,pcPrime,seRegu; Scalar pcvgReg = 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; vgm = 1.-1./params.vgn(); if (se>pcvgReg && se<1-pcvgReg) { r = std::pow(se,-1/vgm); x = r-1; vgm = 1-vgm; x = std::pow(x,vgm); r = x/params.vgAlpha(); return(r); } else { /* value and derivative at regularization point */ if (se<=pcvgReg) seRegu = pcvgReg; else seRegu = 1-pcvgReg; pc = std::pow(std::pow(seRegu,-1/vgm)-1,1/params.vgn())/params.vgAlpha(); pcPrime = std::pow(std::pow(seRegu,-1/vgm)-1,1/params.vgn()-1)*std::pow(seRegu,-1/vgm-1) *(-1/vgm)/params.vgAlpha()/(1-params.snr()-params.swr())/params.vgn(); /* evaluate tangential */ r = (se-seRegu)*pcPrime+pc; return(r/params.betaNw()); } } /*! * \brief The capillary pressure-saturation curve copied from MUFTE/pml/constrel3p3cni.c * \param params Array of parameters * \param St sum of wetting (liquid) phase saturations */ static Scalar pcgn(const Params ¶ms, Scalar St) { /* St = sum of wetting (liquid) phase saturations alpha : VanGenuchten-alpha this function is just copied from MUFTE/pml/constrel3p3cni.c that is why variable names do not yet fulfill Dumux rules, TODO Change */ Scalar r,se,x,vgm; Scalar pc,pcPrime,seRegu; Scalar pcvgReg = 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; vgm = 1.-1./params.vgn(); if (se>pcvgReg && se<1-pcvgReg) { r = std::pow(se,-1/vgm); x = r-1; vgm = 1-vgm; x = std::pow(x,vgm); r = x/params.vgAlpha(); return(r); } else { /* value and derivative at regularization point */ if (se<=pcvgReg) seRegu = pcvgReg; else seRegu = 1-pcvgReg; pc = std::pow(std::pow(seRegu,-1/vgm)-1,1/params.vgn())/params.vgAlpha(); pcPrime = std::pow(std::pow(seRegu,-1/vgm)-1,1/params.vgn()-1)*std::pow(seRegu,-1/vgm-1) *(-1/vgm)/params.vgAlpha()/(1-params.sgr()-params.swrx())/params.vgn(); /* evaluate tangential */ r = (se-seRegu)*pcPrime+pc; return(r/params.betaGn()); } } /*! * \brief The capillary pressure-saturation curve copied from MUFTE/pml/constrel3p3cni.c * \param params Array of parameters * \param sn Non-wetting liquid saturation */ static Scalar pcAlpha(const Params ¶ms, 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. * \param params Array of parameters * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ * */ static Scalar sw(const Params ¶ms, Scalar pc) { DUNE_THROW(Dune::NotImplemented, "sw(pc) for three phases not implemented! Do it yourself!"); } /*! * \brief Returns the partial derivative of the capillary * pressure to the effective saturation. * \param params Array of parameters * \param sw Wetting liquid saturation */ static Scalar dpc_dsw(const Params ¶ms, Scalar sw) { DUNE_THROW(Dune::NotImplemented, "dpc/dsw for three phases not implemented! Do it yourself!"); } /*! * \brief Returns the partial derivative of the effective * saturation to the capillary pressure. * \param params Array of parameters * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ */ static Scalar dsw_dpc(const Params ¶ms, Scalar pc) { DUNE_THROW(Dune::NotImplemented, "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 Non-wetting liquid saturation * \param sg Gas saturation * \param saturation wetting liquid saturation * \param params Array of parameters. */ static Scalar krw(const Params ¶ms, 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 Wetting liquid saturation * \param sg Gas saturation * \param saturation Non-wetting liquid saturation * \param params Array of parameters. */ static Scalar krn(const Params ¶ms, 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 Wetting liquid saturation * \param sn Non-wetting liquid saturation * \param saturation Gas saturation * \param params Array of parameters. */ static Scalar krg(const Params ¶ms, 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 Wetting liquid saturation * \param sg Gas saturation * \param sn Non-wetting liquid saturation * \param params Array of parameters. * \param phaseIdx indicator, The saturation of all phases. */ static Scalar kr(const Params ¶ms, const int phaseIdx, const Scalar sw, const Scalar sn, const Scalar sg) { switch (phaseIdx) { 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 params Array of parameters */ static Scalar bulkDensTimesAdsorpCoeff (const Params ¶ms) { return params.rhoBulk() * params.KdNAPL(); } }; } #endif