Files
opm-common/opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp

1108 lines
52 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::EclMaterialLawManager
*/
#if ! HAVE_ECL_INPUT
#error "Eclipse input support in opm-common is required to use the ECL material manager!"
#endif
#ifndef OPM_ECL_MATERIAL_LAW_MANAGER_HPP
#define OPM_ECL_MATERIAL_LAW_MANAGER_HPP
#include <opm/material/fluidmatrixinteractions/EclTwoPhaseMaterialParams.hpp>
#include <opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterial.hpp>
#include <opm/material/fluidmatrixinteractions/EclEpsTwoPhaseLaw.hpp>
#include <opm/material/fluidmatrixinteractions/EclHysteresisTwoPhaseLaw.hpp>
#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
#include <opm/material/fluidmatrixinteractions/EclEpsConfig.hpp>
#include <opm/material/fluidmatrixinteractions/EclHysteresisConfig.hpp>
#include <opm/material/fluidmatrixinteractions/EclMultiplexerMaterial.hpp>
#include <opm/material/fluidmatrixinteractions/MaterialTraits.hpp>
#include <opm/material/fluidstates/SimpleModularFluidState.hpp>
#if HAVE_OPM_COMMON
#include <opm/common/OpmLog/OpmLog.hpp>
#endif
#include <opm/material/common/Exceptions.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <algorithm>
namespace Opm {
/*!
* \ingroup fluidmatrixinteractions
*
* \brief Provides an simple way to create and manage the material law objects
* for a complete ECL deck.
*/
template <class TraitsT>
class EclMaterialLawManager
{
private:
typedef TraitsT Traits;
typedef typename Traits::Scalar Scalar;
enum { waterPhaseIdx = Traits::wettingPhaseIdx };
enum { oilPhaseIdx = Traits::nonWettingPhaseIdx };
enum { gasPhaseIdx = Traits::gasPhaseIdx };
enum { numPhases = Traits::numPhases };
typedef TwoPhaseMaterialTraits<Scalar, oilPhaseIdx, gasPhaseIdx> GasOilTraits;
typedef TwoPhaseMaterialTraits<Scalar, waterPhaseIdx, oilPhaseIdx> OilWaterTraits;
// the two-phase material law which is defined on effective (unscaled) saturations
typedef PiecewiseLinearTwoPhaseMaterial<GasOilTraits> GasOilEffectiveTwoPhaseLaw;
typedef PiecewiseLinearTwoPhaseMaterial<OilWaterTraits> OilWaterEffectiveTwoPhaseLaw;
typedef typename GasOilEffectiveTwoPhaseLaw::Params GasOilEffectiveTwoPhaseParams;
typedef typename OilWaterEffectiveTwoPhaseLaw::Params OilWaterEffectiveTwoPhaseParams;
// the two-phase material law which is defined on absolute (scaled) saturations
typedef EclEpsTwoPhaseLaw<GasOilEffectiveTwoPhaseLaw> GasOilEpsTwoPhaseLaw;
typedef EclEpsTwoPhaseLaw<OilWaterEffectiveTwoPhaseLaw> OilWaterEpsTwoPhaseLaw;
typedef typename GasOilEpsTwoPhaseLaw::Params GasOilEpsTwoPhaseParams;
typedef typename OilWaterEpsTwoPhaseLaw::Params OilWaterEpsTwoPhaseParams;
// the scaled two-phase material laws with hystersis
typedef EclHysteresisTwoPhaseLaw<GasOilEpsTwoPhaseLaw> GasOilTwoPhaseLaw;
typedef EclHysteresisTwoPhaseLaw<OilWaterEpsTwoPhaseLaw> OilWaterTwoPhaseLaw;
typedef typename GasOilTwoPhaseLaw::Params GasOilTwoPhaseHystParams;
typedef typename OilWaterTwoPhaseLaw::Params OilWaterTwoPhaseHystParams;
public:
// the three-phase material law used by the simulation
typedef EclMultiplexerMaterial<Traits, GasOilTwoPhaseLaw, OilWaterTwoPhaseLaw> MaterialLaw;
typedef typename MaterialLaw::Params MaterialLawParams;
private:
// internal typedefs
typedef std::vector<std::shared_ptr<GasOilEffectiveTwoPhaseParams> > GasOilEffectiveParamVector;
typedef std::vector<std::shared_ptr<OilWaterEffectiveTwoPhaseParams> > OilWaterEffectiveParamVector;
typedef std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar> > > GasOilScalingPointsVector;
typedef std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar> > > OilWaterScalingPointsVector;
typedef std::vector<std::shared_ptr<EclEpsScalingPointsInfo<Scalar> > > GasOilScalingInfoVector;
typedef std::vector<std::shared_ptr<EclEpsScalingPointsInfo<Scalar> > > OilWaterScalingInfoVector;
typedef std::vector<std::shared_ptr<GasOilTwoPhaseHystParams> > GasOilParamVector;
typedef std::vector<std::shared_ptr<OilWaterTwoPhaseHystParams> > OilWaterParamVector;
typedef std::vector<std::shared_ptr<MaterialLawParams> > MaterialLawParamsVector;
public:
EclMaterialLawManager()
{}
void initFromDeck(const Opm::Deck& deck,
const Opm::EclipseState& eclState,
const std::vector<int>& compressedToCartesianElemIdx)
{
// get the number of saturation regions and the number of cells in the deck
const size_t numSatRegions = eclState.runspec().tabdims().getNumSatTables();
// copy the SATNUM grid property. in some cases this is not necessary, but it
// should not require much memory anyway...
#ifdef ENABLE_3DPROPS_TESTING
size_t numCompressedElems = compressedToCartesianElemIdx.size();
satnumRegionArray_.resize(numCompressedElems);
if (eclState.fieldProps().has<int>("SATNUM")) {
const auto& satnumRawData = eclState.fieldProps().get_global<int>("SATNUM");
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
unsigned cartesianElemIdx = static_cast<unsigned>(compressedToCartesianElemIdx[elemIdx]);
satnumRegionArray_[elemIdx] = satnumRawData[cartesianElemIdx] - 1;
}
}
else
std::fill(satnumRegionArray_.begin(), satnumRegionArray_.end(), 0);
// create the information for the imbibition region (IMBNUM). By default this is
// the same as the saturation region (SATNUM)
imbnumRegionArray_ = satnumRegionArray_;
if (eclState.fieldProps().has<int>("IMBNUM")) {
const auto& imbnumRawData = eclState.fieldProps().get_global<int>("IMBNUM");
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
int cartesianElemIdx = compressedToCartesianElemIdx[elemIdx];
imbnumRegionArray_[elemIdx] = imbnumRawData[cartesianElemIdx] - 1;
}
}
#else
size_t numCompressedElems = compressedToCartesianElemIdx.size();
satnumRegionArray_.resize(numCompressedElems);
if (eclState.get3DProperties().hasDeckIntGridProperty("SATNUM")) {
const auto& satnumRawData = eclState.get3DProperties().getIntGridProperty("SATNUM").getData();
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
unsigned cartesianElemIdx = static_cast<unsigned>(compressedToCartesianElemIdx[elemIdx]);
satnumRegionArray_[elemIdx] = satnumRawData[cartesianElemIdx] - 1;
}
}
else
std::fill(satnumRegionArray_.begin(), satnumRegionArray_.end(), 0);
// create the information for the imbibition region (IMBNUM). By default this is
// the same as the saturation region (SATNUM)
imbnumRegionArray_ = satnumRegionArray_;
if (eclState.get3DProperties().hasDeckIntGridProperty("IMBNUM")) {
const auto& imbnumRawData = eclState.get3DProperties().getIntGridProperty("IMBNUM").getData();
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
int cartesianElemIdx = compressedToCartesianElemIdx[elemIdx];
imbnumRegionArray_[elemIdx] = imbnumRawData[cartesianElemIdx] - 1;
}
}
#endif
readGlobalEpsOptions_(deck, eclState);
readGlobalHysteresisOptions_(deck);
readGlobalThreePhaseOptions_(deck);
unscaledEpsInfo_.resize(numSatRegions);
for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx)
unscaledEpsInfo_[satRegionIdx].extractUnscaled(deck, eclState, satRegionIdx);
initParamsForElements_(deck, eclState, compressedToCartesianElemIdx, satnumRegionArray_, imbnumRegionArray_);
}
/*!
* \brief Modify the initial condition according to the SWATINIT keyword.
*
* The method returns the water saturation which yields a givenn capillary
* pressure. The reason this method is not folded directly into initFromDeck() is
* that the capillary pressure given depends on the particuars of how the simulator
* calculates its initial condition.
*/
Scalar applySwatinit(unsigned elemIdx,
Scalar pcow,
Scalar Sw)
{
auto& elemScaledEpsInfo = *oilWaterScaledEpsInfoDrainage_[elemIdx];
// TODO: Mixed wettability systems - see ecl kw OPTIONS switch 74
if (pcow < 0.0)
Sw = elemScaledEpsInfo.Swu;
else {
if (Sw <= elemScaledEpsInfo.Swl)
Sw = elemScaledEpsInfo.Swl;
// specify a fluid state which only stores the saturations
typedef Opm::SimpleModularFluidState<Scalar,
numPhases,
/*numComponents=*/0,
/*FluidSystem=*/void, /* -> don't care */
/*storePressure=*/false,
/*storeTemperature=*/false,
/*storeComposition=*/false,
/*storeFugacity=*/false,
/*storeSaturation=*/true,
/*storeDensity=*/false,
/*storeViscosity=*/false,
/*storeEnthalpy=*/false> FluidState;
FluidState fs;
fs.setSaturation(waterPhaseIdx, Sw);
fs.setSaturation(gasPhaseIdx, 0);
fs.setSaturation(oilPhaseIdx, 0);
Scalar pc[numPhases] = { 0 };
MaterialLaw::capillaryPressures(pc, materialLawParams(elemIdx), fs);
Scalar pcowAtSw = pc[oilPhaseIdx] - pc[waterPhaseIdx];
const Scalar pcowAtSwThreshold = 1.0; //Pascal
// avoid divison by very small number
if (std::abs(pcowAtSw) > pcowAtSwThreshold) {
elemScaledEpsInfo.maxPcow *= pcow/pcowAtSw;
auto& elemEclEpsScalingPoints = oilWaterScaledEpsPointsDrainage(elemIdx);
elemEclEpsScalingPoints.init(elemScaledEpsInfo, *oilWaterEclEpsConfig_, Opm::EclOilWaterSystem);
}
}
return Sw;
}
bool enableEndPointScaling() const
{ return enableEndPointScaling_; }
bool enableHysteresis() const
{ return hysteresisConfig_->enableHysteresis(); }
MaterialLawParams& materialLawParams(unsigned elemIdx)
{
assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
return *materialLawParams_[elemIdx];
}
const MaterialLawParams& materialLawParams(unsigned elemIdx) const
{
assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
return *materialLawParams_[elemIdx];
}
/*!
* \brief Returns a material parameter object for a given element and saturation region.
*
* This method changes the saturation table idx in the original material law parameter object.
* In the context of ECL reservoir simulators, this is required to properly handle
* wells with its own saturation table idx. In order to reset the saturation table idx
* in the materialLawparams_ call the method with the cells satRegionIdx
*/
const MaterialLawParams& connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const
{
MaterialLawParams& mlp = *materialLawParams_[elemIdx];
#if HAVE_OPM_COMMON
if (enableHysteresis())
OpmLog::warning("Warning: Using non-default satnum regions for conenction is not tested in combination with hysteresis");
#endif
// Currently we don't support COMPIMP. I.e. use the same table lookup for the hysteresis curves.
// unsigned impRegionIdx = satRegionIdx;
// change the sat table it points to.
switch (mlp.approach()) {
case EclStone1Approach: {
auto& realParams = mlp.template getRealParams<Opm::EclStone1Approach>();
realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
// if (enableHysteresis()) {
// realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
// realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
// }
}
break;
case EclStone2Approach: {
auto& realParams = mlp.template getRealParams<Opm::EclStone2Approach>();
realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
// if (enableHysteresis()) {
// realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
// realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
// }
}
break;
case EclDefaultApproach: {
auto& realParams = mlp.template getRealParams<Opm::EclDefaultApproach>();
realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
// if (enableHysteresis()) {
// realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
// realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
// }
}
break;
case EclTwoPhaseApproach: {
auto& realParams = mlp.template getRealParams<Opm::EclTwoPhaseApproach>();
realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
// if (enableHysteresis()) {
// realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
// realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
// realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
// }
}
break;
default:
throw std::logic_error("Enum value for material approach unknown!");
}
return mlp;
}
int satnumRegionIdx(unsigned elemIdx) const
{ return satnumRegionArray_[elemIdx]; }
int imbnumRegionIdx(unsigned elemIdx) const
{ return imbnumRegionArray_[elemIdx]; }
std::shared_ptr<MaterialLawParams>& materialLawParamsPointerReferenceHack(unsigned elemIdx)
{
assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
return materialLawParams_[elemIdx];
}
template <class FluidState>
void updateHysteresis(const FluidState& fluidState, unsigned elemIdx)
{
if (!enableHysteresis())
return;
auto threePhaseParams = materialLawParams_[elemIdx];
MaterialLaw::updateHysteresis(*threePhaseParams, fluidState);
}
void oilWaterHysteresisParams(Scalar& pcSwMdc,
Scalar& krnSwMdc,
unsigned elemIdx) const
{
if (!enableHysteresis())
throw std::runtime_error("Cannot get hysteresis parameters if hysteresis not enabled.");
const auto& params = materialLawParams(elemIdx);
MaterialLaw::oilWaterHysteresisParams(pcSwMdc, krnSwMdc, params);
}
void setOilWaterHysteresisParams(const Scalar& pcSwMdc,
const Scalar& krnSwMdc,
unsigned elemIdx)
{
if (!enableHysteresis())
throw std::runtime_error("Cannot set hysteresis parameters if hysteresis not enabled.");
auto& params = materialLawParams(elemIdx);
MaterialLaw::setOilWaterHysteresisParams(pcSwMdc, krnSwMdc, params);
}
void gasOilHysteresisParams(Scalar& pcSwMdc,
Scalar& krnSwMdc,
unsigned elemIdx) const
{
if (!enableHysteresis())
throw std::runtime_error("Cannot get hysteresis parameters if hysteresis not enabled.");
const auto& params = materialLawParams(elemIdx);
MaterialLaw::gasOilHysteresisParams(pcSwMdc, krnSwMdc, params);
}
void setGasOilHysteresisParams(const Scalar& pcSwMdc,
const Scalar& krnSwMdc,
unsigned elemIdx)
{
if (!enableHysteresis())
throw std::runtime_error("Cannot set hysteresis parameters if hysteresis not enabled.");
auto& params = materialLawParams(elemIdx);
MaterialLaw::setGasOilHysteresisParams(pcSwMdc, krnSwMdc, params);
}
EclEpsScalingPoints<Scalar>& oilWaterScaledEpsPointsDrainage(unsigned elemIdx)
{
auto& materialParams = *materialLawParams_[elemIdx];
switch (materialParams.approach()) {
case EclStone1Approach: {
auto& realParams = materialParams.template getRealParams<Opm::EclStone1Approach>();
return realParams.oilWaterParams().drainageParams().scaledPoints();
}
case EclStone2Approach: {
auto& realParams = materialParams.template getRealParams<Opm::EclStone2Approach>();
return realParams.oilWaterParams().drainageParams().scaledPoints();
}
case EclDefaultApproach: {
auto& realParams = materialParams.template getRealParams<Opm::EclDefaultApproach>();
return realParams.oilWaterParams().drainageParams().scaledPoints();
}
case EclTwoPhaseApproach: {
auto& realParams = materialParams.template getRealParams<Opm::EclTwoPhaseApproach>();
return realParams.oilWaterParams().drainageParams().scaledPoints();
}
default:
throw std::logic_error("Enum value for material approach unknown!");
}
}
const Opm::EclEpsScalingPointsInfo<Scalar>& oilWaterScaledEpsInfoDrainage(size_t elemIdx) const
{ return *oilWaterScaledEpsInfoDrainage_[elemIdx]; }
std::shared_ptr<EclEpsScalingPointsInfo<Scalar> >& oilWaterScaledEpsInfoDrainagePointerReferenceHack(unsigned elemIdx)
{ return oilWaterScaledEpsInfoDrainage_[elemIdx]; }
private:
void readGlobalEpsOptions_(const Opm::Deck& deck, const Opm::EclipseState& eclState)
{
oilWaterEclEpsConfig_ = std::make_shared<Opm::EclEpsConfig>();
oilWaterEclEpsConfig_-> initFromDeck(deck, eclState, Opm::EclOilWaterSystem);
enableEndPointScaling_ = deck.hasKeyword("ENDSCALE");
}
void readGlobalHysteresisOptions_(const Opm::Deck& deck)
{
hysteresisConfig_ = std::make_shared<Opm::EclHysteresisConfig>();
hysteresisConfig_->initFromDeck(deck);
}
void readGlobalThreePhaseOptions_(const Opm::Deck& deck)
{
bool gasEnabled = deck.hasKeyword("GAS");
bool oilEnabled = deck.hasKeyword("OIL");
bool waterEnabled = deck.hasKeyword("WATER");
int numEnabled =
(gasEnabled?1:0)
+ (oilEnabled?1:0)
+ (waterEnabled?1:0);
if (numEnabled == 0) {
throw std::runtime_error("At least one fluid phase must be enabled. (Is: "+std::to_string(numEnabled)+")");
} else if (numEnabled == 1) {
threePhaseApproach_ = Opm::EclMultiplexerApproach::EclOnePhaseApproach;
} else if ( numEnabled == 2) {
threePhaseApproach_ = Opm::EclTwoPhaseApproach;
if (!gasEnabled)
twoPhaseApproach_ = Opm::EclTwoPhaseOilWater;
else if (!oilEnabled)
twoPhaseApproach_ = Opm::EclTwoPhaseGasWater;
else if (!waterEnabled)
twoPhaseApproach_ = Opm::EclTwoPhaseGasOil;
}
else {
assert(numEnabled == 3);
threePhaseApproach_ = Opm::EclDefaultApproach;
if (deck.hasKeyword("STONE") || deck.hasKeyword("STONE2"))
threePhaseApproach_ = Opm::EclStone2Approach;
else if (deck.hasKeyword("STONE1"))
threePhaseApproach_ = Opm::EclStone1Approach;
}
}
void initParamsForElements_(const Deck& deck, const EclipseState& eclState,
const std::vector<int>& compressedToCartesianElemIdx,
const std::vector<int>& satnumRegionArray,
const std::vector<int>& imbnumRegionArray)
{
const size_t numSatRegions = eclState.runspec().tabdims().getNumSatTables();
unsigned numCompressedElems = static_cast<unsigned>(compressedToCartesianElemIdx.size());
// read the end point scaling configuration. this needs to be done only once per
// deck.
auto gasOilConfig = std::make_shared<Opm::EclEpsConfig>();
auto oilWaterConfig = std::make_shared<Opm::EclEpsConfig>();
gasOilConfig->initFromDeck(deck, eclState, Opm::EclGasOilSystem);
oilWaterConfig->initFromDeck(deck, eclState, Opm::EclOilWaterSystem);
// read the saturation region specific parameters from the deck
gasOilUnscaledPointsVector_.resize(numSatRegions);
oilWaterUnscaledPointsVector_.resize(numSatRegions);
gasOilEffectiveParamVector_.resize(numSatRegions);
oilWaterEffectiveParamVector_.resize(numSatRegions);
for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
// unscaled points for end-point scaling
readGasOilUnscaledPoints_(gasOilUnscaledPointsVector_, gasOilConfig, deck, eclState, satRegionIdx);
readOilWaterUnscaledPoints_(oilWaterUnscaledPointsVector_, oilWaterConfig, deck, eclState, satRegionIdx);
// the parameters for the effective two-phase matererial laws
readGasOilEffectiveParameters_(gasOilEffectiveParamVector_, deck, eclState, satRegionIdx);
readOilWaterEffectiveParameters_(oilWaterEffectiveParamVector_, deck, eclState, satRegionIdx);
// read the end point scaling info for the saturation region
unscaledEpsInfo_[satRegionIdx].extractUnscaled(deck, eclState, satRegionIdx);
}
// read the scaled end point scaling parameters which are specific for each
// element
GasOilScalingInfoVector gasOilScaledInfoVector(numCompressedElems);
oilWaterScaledEpsInfoDrainage_.resize(numCompressedElems);
GasOilScalingInfoVector gasOilScaledImbInfoVector;
OilWaterScalingInfoVector oilWaterScaledImbInfoVector;
GasOilScalingPointsVector gasOilScaledPointsVector(numCompressedElems);
GasOilScalingPointsVector oilWaterScaledEpsPointsDrainage(numCompressedElems);
GasOilScalingPointsVector gasOilScaledImbPointsVector;
OilWaterScalingPointsVector oilWaterScaledImbPointsVector;
if (enableHysteresis()) {
gasOilScaledImbInfoVector.resize(numCompressedElems);
gasOilScaledImbPointsVector.resize(numCompressedElems);
oilWaterScaledImbInfoVector.resize(numCompressedElems);
oilWaterScaledImbPointsVector.resize(numCompressedElems);
}
EclEpsGridProperties epsGridProperties(eclState, false, compressedToCartesianElemIdx);
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
readGasOilScaledPoints_(gasOilScaledInfoVector,
gasOilScaledPointsVector,
gasOilConfig,
eclState,
epsGridProperties,
elemIdx);
readOilWaterScaledPoints_(oilWaterScaledEpsInfoDrainage_,
oilWaterScaledEpsPointsDrainage,
oilWaterConfig,
eclState,
epsGridProperties,
elemIdx);
}
if (enableHysteresis()) {
EclEpsGridProperties epsImbGridProperties(eclState, true, compressedToCartesianElemIdx);
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
readGasOilScaledPoints_(gasOilScaledImbInfoVector,
gasOilScaledImbPointsVector,
gasOilConfig,
eclState,
epsImbGridProperties,
elemIdx);
readOilWaterScaledPoints_(oilWaterScaledImbInfoVector,
oilWaterScaledImbPointsVector,
oilWaterConfig,
eclState,
epsImbGridProperties,
elemIdx);
}
}
// create the parameter objects for the two-phase laws
GasOilParamVector gasOilParams(numCompressedElems);
OilWaterParamVector oilWaterParams(numCompressedElems);
GasOilParamVector gasOilImbParams;
OilWaterParamVector oilWaterImbParams;
if (enableHysteresis()) {
gasOilImbParams.resize(numCompressedElems);
oilWaterImbParams.resize(numCompressedElems);
}
bool hasGas = deck.hasKeyword("GAS");
bool hasOil = deck.hasKeyword("OIL");
bool hasWater = deck.hasKeyword("WATER");
assert(numCompressedElems == satnumRegionArray.size());
assert(!enableHysteresis() || numCompressedElems == imbnumRegionArray.size());
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
unsigned satRegionIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
gasOilParams[elemIdx] = std::make_shared<GasOilTwoPhaseHystParams>();
oilWaterParams[elemIdx] = std::make_shared<OilWaterTwoPhaseHystParams>();
gasOilParams[elemIdx]->setConfig(hysteresisConfig_);
oilWaterParams[elemIdx]->setConfig(hysteresisConfig_);
if (hasGas && hasOil) {
auto gasOilDrainParams = std::make_shared<GasOilEpsTwoPhaseParams>();
gasOilDrainParams->setConfig(gasOilConfig);
gasOilDrainParams->setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
gasOilDrainParams->setScaledPoints(gasOilScaledPointsVector[elemIdx]);
gasOilDrainParams->setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
gasOilDrainParams->finalize();
gasOilParams[elemIdx]->setDrainageParams(gasOilDrainParams,
*gasOilScaledInfoVector[elemIdx],
EclGasOilSystem);
}
if (hasOil && hasWater) {
auto oilWaterDrainParams = std::make_shared<OilWaterEpsTwoPhaseParams>();
oilWaterDrainParams->setConfig(oilWaterConfig);
oilWaterDrainParams->setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
oilWaterDrainParams->setScaledPoints(oilWaterScaledEpsPointsDrainage[elemIdx]);
oilWaterDrainParams->setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
oilWaterDrainParams->finalize();
oilWaterParams[elemIdx]->setDrainageParams(oilWaterDrainParams,
*oilWaterScaledEpsInfoDrainage_[elemIdx],
EclOilWaterSystem);
}
if (enableHysteresis()) {
unsigned imbRegionIdx = imbnumRegionArray[elemIdx];
if (hasGas && hasOil) {
auto gasOilImbParamsHyst = std::make_shared<GasOilEpsTwoPhaseParams>();
gasOilImbParamsHyst->setConfig(gasOilConfig);
gasOilImbParamsHyst->setUnscaledPoints(gasOilUnscaledPointsVector_[imbRegionIdx]);
gasOilImbParamsHyst->setScaledPoints(gasOilScaledImbPointsVector[elemIdx]);
gasOilImbParamsHyst->setEffectiveLawParams(gasOilEffectiveParamVector_[imbRegionIdx]);
gasOilImbParamsHyst->finalize();
gasOilParams[elemIdx]->setImbibitionParams(gasOilImbParamsHyst,
*gasOilScaledImbInfoVector[elemIdx],
EclGasOilSystem);
}
if (hasOil && hasWater) {
auto oilWaterImbParamsHyst = std::make_shared<OilWaterEpsTwoPhaseParams>();
oilWaterImbParamsHyst->setConfig(oilWaterConfig);
oilWaterImbParamsHyst->setUnscaledPoints(oilWaterUnscaledPointsVector_[imbRegionIdx]);
oilWaterImbParamsHyst->setScaledPoints(oilWaterScaledImbPointsVector[elemIdx]);
oilWaterImbParamsHyst->setEffectiveLawParams(oilWaterEffectiveParamVector_[imbRegionIdx]);
oilWaterImbParamsHyst->finalize();
oilWaterParams[elemIdx]->setImbibitionParams(oilWaterImbParamsHyst,
*gasOilScaledImbInfoVector[elemIdx],
EclGasOilSystem);
}
}
if (hasGas && hasOil)
gasOilParams[elemIdx]->finalize();
if (hasOil && hasWater)
oilWaterParams[elemIdx]->finalize();
}
// create the parameter objects for the three-phase law
materialLawParams_.resize(numCompressedElems);
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
materialLawParams_[elemIdx] = std::make_shared<MaterialLawParams>();
unsigned satRegionIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
initThreePhaseParams_(deck,
eclState,
*materialLawParams_[elemIdx],
satRegionIdx,
*oilWaterScaledEpsInfoDrainage_[elemIdx],
oilWaterParams[elemIdx],
gasOilParams[elemIdx]);
materialLawParams_[elemIdx]->finalize();
}
}
// The saturation function family.
// If SWOF and SGOF are specified in the deck it return FamilyI
// If SWFN, SGFN and SOF3 are specified in the deck it return FamilyII
// If keywords are missing or mixed, an error is given.
enum SaturationFunctionFamily {
noFamily,
FamilyI,
FamilyII
};
SaturationFunctionFamily getSaturationFunctionFamily(const Opm::Deck& deck, const Opm::EclipseState& eclState) const
{
const auto& tableManager = eclState.getTableManager();
const TableContainer& swofTables = tableManager.getSwofTables();
const TableContainer& slgofTables= tableManager.getSlgofTables();
const TableContainer& sgofTables = tableManager.getSgofTables();
const TableContainer& swfnTables = tableManager.getSwfnTables();
const TableContainer& sgfnTables = tableManager.getSgfnTables();
const TableContainer& sof3Tables = tableManager.getSof3Tables();
const TableContainer& sof2Tables = tableManager.getSof2Tables();
bool hasGas = deck.hasKeyword("GAS");
bool hasOil = deck.hasKeyword("OIL");
bool hasWater = deck.hasKeyword("WATER");
bool family1 = false;
bool family2 = false;
if (!hasGas) {
// oil-water case
family1 = !swofTables.empty();
family2 = !swfnTables.empty() && !sof2Tables.empty();
}
else if (!hasWater) {
// oil-gas case
family1 = !sgofTables.empty();
family2 = !sgfnTables.empty() && !sof2Tables.empty();
}
else if (!hasOil) {
// water-gas case
throw std::runtime_error("water-gas two-phase simulations are currently not supported");
}
else {
// three-phase case
family1 = (!sgofTables.empty() || !slgofTables.empty()) && !swofTables.empty();
family2 = !swfnTables.empty() && !sgfnTables.empty() && !sof3Tables.empty();
}
if (family1 && family2)
throw std::invalid_argument("Saturation families should not be mixed \n"
"Use either SGOF and SWOF or SGFN, SWFN and SOF3");
if (!family1 && !family2)
throw std::invalid_argument("Saturations function must be specified using either "
"family 1 or family 2 keywords \n"
"Use either SGOF and SWOF or SGFN, SWFN and SOF3" );
if (family1 && !family2)
return SaturationFunctionFamily::FamilyI;
else if (family2 && !family1)
return SaturationFunctionFamily::FamilyII;
return SaturationFunctionFamily::noFamily; // no family or two families
}
template <class Container>
void readGasOilEffectiveParameters_(Container& dest,
const Opm::Deck& deck,
const Opm::EclipseState& eclState,
unsigned satRegionIdx)
{
bool hasGas = deck.hasKeyword("GAS");
bool hasOil = deck.hasKeyword("OIL");
if (!hasGas || !hasOil)
// we don't read anything if either the gas or the oil phase is not active
return;
dest[satRegionIdx] = std::make_shared<GasOilEffectiveTwoPhaseParams>();
auto& effParams = *dest[satRegionIdx];
// the situation for the gas phase is complicated that all saturations are
// shifted by the connate water saturation.
Scalar Swco = unscaledEpsInfo_[satRegionIdx].Swl;
const auto& tableManager = eclState.getTableManager();
switch (getSaturationFunctionFamily(deck, eclState)) {
case FamilyI:
{
const TableContainer& sgofTables = tableManager.getSgofTables();
const TableContainer& slgofTables = tableManager.getSlgofTables();
if (!sgofTables.empty())
readGasOilEffectiveParametersSgof_(effParams,
Swco,
sgofTables.getTable<SgofTable>(satRegionIdx));
else if (!slgofTables.empty())
readGasOilEffectiveParametersSlgof_(effParams,
Swco,
slgofTables.getTable<SlgofTable>(satRegionIdx));
break;
}
case FamilyII:
{
const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
bool hasWater = deck.hasKeyword("WATER");
if (!hasWater) {
// oil and gas case
const Sof2Table& sof2Table = tableManager.getSof2Tables().getTable<Sof2Table>( satRegionIdx );
readGasOilEffectiveParametersFamily2_(effParams,
Swco,
sof2Table,
sgfnTable);
} else {
const Sof3Table& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>( satRegionIdx );
readGasOilEffectiveParametersFamily2_(effParams,
Swco,
sof3Table,
sgfnTable);
}
break;
}
//default:
case noFamily:
throw std::domain_error("No valid saturation keyword family specified");
}
}
void readGasOilEffectiveParametersSgof_(GasOilEffectiveTwoPhaseParams& effParams,
Scalar Swco,
const Opm::SgofTable& sgofTable)
{
// convert the saturations of the SGOF keyword from gas to oil saturations
std::vector<double> SoSamples(sgofTable.numRows());
std::vector<double> SoKroSamples(sgofTable.numRows());
for (size_t sampleIdx = 0; sampleIdx < sgofTable.numRows(); ++ sampleIdx) {
SoSamples[sampleIdx] = 1 - sgofTable.get("SG", sampleIdx);
SoKroSamples[sampleIdx] = SoSamples[sampleIdx] - Swco;
}
effParams.setKrwSamples(SoKroSamples, sgofTable.getColumn("KROG").vectorCopy());
effParams.setKrnSamples(SoSamples, sgofTable.getColumn("KRG").vectorCopy());
effParams.setPcnwSamples(SoSamples, sgofTable.getColumn("PCOG").vectorCopy());
effParams.finalize();
}
void readGasOilEffectiveParametersSlgof_(GasOilEffectiveTwoPhaseParams& effParams,
Scalar Swco,
const Opm::SlgofTable& slgofTable)
{
// convert the saturations of the SLGOF keyword from "liquid" to oil saturations
std::vector<double> SoSamples(slgofTable.numRows());
std::vector<double> SoKroSamples(slgofTable.numRows());
for (size_t sampleIdx = 0; sampleIdx < slgofTable.numRows(); ++ sampleIdx) {
SoSamples[sampleIdx] = slgofTable.get("SL", sampleIdx);
SoKroSamples[sampleIdx] = slgofTable.get("SL", sampleIdx) - Swco;
}
effParams.setKrwSamples(SoKroSamples, slgofTable.getColumn("KROG").vectorCopy());
effParams.setKrnSamples(SoSamples, slgofTable.getColumn("KRG").vectorCopy());
effParams.setPcnwSamples(SoSamples, slgofTable.getColumn("PCOG").vectorCopy());
effParams.finalize();
}
void readGasOilEffectiveParametersFamily2_(GasOilEffectiveTwoPhaseParams& effParams,
Scalar /* Swco */,
const Opm::Sof3Table& sof3Table,
const Opm::SgfnTable& sgfnTable)
{
// convert the saturations of the SGFN keyword from gas to oil saturations
std::vector<double> SoSamples(sgfnTable.numRows());
std::vector<double> SoColumn = sof3Table.getColumn("SO").vectorCopy();
for (size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) {
SoSamples[sampleIdx] = 1 - sgfnTable.get("SG", sampleIdx);
}
effParams.setKrwSamples(SoColumn, sof3Table.getColumn("KROG").vectorCopy());
effParams.setKrnSamples(SoSamples, sgfnTable.getColumn("KRG").vectorCopy());
effParams.setPcnwSamples(SoSamples, sgfnTable.getColumn("PCOG").vectorCopy());
effParams.finalize();
}
void readGasOilEffectiveParametersFamily2_(GasOilEffectiveTwoPhaseParams& effParams,
Scalar /* Swco */,
const Opm::Sof2Table& sof2Table,
const Opm::SgfnTable& sgfnTable)
{
// convert the saturations of the SGFN keyword from gas to oil saturations
std::vector<double> SoSamples(sgfnTable.numRows());
std::vector<double> SoColumn = sof2Table.getColumn("SO").vectorCopy();
for (size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) {
SoSamples[sampleIdx] = 1 - sgfnTable.get("SG", sampleIdx);
}
effParams.setKrwSamples(SoColumn, sof2Table.getColumn("KRO").vectorCopy());
effParams.setKrnSamples(SoSamples, sgfnTable.getColumn("KRG").vectorCopy());
effParams.setPcnwSamples(SoSamples, sgfnTable.getColumn("PCOG").vectorCopy());
effParams.finalize();
}
template <class Container>
void readOilWaterEffectiveParameters_(Container& dest,
const Opm::Deck& deck,
const Opm::EclipseState& eclState,
unsigned satRegionIdx)
{
bool hasWater = deck.hasKeyword("WATER");
bool hasOil = deck.hasKeyword("OIL");
if (!hasOil || !hasWater)
// we don't read anything if either the water or the oil phase is not active
return;
dest[satRegionIdx] = std::make_shared<OilWaterEffectiveTwoPhaseParams>();
const auto& tableManager = eclState.getTableManager();
auto& effParams = *dest[satRegionIdx];
switch (getSaturationFunctionFamily(deck, eclState)) {
case FamilyI: {
const auto& swofTable = tableManager.getSwofTables().getTable<SwofTable>(satRegionIdx);
std::vector<double> SwColumn = swofTable.getColumn("SW").vectorCopy();
effParams.setKrwSamples(SwColumn, swofTable.getColumn("KRW").vectorCopy());
effParams.setKrnSamples(SwColumn, swofTable.getColumn("KROW").vectorCopy());
effParams.setPcnwSamples(SwColumn, swofTable.getColumn("PCOW").vectorCopy());
effParams.finalize();
break;
}
case FamilyII:
{
const auto& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>(satRegionIdx);
const auto& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>(satRegionIdx);
std::vector<double> SwColumn = swfnTable.getColumn("SW").vectorCopy();
// convert the saturations of the SOF3 keyword from oil to water saturations
std::vector<double> SwSamples(sof3Table.numRows());
for (size_t sampleIdx = 0; sampleIdx < sof3Table.numRows(); ++ sampleIdx)
SwSamples[sampleIdx] = 1 - sof3Table.get("SO", sampleIdx);
effParams.setKrwSamples(SwColumn, swfnTable.getColumn("KRW").vectorCopy());
effParams.setKrnSamples(SwSamples, sof3Table.getColumn("KROW").vectorCopy());
effParams.setPcnwSamples(SwColumn, swfnTable.getColumn("PCOW").vectorCopy());
effParams.finalize();
break;
}
case noFamily:
//default:
throw std::domain_error("No valid saturation keyword family specified");
}
}
template <class Container>
void readGasOilUnscaledPoints_(Container& dest,
std::shared_ptr<EclEpsConfig> config,
const Opm::Deck& deck,
const Opm::EclipseState& /* eclState */,
unsigned satRegionIdx)
{
bool hasGas = deck.hasKeyword("GAS");
bool hasOil = deck.hasKeyword("OIL");
if (!hasGas || !hasOil)
// we don't read anything if either the gas or the oil phase is not active
return;
dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclGasOilSystem);
}
template <class Container>
void readOilWaterUnscaledPoints_(Container& dest,
std::shared_ptr<EclEpsConfig> config,
const Opm::Deck& deck,
const Opm::EclipseState& /* eclState */,
unsigned satRegionIdx)
{
bool hasWater = deck.hasKeyword("WATER");
bool hasOil = deck.hasKeyword("OIL");
if (!hasOil || !hasWater)
// we don't read anything if either the water or the oil phase is not active
return;
dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclOilWaterSystem);
}
template <class InfoContainer, class PointsContainer>
void readGasOilScaledPoints_(InfoContainer& destInfo,
PointsContainer& destPoints,
std::shared_ptr<EclEpsConfig> config,
const Opm::EclipseState& eclState,
const EclEpsGridProperties& epsGridProperties,
unsigned elemIdx)
{
unsigned satRegionIdx = epsGridProperties.satRegion( elemIdx );
destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, elemIdx);
destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
destPoints[elemIdx]->init(*destInfo[elemIdx], *config, EclGasOilSystem);
}
template <class InfoContainer, class PointsContainer>
void readOilWaterScaledPoints_(InfoContainer& destInfo,
PointsContainer& destPoints,
std::shared_ptr<EclEpsConfig> config,
const Opm::EclipseState& eclState,
const EclEpsGridProperties& epsGridProperties,
unsigned elemIdx)
{
unsigned satRegionIdx = epsGridProperties.satRegion( elemIdx );
destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, elemIdx);
destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
destPoints[elemIdx]->init(*destInfo[elemIdx], *config, EclOilWaterSystem);
}
void initThreePhaseParams_(const Opm::Deck& deck,
const Opm::EclipseState& /* eclState */,
MaterialLawParams& materialParams,
unsigned satRegionIdx,
const EclEpsScalingPointsInfo<Scalar>& epsInfo,
std::shared_ptr<OilWaterTwoPhaseHystParams> oilWaterParams,
std::shared_ptr<GasOilTwoPhaseHystParams> gasOilParams)
{
materialParams.setApproach(threePhaseApproach_);
switch (materialParams.approach()) {
case EclStone1Approach: {
auto& realParams = materialParams.template getRealParams<Opm::EclStone1Approach>();
realParams.setGasOilParams(gasOilParams);
realParams.setOilWaterParams(oilWaterParams);
realParams.setSwl(epsInfo.Swl);
if (deck.hasKeyword("STONE1EX")) {
Scalar eta =
deck.getKeyword("STONE1EX").getRecord(satRegionIdx).getItem(0).getSIDouble(0);
realParams.setEta(eta);
}
else
realParams.setEta(1.0);
realParams.finalize();
break;
}
case EclStone2Approach: {
auto& realParams = materialParams.template getRealParams<Opm::EclStone2Approach>();
realParams.setGasOilParams(gasOilParams);
realParams.setOilWaterParams(oilWaterParams);
realParams.setSwl(epsInfo.Swl);
realParams.finalize();
break;
}
case EclDefaultApproach: {
auto& realParams = materialParams.template getRealParams<Opm::EclDefaultApproach>();
realParams.setGasOilParams(gasOilParams);
realParams.setOilWaterParams(oilWaterParams);
realParams.setSwl(epsInfo.Swl);
realParams.finalize();
break;
}
case EclTwoPhaseApproach: {
auto& realParams = materialParams.template getRealParams<Opm::EclTwoPhaseApproach>();
realParams.setGasOilParams(gasOilParams);
realParams.setOilWaterParams(oilWaterParams);
realParams.setApproach(twoPhaseApproach_);
realParams.finalize();
break;
}
case EclOnePhaseApproach: {
// Nothing to do, no parameters.
break;
}
}
}
bool enableEndPointScaling_;
std::shared_ptr<EclHysteresisConfig> hysteresisConfig_;
std::shared_ptr<EclEpsConfig> oilWaterEclEpsConfig_;
std::vector<Opm::EclEpsScalingPointsInfo<Scalar>> unscaledEpsInfo_;
OilWaterScalingInfoVector oilWaterScaledEpsInfoDrainage_;
GasOilScalingPointsVector gasOilUnscaledPointsVector_;
OilWaterScalingPointsVector oilWaterUnscaledPointsVector_;
GasOilEffectiveParamVector gasOilEffectiveParamVector_;
OilWaterEffectiveParamVector oilWaterEffectiveParamVector_;
Opm::EclMultiplexerApproach threePhaseApproach_;
// this attribute only makes sense for twophase simulations!
enum EclTwoPhaseApproach twoPhaseApproach_;
std::vector<std::shared_ptr<MaterialLawParams> > materialLawParams_;
std::vector<int> satnumRegionArray_;
std::vector<int> imbnumRegionArray_;
};
} // namespace Opm
#endif