28#error "Eclipse input support in opm-common is required to use the ECL material manager!"
31#ifndef OPM_ECL_MATERIAL_LAW_MANAGER_HPP
32#define OPM_ECL_MATERIAL_LAW_MANAGER_HPP
46#include <opm/common/OpmLog/OpmLog.hpp>
49#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
50#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
51#include <opm/input/eclipse/EclipseState/Tables/TableColumn.hpp>
52#include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
68template <
class TraitsT>
72 using Traits = TraitsT;
73 using Scalar =
typename Traits::Scalar;
74 enum { waterPhaseIdx = Traits::wettingPhaseIdx };
75 enum { oilPhaseIdx = Traits::nonWettingPhaseIdx };
76 enum { gasPhaseIdx = Traits::gasPhaseIdx };
77 enum { numPhases = Traits::numPhases };
115 using GasOilEffectiveParamVector = std::vector<std::shared_ptr<GasOilEffectiveTwoPhaseParams>>;
116 using OilWaterEffectiveParamVector = std::vector<std::shared_ptr<OilWaterEffectiveTwoPhaseParams>>;
117 using GasWaterEffectiveParamVector = std::vector<std::shared_ptr<GasWaterEffectiveTwoPhaseParams>>;
119 using GasOilScalingPointsVector = std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar>>>;
120 using OilWaterScalingPointsVector = std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar>>>;
121 using GasWaterScalingPointsVector = std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar>>>;
122 using OilWaterScalingInfoVector = std::vector<EclEpsScalingPointsInfo<Scalar>>;
123 using GasOilParamVector = std::vector<std::shared_ptr<GasOilTwoPhaseHystParams>>;
124 using OilWaterParamVector = std::vector<std::shared_ptr<OilWaterTwoPhaseHystParams>>;
125 using GasWaterParamVector = std::vector<std::shared_ptr<GasWaterTwoPhaseHystParams>>;
126 using MaterialLawParamsVector = std::vector<std::shared_ptr<MaterialLawParams>>;
135 const auto& runspec = eclState.runspec();
136 const size_t numSatRegions = runspec.tabdims().getNumSatTables();
138 const auto& ph = runspec.phases();
139 this->hasGas = ph.active(Phase::GAS);
140 this->hasOil = ph.active(Phase::OIL);
141 this->hasWater = ph.active(Phase::WATER);
143 readGlobalEpsOptions_(eclState);
144 readGlobalHysteresisOptions_(eclState);
145 readGlobalThreePhaseOptions_(runspec);
148 gasOilConfig = std::make_shared<EclEpsConfig>();
149 oilWaterConfig = std::make_shared<EclEpsConfig>();
150 gasWaterConfig = std::make_shared<EclEpsConfig>();
156 const auto& tables = eclState.getTableManager();
159 const auto& stone1exTables = tables.getStone1exTable();
161 if (! stone1exTables.empty()) {
163 stoneEtas.reserve(numSatRegions);
165 for (
const auto& table : stone1exTables) {
166 stoneEtas.push_back(table.eta);
171 this->unscaledEpsInfo_.resize(numSatRegions);
173 if (this->hasGas + this->hasOil + this->hasWater == 1) {
179 const auto tolcrit = runspec.saturationFunctionControls()
180 .minimumRelpermMobilityThreshold();
182 const auto rtep = satfunc::getRawTableEndpoints(tables, ph, tolcrit);
183 const auto rfunc = satfunc::getRawFunctionValues(tables, ph, rtep);
185 for (
unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
186 this->unscaledEpsInfo_[satRegionIdx]
187 .extractUnscaled(rtep, rfunc, satRegionIdx);
194 const size_t numSatRegions = eclState.runspec().tabdims().getNumSatTables();
197 gasOilUnscaledPointsVector_.resize(numSatRegions);
198 oilWaterUnscaledPointsVector_.resize(numSatRegions);
199 gasWaterUnscaledPointsVector_.resize(numSatRegions);
201 gasOilEffectiveParamVector_.resize(numSatRegions);
202 oilWaterEffectiveParamVector_.resize(numSatRegions);
203 gasWaterEffectiveParamVector_.resize(numSatRegions);
204 for (
unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
206 readGasOilUnscaledPoints_(gasOilUnscaledPointsVector_, gasOilConfig, eclState, satRegionIdx);
207 readOilWaterUnscaledPoints_(oilWaterUnscaledPointsVector_, oilWaterConfig, eclState, satRegionIdx);
208 readGasWaterUnscaledPoints_(gasWaterUnscaledPointsVector_, gasWaterConfig, eclState, satRegionIdx);
211 readGasOilEffectiveParameters_(gasOilEffectiveParamVector_, eclState, satRegionIdx);
212 readOilWaterEffectiveParameters_(oilWaterEffectiveParamVector_, eclState, satRegionIdx);
213 readGasWaterEffectiveParameters_(gasWaterEffectiveParamVector_, eclState, satRegionIdx);
218 satnumRegionArray_.resize(numCompressedElems);
219 if (eclState.fieldProps().has_int(
"SATNUM")) {
220 const auto& satnumRawData = eclState.fieldProps().get_int(
"SATNUM");
221 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
222 satnumRegionArray_[elemIdx] = satnumRawData[elemIdx] - 1;
226 std::fill(satnumRegionArray_.begin(), satnumRegionArray_.end(), 0);
228 auto copy_krnum = [&eclState, numCompressedElems](std::vector<int>& dest,
const std::string keyword) {
229 if (eclState.fieldProps().has_int(keyword)) {
230 dest.resize(numCompressedElems);
231 const auto& satnumRawData = eclState.fieldProps().get_int(keyword);
232 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
233 dest[elemIdx] = satnumRawData[elemIdx] - 1;
237 copy_krnum(krnumXArray_,
"KRNUMX");
238 copy_krnum(krnumYArray_,
"KRNUMY");
239 copy_krnum(krnumZArray_,
"KRNUMZ");
243 imbnumRegionArray_ = satnumRegionArray_;
244 if (eclState.fieldProps().has_int(
"IMBNUM")) {
245 const auto& imbnumRawData = eclState.fieldProps().get_int(
"IMBNUM");
246 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
247 imbnumRegionArray_[elemIdx] = imbnumRawData[elemIdx] - 1;
251 assert(numCompressedElems == satnumRegionArray_.size());
252 assert(!
enableHysteresis() || numCompressedElems == imbnumRegionArray_.size());
256 oilWaterScaledEpsInfoDrainage_.resize(numCompressedElems);
258 std::unique_ptr<EclEpsGridProperties> epsImbGridProperties;
261 epsImbGridProperties = std::make_unique<EclEpsGridProperties>(eclState,
true);
265 materialLawParams_.resize(numCompressedElems);
267 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
268 unsigned satRegionIdx =
static_cast<unsigned>(satnumRegionArray_[elemIdx]);
269 auto gasOilParams = std::make_shared<GasOilTwoPhaseHystParams>();
270 auto oilWaterParams = std::make_shared<OilWaterTwoPhaseHystParams>();
271 auto gasWaterParams = std::make_shared<GasWaterTwoPhaseHystParams>();
272 gasOilParams->setConfig(hysteresisConfig_);
273 oilWaterParams->setConfig(hysteresisConfig_);
274 gasWaterParams->setConfig(hysteresisConfig_);
276 auto [gasOilScaledInfo, gasOilScaledPoint] =
277 readScaledPoints_(*gasOilConfig,
283 auto [owinfo, oilWaterScaledEpsPointDrainage] =
284 readScaledPoints_(*oilWaterConfig,
289 oilWaterScaledEpsInfoDrainage_[elemIdx] = owinfo;
291 auto [gasWaterScaledInfo, gasWaterScaledPoint] =
292 readScaledPoints_(*gasWaterConfig,
298 if (hasGas && hasOil) {
299 GasOilEpsTwoPhaseParams gasOilDrainParams;
300 gasOilDrainParams.setConfig(gasOilConfig);
301 gasOilDrainParams.setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
302 gasOilDrainParams.setScaledPoints(gasOilScaledPoint);
303 gasOilDrainParams.setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
304 gasOilDrainParams.finalize();
306 gasOilParams->setDrainageParams(gasOilDrainParams,
311 if (hasOil && hasWater) {
312 OilWaterEpsTwoPhaseParams oilWaterDrainParams;
313 oilWaterDrainParams.setConfig(oilWaterConfig);
314 oilWaterDrainParams.setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
315 oilWaterDrainParams.setScaledPoints(oilWaterScaledEpsPointDrainage);
316 oilWaterDrainParams.setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
317 oilWaterDrainParams.finalize();
319 oilWaterParams->setDrainageParams(oilWaterDrainParams,
324 if (hasGas && hasWater && !hasOil) {
325 GasWaterEpsTwoPhaseParams gasWaterDrainParams;
326 gasWaterDrainParams.setConfig(gasWaterConfig);
327 gasWaterDrainParams.setUnscaledPoints(gasWaterUnscaledPointsVector_[satRegionIdx]);
328 gasWaterDrainParams.setScaledPoints(gasWaterScaledPoint);
329 gasWaterDrainParams.setEffectiveLawParams(gasWaterEffectiveParamVector_[satRegionIdx]);
330 gasWaterDrainParams.finalize();
332 gasWaterParams->setDrainageParams(gasWaterDrainParams,
338 auto [gasOilScaledImbInfo, gasOilScaledImbPoint] =
339 readScaledPoints_(*gasOilConfig,
341 *epsImbGridProperties,
345 auto [oilWaterScaledImbInfo, oilWaterScaledImbPoint] =
346 readScaledPoints_(*oilWaterConfig,
348 *epsImbGridProperties,
352 auto [gasWaterScaledImbInfo, gasWaterScaledImbPoint] =
353 readScaledPoints_(*gasWaterConfig,
355 *epsImbGridProperties,
359 unsigned imbRegionIdx = imbnumRegionArray_[elemIdx];
360 if (hasGas && hasOil) {
361 GasOilEpsTwoPhaseParams gasOilImbParamsHyst;
362 gasOilImbParamsHyst.setConfig(gasOilConfig);
363 gasOilImbParamsHyst.setUnscaledPoints(gasOilUnscaledPointsVector_[imbRegionIdx]);
364 gasOilImbParamsHyst.setScaledPoints(gasOilScaledImbPoint);
365 gasOilImbParamsHyst.setEffectiveLawParams(gasOilEffectiveParamVector_[imbRegionIdx]);
366 gasOilImbParamsHyst.finalize();
368 gasOilParams->setImbibitionParams(gasOilImbParamsHyst,
373 if (hasOil && hasWater) {
374 OilWaterEpsTwoPhaseParams oilWaterImbParamsHyst;
375 oilWaterImbParamsHyst.setConfig(oilWaterConfig);
376 oilWaterImbParamsHyst.setUnscaledPoints(oilWaterUnscaledPointsVector_[imbRegionIdx]);
377 oilWaterImbParamsHyst.setScaledPoints(oilWaterScaledImbPoint);
378 oilWaterImbParamsHyst.setEffectiveLawParams(oilWaterEffectiveParamVector_[imbRegionIdx]);
379 oilWaterImbParamsHyst.finalize();
381 oilWaterParams->setImbibitionParams(oilWaterImbParamsHyst,
382 oilWaterScaledImbInfo,
386 if (hasGas && hasWater && !hasOil) {
387 GasWaterEpsTwoPhaseParams gasWaterImbParamsHyst;
388 gasWaterImbParamsHyst.setConfig(gasWaterConfig);
389 gasWaterImbParamsHyst.setUnscaledPoints(gasWaterUnscaledPointsVector_[imbRegionIdx]);
390 gasWaterImbParamsHyst.setScaledPoints(gasWaterScaledImbPoint);
391 gasWaterImbParamsHyst.setEffectiveLawParams(gasWaterEffectiveParamVector_[imbRegionIdx]);
392 gasWaterImbParamsHyst.finalize();
394 gasWaterParams->setImbibitionParams(gasWaterImbParamsHyst,
395 gasWaterScaledImbInfo,
400 if (hasGas && hasOil)
401 gasOilParams->finalize();
403 if (hasOil && hasWater)
404 oilWaterParams->finalize();
406 if (hasGas && hasWater && !hasOil)
407 gasWaterParams->finalize();
409 initThreePhaseParams_(eclState,
410 materialLawParams_[elemIdx],
412 oilWaterScaledEpsInfoDrainage_[elemIdx],
417 materialLawParams_[elemIdx].finalize();
434 auto& elemScaledEpsInfo = oilWaterScaledEpsInfoDrainage_[elemIdx];
439 Sw = elemScaledEpsInfo.Swu;
442 if (Sw <= elemScaledEpsInfo.Swl)
443 Sw = elemScaledEpsInfo.Swl;
459 fs.setSaturation(waterPhaseIdx, Sw);
460 fs.setSaturation(gasPhaseIdx, 0);
461 fs.setSaturation(oilPhaseIdx, 0);
462 std::array<Scalar, numPhases> pc = { 0 };
465 Scalar pcowAtSw = pc[oilPhaseIdx] - pc[waterPhaseIdx];
466 constexpr const Scalar pcowAtSwThreshold = 1.0;
468 if (
std::abs(pcowAtSw) > pcowAtSwThreshold) {
469 elemScaledEpsInfo.maxPcow *= pcow/pcowAtSw;
471 elemEclEpsScalingPoints.init(elemScaledEpsInfo, *oilWaterEclEpsConfig_,
EclOilWaterSystem);
479 {
return enableEndPointScaling_; }
482 {
return hysteresisConfig_->enableHysteresis(); }
486 assert(elemIdx < materialLawParams_.size());
487 return materialLawParams_[elemIdx];
492 assert(elemIdx < materialLawParams_.size());
493 return materialLawParams_[elemIdx];
510 OpmLog::warning(
"Warning: Using non-default satnum regions for connection is not tested in combination with hysteresis");
516 switch (mlp.approach()) {
518 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclStone1Approach>();
520 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
521 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
522 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
523 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
534 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclStone2Approach>();
535 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
536 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
537 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
538 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
549 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclDefaultApproach>();
550 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
551 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
552 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
553 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
564 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclTwoPhaseApproach>();
565 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
566 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
567 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
568 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
579 throw std::logic_error(
"Enum value for material approach unknown!");
586 {
return satnumRegionArray_[elemIdx]; }
589 using Dir = FaceDir::DirEnum;
590 const std::vector<int>* array =
nullptr;
593 array = &krnumXArray_;
596 array = &krnumYArray_;
599 array = &krnumZArray_;
602 throw std::runtime_error(
"Unknown face direction");
604 if (array->size() > 0) {
605 return (*array)[elemIdx];
608 return satnumRegionArray_[elemIdx];
612 if (krnumXArray_.size() > 0 || krnumYArray_.size() > 0 || krnumZArray_.size() > 0) {
618 {
return imbnumRegionArray_[elemIdx]; }
622 assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
623 return materialLawParams_[elemIdx];
626 template <
class Flu
idState>
637 unsigned elemIdx)
const
640 throw std::runtime_error(
"Cannot get hysteresis parameters if hysteresis not enabled.");
647 const Scalar& krnSwMdc,
651 throw std::runtime_error(
"Cannot set hysteresis parameters if hysteresis not enabled.");
659 unsigned elemIdx)
const
662 throw std::runtime_error(
"Cannot get hysteresis parameters if hysteresis not enabled.");
669 const Scalar& krnSwMdc,
673 throw std::runtime_error(
"Cannot set hysteresis parameters if hysteresis not enabled.");
681 auto& materialParams = materialLawParams_[elemIdx];
682 switch (materialParams.approach()) {
684 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone1Approach>();
685 return realParams.oilWaterParams().drainageParams().scaledPoints();
689 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone2Approach>();
690 return realParams.oilWaterParams().drainageParams().scaledPoints();
694 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclDefaultApproach>();
695 return realParams.oilWaterParams().drainageParams().scaledPoints();
699 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclTwoPhaseApproach>();
700 return realParams.oilWaterParams().drainageParams().scaledPoints();
703 throw std::logic_error(
"Enum value for material approach unknown!");
708 {
return oilWaterScaledEpsInfoDrainage_[elemIdx]; }
711 void readGlobalEpsOptions_(
const EclipseState& eclState)
713 oilWaterEclEpsConfig_ = std::make_shared<EclEpsConfig>();
716 enableEndPointScaling_ = eclState.getTableManager().hasTables(
"ENKRVD");
719 void readGlobalHysteresisOptions_(
const EclipseState& state)
721 hysteresisConfig_ = std::make_shared<EclHysteresisConfig>();
722 hysteresisConfig_->initFromState(state.runspec());
725 void readGlobalThreePhaseOptions_(
const Runspec& runspec)
727 bool gasEnabled = runspec.phases().active(Phase::GAS);
728 bool oilEnabled = runspec.phases().active(Phase::OIL);
729 bool waterEnabled = runspec.phases().active(Phase::WATER);
734 + (waterEnabled?1:0);
736 if (numEnabled == 0) {
737 throw std::runtime_error(
"At least one fluid phase must be enabled. (Is: "+std::to_string(numEnabled)+
")");
738 }
else if (numEnabled == 1) {
740 }
else if ( numEnabled == 2) {
744 else if (!oilEnabled)
746 else if (!waterEnabled)
750 assert(numEnabled == 3);
753 const auto& satctrls = runspec.saturationFunctionControls();
754 if (satctrls.krModel() == SatFuncControls::ThreePhaseOilKrModel::Stone2)
756 else if (satctrls.krModel() == SatFuncControls::ThreePhaseOilKrModel::Stone1)
761 template <
class Container>
762 void readGasOilEffectiveParameters_(Container& dest,
763 const EclipseState& eclState,
764 unsigned satRegionIdx)
766 if (!hasGas || !hasOil)
770 dest[satRegionIdx] = std::make_shared<GasOilEffectiveTwoPhaseParams>();
772 auto& effParams = *dest[satRegionIdx];
776 const Scalar Swco = unscaledEpsInfo_[satRegionIdx].Swl;
777 const auto tolcrit = eclState.runspec().saturationFunctionControls()
778 .minimumRelpermMobilityThreshold();
780 const auto& tableManager = eclState.getTableManager();
782 switch (eclState.runspec().saturationFunctionControls().family()) {
783 case SatFuncControls::KeywordFamily::Family_I:
785 const TableContainer& sgofTables = tableManager.getSgofTables();
786 const TableContainer& slgofTables = tableManager.getSlgofTables();
787 if (!sgofTables.empty())
788 readGasOilEffectiveParametersSgof_(effParams, Swco, tolcrit,
789 sgofTables.getTable<SgofTable>(satRegionIdx));
790 else if (!slgofTables.empty())
791 readGasOilEffectiveParametersSlgof_(effParams, Swco, tolcrit,
792 slgofTables.getTable<SlgofTable>(satRegionIdx));
793 else if ( !tableManager.getSgofletTable().empty() ) {
794 const auto& letSgofTab = tableManager.getSgofletTable()[satRegionIdx];
795 const std::vector<Scalar> dum;
798 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::LETApproach>();
801 const Scalar s_min_w = letSgofTab.s2_critical;
802 const Scalar s_max_w = 1.0-letSgofTab.s1_critical-Swco;
803 const std::vector<Scalar>& letCoeffsOil = {s_min_w, s_max_w,
804 static_cast<Scalar
>(letSgofTab.l2_relperm),
805 static_cast<Scalar
>(letSgofTab.e2_relperm),
806 static_cast<Scalar
>(letSgofTab.t2_relperm),
807 static_cast<Scalar
>(letSgofTab.krt2_relperm)};
808 realParams.setKrwSamples(letCoeffsOil, dum);
811 const Scalar s_min_nw = letSgofTab.s1_critical+Swco;
812 const Scalar s_max_nw = 1.0-letSgofTab.s2_critical;
813 const std::vector<Scalar>& letCoeffsGas = {s_min_nw, s_max_nw,
814 static_cast<Scalar
>(letSgofTab.l1_relperm),
815 static_cast<Scalar
>(letSgofTab.e1_relperm),
816 static_cast<Scalar
>(letSgofTab.t1_relperm),
817 static_cast<Scalar
>(letSgofTab.krt1_relperm)};
818 realParams.setKrnSamples(letCoeffsGas, dum);
821 const std::vector<Scalar>& letCoeffsPc = {
static_cast<Scalar
>(letSgofTab.s2_residual),
822 static_cast<Scalar
>(letSgofTab.s1_residual+Swco),
823 static_cast<Scalar
>(letSgofTab.l_pc),
824 static_cast<Scalar
>(letSgofTab.e_pc),
825 static_cast<Scalar
>(letSgofTab.t_pc),
826 static_cast<Scalar
>(letSgofTab.pcir_pc),
827 static_cast<Scalar
>(letSgofTab.pct_pc)};
828 realParams.setPcnwSamples(letCoeffsPc, dum);
830 realParams.finalize();
835 case SatFuncControls::KeywordFamily::Family_II:
837 const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
840 const Sof2Table& sof2Table = tableManager.getSof2Tables().getTable<Sof2Table>( satRegionIdx );
841 readGasOilEffectiveParametersFamily2_(effParams, Swco, tolcrit, sof2Table, sgfnTable);
844 const Sof3Table& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>( satRegionIdx );
845 readGasOilEffectiveParametersFamily2_(effParams, Swco, tolcrit, sof3Table, sgfnTable);
850 case SatFuncControls::KeywordFamily::Undefined:
851 throw std::domain_error(
"No valid saturation keyword family specified");
855 void readGasOilEffectiveParametersSgof_(GasOilEffectiveTwoPhaseParams& effParams,
857 const double tolcrit,
858 const SgofTable& sgofTable)
861 std::vector<double> SoSamples(sgofTable.numRows());
862 for (
size_t sampleIdx = 0; sampleIdx < sgofTable.numRows(); ++ sampleIdx) {
863 SoSamples[sampleIdx] = (1.0 - Swco) - sgofTable.get(
"SG", sampleIdx);
867 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::PiecewiseLinearApproach>();
869 realParams.setKrwSamples(SoSamples, normalizeKrValues_(tolcrit, sgofTable.getColumn(
"KROG")));
870 realParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, sgofTable.getColumn(
"KRG")));
871 realParams.setPcnwSamples(SoSamples, sgofTable.getColumn(
"PCOG").vectorCopy());
872 realParams.finalize();
875 void readGasOilEffectiveParametersSlgof_(GasOilEffectiveTwoPhaseParams& effParams,
877 const double tolcrit,
878 const SlgofTable& slgofTable)
881 std::vector<double> SoSamples(slgofTable.numRows());
882 for (
size_t sampleIdx = 0; sampleIdx < slgofTable.numRows(); ++ sampleIdx) {
883 SoSamples[sampleIdx] = slgofTable.get(
"SL", sampleIdx) - Swco;
887 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::PiecewiseLinearApproach>();
889 realParams.setKrwSamples(SoSamples, normalizeKrValues_(tolcrit, slgofTable.getColumn(
"KROG")));
890 realParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, slgofTable.getColumn(
"KRG")));
891 realParams.setPcnwSamples(SoSamples, slgofTable.getColumn(
"PCOG").vectorCopy());
892 realParams.finalize();
895 void readGasOilEffectiveParametersFamily2_(GasOilEffectiveTwoPhaseParams& effParams,
897 const double tolcrit,
898 const Sof3Table& sof3Table,
899 const SgfnTable& sgfnTable)
902 std::vector<double> SoSamples(sgfnTable.numRows());
903 std::vector<double> SoColumn = sof3Table.getColumn(
"SO").vectorCopy();
904 for (
size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) {
905 SoSamples[sampleIdx] = (1.0 - Swco) - sgfnTable.get(
"SG", sampleIdx);
909 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::PiecewiseLinearApproach>();
911 realParams.setKrwSamples(SoColumn, normalizeKrValues_(tolcrit, sof3Table.getColumn(
"KROG")));
912 realParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, sgfnTable.getColumn(
"KRG")));
913 realParams.setPcnwSamples(SoSamples, sgfnTable.getColumn(
"PCOG").vectorCopy());
914 realParams.finalize();
917 void readGasOilEffectiveParametersFamily2_(GasOilEffectiveTwoPhaseParams& effParams,
919 const double tolcrit,
920 const Sof2Table& sof2Table,
921 const SgfnTable& sgfnTable)
924 std::vector<double> SoSamples(sgfnTable.numRows());
925 std::vector<double> SoColumn = sof2Table.getColumn(
"SO").vectorCopy();
926 for (
size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) {
927 SoSamples[sampleIdx] = (1.0 - Swco) - sgfnTable.get(
"SG", sampleIdx);
931 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::PiecewiseLinearApproach>();
933 realParams.setKrwSamples(SoColumn, normalizeKrValues_(tolcrit, sof2Table.getColumn(
"KRO")));
934 realParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, sgfnTable.getColumn(
"KRG")));
935 realParams.setPcnwSamples(SoSamples, sgfnTable.getColumn(
"PCOG").vectorCopy());
936 realParams.finalize();
939 template <
class Container>
940 void readOilWaterEffectiveParameters_(Container& dest,
941 const EclipseState& eclState,
942 unsigned satRegionIdx)
944 if (!hasOil || !hasWater)
948 dest[satRegionIdx] = std::make_shared<OilWaterEffectiveTwoPhaseParams>();
950 const auto tolcrit = eclState.runspec().saturationFunctionControls()
951 .minimumRelpermMobilityThreshold();
953 const auto& tableManager = eclState.getTableManager();
954 auto& effParams = *dest[satRegionIdx];
956 switch (eclState.runspec().saturationFunctionControls().family()) {
957 case SatFuncControls::KeywordFamily::Family_I:
959 if (tableManager.hasTables(
"SWOF")) {
960 const auto& swofTable = tableManager.getSwofTables().getTable<SwofTable>(satRegionIdx);
961 const std::vector<double> SwColumn = swofTable.getColumn(
"SW").vectorCopy();
964 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::PiecewiseLinearApproach>();
966 realParams.setKrwSamples(SwColumn, normalizeKrValues_(tolcrit, swofTable.getColumn(
"KRW")));
967 realParams.setKrnSamples(SwColumn, normalizeKrValues_(tolcrit, swofTable.getColumn(
"KROW")));
968 realParams.setPcnwSamples(SwColumn, swofTable.getColumn(
"PCOW").vectorCopy());
969 realParams.finalize();
971 else if ( !tableManager.getSwofletTable().empty() ) {
972 const auto& letTab = tableManager.getSwofletTable()[satRegionIdx];
973 const std::vector<Scalar> dum;
976 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::LETApproach>();
979 const Scalar s_min_w = letTab.s1_critical;
980 const Scalar s_max_w = 1.0-letTab.s2_critical;
981 const std::vector<Scalar>& letCoeffsWat = {s_min_w, s_max_w,
982 static_cast<Scalar
>(letTab.l1_relperm),
983 static_cast<Scalar
>(letTab.e1_relperm),
984 static_cast<Scalar
>(letTab.t1_relperm),
985 static_cast<Scalar
>(letTab.krt1_relperm)};
986 realParams.setKrwSamples(letCoeffsWat, dum);
989 const Scalar s_min_nw = letTab.s2_critical;
990 const Scalar s_max_nw = 1.0-letTab.s1_critical;
991 const std::vector<Scalar>& letCoeffsOil = {s_min_nw, s_max_nw,
992 static_cast<Scalar
>(letTab.l2_relperm),
993 static_cast<Scalar
>(letTab.e2_relperm),
994 static_cast<Scalar
>(letTab.t2_relperm),
995 static_cast<Scalar
>(letTab.krt2_relperm)};
996 realParams.setKrnSamples(letCoeffsOil, dum);
999 const std::vector<Scalar>& letCoeffsPc = {
static_cast<Scalar
>(letTab.s1_residual),
1000 static_cast<Scalar
>(letTab.s2_residual),
1001 static_cast<Scalar
>(letTab.l_pc),
1002 static_cast<Scalar
>(letTab.e_pc),
1003 static_cast<Scalar
>(letTab.t_pc),
1004 static_cast<Scalar
>(letTab.pcir_pc),
1005 static_cast<Scalar
>(letTab.pct_pc)};
1006 realParams.setPcnwSamples(letCoeffsPc, dum);
1008 realParams.finalize();
1013 case SatFuncControls::KeywordFamily::Family_II:
1015 const auto& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>(satRegionIdx);
1016 const std::vector<double> SwColumn = swfnTable.getColumn(
"SW").vectorCopy();
1019 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::PiecewiseLinearApproach>();
1021 realParams.setKrwSamples(SwColumn, normalizeKrValues_(tolcrit, swfnTable.getColumn(
"KRW")));
1022 realParams.setPcnwSamples(SwColumn, swfnTable.getColumn(
"PCOW").vectorCopy());
1025 const auto& sof2Table = tableManager.getSof2Tables().getTable<Sof2Table>(satRegionIdx);
1027 std::vector<double> SwSamples(sof2Table.numRows());
1028 for (
size_t sampleIdx = 0; sampleIdx < sof2Table.numRows(); ++ sampleIdx)
1029 SwSamples[sampleIdx] = 1 - sof2Table.get(
"SO", sampleIdx);
1031 realParams.setKrnSamples(SwSamples, normalizeKrValues_(tolcrit, sof2Table.getColumn(
"KRO")));
1033 const auto& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>(satRegionIdx);
1035 std::vector<double> SwSamples(sof3Table.numRows());
1036 for (
size_t sampleIdx = 0; sampleIdx < sof3Table.numRows(); ++ sampleIdx)
1037 SwSamples[sampleIdx] = 1 - sof3Table.get(
"SO", sampleIdx);
1039 realParams.setKrnSamples(SwSamples, normalizeKrValues_(tolcrit, sof3Table.getColumn(
"KROW")));
1041 realParams.finalize();
1045 case SatFuncControls::KeywordFamily::Undefined:
1046 throw std::domain_error(
"No valid saturation keyword family specified");
1050 template <
class Container>
1051 void readGasWaterEffectiveParameters_(Container& dest,
1052 const EclipseState& eclState,
1053 unsigned satRegionIdx)
1055 if (!hasGas || !hasWater || hasOil)
1059 dest[satRegionIdx] = std::make_shared<GasWaterEffectiveTwoPhaseParams>();
1061 auto& effParams = *dest[satRegionIdx];
1063 const auto tolcrit = eclState.runspec().saturationFunctionControls()
1064 .minimumRelpermMobilityThreshold();
1066 const auto& tableManager = eclState.getTableManager();
1068 switch (eclState.runspec().saturationFunctionControls().family()) {
1069 case SatFuncControls::KeywordFamily::Family_I:
1071 throw std::domain_error(
"Saturation keyword family I is not applicable for a gas-water system");
1074 case SatFuncControls::KeywordFamily::Family_II:
1077 const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
1078 const SwfnTable& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>( satRegionIdx );
1081 auto& realParams = effParams.template getRealParams<SatCurveMultiplexerApproach::PiecewiseLinearApproach>();
1083 std::vector<double> SwColumn = swfnTable.getColumn(
"SW").vectorCopy();
1085 realParams.setKrwSamples(SwColumn, normalizeKrValues_(tolcrit, swfnTable.getColumn(
"KRW")));
1086 std::vector<double> SwSamples(sgfnTable.numRows());
1087 for (
size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx)
1088 SwSamples[sampleIdx] = 1 - sgfnTable.get(
"SG", sampleIdx);
1089 realParams.setKrnSamples(SwSamples, normalizeKrValues_(tolcrit, sgfnTable.getColumn(
"KRG")));
1092 realParams.setPcnwSamples(SwColumn, swfnTable.getColumn(
"PCOW").vectorCopy());
1093 realParams.finalize();
1098 case SatFuncControls::KeywordFamily::Undefined:
1099 throw std::domain_error(
"No valid saturation keyword family specified");
1103 template <
class Container>
1104 void readGasOilUnscaledPoints_(Container& dest,
1105 std::shared_ptr<EclEpsConfig> config,
1106 const EclipseState& ,
1107 unsigned satRegionIdx)
1109 if (!hasGas || !hasOil)
1113 dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1114 dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config,
EclGasOilSystem);
1117 template <
class Container>
1118 void readOilWaterUnscaledPoints_(Container& dest,
1119 std::shared_ptr<EclEpsConfig> config,
1120 const EclipseState& ,
1121 unsigned satRegionIdx)
1123 if (!hasOil || !hasWater)
1127 dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1128 dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config,
EclOilWaterSystem);
1131 template <
class Container>
1132 void readGasWaterUnscaledPoints_(Container& dest,
1133 std::shared_ptr<EclEpsConfig> config,
1134 const EclipseState& ,
1135 unsigned satRegionIdx)
1141 dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1142 dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config,
EclGasWaterSystem);
1145 std::tuple<EclEpsScalingPointsInfo<Scalar>,
1146 EclEpsScalingPoints<Scalar>>
1147 readScaledPoints_(
const EclEpsConfig& config,
1148 const EclipseState& eclState,
1149 const EclEpsGridProperties& epsGridProperties,
1153 unsigned satRegionIdx = epsGridProperties.satRegion( elemIdx );
1155 EclEpsScalingPointsInfo<Scalar> destInfo(unscaledEpsInfo_[satRegionIdx]);
1156 destInfo.extractScaled(eclState, epsGridProperties, elemIdx);
1158 EclEpsScalingPoints<Scalar> destPoint;
1159 destPoint.init(destInfo, config, type);
1161 return {destInfo, destPoint};
1164 void initThreePhaseParams_(
const EclipseState& ,
1166 unsigned satRegionIdx,
1167 const EclEpsScalingPointsInfo<Scalar>& epsInfo,
1168 std::shared_ptr<OilWaterTwoPhaseHystParams> oilWaterParams,
1169 std::shared_ptr<GasOilTwoPhaseHystParams> gasOilParams,
1170 std::shared_ptr<GasWaterTwoPhaseHystParams> gasWaterParams)
1172 materialParams.setApproach(threePhaseApproach_);
1174 switch (materialParams.approach()) {
1176 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone1Approach>();
1177 realParams.setGasOilParams(gasOilParams);
1178 realParams.setOilWaterParams(oilWaterParams);
1179 realParams.setSwl(epsInfo.Swl);
1181 if (!stoneEtas.empty()) {
1182 realParams.setEta(stoneEtas[satRegionIdx]);
1185 realParams.setEta(1.0);
1186 realParams.finalize();
1191 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone2Approach>();
1192 realParams.setGasOilParams(gasOilParams);
1193 realParams.setOilWaterParams(oilWaterParams);
1194 realParams.setSwl(epsInfo.Swl);
1195 realParams.finalize();
1200 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclDefaultApproach>();
1201 realParams.setGasOilParams(gasOilParams);
1202 realParams.setOilWaterParams(oilWaterParams);
1203 realParams.setSwl(epsInfo.Swl);
1204 realParams.finalize();
1209 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclTwoPhaseApproach>();
1210 realParams.setGasOilParams(gasOilParams);
1211 realParams.setOilWaterParams(oilWaterParams);
1212 realParams.setGasWaterParams(gasWaterParams);
1213 realParams.setApproach(twoPhaseApproach_);
1214 realParams.finalize();
1226 std::vector<double> normalizeKrValues_(
const double tolcrit,
1227 const TableColumn& krValues)
const
1229 auto kr = krValues.vectorCopy();
1230 std::transform(kr.begin(), kr.end(), kr.begin(),
1231 [tolcrit](
const double kri)
1233 return (kri > tolcrit) ? kri : 0.0;
1239 bool enableEndPointScaling_;
1240 std::shared_ptr<EclHysteresisConfig> hysteresisConfig_;
1242 std::shared_ptr<EclEpsConfig> oilWaterEclEpsConfig_;
1243 std::vector<EclEpsScalingPointsInfo<Scalar>> unscaledEpsInfo_;
1244 OilWaterScalingInfoVector oilWaterScaledEpsInfoDrainage_;
1246 std::shared_ptr<EclEpsConfig> gasWaterEclEpsConfig_;
1248 GasOilScalingPointsVector gasOilUnscaledPointsVector_;
1249 OilWaterScalingPointsVector oilWaterUnscaledPointsVector_;
1250 GasWaterScalingPointsVector gasWaterUnscaledPointsVector_;
1252 GasOilEffectiveParamVector gasOilEffectiveParamVector_;
1253 OilWaterEffectiveParamVector oilWaterEffectiveParamVector_;
1254 GasWaterEffectiveParamVector gasWaterEffectiveParamVector_;
1260 std::vector<MaterialLawParams> materialLawParams_;
1262 std::vector<int> satnumRegionArray_;
1263 std::vector<int> krnumXArray_;
1264 std::vector<int> krnumYArray_;
1265 std::vector<int> krnumZArray_;
1266 std::vector<int> imbnumRegionArray_;
1267 std::vector<Scalar> stoneEtas;
1273 std::shared_ptr<EclEpsConfig> gasOilConfig;
1274 std::shared_ptr<EclEpsConfig> oilWaterConfig;
1275 std::shared_ptr<EclEpsConfig> gasWaterConfig;
This file contains helper classes for the material laws.
Collects all grid properties which are relevant for end point scaling.
Definition: EclEpsGridProperties.hpp:69
Represents the points on the X and Y axis to be scaled if endpoint scaling is used.
Definition: EclEpsScalingPoints.hpp:306
This material law takes a material law defined for unscaled saturation and converts it to a material ...
Definition: EclEpsTwoPhaseLaw.hpp:51
ParamsT Params
Definition: EclEpsTwoPhaseLaw.hpp:56
This material law implements the hysteresis model of the ECL file format.
Definition: EclHysteresisTwoPhaseLaw.hpp:44
ParamsT Params
Definition: EclHysteresisTwoPhaseLaw.hpp:50
Provides an simple way to create and manage the material law objects for a complete ECL deck.
Definition: EclMaterialLawManager.hpp:70
bool enableEndPointScaling() const
Definition: EclMaterialLawManager.hpp:478
int satnumRegionIdx(unsigned elemIdx) const
Definition: EclMaterialLawManager.hpp:585
std::shared_ptr< MaterialLawParams > & materialLawParamsPointerReferenceHack(unsigned elemIdx)
Definition: EclMaterialLawManager.hpp:620
void initFromState(const EclipseState &eclState)
Definition: EclMaterialLawManager.hpp:132
void setOilWaterHysteresisParams(const Scalar &pcSwMdc, const Scalar &krnSwMdc, unsigned elemIdx)
Definition: EclMaterialLawManager.hpp:646
EclMaterialLawManager()
Definition: EclMaterialLawManager.hpp:129
bool enableHysteresis() const
Definition: EclMaterialLawManager.hpp:481
typename MaterialLaw::Params MaterialLawParams
Definition: EclMaterialLawManager.hpp:111
EclEpsScalingPoints< Scalar > & oilWaterScaledEpsPointsDrainage(unsigned elemIdx)
Definition: EclMaterialLawManager.hpp:679
bool hasDirectionalRelperms() const
Definition: EclMaterialLawManager.hpp:611
MaterialLawParams & materialLawParams(unsigned elemIdx)
Definition: EclMaterialLawManager.hpp:484
int getKrnumSatIdx(unsigned elemIdx, FaceDir::DirEnum facedir) const
Definition: EclMaterialLawManager.hpp:588
void updateHysteresis(const FluidState &fluidState, unsigned elemIdx)
Definition: EclMaterialLawManager.hpp:627
void initParamsForElements(const EclipseState &eclState, size_t numCompressedElems)
Definition: EclMaterialLawManager.hpp:191
int imbnumRegionIdx(unsigned elemIdx) const
Definition: EclMaterialLawManager.hpp:617
const MaterialLawParams & connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const
Returns a material parameter object for a given element and saturation region.
Definition: EclMaterialLawManager.hpp:504
void setGasOilHysteresisParams(const Scalar &pcSwMdc, const Scalar &krnSwMdc, unsigned elemIdx)
Definition: EclMaterialLawManager.hpp:668
void oilWaterHysteresisParams(Scalar &pcSwMdc, Scalar &krnSwMdc, unsigned elemIdx) const
Definition: EclMaterialLawManager.hpp:635
Scalar applySwatinit(unsigned elemIdx, Scalar pcow, Scalar Sw)
Modify the initial condition according to the SWATINIT keyword.
Definition: EclMaterialLawManager.hpp:430
void gasOilHysteresisParams(Scalar &pcSwMdc, Scalar &krnSwMdc, unsigned elemIdx) const
Definition: EclMaterialLawManager.hpp:657
const EclEpsScalingPointsInfo< Scalar > & oilWaterScaledEpsInfoDrainage(size_t elemIdx) const
Definition: EclMaterialLawManager.hpp:707
const MaterialLawParams & materialLawParams(unsigned elemIdx) const
Definition: EclMaterialLawManager.hpp:490
Implements a multiplexer class that provides all three phase capillary pressure laws used by the ECLi...
Definition: EclMultiplexerMaterial.hpp:56
static void capillaryPressures(ContainerT &values, const Params ¶ms, const FluidState &fluidState)
Implements the multiplexer three phase capillary pressure law used by the ECLipse simulator.
Definition: EclMultiplexerMaterial.hpp:133
static void oilWaterHysteresisParams(Scalar &pcSwMdc, Scalar &krnSwMdc, const Params ¶ms)
Definition: EclMultiplexerMaterial.hpp:174
static void gasOilHysteresisParams(Scalar &pcSwMdc, Scalar &krnSwMdc, const Params ¶ms)
Definition: EclMultiplexerMaterial.hpp:248
static void updateHysteresis(Params ¶ms, const FluidState &fluidState)
Update the hysteresis parameters after a time step.
Definition: EclMultiplexerMaterial.hpp:543
static void setOilWaterHysteresisParams(const Scalar &pcSwMdc, const Scalar &krnSwMdc, Params ¶ms)
Definition: EclMultiplexerMaterial.hpp:211
ParamsT Params
Definition: EclMultiplexerMaterial.hpp:86
static void setGasOilHysteresisParams(const Scalar &pcSwMdc, const Scalar &krnSwMdc, Params ¶ms)
Definition: EclMultiplexerMaterial.hpp:285
Implements a multiplexer class that provides LET curves and piecewise linear saturation functions.
Definition: SatCurveMultiplexer.hpp:44
ParamsT Params
Definition: SatCurveMultiplexer.hpp:47
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system assum...
Definition: SimpleModularFluidState.hpp:104
A generic traits class for two-phase material laws.
Definition: MaterialTraits.hpp:61
Definition: Air_Mesitylene.hpp:34
EclTwoPhaseSystemType
Specified which fluids are involved in a given twophase material law for endpoint scaling.
Definition: EclEpsConfig.hpp:43
@ EclGasOilSystem
Definition: EclEpsConfig.hpp:44
@ EclGasWaterSystem
Definition: EclEpsConfig.hpp:46
@ EclOilWaterSystem
Definition: EclEpsConfig.hpp:45
EclMultiplexerApproach
Definition: EclMultiplexerMaterialParams.hpp:43
EclTwoPhaseApproach
Definition: EclTwoPhaseMaterialParams.hpp:36
@ PiecewiseLinearApproach
Evaluation abs(const Evaluation &value)
Definition: MathToolbox.hpp:350
This structure represents all values which can be possibly used as scaling points in the endpoint sca...
Definition: EclEpsScalingPoints.hpp:60