diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index 2d49dfcc291..f4d9b056fca 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -344,7 +344,11 @@ if(ENABLE_ECL_INPUT)
opm/material/fluidmatrixinteractions/EclHysteresisConfig.cpp
opm/material/fluidmatrixinteractions/EclMaterialLawManager.cpp
opm/material/fluidmatrixinteractions/EclMaterialLawManagerReadEffectiveParams.cpp
+ opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.cpp
+ opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleReadEffectiveParams.cpp
+ opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleHystParams.cpp
opm/material/fluidmatrixinteractions/EclMaterialLawManagerInitParams.cpp
+ opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleInitParams.cpp
opm/material/fluidmatrixinteractions/EclMaterialLawManagerHystParams.cpp
opm/material/thermal/EclThermalLawManager.cpp
)
@@ -997,6 +1001,7 @@ list( APPEND PUBLIC_HEADER_FILES
opm/material/fluidmatrixinteractions/EclEpsTwoPhaseLaw.hpp
opm/material/fluidmatrixinteractions/TwoPhaseLETCurves.hpp
opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp
+ opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.hpp
opm/material/fluidmatrixinteractions/DirectionalMaterialLawParams.hpp
opm/material/fluidmatrixinteractions/DirectionalMaterialLawParams.hpp
opm/material/fluidmatrixinteractions/RegularizedVanGenuchten.hpp
diff --git a/opm/material/fluidmatrixinteractions/EclHysteresisTwoPhaseLaw.hpp b/opm/material/fluidmatrixinteractions/EclHysteresisTwoPhaseLaw.hpp
index 061c288db78..50fef84183f 100644
--- a/opm/material/fluidmatrixinteractions/EclHysteresisTwoPhaseLaw.hpp
+++ b/opm/material/fluidmatrixinteractions/EclHysteresisTwoPhaseLaw.hpp
@@ -90,6 +90,8 @@ class EclHysteresisTwoPhaseLaw : public EffectiveLawT::Traits
//! are dependent on the phase composition
static constexpr bool isCompositionDependent = false;
+ static constexpr bool isHysteresisDependent = true;
+
/*!
* \brief The capillary pressure-saturation curves depending on absolute saturations.
*
diff --git a/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.cpp b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.cpp
new file mode 100644
index 00000000000..8b9a956db15
--- /dev/null
+++ b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.cpp
@@ -0,0 +1,437 @@
+// -*- 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 .
+
+ 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.
+*/
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+namespace Opm {
+
+template
+EclMaterialLawManagerSimple::EclMaterialLawManagerSimple() = default;
+
+template
+EclMaterialLawManagerSimple::~EclMaterialLawManagerSimple() = default;
+
+template
+void EclMaterialLawManagerSimple::
+initFromState(const EclipseState& eclState)
+{
+ // get the number of saturation regions and the number of cells in the deck
+ const auto& runspec = eclState.runspec();
+ const size_t numSatRegions = runspec.tabdims().getNumSatTables();
+
+ const auto& ph = runspec.phases();
+ this->hasGas = ph.active(Phase::GAS);
+ this->hasOil = ph.active(Phase::OIL);
+ this->hasWater = ph.active(Phase::WATER);
+
+ // readGlobalEpsOptions_(eclState);
+ // readGlobalHysteresisOptions_(eclState);
+ readGlobalThreePhaseOptions_(runspec);
+
+ // Read the end point scaling configuration (once per run).
+ // gasOilConfig_ = std::make_shared();
+ // oilWaterConfig_ = std::make_shared();
+ // gasWaterConfig_ = std::make_shared();
+ // gasOilConfig_->initFromState(eclState, EclTwoPhaseSystemType::GasOil);
+ // oilWaterConfig_->initFromState(eclState, EclTwoPhaseSystemType::OilWater);
+ // gasWaterConfig_->initFromState(eclState, EclTwoPhaseSystemType::GasWater);
+
+
+ const auto& tables = eclState.getTableManager();
+
+ {
+ const auto& stone1exTables = tables.getStone1exTable();
+
+ if (! stone1exTables.empty()) {
+ stoneEtas_.clear();
+ stoneEtas_.reserve(numSatRegions);
+
+ for (const auto& table : stone1exTables) {
+ stoneEtas_.push_back(table.eta);
+ }
+ }
+
+ const auto& ppcwmaxTables = tables.getPpcwmax();
+ this->enablePpcwmax_ = !ppcwmaxTables.empty();
+
+ if (this->enablePpcwmax_) {
+ maxAllowPc_.clear();
+ modifySwl_.clear();
+
+ maxAllowPc_.reserve(numSatRegions);
+ modifySwl_.reserve(numSatRegions);
+
+ for (const auto& table : ppcwmaxTables) {
+ maxAllowPc_.push_back(table.max_cap_pres);
+ modifySwl_.push_back(table.option);
+ }
+ }
+ }
+
+ this->unscaledEpsInfo_.resize(numSatRegions);
+
+ if (this->hasGas + this->hasOil + this->hasWater == 1) {
+ // Single-phase simulation. Special case. Nothing to do here.
+ return;
+ }
+
+ // Multiphase simulation. Common case.
+ const auto tolcrit = runspec.saturationFunctionControls()
+ .minimumRelpermMobilityThreshold();
+
+ const auto rtep = satfunc::getRawTableEndpoints(tables, ph, tolcrit);
+ const auto rfunc = satfunc::getRawFunctionValues(tables, ph, rtep);
+
+ for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
+ this->unscaledEpsInfo_[satRegionIdx]
+ .extractUnscaled(rtep, rfunc, satRegionIdx);
+ }
+
+ // WAG hysteresis parameters per SATNUM.
+ // if (eclState.runspec().hysterPar().activeWag()) {
+ // if (numSatRegions != eclState.getWagHysteresis().size())
+ // throw std::runtime_error("Inconsistent Wag-hysteresis data");
+ // wagHystersisConfig_.resize(numSatRegions);
+ // for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
+ // wagHystersisConfig_[satRegionIdx] = std::make_shared(eclState.getWagHysteresis()[satRegionIdx]);
+ // }
+ // }
+}
+
+template
+void EclMaterialLawManagerSimple::
+initParamsForElements(const EclipseState& eclState, size_t numCompressedElems,
+ const std::function(const FieldPropsManager&, const std::string&, bool)>& fieldPropIntOnLeafAssigner,
+ const std::function& lookupIdxOnLevelZeroAssigner)
+{
+ InitParams initParams {*this, eclState, numCompressedElems};
+ initParams.run(fieldPropIntOnLeafAssigner, lookupIdxOnLevelZeroAssigner);
+}
+
+// TODO: Better (proper?) handling of mixed wettability systems - see ecl kw OPTIONS switch 74
+// Note: Without OPTIONS[74] the negative part of the Pcow curve is not scaled
+template
+std::pair EclMaterialLawManagerSimple::
+applySwatinit(unsigned elemIdx,
+ Scalar pcow,
+ Scalar Sw)
+{
+ // Default is no SWATINIT scaling of the negative part of the Pcow curve, so look up saturation using the input Pcow curve
+ if (pcow <= 0.0) {
+ return {Sw, /*newSwatInit*/ true};
+ }
+
+ auto& elemScaledEpsInfo = oilWaterScaledEpsInfoDrainage_[elemIdx];
+ if (Sw <= elemScaledEpsInfo.Swl)
+ Sw = elemScaledEpsInfo.Swl;
+
+ // specify a fluid state which only stores the saturations
+ using FluidState = SimpleModularFluidState don't care */
+ /*storePressure=*/false,
+ /*storeTemperature=*/false,
+ /*storeComposition=*/false,
+ /*storeFugacity=*/false,
+ /*storeSaturation=*/true,
+ /*storeDensity=*/false,
+ /*storeViscosity=*/false,
+ /*storeEnthalpy=*/false>;
+ FluidState fs;
+ fs.setSaturation(waterPhaseIdx, Sw);
+ fs.setSaturation(gasPhaseIdx, 0);
+ fs.setSaturation(oilPhaseIdx, 0);
+ std::array pc = { 0 };
+ MaterialLaw::capillaryPressures(pc, materialLawParams(elemIdx), fs);
+ Scalar pcowAtSw = pc[oilPhaseIdx] - pc[waterPhaseIdx];
+ constexpr const Scalar pcowAtSwThreshold = 1.0e-6; //Pascal
+
+ // avoid division by very small number and avoid negative PCW at connate Sw
+ // (look up saturation on input Pcow curve in this case)
+ if (pcowAtSw < pcowAtSwThreshold) {
+ return {Sw, /*newSwatInit*/ true};
+ }
+
+ // Sufficiently positive value, continue with max. capillary pressure (PCW) scaling to honor SWATINIT value
+ Scalar newMaxPcow = elemScaledEpsInfo.maxPcow * (pcow/pcowAtSw);
+
+ // Limit max. capillary pressure with PPCWMAX
+ bool newSwatInit = false;
+ int satRegionIdx = satnumRegionIdx(elemIdx);
+ if (enablePpcwmax() && (newMaxPcow > maxAllowPc_[satRegionIdx])) {
+ // Two options in PPCWMAX to modify connate Sw or not. In both cases, init. Sw needs to be
+ // re-calculated (done in opm-simulators)
+ newSwatInit = true;
+ if (modifySwl_[satRegionIdx] == false) {
+ // Max. cap. pressure set to PCWO in PPCWMAX
+ elemScaledEpsInfo.maxPcow = maxAllowPc_[satRegionIdx];
+ }
+ else {
+ // Max. cap. pressure remains unscaled and connate Sw is set to SWATINIT value
+ elemScaledEpsInfo.Swl = Sw;
+ }
+ }
+ // Max. cap. pressure adjusted from SWATINIT data
+ else
+ elemScaledEpsInfo.maxPcow = newMaxPcow;
+
+ // auto& elemEclEpsScalingPoints = oilWaterScaledEpsPointsDrainage(elemIdx);
+ // elemEclEpsScalingPoints.init(elemScaledEpsInfo,
+ // *oilWaterEclEpsConfig_,
+ // EclTwoPhaseSystemType::OilWater);
+
+ return {Sw, newSwatInit};
+}
+
+template
+void
+EclMaterialLawManagerSimple::applyRestartSwatInit(const unsigned elemIdx,
+ const Scalar maxPcow)
+{
+ // Maximum capillary pressure adjusted from SWATINIT data.
+
+ auto& elemScaledEpsInfo =
+ this->oilWaterScaledEpsInfoDrainage_[elemIdx];
+
+ elemScaledEpsInfo.maxPcow = maxPcow;
+
+ // this->oilWaterScaledEpsPointsDrainage(elemIdx)
+ // .init(elemScaledEpsInfo,
+ // *this->oilWaterEclEpsConfig_,
+ // EclTwoPhaseSystemType::OilWater);
+}
+
+template
+const typename EclMaterialLawManagerSimple::MaterialLawParams&
+EclMaterialLawManagerSimple::
+connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const
+{
+ MaterialLawParams& mlp = const_cast(materialLawParams_[elemIdx]);
+
+ if (enableHysteresis())
+ OpmLog::warning("Warning: Using non-default satnum regions for connection is not tested in combination with hysteresis");
+
+ auto& realParams = mlp;
+ if (realParams.approach() == EclTwoPhaseApproach::GasOil) {
+ realParams.setGasOilParams(gasOilEffectiveParamVector_[satRegionIdx]);
+ }
+ else if (realParams.approach() == EclTwoPhaseApproach::GasWater) {
+ realParams.setGasWaterParams(gasWaterEffectiveParamVector_[satRegionIdx]);
+ }
+ else if (realParams.approach() == EclTwoPhaseApproach::OilWater) {
+ realParams.setOilWaterParams(oilWaterEffectiveParamVector_[satRegionIdx]);
+ }
+ return mlp;
+}
+
+template
+int EclMaterialLawManagerSimple::
+getKrnumSatIdx(unsigned elemIdx, FaceDir::DirEnum facedir) const
+{
+ using Dir = FaceDir::DirEnum;
+ const std::vector* array = nullptr;
+ switch(facedir) {
+ case Dir::XPlus:
+ array = &krnumXArray_;
+ break;
+ case Dir::YPlus:
+ array = &krnumYArray_;
+ break;
+ case Dir::ZPlus:
+ array = &krnumZArray_;
+ break;
+ default:
+ throw std::runtime_error("Unknown face direction");
+ }
+ if (array->size() > 0) {
+ return (*array)[elemIdx];
+ }
+ else {
+ return satnumRegionArray_[elemIdx];
+ }
+}
+
+template
+void EclMaterialLawManagerSimple::
+oilWaterHysteresisParams(Scalar& soMax,
+ Scalar& swMax,
+ Scalar& swMin,
+ unsigned elemIdx) const
+{
+ if (!enableHysteresis())
+ throw std::runtime_error("Cannot get hysteresis parameters if hysteresis not enabled.");
+
+ const auto& params = materialLawParams(elemIdx);
+ MaterialLaw::oilWaterHysteresisParams(soMax, swMax, swMin, params);
+}
+
+template
+void EclMaterialLawManagerSimple::
+setOilWaterHysteresisParams(const Scalar& soMax,
+ const Scalar& swMax,
+ const Scalar& swMin,
+ unsigned elemIdx)
+{
+ if (!enableHysteresis())
+ throw std::runtime_error("Cannot set hysteresis parameters if hysteresis not enabled.");
+
+ auto& params = materialLawParams(elemIdx);
+ MaterialLaw::setOilWaterHysteresisParams(soMax, swMax, swMin, params);
+}
+
+template
+void EclMaterialLawManagerSimple::
+gasOilHysteresisParams(Scalar& sgmax,
+ Scalar& shmax,
+ Scalar& somin,
+ unsigned elemIdx) const
+{
+ if (!enableHysteresis())
+ throw std::runtime_error("Cannot get hysteresis parameters if hysteresis not enabled.");
+
+ const auto& params = materialLawParams(elemIdx);
+ MaterialLaw::gasOilHysteresisParams(sgmax, shmax, somin, params);
+}
+
+template
+void EclMaterialLawManagerSimple::
+setGasOilHysteresisParams(const Scalar& sgmax,
+ const Scalar& shmax,
+ const Scalar& somin,
+ unsigned elemIdx)
+{
+ if (!enableHysteresis())
+ throw std::runtime_error("Cannot set hysteresis parameters if hysteresis not enabled.");
+
+ auto& params = materialLawParams(elemIdx);
+ MaterialLaw::setGasOilHysteresisParams(sgmax, shmax, somin, params);
+}
+
+// template
+// EclEpsScalingPoints&
+// EclMaterialLawManagerSimple::
+// oilWaterScaledEpsPointsDrainage(unsigned elemIdx)
+// {
+// auto& materialParams = materialLawParams_[elemIdx];
+// auto& realParams = materialParams;
+// return realParams.oilWaterParams().drainageParams().scaledPoints();
+// }
+
+template
+const typename EclMaterialLawManagerSimple::MaterialLawParams& EclMaterialLawManagerSimple::
+materialLawParamsFunc_(unsigned elemIdx, FaceDir::DirEnum facedir) const
+{
+ using Dir = FaceDir::DirEnum;
+ if (dirMaterialLawParams_) {
+ switch(facedir) {
+ case Dir::XMinus:
+ case Dir::XPlus:
+ return dirMaterialLawParams_->materialLawParamsX_[elemIdx];
+ case Dir::YMinus:
+ case Dir::YPlus:
+ return dirMaterialLawParams_->materialLawParamsY_[elemIdx];
+ case Dir::ZMinus:
+ case Dir::ZPlus:
+ return dirMaterialLawParams_->materialLawParamsZ_[elemIdx];
+ default:
+ throw std::runtime_error("Unexpected face direction");
+ }
+ }
+ else {
+ return materialLawParams_[elemIdx];
+ }
+}
+
+// template
+// void EclMaterialLawManagerSimple::
+// readGlobalEpsOptions_(const EclipseState& eclState)
+// {
+// oilWaterEclEpsConfig_ = std::make_shared();
+// oilWaterEclEpsConfig_->initFromState(eclState, EclTwoPhaseSystemType::OilWater);
+
+// enableEndPointScaling_ = eclState.getTableManager().hasTables("ENKRVD");
+// }
+
+// template
+// void EclMaterialLawManagerSimple::
+// readGlobalHysteresisOptions_(const EclipseState& state)
+// {
+// hysteresisConfig_ = std::make_shared();
+// hysteresisConfig_->initFromState(state.runspec());
+// }
+
+template
+void EclMaterialLawManagerSimple::
+readGlobalThreePhaseOptions_(const Runspec& runspec)
+{
+ bool gasEnabled = runspec.phases().active(Phase::GAS);
+ bool oilEnabled = runspec.phases().active(Phase::OIL);
+ bool waterEnabled = runspec.phases().active(Phase::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_ = EclMultiplexerApproach::OnePhase;
+ } else if ( numEnabled == 2) {
+ threePhaseApproach_ = EclMultiplexerApproach::TwoPhase;
+ if (!gasEnabled)
+ twoPhaseApproach_ = EclTwoPhaseApproach::OilWater;
+ else if (!oilEnabled)
+ twoPhaseApproach_ = EclTwoPhaseApproach::GasWater;
+ else if (!waterEnabled)
+ twoPhaseApproach_ = EclTwoPhaseApproach::GasOil;
+ }
+ else {
+ assert(numEnabled == 3);
+
+ threePhaseApproach_ = EclMultiplexerApproach::Default;
+ const auto& satctrls = runspec.saturationFunctionControls();
+ if (satctrls.krModel() == SatFuncControls::ThreePhaseOilKrModel::Stone2)
+ threePhaseApproach_ = EclMultiplexerApproach::Stone2;
+ else if (satctrls.krModel() == SatFuncControls::ThreePhaseOilKrModel::Stone1)
+ threePhaseApproach_ = EclMultiplexerApproach::Stone1;
+ }
+}
+
+
+template class EclMaterialLawManagerSimple>;
+template class EclMaterialLawManagerSimple>;
+
+} // namespace Opm
diff --git a/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.hpp b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.hpp
new file mode 100644
index 00000000000..a6ed36ddc4c
--- /dev/null
+++ b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimple.hpp
@@ -0,0 +1,503 @@
+// -*- 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 .
+
+ 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::EclMaterialLawManagerSimple
+ */
+#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_SIMPLE_HPP
+#define OPM_ECL_MATERIAL_LAW_MANAGER_SIMPLE_HPP
+
+#include
+#include
+#include "EclTwoPhaseMaterial.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Opm {
+
+class EclipseState;
+class EclEpsConfig;
+class EclEpsGridProperties;
+template class EclEpsScalingPoints;
+template struct EclEpsScalingPointsInfo;
+class EclHysteresisConfig;
+enum class EclTwoPhaseSystemType;
+class FieldPropsManager;
+class Runspec;
+class SgfnTable;
+class SgofTable;
+class SlgofTable;
+class TableColumn;
+
+/*!
+ * \ingroup fluidmatrixinteractions
+ *
+ * \brief Provides an simple way to create and manage the material law objects
+ * for a complete ECL deck.
+ */
+template
+class EclMaterialLawManagerSimple
+{
+private:
+ using Traits = TraitsT;
+ using Scalar = typename Traits::Scalar;
+ enum { waterPhaseIdx = Traits::wettingPhaseIdx };
+ enum { oilPhaseIdx = Traits::nonWettingPhaseIdx };
+ enum { gasPhaseIdx = Traits::gasPhaseIdx };
+ enum { numPhases = Traits::numPhases };
+
+ using GasOilTraits = TwoPhaseMaterialTraits;
+ using OilWaterTraits = TwoPhaseMaterialTraits;
+ using GasWaterTraits = TwoPhaseMaterialTraits;
+
+ // the two-phase material law which is defined on effective (unscaled) saturations
+ using GasOilEffectiveTwoPhaseLaw = PiecewiseLinearTwoPhaseMaterial;
+ using OilWaterEffectiveTwoPhaseLaw = PiecewiseLinearTwoPhaseMaterial;
+ using GasWaterEffectiveTwoPhaseLaw = PiecewiseLinearTwoPhaseMaterial;
+
+ using GasOilEffectiveTwoPhaseParams = typename GasOilEffectiveTwoPhaseLaw::Params;
+ using OilWaterEffectiveTwoPhaseParams = typename OilWaterEffectiveTwoPhaseLaw::Params;
+ using GasWaterEffectiveTwoPhaseParams = typename GasWaterEffectiveTwoPhaseLaw::Params;
+
+ // the two-phase material law which is defined on absolute (scaled) saturations
+ // using GasOilEpsTwoPhaseLaw = EclEpsTwoPhaseLaw;
+ // using OilWaterEpsTwoPhaseLaw = EclEpsTwoPhaseLaw;
+ // using GasWaterEpsTwoPhaseLaw = EclEpsTwoPhaseLaw;
+ // using GasOilEpsTwoPhaseParams = typename GasOilEpsTwoPhaseLaw::Params;
+ // using OilWaterEpsTwoPhaseParams = typename OilWaterEpsTwoPhaseLaw::Params;
+ // using GasWaterEpsTwoPhaseParams = typename GasWaterEpsTwoPhaseLaw::Params;
+
+ // the scaled two-phase material laws with hystersis
+ // using GasOilTwoPhaseLaw = EclHysteresisTwoPhaseLaw;
+ // using OilWaterTwoPhaseLaw = EclHysteresisTwoPhaseLaw;
+ // using GasWaterTwoPhaseLaw = EclHysteresisTwoPhaseLaw;
+ // using GasOilTwoPhaseHystParams = typename GasOilTwoPhaseLaw::Params;
+ // using OilWaterTwoPhaseHystParams = typename OilWaterTwoPhaseLaw::Params;
+ // using GasWaterTwoPhaseHystParams = typename GasWaterTwoPhaseLaw::Params;
+
+ using GasOilTwoPhaseLaw = GasOilEffectiveTwoPhaseLaw;
+ using OilWaterTwoPhaseLaw = OilWaterEffectiveTwoPhaseLaw;
+ using GasWaterTwoPhaseLaw = GasWaterEffectiveTwoPhaseLaw;
+
+public:
+ // the three-phase material law used by the simulation
+ // using MaterialLaw = EclMultiplexerMaterial;
+ using MaterialLaw = EclTwoPhaseMaterial;
+ using MaterialLawParams = typename MaterialLaw::Params;
+ using DirectionalMaterialLawParamsPtr = std::unique_ptr>;
+
+ EclMaterialLawManagerSimple();
+ ~EclMaterialLawManagerSimple();
+
+private:
+ // internal typedefs
+ using GasOilEffectiveParamVector = std::vector>;
+ using OilWaterEffectiveParamVector = std::vector>;
+ using GasWaterEffectiveParamVector = std::vector>;
+
+ // using GasOilScalingPointsVector = std::vector>>;
+ // using OilWaterScalingPointsVector = std::vector>>;
+ // using GasWaterScalingPointsVector = std::vector>>;
+ using OilWaterScalingInfoVector = std::vector>;
+ // using GasOilParamVector = std::vector>;
+ // using OilWaterParamVector = std::vector>;
+ // using GasWaterParamVector = std::vector>;
+ using MaterialLawParamsVector = std::vector>;
+
+ // helper classes
+
+ // This class' implementation is defined in "EclMaterialLawManagerSimpleInitParams.cpp"
+ class InitParams {
+ public:
+ InitParams(EclMaterialLawManagerSimple& parent, const EclipseState& eclState, size_t numCompressedElems);
+ // \brief Function argument 'fieldPropIntOnLeadAssigner' needed to lookup
+ // field properties of cells on the leaf grid view for CpGrid with local grid refinement.
+ // Function argument 'lookupIdxOnLevelZeroAssigner' is added to lookup, for each
+ // leaf gridview cell with index 'elemIdx', its 'lookupIdx' (index of the parent/equivalent cell on level zero).
+ void run(const std::function(const FieldPropsManager&, const std::string&, bool)>& fieldPropIntOnLeafAssigner,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ private:
+ // class HystParams;
+ // \brief Function argument 'fieldPropIntOnLeadAssigner' needed to lookup
+ // field properties of cells on the leaf grid view for CpGrid with local grid refinement.
+ void copySatnumArrays_(const std::function(const FieldPropsManager&, const std::string&, bool)>&
+ fieldPropIntOnLeafAssigner);
+ // \brief Function argument 'fieldPropIntOnLeadAssigner' needed to lookup
+ // field properties of cells on the leaf grid view for CpGrid with local grid refinement.
+ void copyIntArray_(std::vector& dest, const std::string keyword,
+ const std::function(const FieldPropsManager&, const std::string&, bool)>&
+ fieldPropIntOnLeafAssigner);
+ unsigned imbRegion_(std::vector& array, unsigned elemIdx);
+ void initArrays_(
+ std::vector*>& satnumArray,
+ std::vector*>& imbnumArray,
+ std::vector*>& mlpArray);
+ void initMaterialLawParamVectors_();
+ void initOilWaterScaledEpsInfo_();
+ // \brief Function argument 'fieldProptOnLeadAssigner' needed to lookup
+ // field properties of cells on the leaf grid view for CpGrid with local grid refinement.
+ void initSatnumRegionArray_(const std::function(const FieldPropsManager&, const std::string&, bool)>&
+ fieldPropIntOnLeafAssigner);
+ void initThreePhaseParams_(
+ // HystParams &hystParams,
+ MaterialLawParams& materialParams,
+ unsigned satRegionIdx,
+ unsigned elemIdx);
+ void readEffectiveParameters_();
+ // void readUnscaledEpsPointsVectors_();
+ // template
+ // void readUnscaledEpsPoints_(Container& dest, std::shared_ptr config, EclTwoPhaseSystemType system_type);
+ unsigned satRegion_(std::vector& array, unsigned elemIdx);
+ unsigned satOrImbRegion_(std::vector& array, std::vector& default_vec, unsigned elemIdx);
+/*
+ // This class' implementation is defined in "EclMaterialLawManagerSimpleHystParams.cpp"
+ class HystParams {
+ public:
+ HystParams(EclMaterialLawManagerSimple::InitParams& init_params);
+ void finalize();
+ std::shared_ptr getGasOilParams();
+ std::shared_ptr getOilWaterParams();
+ std::shared_ptr getGasWaterParams();
+ void setConfig(unsigned satRegionIdx);
+ // Function argument 'lookupIdxOnLevelZeroAssigner' is added to lookup, for each
+ // leaf gridview cell with index 'elemIdx', its 'lookupIdx' (index of the parent/equivalent cell on level zero).
+ void setDrainageParamsOilGas(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ void setDrainageParamsOilWater(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ void setDrainageParamsGasWater(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ void setImbibitionParamsOilGas(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ void setImbibitionParamsOilWater(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ void setImbibitionParamsGasWater(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ private:
+ bool hasGasWater_();
+ bool hasGasOil_();
+ bool hasOilWater_();
+
+ // Function argument 'lookupIdxOnLevelZeroAssigner' is added to lookup, for each
+ // leaf gridview cell with index 'elemIdx', its 'lookupIdx' (index of the parent/equivalent cell on level zero).
+ std::tuple, EclEpsScalingPoints>
+ readScaledEpsPoints_(const EclEpsGridProperties& epsGridProperties, unsigned elemIdx, EclTwoPhaseSystemType type,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ std::tuple, EclEpsScalingPoints>
+ readScaledEpsPointsDrainage_(unsigned elemIdx, EclTwoPhaseSystemType type,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+ std::tuple, EclEpsScalingPoints>
+ readScaledEpsPointsImbibition_(unsigned elemIdx, EclTwoPhaseSystemType type,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+
+ EclMaterialLawManagerSimple::InitParams& init_params_;
+ EclMaterialLawManagerSimple& parent_;
+ const EclipseState& eclState_;
+ std::shared_ptr gasOilParams_;
+ std::shared_ptr oilWaterParams_;
+ std::shared_ptr gasWaterParams_;
+ };
+*/
+
+ // This class' implementation is defined in "EclMaterialLawManagerSimpleReadEffectiveParams.cpp"
+ class ReadEffectiveParams {
+ public:
+ ReadEffectiveParams(EclMaterialLawManagerSimple::InitParams& init_params);
+ void read();
+ private:
+ std::vector normalizeKrValues_(const double tolcrit, const TableColumn& krValues) const;
+ void readGasOilParameters_(GasOilEffectiveParamVector& dest, unsigned satRegionIdx);
+ template
+ void readGasOilFamily2_(
+ GasOilEffectiveTwoPhaseParams& effParams,
+ const Scalar Swco,
+ const double tolcrit,
+ const TableType& sofTable,
+ const SgfnTable& sgfnTable,
+ const std::string& columnName);
+ void readGasOilSgof_(GasOilEffectiveTwoPhaseParams& effParams,
+ const Scalar Swco,
+ const double tolcrit,
+ const SgofTable& sgofTable);
+
+ void readGasOilSlgof_(GasOilEffectiveTwoPhaseParams& effParams,
+ const Scalar Swco,
+ const double tolcrit,
+ const SlgofTable& slgofTable);
+ void readGasWaterParameters_(GasWaterEffectiveParamVector& dest, unsigned satRegionIdx);
+ void readOilWaterParameters_(OilWaterEffectiveParamVector& dest, unsigned satRegionIdx);
+
+ EclMaterialLawManagerSimple::InitParams& init_params_;
+ EclMaterialLawManagerSimple& parent_;
+ const EclipseState& eclState_;
+ }; // end of "class ReadEffectiveParams"
+
+ EclMaterialLawManagerSimple& parent_;
+ const EclipseState& eclState_;
+ size_t numCompressedElems_;
+
+ std::unique_ptr epsImbGridProperties_; //imbibition
+ std::unique_ptr epsGridProperties_; // drainage
+
+ }; // end of "class InitParams"
+
+public:
+ void initFromState(const EclipseState& eclState);
+
+ // \brief Function argument 'fieldPropIntOnLeadAssigner' needed to lookup
+ // field properties of cells on the leaf grid view for CpGrid with local grid refinement.
+ // Function argument 'lookupIdxOnLevelZeroAssigner' is added to lookup, for each
+ // leaf gridview cell with index 'elemIdx', its 'lookupIdx' (index of the parent/equivalent cell on level zero).
+ void initParamsForElements(const EclipseState& eclState, size_t numCompressedElems,
+ const std::function(const FieldPropsManager&, const std::string&, bool)>&
+ fieldPropIntOnLeafAssigner,
+ const std::function& lookupIdxOnLevelZeroAssigner);
+
+ /*!
+ * \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 initFromState() is
+ * that the capillary pressure given depends on the particuars of how the simulator
+ * calculates its initial condition.
+ */
+ std::pair
+ applySwatinit(unsigned elemIdx,
+ Scalar pcow,
+ Scalar Sw);
+
+ /// Apply SWATINIT-like scaling of oil/water capillary pressure curve at
+ /// simulation restart.
+ ///
+ /// \param[in] elemIdx Active cell index
+ ///
+ /// \param[in] maxPcow Scaled maximum oil/water capillary pressure.
+ /// Typically the PPCW restart file array's entry for the
+ /// corresponding cell.
+ void applyRestartSwatInit(const unsigned elemIdx, const Scalar maxPcow);
+
+ bool enableEndPointScaling() const
+ { return enableEndPointScaling_; }
+
+ bool enablePpcwmax() const
+ { return enablePpcwmax_; }
+
+ bool enableHysteresis() const
+ //{ return hysteresisConfig_->enableHysteresis(); }
+ { return false; }
+
+ bool enablePCHysteresis() const
+ //{ return (enableHysteresis() && hysteresisConfig_->pcHysteresisModel() >= 0); }
+ { return false; }
+
+ bool enableWettingHysteresis() const
+ //{ return (enableHysteresis() && hysteresisConfig_->krHysteresisModel() >= 4); }
+ { return false; }
+
+ bool enableNonWettingHysteresis() const
+ //{ return (enableHysteresis() && hysteresisConfig_->krHysteresisModel() >= 0); }
+ { return false; }
+
+ MaterialLawParams& materialLawParams(unsigned elemIdx)
+ {
+ assert(elemIdx < materialLawParams_.size());
+ return materialLawParams_[elemIdx];
+ }
+
+ const MaterialLawParams& materialLawParams(unsigned elemIdx) const
+ {
+ assert(elemIdx < materialLawParams_.size());
+ return materialLawParams_[elemIdx];
+ }
+
+ const MaterialLawParams& materialLawParams(unsigned elemIdx, FaceDir::DirEnum facedir) const
+ {
+ return materialLawParamsFunc_(elemIdx, facedir);
+ }
+
+ MaterialLawParams& materialLawParams(unsigned elemIdx, FaceDir::DirEnum facedir)
+ {
+ return const_cast(materialLawParamsFunc_(elemIdx, facedir));
+ }
+
+ /*!
+ * \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;
+
+ int satnumRegionIdx(unsigned elemIdx) const
+ { return satnumRegionArray_[elemIdx]; }
+
+ int getKrnumSatIdx(unsigned elemIdx, FaceDir::DirEnum facedir) const;
+
+ bool hasDirectionalRelperms() const
+ {
+ return !krnumXArray_.empty() || !krnumYArray_.empty() || !krnumZArray_.empty();
+ }
+
+ bool hasDirectionalImbnum() const {
+ if (imbnumXArray_.size() > 0 || imbnumYArray_.size() > 0 || imbnumZArray_.size() > 0) {
+ return true;
+ }
+ return false;
+ }
+
+ int imbnumRegionIdx(unsigned elemIdx) const
+ { return imbnumRegionArray_[elemIdx]; }
+
+ template
+ bool updateHysteresis(const FluidState& fluidState, unsigned elemIdx)
+ {
+ OPM_TIMEFUNCTION_LOCAL();
+ if (!enableHysteresis())
+ return false;
+ bool changed = MaterialLaw::updateHysteresis(materialLawParams(elemIdx), fluidState);
+ if (hasDirectionalRelperms() || hasDirectionalImbnum()) {
+ using Dir = FaceDir::DirEnum;
+ constexpr int ndim = 3;
+ Dir facedirs[ndim] = {Dir::XPlus, Dir::YPlus, Dir::ZPlus};
+ for (int i = 0; i& oilWaterScaledEpsPointsDrainage(unsigned elemIdx);
+
+ const EclEpsScalingPointsInfo& oilWaterScaledEpsInfoDrainage(size_t elemIdx) const
+ { return oilWaterScaledEpsInfoDrainage_[elemIdx]; }
+
+ template
+ void serializeOp(Serializer& serializer)
+ {
+ // This is for restart serialization.
+ // Only dynamic state in the parameters need to be stored.
+ // For that reason we do not serialize the vector
+ // as that would recreate the objects inside.
+ for (auto& mat : materialLawParams_) {
+ serializer(mat);
+ }
+ }
+
+private:
+ const MaterialLawParams& materialLawParamsFunc_(unsigned elemIdx, FaceDir::DirEnum facedir) const;
+
+ // void readGlobalEpsOptions_(const EclipseState& eclState);
+
+ // void readGlobalHysteresisOptions_(const EclipseState& state);
+
+ void readGlobalThreePhaseOptions_(const Runspec& runspec);
+
+ bool enableEndPointScaling_;
+ // std::shared_ptr hysteresisConfig_;
+ // std::vector> wagHystersisConfig_;
+
+
+ std::shared_ptr oilWaterEclEpsConfig_;
+ std::vector> unscaledEpsInfo_;
+ OilWaterScalingInfoVector oilWaterScaledEpsInfoDrainage_;
+
+ // std::shared_ptr gasWaterEclEpsConfig_;
+
+ // GasOilScalingPointsVector gasOilUnscaledPointsVector_;
+ // OilWaterScalingPointsVector oilWaterUnscaledPointsVector_;
+ // GasWaterScalingPointsVector gasWaterUnscaledPointsVector_;
+
+ GasOilEffectiveParamVector gasOilEffectiveParamVector_;
+ OilWaterEffectiveParamVector oilWaterEffectiveParamVector_;
+ GasWaterEffectiveParamVector gasWaterEffectiveParamVector_;
+
+ EclMultiplexerApproach threePhaseApproach_ = EclMultiplexerApproach::Default;
+ // this attribute only makes sense for twophase simulations!
+ enum EclTwoPhaseApproach twoPhaseApproach_ = EclTwoPhaseApproach::GasWater;
+
+ std::vector materialLawParams_;
+ DirectionalMaterialLawParamsPtr dirMaterialLawParams_;
+
+ std::vector satnumRegionArray_;
+ std::vector krnumXArray_;
+ std::vector krnumYArray_;
+ std::vector krnumZArray_;
+ std::vector imbnumXArray_;
+ std::vector imbnumYArray_;
+ std::vector imbnumZArray_;
+ std::vector imbnumRegionArray_;
+ std::vector stoneEtas_;
+
+ bool enablePpcwmax_;
+ std::vector maxAllowPc_;
+ std::vector modifySwl_;
+
+ bool hasGas;
+ bool hasOil;
+ bool hasWater;
+
+ std::shared_ptr gasOilConfig_;
+ std::shared_ptr oilWaterConfig_;
+ std::shared_ptr gasWaterConfig_;
+};
+} // namespace Opm
+
+#endif
diff --git a/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleHystParams.cpp b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleHystParams.cpp
new file mode 100644
index 00000000000..b9df445069a
--- /dev/null
+++ b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleHystParams.cpp
@@ -0,0 +1,314 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*
+ Copyright 2022 Equinor ASA.
+
+ 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 3 of the License, or
+
+ 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 .
+*/
+
+#if 0
+
+#include
+#include
+#include
+
+namespace Opm {
+
+/* constructors*/
+template
+EclMaterialLawManagerSimple::InitParams::HystParams::
+HystParams(EclMaterialLawManagerSimple::InitParams& init_params) :
+ init_params_{init_params}, parent_{init_params_.parent_},
+ eclState_{init_params_.eclState_}
+{
+ gasOilParams_ = std::make_shared();
+ oilWaterParams_ = std::make_shared();
+ gasWaterParams_ = std::make_shared();
+}
+
+/* public methods, alphabetically sorted */
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+finalize()
+{
+ if (hasGasOil_())
+ this->gasOilParams_->finalize();
+ if (hasOilWater_())
+ this->oilWaterParams_->finalize();
+ if (hasGasWater_())
+ this->gasWaterParams_->finalize();
+}
+
+template
+std::shared_ptr::GasOilTwoPhaseHystParams>
+EclMaterialLawManagerSimple::InitParams::HystParams::
+getGasOilParams()
+{
+ return gasOilParams_;
+}
+
+template
+std::shared_ptr::OilWaterTwoPhaseHystParams>
+EclMaterialLawManagerSimple::InitParams::HystParams::
+getOilWaterParams()
+{
+ return oilWaterParams_;
+}
+
+template
+std::shared_ptr::GasWaterTwoPhaseHystParams>
+EclMaterialLawManagerSimple::InitParams::HystParams::
+getGasWaterParams()
+{
+ return gasWaterParams_;
+}
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+setConfig(unsigned satRegionIdx)
+{
+ this->gasOilParams_->setConfig(this->parent_.hysteresisConfig_);
+ this->oilWaterParams_->setConfig(this->parent_.hysteresisConfig_);
+ this->gasWaterParams_->setConfig(this->parent_.hysteresisConfig_);
+
+ if (this->parent_.hysteresisConfig_->enableWagHysteresis()) {
+ this->gasOilParams_->setWagConfig(this->parent_.wagHystersisConfig_[satRegionIdx]);
+ this->oilWaterParams_->setWagConfig(this->parent_.wagHystersisConfig_[satRegionIdx]);
+ this->gasWaterParams_->setWagConfig(this->parent_.wagHystersisConfig_[satRegionIdx]);
+ }
+
+} // namespace Opm
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+setDrainageParamsGasWater(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner)
+{
+ if (hasGasWater_()) {
+ auto [gasWaterScaledInfo, gasWaterScaledPoints]
+ = readScaledEpsPointsDrainage_(elemIdx, EclTwoPhaseSystemType::GasWater, lookupIdxOnLevelZeroAssigner);
+ GasWaterEpsTwoPhaseParams gasWaterDrainParams;
+ gasWaterDrainParams.setConfig(this->parent_.gasWaterConfig_);
+ gasWaterDrainParams.setUnscaledPoints(this->parent_.gasWaterUnscaledPointsVector_[satRegionIdx]);
+ gasWaterDrainParams.setScaledPoints(gasWaterScaledPoints);
+ gasWaterDrainParams.setEffectiveLawParams(this->parent_.gasWaterEffectiveParamVector_[satRegionIdx]);
+ gasWaterDrainParams.finalize();
+ this->gasWaterParams_->setDrainageParams(gasWaterDrainParams, gasWaterScaledInfo, EclTwoPhaseSystemType::GasWater);
+ }
+}
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+setDrainageParamsOilGas(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner)
+{
+ if (hasGasOil_()) {
+ auto [gasOilScaledInfo, gasOilScaledPoints]
+ = readScaledEpsPointsDrainage_(elemIdx, EclTwoPhaseSystemType::GasOil, lookupIdxOnLevelZeroAssigner);
+ GasOilEpsTwoPhaseParams gasOilDrainParams;
+ gasOilDrainParams.setConfig(this->parent_.gasOilConfig_);
+ gasOilDrainParams.setUnscaledPoints(this->parent_.gasOilUnscaledPointsVector_[satRegionIdx]);
+ gasOilDrainParams.setScaledPoints(gasOilScaledPoints);
+ gasOilDrainParams.setEffectiveLawParams(this->parent_.gasOilEffectiveParamVector_[satRegionIdx]);
+ gasOilDrainParams.finalize();
+ this->gasOilParams_->setDrainageParams(gasOilDrainParams, gasOilScaledInfo, EclTwoPhaseSystemType::GasOil);
+ }
+}
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+setDrainageParamsOilWater(unsigned elemIdx, unsigned satRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner)
+{
+ // We need to compute the oil-water scaled info even if we are running a two-phase case without
+ // water (e.g. gas-oil). The reason is that the oil-water scaled info is used when computing
+ // the initial condition see e.g. equilibrationhelpers.cc and initstateequil.cc
+ // Therefore, the below 7 lines should not be put inside the if(hasOilWater_){} below.
+ auto [oilWaterScaledInfo, oilWaterScaledPoints]
+ = readScaledEpsPointsDrainage_(elemIdx, EclTwoPhaseSystemType::OilWater, lookupIdxOnLevelZeroAssigner);
+ // TODO: This will reassign the same EclEpsScalingPointsInfo for each facedir
+ // since we currently does not support facedir for the scaling points info
+ // When such support is added, we need to extend the below vector which has info for each cell
+ // to include three more vectors, one with info for each facedir of a cell
+ this->parent_.oilWaterScaledEpsInfoDrainage_[elemIdx] = oilWaterScaledInfo;
+ if (hasOilWater_()) {
+ OilWaterEpsTwoPhaseParams oilWaterDrainParams;
+ oilWaterDrainParams.setConfig(this->parent_.oilWaterConfig_);
+ oilWaterDrainParams.setUnscaledPoints(this->parent_.oilWaterUnscaledPointsVector_[satRegionIdx]);
+ oilWaterDrainParams.setScaledPoints(oilWaterScaledPoints);
+ oilWaterDrainParams.setEffectiveLawParams(this->parent_.oilWaterEffectiveParamVector_[satRegionIdx]);
+ oilWaterDrainParams.finalize();
+ oilWaterParams_->setDrainageParams(oilWaterDrainParams, oilWaterScaledInfo, EclTwoPhaseSystemType::OilWater);
+ }
+}
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+setImbibitionParamsGasWater(unsigned elemIdx, unsigned imbRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner)
+{
+ if (hasGasWater_()) {
+ auto [gasWaterScaledInfo, gasWaterScaledPoints]
+ = readScaledEpsPointsImbibition_(elemIdx, EclTwoPhaseSystemType::GasWater, lookupIdxOnLevelZeroAssigner);
+ GasWaterEpsTwoPhaseParams gasWaterImbParamsHyst;
+ gasWaterImbParamsHyst.setConfig(this->parent_.gasWaterConfig_);
+ gasWaterImbParamsHyst.setUnscaledPoints(this->parent_.gasWaterUnscaledPointsVector_[imbRegionIdx]);
+ gasWaterImbParamsHyst.setScaledPoints(gasWaterScaledPoints);
+ gasWaterImbParamsHyst.setEffectiveLawParams(this->parent_.gasWaterEffectiveParamVector_[imbRegionIdx]);
+ gasWaterImbParamsHyst.finalize();
+ this->gasWaterParams_->setImbibitionParams(gasWaterImbParamsHyst,
+ gasWaterScaledInfo,
+ EclTwoPhaseSystemType::GasWater);
+
+ }
+}
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+setImbibitionParamsOilGas(unsigned elemIdx, unsigned imbRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner)
+{
+ if (hasGasOil_()) {
+ auto [gasOilScaledInfo, gasOilScaledPoints]
+ = readScaledEpsPointsImbibition_(elemIdx, EclTwoPhaseSystemType::GasOil, lookupIdxOnLevelZeroAssigner);
+
+ GasOilEpsTwoPhaseParams gasOilImbParamsHyst;
+ gasOilImbParamsHyst.setConfig(this->parent_.gasOilConfig_);
+ gasOilImbParamsHyst.setUnscaledPoints(this->parent_.gasOilUnscaledPointsVector_[imbRegionIdx]);
+ gasOilImbParamsHyst.setScaledPoints(gasOilScaledPoints);
+ gasOilImbParamsHyst.setEffectiveLawParams(this->parent_.gasOilEffectiveParamVector_[imbRegionIdx]);
+ gasOilImbParamsHyst.finalize();
+ this->gasOilParams_->setImbibitionParams(gasOilImbParamsHyst,
+ gasOilScaledInfo,
+ EclTwoPhaseSystemType::GasOil);
+ }
+}
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::HystParams::
+setImbibitionParamsOilWater(unsigned elemIdx, unsigned imbRegionIdx,
+ const std::function& lookupIdxOnLevelZeroAssigner)
+{
+ if (hasOilWater_()) {
+ auto [oilWaterScaledInfo, oilWaterScaledPoints]
+ = readScaledEpsPointsImbibition_(elemIdx, EclTwoPhaseSystemType::OilWater, lookupIdxOnLevelZeroAssigner);
+ OilWaterEpsTwoPhaseParams oilWaterImbParamsHyst;
+ oilWaterImbParamsHyst.setConfig(this->parent_.oilWaterConfig_);
+ oilWaterImbParamsHyst.setUnscaledPoints(this->parent_.oilWaterUnscaledPointsVector_[imbRegionIdx]);
+ oilWaterImbParamsHyst.setScaledPoints(oilWaterScaledPoints);
+ oilWaterImbParamsHyst.setEffectiveLawParams(this->parent_.oilWaterEffectiveParamVector_[imbRegionIdx]);
+ oilWaterImbParamsHyst.finalize();
+ this->oilWaterParams_->setImbibitionParams(oilWaterImbParamsHyst,
+ oilWaterScaledInfo,
+ EclTwoPhaseSystemType::OilWater);
+
+ }
+}
+
+/* private methods, alphabetically sorted */
+
+template
+bool
+EclMaterialLawManagerSimple::InitParams::HystParams::
+hasGasOil_()
+{
+ return this->parent_.hasGas && this->parent_.hasOil;
+}
+
+template
+bool
+EclMaterialLawManagerSimple::InitParams::HystParams::
+hasGasWater_()
+{
+ return this->parent_.hasGas && this->parent_.hasWater && !this->parent_.hasOil;
+}
+
+template
+bool
+EclMaterialLawManagerSimple::InitParams::HystParams::
+hasOilWater_()
+{
+ return this->parent_.hasOil && this->parent_.hasWater;
+}
+
+template
+std::tuple<
+ EclEpsScalingPointsInfo::Scalar>,
+ EclEpsScalingPoints::Scalar>
+>
+EclMaterialLawManagerSimple::InitParams::HystParams::
+readScaledEpsPoints_(const EclEpsGridProperties& epsGridProperties, unsigned elemIdx, EclTwoPhaseSystemType type,
+ const std::function& fieldPropIdxOnLevelZero)
+{
+ const EclEpsConfig& config = (type == EclTwoPhaseSystemType::OilWater)? *(this->parent_.oilWaterConfig_): *(this->parent_.gasOilConfig_);
+ // For CpGrids with LGRs, field prop is inherited from parent/equivalent cell from level 0.
+ // 'lookupIdx' is the index on level zero of the parent cell or the equivalent cell of the
+ // leaf grid view cell with index 'elemIdx'.
+ const auto lookupIdx = fieldPropIdxOnLevelZero(elemIdx);
+ unsigned satRegionIdx = epsGridProperties.satRegion( lookupIdx /* coincides with elemIdx when no LGRs */ );
+ // Copy-construct a new instance of EclEpsScalingPointsInfo
+ EclEpsScalingPointsInfo destInfo(this->parent_.unscaledEpsInfo_[satRegionIdx]);
+ // TODO: currently epsGridProperties does not implement a face direction, e.g. SWLX, SWLY,...
+ // when these keywords get implemented, we need to use include facedir in the lookup
+ destInfo.extractScaled(this->eclState_, epsGridProperties, lookupIdx /* coincides with elemIdx when no LGRs */);
+
+ EclEpsScalingPoints destPoint;
+ destPoint.init(destInfo, config, type);
+ return {destInfo, destPoint};
+}
+
+template
+std::tuple<
+ EclEpsScalingPointsInfo::Scalar>,
+ EclEpsScalingPoints::Scalar>
+>
+EclMaterialLawManagerSimple::InitParams::HystParams::
+readScaledEpsPointsDrainage_(unsigned elemIdx, EclTwoPhaseSystemType type,
+ const std::function& fieldPropIdxOnLevelZero)
+{
+ const auto& epsGridProperties = this->init_params_.epsGridProperties_;
+ return readScaledEpsPoints_(*epsGridProperties, elemIdx, type, fieldPropIdxOnLevelZero);
+}
+
+template
+std::tuple<
+ EclEpsScalingPointsInfo::Scalar>,
+ EclEpsScalingPoints::Scalar>
+>
+EclMaterialLawManagerSimple::InitParams::HystParams::
+readScaledEpsPointsImbibition_(unsigned elemIdx, EclTwoPhaseSystemType type,
+ const std::function& fieldPropIdxOnLevelZero)
+{
+ const auto& epsGridProperties = this->init_params_.epsImbGridProperties_;
+ return readScaledEpsPoints_(*epsGridProperties, elemIdx, type, fieldPropIdxOnLevelZero);
+}
+
+// Make some actual code, by realizing the previously defined templated class
+template class EclMaterialLawManagerSimple>::InitParams::HystParams;
+template class EclMaterialLawManagerSimple>::InitParams::HystParams;
+
+
+} // namespace Opm
+
+#endif // 0
diff --git a/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleInitParams.cpp b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleInitParams.cpp
new file mode 100644
index 00000000000..0ce62ed1230
--- /dev/null
+++ b/opm/material/fluidmatrixinteractions/EclMaterialLawManagerSimpleInitParams.cpp
@@ -0,0 +1,300 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*
+ Copyright 2022 Equinor ASA.
+
+ 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 3 of the License, or
+
+ 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 .
+*/
+
+#include
+
+#include
+
+#include
+#include
+
+
+namespace Opm {
+
+/* constructors*/
+
+template
+EclMaterialLawManagerSimple::InitParams::
+InitParams(EclMaterialLawManagerSimple& parent, const EclipseState& eclState, size_t numCompressedElems) :
+ parent_{parent},
+ eclState_{eclState},
+ numCompressedElems_{numCompressedElems}
+{
+ // read end point scaling grid properties
+ // TODO: these objects might require some memory, can this be simplified?
+ if (this->parent_.enableHysteresis()) {
+ this->epsImbGridProperties_
+ = std::make_unique(this->eclState_, /*useImbibition=*/true);
+ }
+ this->epsGridProperties_
+ = std::make_unique(this->eclState_, /*useImbibition=*/false);
+}
+
+/* public methods */
+
+template
+void
+EclMaterialLawManagerSimple::InitParams::
+run(const std::function