this patch removes the in-file lists in favor of a global list of in the COPYING file. this is done because (a) maintaining a list of authors at the beginning of each source file is a major pain in the a**, (b) for this reason, the list of authors was not accurate in about 85% of all cases where more than one person was involved and (c) this list is not legally binding in any way (the copyright is at the person who authored a given change; if these lists had any legal relevance, one could "aquire" the copyright of the module by forking it and replacing the lists...)
393 lines
17 KiB
C++
393 lines
17 KiB
C++
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
// vi: set et ts=4 sw=4 sts=4:
|
|
/*
|
|
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/>.
|
|
|
|
Consult the COPYING file in the top-level source directory of this
|
|
module for the precise wording of the license and the list of
|
|
copyright holders.
|
|
*/
|
|
/*!
|
|
* \file
|
|
* \copydoc Opm::EffToAbsLaw
|
|
*/
|
|
#ifndef OPM_EFF_TO_ABS_LAW_HPP
|
|
#define OPM_EFF_TO_ABS_LAW_HPP
|
|
|
|
#include "EffToAbsLawParams.hpp"
|
|
|
|
#include <opm/material/fluidstates/SaturationOverlayFluidState.hpp>
|
|
|
|
namespace Opm {
|
|
/*!
|
|
* \ingroup FluidMatrixInteractions
|
|
*
|
|
* \brief This material law takes a material law defined for effective
|
|
* saturations and converts it to a material law defined on absolute
|
|
* saturations.
|
|
*
|
|
* The idea: "material laws" (like VanGenuchten or BrooksCorey) are
|
|
* defined for effective saturations. The numeric calculations
|
|
* however are performed with absolute saturations. The EffToAbsLaw
|
|
* class gets the "material laws" actually used as well as the
|
|
* corresponding parameter container as template arguments.
|
|
*
|
|
* Subsequently, the desired function (pc, Sw... ) of the actually
|
|
* used "material laws" are called but with the saturations already
|
|
* converted from absolute to effective.
|
|
*
|
|
* This approach makes sure that in the "material laws" only effective
|
|
* saturations are considered, which makes sense, as these laws only
|
|
* deal with effective saturations. This also allows for changing the
|
|
* calculation of the effective saturations easily, as this is subject
|
|
* of discussion / may be problem specific.
|
|
*
|
|
* Additionally, handing over effective saturations to the "material
|
|
* laws" in stead of them calculating effective saturations prevents
|
|
* accidently "converting twice".
|
|
*
|
|
* This boils down to:
|
|
* - the actual material laws (linear, VanGenuchten...) do not need to
|
|
* deal with any kind of conversion
|
|
* - the definition of the material law in the spatial parameters is
|
|
* not really intuitive, but using it is: Hand in values, get back
|
|
* values, do not deal with conversion.
|
|
*/
|
|
template <class EffLawT, class ParamsT = EffToAbsLawParams<typename EffLawT::Params, EffLawT::numPhases> >
|
|
class EffToAbsLaw : public EffLawT::Traits
|
|
{
|
|
typedef EffLawT EffLaw;
|
|
|
|
public:
|
|
typedef typename EffLaw::Traits Traits;
|
|
typedef ParamsT Params;
|
|
typedef typename EffLaw::Scalar Scalar;
|
|
|
|
//! The number of fluid phases
|
|
static const int numPhases = EffLaw::numPhases;
|
|
|
|
//! Specify whether this material law implements the two-phase
|
|
//! convenience API
|
|
static const bool implementsTwoPhaseApi = EffLaw::implementsTwoPhaseApi;
|
|
|
|
//! Specify whether this material law implements the two-phase
|
|
//! convenience API which only depends on the phase saturations
|
|
static const bool implementsTwoPhaseSatApi = EffLaw::implementsTwoPhaseSatApi;
|
|
|
|
//! Specify whether the quantities defined by this material law
|
|
//! are saturation dependent
|
|
static const bool isSaturationDependent = EffLaw::isSaturationDependent;
|
|
|
|
//! Specify whether the quantities defined by this material law
|
|
//! are dependent on the absolute pressure
|
|
static const bool isPressureDependent = EffLaw::isPressureDependent;
|
|
|
|
//! Specify whether the quantities defined by this material law
|
|
//! are temperature dependent
|
|
static const bool isTemperatureDependent = EffLaw::isTemperatureDependent;
|
|
|
|
//! Specify whether the quantities defined by this material law
|
|
//! are dependent on the phase composition
|
|
static const bool isCompositionDependent = EffLaw::isCompositionDependent;
|
|
|
|
/*!
|
|
* \brief The capillary pressure-saturation curves depending on absolute saturations.
|
|
*
|
|
* \param values A random access container which stores the
|
|
* relative pressure of each fluid phase.
|
|
* \param params The parameter object expressing the coefficients
|
|
* required by the van Genuchten law.
|
|
* \param fs The fluid state for which the capillary pressure
|
|
* ought to be calculated
|
|
*/
|
|
template <class Container, class FluidState>
|
|
static void capillaryPressures(Container &values, const Params ¶ms, const FluidState &fs)
|
|
{
|
|
typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;
|
|
|
|
OverlayFluidState overlayFs(fs);
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
overlayFs.setSaturation(phaseIdx,
|
|
effectiveSaturation(params,
|
|
fs.saturation(phaseIdx),
|
|
phaseIdx));
|
|
}
|
|
|
|
EffLaw::template capillaryPressures<Container, OverlayFluidState>(values, params, overlayFs);
|
|
}
|
|
|
|
/*!
|
|
* \brief The relative permeability-saturation curves depending on absolute saturations.
|
|
*
|
|
* \param values A random access container which stores the
|
|
* relative permeability of each fluid phase.
|
|
* \param params The parameter object expressing the coefficients
|
|
* required by the van Genuchten law.
|
|
* \param fs The fluid state for which the relative permeabilities
|
|
* ought to be calculated
|
|
*/
|
|
template <class Container, class FluidState>
|
|
static void relativePermeabilities(Container &values, const Params ¶ms, const FluidState &fs)
|
|
{
|
|
typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;
|
|
|
|
OverlayFluidState overlayFs(fs);
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
overlayFs.setSaturation(phaseIdx,
|
|
effectiveSaturation(params,
|
|
fs.saturation(phaseIdx),
|
|
phaseIdx));
|
|
}
|
|
|
|
EffLaw::template relativePermeabilities<Container, OverlayFluidState>(values, params, overlayFs);
|
|
}
|
|
|
|
/*!
|
|
* \brief The capillary pressure-saturation curve.
|
|
*
|
|
*
|
|
* \param params A object that stores the appropriate coefficients
|
|
* for the respective law.
|
|
*
|
|
* \return Capillary pressure [Pa] calculated by specific
|
|
* constitutive relation (e.g. Brooks & Corey, van
|
|
* Genuchten, linear...)
|
|
*/
|
|
template <class FluidState, class Evaluation = typename FluidState::Scalar>
|
|
static Evaluation pcnw(const Params ¶ms, const FluidState &fs)
|
|
{
|
|
typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;
|
|
|
|
static_assert(FluidState::numPhases == numPhases,
|
|
"The fluid state and the material law must exhibit the same "
|
|
"number of phases!");
|
|
|
|
OverlayFluidState overlayFs(fs);
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
overlayFs.setSaturation(phaseIdx,
|
|
effectiveSaturation(params,
|
|
fs.saturation(phaseIdx),
|
|
phaseIdx));
|
|
}
|
|
|
|
return EffLaw::template pcnw<OverlayFluidState, Evaluation>(params, overlayFs);
|
|
}
|
|
|
|
template <class Evaluation>
|
|
static typename std::enable_if<implementsTwoPhaseSatApi, Evaluation>::type
|
|
twoPhaseSatPcnw(const Params ¶ms, const Evaluation& SwAbs)
|
|
{
|
|
const Evaluation& SwEff = effectiveSaturation(params, SwAbs, Traits::wettingPhaseIdx);
|
|
|
|
return EffLaw::twoPhaseSatPcnw(params, SwEff);
|
|
}
|
|
|
|
/*!
|
|
* \brief The saturation-capillary pressure curves.
|
|
*/
|
|
template <class Container, class FluidState>
|
|
static void saturations(Container &values, const Params ¶ms, const FluidState &fs)
|
|
{
|
|
EffLaw::template saturations<Container, FluidState>(values, params, fs);
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
|
|
values[phaseIdx] = absoluteSaturation(params, values[phaseIdx], phaseIdx);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Calculate wetting liquid phase saturation given that
|
|
* the rest of the fluid state has been initialized
|
|
*/
|
|
template <class FluidState, class Evaluation = typename FluidState::Scalar>
|
|
static Evaluation Sw(const Params ¶ms, const FluidState &fs)
|
|
{
|
|
return absoluteSaturation(params,
|
|
EffLaw::template Sw<FluidState, Evaluation>(params, fs),
|
|
Traits::wettingPhaseIdx);
|
|
}
|
|
|
|
template <class Evaluation>
|
|
static typename std::enable_if<implementsTwoPhaseSatApi, Evaluation>::type
|
|
twoPhaseSatSw(const Params ¶ms, const Evaluation& Sw)
|
|
{ return absoluteSaturation(params,
|
|
EffLaw::twoPhaseSatSw(params, Sw),
|
|
Traits::wettingPhaseIdx); }
|
|
|
|
/*!
|
|
* \brief Calculate non-wetting liquid phase saturation given that
|
|
* the rest of the fluid state has been initialized
|
|
*/
|
|
template <class FluidState, class Evaluation = typename FluidState::Scalar>
|
|
static Evaluation Sn(const Params ¶ms, const FluidState &fs)
|
|
{
|
|
return absoluteSaturation(params,
|
|
EffLaw::template Sn<FluidState, Evaluation>(params, fs),
|
|
Traits::nonWettingPhaseIdx);
|
|
}
|
|
|
|
template <class Evaluation>
|
|
static typename std::enable_if<implementsTwoPhaseSatApi, Evaluation>::type
|
|
twoPhaseSatSn(const Params ¶ms, const Evaluation& Sw)
|
|
{
|
|
return absoluteSaturation(params,
|
|
EffLaw::twoPhaseSatSn(params, Sw),
|
|
Traits::nonWettingPhaseIdx);
|
|
}
|
|
|
|
/*!
|
|
* \brief Calculate gas phase saturation given that the rest of
|
|
* the fluid state has been initialized
|
|
*
|
|
* This method is only available for at least three fluid phases
|
|
*/
|
|
template <class FluidState, class Evaluation = typename FluidState::Scalar>
|
|
static typename std::enable_if< (Traits::numPhases > 2), Evaluation>::type
|
|
Sg(const Params ¶ms, const FluidState &fs)
|
|
{
|
|
return absoluteSaturation(params,
|
|
EffLaw::template Sg<FluidState, Evaluation>(params, fs),
|
|
Traits::gasPhaseIdx);
|
|
}
|
|
|
|
/*!
|
|
* \brief The relative permeability for the wetting phase.
|
|
*
|
|
* \param params A container object that is populated with the appropriate coefficients for the respective law.
|
|
* Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container
|
|
* is constructed accordingly. Afterwards the values are set there, too.
|
|
* \return Relative permeability of the wetting phase calculated as implied by EffLaw e.g. Brooks & Corey, van Genuchten, linear... .
|
|
*
|
|
*/
|
|
template <class FluidState, class Evaluation = typename FluidState::Scalar>
|
|
static Evaluation krw(const Params ¶ms, const FluidState &fs)
|
|
{
|
|
typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;
|
|
|
|
static_assert(FluidState::numPhases == numPhases,
|
|
"The fluid state and the material law must exhibit the same "
|
|
"number of phases!");
|
|
|
|
OverlayFluidState overlayFs(fs);
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
overlayFs.setSaturation(phaseIdx,
|
|
effectiveSaturation(params,
|
|
fs.saturation(phaseIdx),
|
|
phaseIdx));
|
|
}
|
|
|
|
return EffLaw::template krw<OverlayFluidState, Evaluation>(params, overlayFs);
|
|
}
|
|
|
|
template <class Evaluation>
|
|
static typename std::enable_if<implementsTwoPhaseSatApi, Evaluation>::type
|
|
twoPhaseSatKrw(const Params ¶ms, const Evaluation& Sw)
|
|
{ return EffLaw::twoPhaseSatKrw(params, effectiveSaturation(params, Sw, Traits::nonWettingPhaseIdx)); }
|
|
|
|
/*!
|
|
* \brief The relative permeability of the non-wetting phase.
|
|
*/
|
|
template <class FluidState, class Evaluation = typename FluidState::Scalar>
|
|
static Evaluation krn(const Params ¶ms, const FluidState &fs)
|
|
{
|
|
typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;
|
|
|
|
static_assert(FluidState::numPhases == numPhases,
|
|
"The fluid state and the material law must exhibit the same "
|
|
"number of phases!");
|
|
|
|
OverlayFluidState overlayFs(fs);
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
overlayFs.setSaturation(phaseIdx,
|
|
effectiveSaturation(params,
|
|
fs.saturation(phaseIdx),
|
|
phaseIdx));
|
|
}
|
|
|
|
return EffLaw::template krn<OverlayFluidState, Evaluation>(params, overlayFs);
|
|
}
|
|
|
|
template <class Evaluation>
|
|
static typename std::enable_if<implementsTwoPhaseSatApi, Evaluation>::type
|
|
twoPhaseSatKrn(const Params ¶ms, const Evaluation& Sw)
|
|
{ return EffLaw::twoPhaseSatKrn(params, effectiveSaturation(params, Sw, Traits::nonWettingPhaseIdx)); }
|
|
|
|
/*!
|
|
* \brief The relative permability of the gas phase
|
|
*
|
|
* This method is only available for at least three fluid phases
|
|
*/
|
|
template <class FluidState, class Evaluation = typename FluidState::Scalar>
|
|
static typename std::enable_if< (Traits::numPhases > 2), Evaluation>::type
|
|
krg(const Params ¶ms, const FluidState &fs)
|
|
{
|
|
typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;
|
|
|
|
static_assert(FluidState::numPhases == numPhases,
|
|
"The fluid state and the material law must exhibit the same "
|
|
"number of phases!");
|
|
|
|
OverlayFluidState overlayFs(fs);
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
overlayFs.setSaturation(phaseIdx,
|
|
effectiveSaturation(params,
|
|
fs.saturation(phaseIdx),
|
|
phaseIdx));
|
|
}
|
|
|
|
return EffLaw::template krg<OverlayFluidState, Evaluation>(params, overlayFs);
|
|
}
|
|
|
|
/*!
|
|
* \brief Convert an absolute saturation to an effective one.
|
|
*/
|
|
template <class Evaluation>
|
|
static Evaluation effectiveSaturation(const Params ¶ms, const Evaluation& S, unsigned phaseIdx)
|
|
{ return (S - params.residualSaturation(phaseIdx))/(1.0 - params.sumResidualSaturations()); }
|
|
|
|
/*!
|
|
* \brief Convert an effective saturation to an absolute one.
|
|
*/
|
|
template <class Evaluation>
|
|
static Evaluation absoluteSaturation(const Params ¶ms, const Evaluation& S, unsigned phaseIdx)
|
|
{ return S*(1.0 - params.sumResidualSaturations()) + params.residualSaturation(phaseIdx); }
|
|
|
|
private:
|
|
/*!
|
|
* \brief Derivative of the effective saturation w.r.t. the absolute saturation.
|
|
*
|
|
* \param params A container object that is populated with the appropriate coefficients for the respective law.
|
|
* Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container
|
|
* is constructed accordingly. Afterwards the values are set there, too.
|
|
* \return Derivative of the effective saturation w.r.t. the absolute saturation.
|
|
*/
|
|
static Scalar dSeff_dSabs_(const Params ¶ms, int /*phaseIdx*/)
|
|
{ return 1.0/(1 - params.sumResidualSaturations()); }
|
|
|
|
/*!
|
|
* \brief Derivative of the absolute saturation w.r.t. the effective saturation.
|
|
*
|
|
* \param params A container object that is populated with the appropriate coefficients for the respective law.
|
|
* Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container
|
|
* is constructed accordingly. Afterwards the values are set there, too.
|
|
* \return Derivative of the absolute saturation w.r.t. the effective saturation.
|
|
*/
|
|
static Scalar dSabs_dSeff_(const Params ¶ms, int /*phaseIdx*/)
|
|
{ return 1 - params.sumResidualSaturations(); }
|
|
};
|
|
} // namespace Opm
|
|
|
|
#endif
|