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/parser/eclipse/EclipseState/EclipseState.hpp>
50 #include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
51 #include <opm/parser/eclipse/EclipseState/Tables/TableColumn.hpp>
67 template <
class TraitsT>
71 typedef TraitsT Traits;
72 typedef typename Traits::Scalar Scalar;
73 enum { waterPhaseIdx = Traits::wettingPhaseIdx };
74 enum { oilPhaseIdx = Traits::nonWettingPhaseIdx };
75 enum { gasPhaseIdx = Traits::gasPhaseIdx };
76 enum { numPhases = Traits::numPhases };
95 typedef typename GasOilEpsTwoPhaseLaw::Params GasOilEpsTwoPhaseParams;
96 typedef typename OilWaterEpsTwoPhaseLaw::Params OilWaterEpsTwoPhaseParams;
97 typedef typename GasWaterEpsTwoPhaseLaw::Params GasWaterEpsTwoPhaseParams;
103 typedef typename GasOilTwoPhaseLaw::Params GasOilTwoPhaseHystParams;
104 typedef typename OilWaterTwoPhaseLaw::Params OilWaterTwoPhaseHystParams;
105 typedef typename GasWaterTwoPhaseLaw::Params GasWaterTwoPhaseHystParams;
110 typedef typename MaterialLaw::Params MaterialLawParams;
114 typedef std::vector<std::shared_ptr<GasOilEffectiveTwoPhaseParams> > GasOilEffectiveParamVector;
115 typedef std::vector<std::shared_ptr<OilWaterEffectiveTwoPhaseParams> > OilWaterEffectiveParamVector;
116 typedef std::vector<std::shared_ptr<GasWaterEffectiveTwoPhaseParams> > GasWaterEffectiveParamVector;
118 typedef std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar> > > GasOilScalingPointsVector;
119 typedef std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar> > > OilWaterScalingPointsVector;
120 typedef std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar> > > GasWaterScalingPointsVector;
121 typedef std::vector<std::shared_ptr<EclEpsScalingPointsInfo<Scalar> > > GasOilScalingInfoVector;
122 typedef std::vector<std::shared_ptr<EclEpsScalingPointsInfo<Scalar> > > OilWaterScalingInfoVector;
123 typedef std::vector<std::shared_ptr<EclEpsScalingPointsInfo<Scalar> > > GasWaterScalingInfoVector;
124 typedef std::vector<std::shared_ptr<GasOilTwoPhaseHystParams> > GasOilParamVector;
125 typedef std::vector<std::shared_ptr<OilWaterTwoPhaseHystParams> > OilWaterParamVector;
126 typedef std::vector<std::shared_ptr<GasWaterTwoPhaseHystParams> > GasWaterParamVector;
127 typedef std::vector<std::shared_ptr<MaterialLawParams> > MaterialLawParamsVector;
133 void initFromState(
const EclipseState& eclState)
136 const auto& runspec = eclState.runspec();
137 const size_t numSatRegions = runspec.tabdims().getNumSatTables();
139 const auto& ph = runspec.phases();
140 this->hasGas = ph.active(Phase::GAS);
141 this->hasOil = ph.active(Phase::OIL);
142 this->hasWater = ph.active(Phase::WATER);
144 readGlobalEpsOptions_(eclState);
145 readGlobalHysteresisOptions_(eclState);
146 readGlobalThreePhaseOptions_(runspec);
149 gasOilConfig = std::make_shared<EclEpsConfig>();
150 oilWaterConfig = std::make_shared<EclEpsConfig>();
151 gasWaterConfig = std::make_shared<EclEpsConfig>();
152 gasOilConfig->initFromState(eclState, EclGasOilSystem);
153 oilWaterConfig->initFromState(eclState, EclOilWaterSystem);
154 gasWaterConfig->initFromState(eclState, EclGasWaterSystem);
157 const auto& tables = eclState.getTableManager();
160 const auto& stone1exTables = tables.getStone1exTable();
162 if (! stone1exTables.empty()) {
164 stoneEtas.reserve(numSatRegions);
166 for (
const auto& table : stone1exTables) {
167 stoneEtas.push_back(table.eta);
172 this->unscaledEpsInfo_.resize(numSatRegions);
174 if (this->hasGas + this->hasOil + this->hasWater == 1) {
180 const auto tolcrit = runspec.saturationFunctionControls()
181 .minimumRelpermMobilityThreshold();
183 const auto rtep = satfunc::getRawTableEndpoints(tables, ph, tolcrit);
184 const auto rfunc = satfunc::getRawFunctionValues(tables, ph, rtep);
186 for (
unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
187 this->unscaledEpsInfo_[satRegionIdx]
188 .extractUnscaled(rtep, rfunc, satRegionIdx);
192 void initParamsForElements(
const EclipseState& eclState,
size_t numCompressedElems)
195 const size_t numSatRegions = eclState.runspec().tabdims().getNumSatTables();
198 gasOilUnscaledPointsVector_.resize(numSatRegions);
199 oilWaterUnscaledPointsVector_.resize(numSatRegions);
200 gasWaterUnscaledPointsVector_.resize(numSatRegions);
202 gasOilEffectiveParamVector_.resize(numSatRegions);
203 oilWaterEffectiveParamVector_.resize(numSatRegions);
204 gasWaterEffectiveParamVector_.resize(numSatRegions);
205 for (
unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
207 readGasOilUnscaledPoints_(gasOilUnscaledPointsVector_, gasOilConfig, eclState, satRegionIdx);
208 readOilWaterUnscaledPoints_(oilWaterUnscaledPointsVector_, oilWaterConfig, eclState, satRegionIdx);
209 readGasWaterUnscaledPoints_(gasWaterUnscaledPointsVector_, gasWaterConfig, eclState, satRegionIdx);
212 readGasOilEffectiveParameters_(gasOilEffectiveParamVector_, eclState, satRegionIdx);
213 readOilWaterEffectiveParameters_(oilWaterEffectiveParamVector_, eclState, satRegionIdx);
214 readGasWaterEffectiveParameters_(gasWaterEffectiveParamVector_, eclState, satRegionIdx);
219 satnumRegionArray_.resize(numCompressedElems);
220 if (eclState.fieldProps().has_int(
"SATNUM")) {
221 const auto& satnumRawData = eclState.fieldProps().get_int(
"SATNUM");
222 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
223 satnumRegionArray_[elemIdx] = satnumRawData[elemIdx] - 1;
227 std::fill(satnumRegionArray_.begin(), satnumRegionArray_.end(), 0);
231 imbnumRegionArray_ = satnumRegionArray_;
232 if (eclState.fieldProps().has_int(
"IMBNUM")) {
233 const auto& imbnumRawData = eclState.fieldProps().get_int(
"IMBNUM");
234 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
235 imbnumRegionArray_[elemIdx] = imbnumRawData[elemIdx] - 1;
241 GasOilScalingInfoVector gasOilScaledInfoVector(numCompressedElems);
242 oilWaterScaledEpsInfoDrainage_.resize(numCompressedElems);
243 GasOilScalingInfoVector gasOilScaledImbInfoVector;
244 OilWaterScalingInfoVector oilWaterScaledImbInfoVector;
246 GasOilScalingPointsVector gasOilScaledPointsVector(numCompressedElems);
247 GasOilScalingPointsVector oilWaterScaledEpsPointsDrainage(numCompressedElems);
248 GasOilScalingPointsVector gasOilScaledImbPointsVector;
249 OilWaterScalingPointsVector oilWaterScaledImbPointsVector;
251 GasWaterScalingInfoVector gasWaterScaledInfoVector(numCompressedElems);
252 GasWaterScalingPointsVector gasWaterScaledPointsVector(numCompressedElems);
253 GasWaterScalingInfoVector gasWaterScaledImbInfoVector;
254 GasWaterScalingPointsVector gasWaterScaledImbPointsVector;
256 if (enableHysteresis()) {
257 gasOilScaledImbInfoVector.resize(numCompressedElems);
258 gasOilScaledImbPointsVector.resize(numCompressedElems);
259 oilWaterScaledImbInfoVector.resize(numCompressedElems);
260 oilWaterScaledImbPointsVector.resize(numCompressedElems);
261 gasWaterScaledImbInfoVector.resize(numCompressedElems);
262 gasWaterScaledImbPointsVector.resize(numCompressedElems);
267 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
268 readGasOilScaledPoints_(gasOilScaledInfoVector,
269 gasOilScaledPointsVector,
275 readOilWaterScaledPoints_(oilWaterScaledEpsInfoDrainage_,
276 oilWaterScaledEpsPointsDrainage,
282 readGasWaterScaledPoints_(gasWaterScaledInfoVector,
283 gasWaterScaledPointsVector,
291 if (enableHysteresis()) {
293 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
294 readGasOilScaledPoints_(gasOilScaledImbInfoVector,
295 gasOilScaledImbPointsVector,
298 epsImbGridProperties,
301 readOilWaterScaledPoints_(oilWaterScaledImbInfoVector,
302 oilWaterScaledImbPointsVector,
305 epsImbGridProperties,
308 readGasWaterScaledPoints_(gasWaterScaledImbInfoVector,
309 gasWaterScaledImbPointsVector,
312 epsImbGridProperties,
318 GasOilParamVector gasOilParams(numCompressedElems);
319 OilWaterParamVector oilWaterParams(numCompressedElems);
320 GasWaterParamVector gasWaterParams(numCompressedElems);
322 GasOilParamVector gasOilImbParams;
323 OilWaterParamVector oilWaterImbParams;
324 GasWaterParamVector gasWaterImbParams;
326 if (enableHysteresis()) {
327 gasOilImbParams.resize(numCompressedElems);
328 oilWaterImbParams.resize(numCompressedElems);
329 gasWaterImbParams.resize(numCompressedElems);
332 assert(numCompressedElems == satnumRegionArray_.size());
333 assert(!enableHysteresis() || numCompressedElems == imbnumRegionArray_.size());
334 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
335 unsigned satRegionIdx =
static_cast<unsigned>(satnumRegionArray_[elemIdx]);
337 gasOilParams[elemIdx] = std::make_shared<GasOilTwoPhaseHystParams>();
338 oilWaterParams[elemIdx] = std::make_shared<OilWaterTwoPhaseHystParams>();
339 gasWaterParams[elemIdx] = std::make_shared<GasWaterTwoPhaseHystParams>();
340 gasOilParams[elemIdx]->setConfig(hysteresisConfig_);
341 oilWaterParams[elemIdx]->setConfig(hysteresisConfig_);
342 gasWaterParams[elemIdx]->setConfig(hysteresisConfig_);
344 if (hasGas && hasOil) {
345 auto gasOilDrainParams = std::make_shared<GasOilEpsTwoPhaseParams>();
346 gasOilDrainParams->setConfig(gasOilConfig);
347 gasOilDrainParams->setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
348 gasOilDrainParams->setScaledPoints(gasOilScaledPointsVector[elemIdx]);
349 gasOilDrainParams->setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
350 gasOilDrainParams->finalize();
352 gasOilParams[elemIdx]->setDrainageParams(gasOilDrainParams,
353 *gasOilScaledInfoVector[elemIdx],
357 if (hasOil && hasWater) {
358 auto oilWaterDrainParams = std::make_shared<OilWaterEpsTwoPhaseParams>();
359 oilWaterDrainParams->setConfig(oilWaterConfig);
360 oilWaterDrainParams->setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
361 oilWaterDrainParams->setScaledPoints(oilWaterScaledEpsPointsDrainage[elemIdx]);
362 oilWaterDrainParams->setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
363 oilWaterDrainParams->finalize();
365 oilWaterParams[elemIdx]->setDrainageParams(oilWaterDrainParams,
366 *oilWaterScaledEpsInfoDrainage_[elemIdx],
370 if (hasGas && hasWater && !hasOil) {
371 auto gasWaterDrainParams = std::make_shared<GasWaterEpsTwoPhaseParams>();
372 gasWaterDrainParams->setConfig(gasWaterConfig);
373 gasWaterDrainParams->setUnscaledPoints(gasWaterUnscaledPointsVector_[satRegionIdx]);
374 gasWaterDrainParams->setScaledPoints(gasWaterScaledPointsVector[elemIdx]);
375 gasWaterDrainParams->setEffectiveLawParams(gasWaterEffectiveParamVector_[satRegionIdx]);
376 gasWaterDrainParams->finalize();
378 gasWaterParams[elemIdx]->setDrainageParams(gasWaterDrainParams,
379 *gasWaterScaledInfoVector[elemIdx],
384 if (enableHysteresis()) {
385 unsigned imbRegionIdx = imbnumRegionArray_[elemIdx];
387 if (hasGas && hasOil) {
388 auto gasOilImbParamsHyst = std::make_shared<GasOilEpsTwoPhaseParams>();
389 gasOilImbParamsHyst->setConfig(gasOilConfig);
390 gasOilImbParamsHyst->setUnscaledPoints(gasOilUnscaledPointsVector_[imbRegionIdx]);
391 gasOilImbParamsHyst->setScaledPoints(gasOilScaledImbPointsVector[elemIdx]);
392 gasOilImbParamsHyst->setEffectiveLawParams(gasOilEffectiveParamVector_[imbRegionIdx]);
393 gasOilImbParamsHyst->finalize();
395 gasOilParams[elemIdx]->setImbibitionParams(gasOilImbParamsHyst,
396 *gasOilScaledImbInfoVector[elemIdx],
400 if (hasOil && hasWater) {
401 auto oilWaterImbParamsHyst = std::make_shared<OilWaterEpsTwoPhaseParams>();
402 oilWaterImbParamsHyst->setConfig(oilWaterConfig);
403 oilWaterImbParamsHyst->setUnscaledPoints(oilWaterUnscaledPointsVector_[imbRegionIdx]);
404 oilWaterImbParamsHyst->setScaledPoints(oilWaterScaledImbPointsVector[elemIdx]);
405 oilWaterImbParamsHyst->setEffectiveLawParams(oilWaterEffectiveParamVector_[imbRegionIdx]);
406 oilWaterImbParamsHyst->finalize();
408 oilWaterParams[elemIdx]->setImbibitionParams(oilWaterImbParamsHyst,
409 *gasOilScaledImbInfoVector[elemIdx],
413 if (hasGas && hasWater && !hasOil) {
414 auto gasWaterImbParamsHyst = std::make_shared<GasWaterEpsTwoPhaseParams>();
415 gasWaterImbParamsHyst->setConfig(gasWaterConfig);
416 gasWaterImbParamsHyst->setUnscaledPoints(gasWaterUnscaledPointsVector_[imbRegionIdx]);
417 gasWaterImbParamsHyst->setScaledPoints(gasWaterScaledImbPointsVector[elemIdx]);
418 gasWaterImbParamsHyst->setEffectiveLawParams(gasWaterEffectiveParamVector_[imbRegionIdx]);
419 gasWaterImbParamsHyst->finalize();
421 gasWaterParams[elemIdx]->setImbibitionParams(gasWaterImbParamsHyst,
422 *gasWaterScaledImbInfoVector[elemIdx],
427 if (hasGas && hasOil)
428 gasOilParams[elemIdx]->finalize();
430 if (hasOil && hasWater)
431 oilWaterParams[elemIdx]->finalize();
433 if (hasGas && hasWater && !hasOil)
434 gasWaterParams[elemIdx]->finalize();
438 materialLawParams_.resize(numCompressedElems);
439 for (
unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
440 materialLawParams_[elemIdx] = std::make_shared<MaterialLawParams>();
441 unsigned satRegionIdx =
static_cast<unsigned>(satnumRegionArray_[elemIdx]);
443 initThreePhaseParams_(eclState,
444 *materialLawParams_[elemIdx],
446 *oilWaterScaledEpsInfoDrainage_[elemIdx],
447 oilWaterParams[elemIdx],
448 gasOilParams[elemIdx],
449 gasWaterParams[elemIdx]);
451 materialLawParams_[elemIdx]->finalize();
468 auto& elemScaledEpsInfo = *oilWaterScaledEpsInfoDrainage_[elemIdx];
473 Sw = elemScaledEpsInfo.Swu;
476 if (Sw <= elemScaledEpsInfo.Swl)
477 Sw = elemScaledEpsInfo.Swl;
493 fs.setSaturation(waterPhaseIdx, Sw);
494 fs.setSaturation(gasPhaseIdx, 0);
495 fs.setSaturation(oilPhaseIdx, 0);
496 Scalar pc[numPhases] = { 0 };
499 Scalar pcowAtSw = pc[oilPhaseIdx] - pc[waterPhaseIdx];
500 const Scalar pcowAtSwThreshold = 1.0;
502 if (std::abs(pcowAtSw) > pcowAtSwThreshold) {
503 elemScaledEpsInfo.maxPcow *= pcow/pcowAtSw;
504 auto& elemEclEpsScalingPoints = oilWaterScaledEpsPointsDrainage(elemIdx);
505 elemEclEpsScalingPoints.init(elemScaledEpsInfo, *oilWaterEclEpsConfig_, EclOilWaterSystem);
512 bool enableEndPointScaling()
const
513 {
return enableEndPointScaling_; }
515 bool enableHysteresis()
const
516 {
return hysteresisConfig_->enableHysteresis(); }
518 MaterialLawParams& materialLawParams(
unsigned elemIdx)
520 assert(elemIdx < materialLawParams_.size());
521 return *materialLawParams_[elemIdx];
524 const MaterialLawParams& materialLawParams(
unsigned elemIdx)
const
526 assert(elemIdx < materialLawParams_.size());
527 return *materialLawParams_[elemIdx];
540 MaterialLawParams& mlp = *materialLawParams_[elemIdx];
543 if (enableHysteresis())
544 OpmLog::warning(
"Warning: Using non-default satnum regions for connection is not tested in combination with hysteresis");
550 switch (mlp.approach()) {
551 case EclMultiplexerApproach::EclStone1Approach: {
552 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclStone1Approach>();
554 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
555 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
556 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
557 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
567 case EclMultiplexerApproach::EclStone2Approach: {
568 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclStone2Approach>();
569 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
570 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
571 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
572 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
582 case EclMultiplexerApproach::EclDefaultApproach: {
583 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclDefaultApproach>();
584 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
585 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
586 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
587 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
597 case EclMultiplexerApproach::EclTwoPhaseApproach: {
598 auto& realParams = mlp.template getRealParams<EclMultiplexerApproach::EclTwoPhaseApproach>();
599 realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
600 realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
601 realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
602 realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
613 throw std::logic_error(
"Enum value for material approach unknown!");
619 int satnumRegionIdx(
unsigned elemIdx)
const
620 {
return satnumRegionArray_[elemIdx]; }
622 int imbnumRegionIdx(
unsigned elemIdx)
const
623 {
return imbnumRegionArray_[elemIdx]; }
625 std::shared_ptr<MaterialLawParams>& materialLawParamsPointerReferenceHack(
unsigned elemIdx)
627 assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
628 return materialLawParams_[elemIdx];
631 template <
class Flu
idState>
632 void updateHysteresis(
const FluidState& fluidState,
unsigned elemIdx)
634 if (!enableHysteresis())
637 auto threePhaseParams = materialLawParams_[elemIdx];
641 void oilWaterHysteresisParams(Scalar& pcSwMdc,
643 unsigned elemIdx)
const
645 if (!enableHysteresis())
646 throw std::runtime_error(
"Cannot get hysteresis parameters if hysteresis not enabled.");
648 const auto& params = materialLawParams(elemIdx);
649 MaterialLaw::oilWaterHysteresisParams(pcSwMdc, krnSwMdc, params);
652 void setOilWaterHysteresisParams(
const Scalar& pcSwMdc,
653 const Scalar& krnSwMdc,
656 if (!enableHysteresis())
657 throw std::runtime_error(
"Cannot set hysteresis parameters if hysteresis not enabled.");
659 auto& params = materialLawParams(elemIdx);
660 MaterialLaw::setOilWaterHysteresisParams(pcSwMdc, krnSwMdc, params);
663 void gasOilHysteresisParams(Scalar& pcSwMdc,
665 unsigned elemIdx)
const
667 if (!enableHysteresis())
668 throw std::runtime_error(
"Cannot get hysteresis parameters if hysteresis not enabled.");
670 const auto& params = materialLawParams(elemIdx);
671 MaterialLaw::gasOilHysteresisParams(pcSwMdc, krnSwMdc, params);
674 void setGasOilHysteresisParams(
const Scalar& pcSwMdc,
675 const Scalar& krnSwMdc,
678 if (!enableHysteresis())
679 throw std::runtime_error(
"Cannot set hysteresis parameters if hysteresis not enabled.");
681 auto& params = materialLawParams(elemIdx);
682 MaterialLaw::setGasOilHysteresisParams(pcSwMdc, krnSwMdc, params);
685 EclEpsScalingPoints<Scalar>& oilWaterScaledEpsPointsDrainage(
unsigned elemIdx)
687 auto& materialParams = *materialLawParams_[elemIdx];
688 switch (materialParams.approach()) {
689 case EclMultiplexerApproach::EclStone1Approach: {
690 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone1Approach>();
691 return realParams.oilWaterParams().drainageParams().scaledPoints();
694 case EclMultiplexerApproach::EclStone2Approach: {
695 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone2Approach>();
696 return realParams.oilWaterParams().drainageParams().scaledPoints();
699 case EclMultiplexerApproach::EclDefaultApproach: {
700 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclDefaultApproach>();
701 return realParams.oilWaterParams().drainageParams().scaledPoints();
704 case EclMultiplexerApproach::EclTwoPhaseApproach: {
705 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclTwoPhaseApproach>();
706 return realParams.oilWaterParams().drainageParams().scaledPoints();
709 throw std::logic_error(
"Enum value for material approach unknown!");
713 const EclEpsScalingPointsInfo<Scalar>& oilWaterScaledEpsInfoDrainage(
size_t elemIdx)
const
714 {
return *oilWaterScaledEpsInfoDrainage_[elemIdx]; }
716 std::shared_ptr<EclEpsScalingPointsInfo<Scalar> >& oilWaterScaledEpsInfoDrainagePointerReferenceHack(
unsigned elemIdx)
717 {
return oilWaterScaledEpsInfoDrainage_[elemIdx]; }
720 void readGlobalEpsOptions_(
const EclipseState& eclState)
722 oilWaterEclEpsConfig_ = std::make_shared<EclEpsConfig>();
723 oilWaterEclEpsConfig_->initFromState(eclState, EclOilWaterSystem);
725 enableEndPointScaling_ = eclState.getTableManager().hasTables(
"ENKRVD");
728 void readGlobalHysteresisOptions_(
const EclipseState& state)
730 hysteresisConfig_ = std::make_shared<EclHysteresisConfig>();
731 hysteresisConfig_->initFromState(state.runspec());
734 void readGlobalThreePhaseOptions_(
const Runspec& runspec)
736 bool gasEnabled = runspec.phases().active(Phase::GAS);
737 bool oilEnabled = runspec.phases().active(Phase::OIL);
738 bool waterEnabled = runspec.phases().active(Phase::WATER);
743 + (waterEnabled?1:0);
745 if (numEnabled == 0) {
746 throw std::runtime_error(
"At least one fluid phase must be enabled. (Is: "+std::to_string(numEnabled)+
")");
747 }
else if (numEnabled == 1) {
748 threePhaseApproach_ = EclMultiplexerApproach::EclOnePhaseApproach;
749 }
else if ( numEnabled == 2) {
750 threePhaseApproach_ = EclMultiplexerApproach::EclTwoPhaseApproach;
752 twoPhaseApproach_ = EclTwoPhaseApproach::EclTwoPhaseOilWater;
753 else if (!oilEnabled)
754 twoPhaseApproach_ = EclTwoPhaseApproach::EclTwoPhaseGasWater;
755 else if (!waterEnabled)
756 twoPhaseApproach_ = EclTwoPhaseApproach::EclTwoPhaseGasOil;
759 assert(numEnabled == 3);
761 threePhaseApproach_ = EclMultiplexerApproach::EclDefaultApproach;
762 const auto& satctrls = runspec.saturationFunctionControls();
763 if (satctrls.krModel() == SatFuncControls::ThreePhaseOilKrModel::Stone2)
764 threePhaseApproach_ = EclMultiplexerApproach::EclStone2Approach;
765 else if (satctrls.krModel() == SatFuncControls::ThreePhaseOilKrModel::Stone1)
766 threePhaseApproach_ = EclMultiplexerApproach::EclStone1Approach;
770 template <
class Container>
771 void readGasOilEffectiveParameters_(Container& dest,
772 const EclipseState& eclState,
773 unsigned satRegionIdx)
775 if (!hasGas || !hasOil)
779 dest[satRegionIdx] = std::make_shared<GasOilEffectiveTwoPhaseParams>();
781 auto& effParams = *dest[satRegionIdx];
785 const Scalar Swco = unscaledEpsInfo_[satRegionIdx].Swl;
786 const auto tolcrit = eclState.runspec().saturationFunctionControls()
787 .minimumRelpermMobilityThreshold();
789 const auto& tableManager = eclState.getTableManager();
791 switch (eclState.runspec().saturationFunctionControls().family()) {
792 case SatFuncControls::KeywordFamily::Family_I:
794 const TableContainer& sgofTables = tableManager.getSgofTables();
795 const TableContainer& slgofTables = tableManager.getSlgofTables();
796 if (!sgofTables.empty())
797 readGasOilEffectiveParametersSgof_(effParams, Swco, tolcrit,
798 sgofTables.getTable<SgofTable>(satRegionIdx));
799 else if (!slgofTables.empty())
800 readGasOilEffectiveParametersSlgof_(effParams, Swco, tolcrit,
801 slgofTables.getTable<SlgofTable>(satRegionIdx));
805 case SatFuncControls::KeywordFamily::Family_II:
807 const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
810 const Sof2Table& sof2Table = tableManager.getSof2Tables().getTable<Sof2Table>( satRegionIdx );
811 readGasOilEffectiveParametersFamily2_(effParams, Swco, tolcrit, sof2Table, sgfnTable);
814 const Sof3Table& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>( satRegionIdx );
815 readGasOilEffectiveParametersFamily2_(effParams, Swco, tolcrit, sof3Table, sgfnTable);
820 case SatFuncControls::KeywordFamily::Undefined:
821 throw std::domain_error(
"No valid saturation keyword family specified");
825 void readGasOilEffectiveParametersSgof_(GasOilEffectiveTwoPhaseParams& effParams,
827 const double tolcrit,
828 const SgofTable& sgofTable)
831 std::vector<double> SoSamples(sgofTable.numRows());
832 for (
size_t sampleIdx = 0; sampleIdx < sgofTable.numRows(); ++ sampleIdx) {
833 SoSamples[sampleIdx] = (1.0 - Swco) - sgofTable.get(
"SG", sampleIdx);
836 effParams.setKrwSamples(SoSamples, normalizeKrValues_(tolcrit, sgofTable.getColumn(
"KROG")));
837 effParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, sgofTable.getColumn(
"KRG")));
838 effParams.setPcnwSamples(SoSamples, sgofTable.getColumn(
"PCOG").vectorCopy());
839 effParams.finalize();
842 void readGasOilEffectiveParametersSlgof_(GasOilEffectiveTwoPhaseParams& effParams,
844 const double tolcrit,
845 const SlgofTable& slgofTable)
848 std::vector<double> SoSamples(slgofTable.numRows());
849 for (
size_t sampleIdx = 0; sampleIdx < slgofTable.numRows(); ++ sampleIdx) {
850 SoSamples[sampleIdx] = slgofTable.get(
"SL", sampleIdx) - Swco;
853 effParams.setKrwSamples(SoSamples, normalizeKrValues_(tolcrit, slgofTable.getColumn(
"KROG")));
854 effParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, slgofTable.getColumn(
"KRG")));
855 effParams.setPcnwSamples(SoSamples, slgofTable.getColumn(
"PCOG").vectorCopy());
856 effParams.finalize();
859 void readGasOilEffectiveParametersFamily2_(GasOilEffectiveTwoPhaseParams& effParams,
861 const double tolcrit,
862 const Sof3Table& sof3Table,
863 const SgfnTable& sgfnTable)
866 std::vector<double> SoSamples(sgfnTable.numRows());
867 std::vector<double> SoColumn = sof3Table.getColumn(
"SO").vectorCopy();
868 for (
size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) {
869 SoSamples[sampleIdx] = (1.0 - Swco) - sgfnTable.get(
"SG", sampleIdx);
872 effParams.setKrwSamples(SoColumn, normalizeKrValues_(tolcrit, sof3Table.getColumn(
"KROG")));
873 effParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, sgfnTable.getColumn(
"KRG")));
874 effParams.setPcnwSamples(SoSamples, sgfnTable.getColumn(
"PCOG").vectorCopy());
875 effParams.finalize();
878 void readGasOilEffectiveParametersFamily2_(GasOilEffectiveTwoPhaseParams& effParams,
880 const double tolcrit,
881 const Sof2Table& sof2Table,
882 const SgfnTable& sgfnTable)
885 std::vector<double> SoSamples(sgfnTable.numRows());
886 std::vector<double> SoColumn = sof2Table.getColumn(
"SO").vectorCopy();
887 for (
size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) {
888 SoSamples[sampleIdx] = (1.0 - Swco) - sgfnTable.get(
"SG", sampleIdx);
891 effParams.setKrwSamples(SoColumn, normalizeKrValues_(tolcrit, sof2Table.getColumn(
"KRO")));
892 effParams.setKrnSamples(SoSamples, normalizeKrValues_(tolcrit, sgfnTable.getColumn(
"KRG")));
893 effParams.setPcnwSamples(SoSamples, sgfnTable.getColumn(
"PCOG").vectorCopy());
894 effParams.finalize();
897 template <
class Container>
898 void readOilWaterEffectiveParameters_(Container& dest,
899 const EclipseState& eclState,
900 unsigned satRegionIdx)
902 if (!hasOil || !hasWater)
906 dest[satRegionIdx] = std::make_shared<OilWaterEffectiveTwoPhaseParams>();
908 const auto tolcrit = eclState.runspec().saturationFunctionControls()
909 .minimumRelpermMobilityThreshold();
911 const auto& tableManager = eclState.getTableManager();
912 auto& effParams = *dest[satRegionIdx];
914 switch (eclState.runspec().saturationFunctionControls().family()) {
915 case SatFuncControls::KeywordFamily::Family_I:
917 const auto& swofTable = tableManager.getSwofTables().getTable<SwofTable>(satRegionIdx);
918 const std::vector<double> SwColumn = swofTable.getColumn(
"SW").vectorCopy();
920 effParams.setKrwSamples(SwColumn, normalizeKrValues_(tolcrit, swofTable.getColumn(
"KRW")));
921 effParams.setKrnSamples(SwColumn, normalizeKrValues_(tolcrit, swofTable.getColumn(
"KROW")));
922 effParams.setPcnwSamples(SwColumn, swofTable.getColumn(
"PCOW").vectorCopy());
923 effParams.finalize();
927 case SatFuncControls::KeywordFamily::Family_II:
929 const auto& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>(satRegionIdx);
930 const auto& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>(satRegionIdx);
931 const std::vector<double> SwColumn = swfnTable.getColumn(
"SW").vectorCopy();
934 std::vector<double> SwSamples(sof3Table.numRows());
935 for (
size_t sampleIdx = 0; sampleIdx < sof3Table.numRows(); ++ sampleIdx)
936 SwSamples[sampleIdx] = 1 - sof3Table.get(
"SO", sampleIdx);
938 effParams.setKrwSamples(SwColumn, normalizeKrValues_(tolcrit, swfnTable.getColumn(
"KRW")));
939 effParams.setKrnSamples(SwSamples, normalizeKrValues_(tolcrit, sof3Table.getColumn(
"KROW")));
940 effParams.setPcnwSamples(SwColumn, swfnTable.getColumn(
"PCOW").vectorCopy());
941 effParams.finalize();
945 case SatFuncControls::KeywordFamily::Undefined:
946 throw std::domain_error(
"No valid saturation keyword family specified");
950 template <
class Container>
951 void readGasWaterEffectiveParameters_(Container& dest,
952 const EclipseState& eclState,
953 unsigned satRegionIdx)
955 if (!hasGas || !hasWater || hasOil)
959 dest[satRegionIdx] = std::make_shared<GasWaterEffectiveTwoPhaseParams>();
961 auto& effParams = *dest[satRegionIdx];
963 const auto tolcrit = eclState.runspec().saturationFunctionControls()
964 .minimumRelpermMobilityThreshold();
966 const auto& tableManager = eclState.getTableManager();
968 switch (eclState.runspec().saturationFunctionControls().family()) {
969 case SatFuncControls::KeywordFamily::Family_I:
971 throw std::domain_error(
"Saturation keyword family I is not applicable for a gas-water system");
974 case SatFuncControls::KeywordFamily::Family_II:
977 const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
978 const SwfnTable& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>( satRegionIdx );
980 std::vector<double> SwColumn = swfnTable.getColumn(
"SW").vectorCopy();
982 effParams.setKrwSamples(SwColumn, normalizeKrValues_(tolcrit, swfnTable.getColumn(
"KRW")));
983 std::vector<double> SwSamples(sgfnTable.numRows());
984 for (
size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx)
985 SwSamples[sampleIdx] = 1 - sgfnTable.get(
"SG", sampleIdx);
986 effParams.setKrnSamples(SwSamples, normalizeKrValues_(tolcrit, sgfnTable.getColumn(
"KRG")));
989 effParams.setPcnwSamples(SwColumn, swfnTable.getColumn(
"PCOW").vectorCopy());
990 effParams.finalize();
995 case SatFuncControls::KeywordFamily::Undefined:
996 throw std::domain_error(
"No valid saturation keyword family specified");
1000 template <
class Container>
1001 void readGasOilUnscaledPoints_(Container& dest,
1002 std::shared_ptr<EclEpsConfig> config,
1003 const EclipseState& ,
1004 unsigned satRegionIdx)
1006 if (!hasGas || !hasOil)
1010 dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1011 dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclGasOilSystem);
1014 template <
class Container>
1015 void readOilWaterUnscaledPoints_(Container& dest,
1016 std::shared_ptr<EclEpsConfig> config,
1017 const EclipseState& ,
1018 unsigned satRegionIdx)
1020 if (!hasOil || !hasWater)
1024 dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1025 dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclOilWaterSystem);
1028 template <
class Container>
1029 void readGasWaterUnscaledPoints_(Container& dest,
1030 std::shared_ptr<EclEpsConfig> config,
1031 const EclipseState& ,
1032 unsigned satRegionIdx)
1038 dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1039 dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclGasWaterSystem);
1042 template <
class InfoContainer,
class Po
intsContainer>
1043 void readGasOilScaledPoints_(InfoContainer& destInfo,
1044 PointsContainer& destPoints,
1045 std::shared_ptr<EclEpsConfig> config,
1046 const EclipseState& eclState,
1047 const EclEpsGridProperties& epsGridProperties,
1050 unsigned satRegionIdx = epsGridProperties.satRegion( elemIdx );
1052 destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
1053 destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, elemIdx);
1055 destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1056 destPoints[elemIdx]->init(*destInfo[elemIdx], *config, EclGasOilSystem);
1059 template <
class InfoContainer,
class Po
intsContainer>
1060 void readOilWaterScaledPoints_(InfoContainer& destInfo,
1061 PointsContainer& destPoints,
1062 std::shared_ptr<EclEpsConfig> config,
1063 const EclipseState& eclState,
1064 const EclEpsGridProperties& epsGridProperties,
1067 unsigned satRegionIdx = epsGridProperties.satRegion( elemIdx );
1069 destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
1070 destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, elemIdx);
1072 destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1073 destPoints[elemIdx]->init(*destInfo[elemIdx], *config, EclOilWaterSystem);
1076 template <
class InfoContainer,
class Po
intsContainer>
1077 void readGasWaterScaledPoints_(InfoContainer& destInfo,
1078 PointsContainer& destPoints,
1079 std::shared_ptr<EclEpsConfig> config,
1080 const EclipseState& eclState,
1081 const EclEpsGridProperties& epsGridProperties,
1084 unsigned satRegionIdx = epsGridProperties.satRegion( elemIdx );
1086 destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
1087 destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, elemIdx);
1089 destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
1090 destPoints[elemIdx]->init(*destInfo[elemIdx], *config, EclGasWaterSystem);
1093 void initThreePhaseParams_(
const EclipseState& ,
1094 MaterialLawParams& materialParams,
1095 unsigned satRegionIdx,
1096 const EclEpsScalingPointsInfo<Scalar>& epsInfo,
1097 std::shared_ptr<OilWaterTwoPhaseHystParams> oilWaterParams,
1098 std::shared_ptr<GasOilTwoPhaseHystParams> gasOilParams,
1099 std::shared_ptr<GasWaterTwoPhaseHystParams> gasWaterParams)
1101 materialParams.setApproach(threePhaseApproach_);
1103 switch (materialParams.approach()) {
1104 case EclMultiplexerApproach::EclStone1Approach: {
1105 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone1Approach>();
1106 realParams.setGasOilParams(gasOilParams);
1107 realParams.setOilWaterParams(oilWaterParams);
1108 realParams.setSwl(epsInfo.Swl);
1110 if (!stoneEtas.empty()) {
1111 realParams.setEta(stoneEtas[satRegionIdx]);
1114 realParams.setEta(1.0);
1115 realParams.finalize();
1119 case EclMultiplexerApproach::EclStone2Approach: {
1120 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclStone2Approach>();
1121 realParams.setGasOilParams(gasOilParams);
1122 realParams.setOilWaterParams(oilWaterParams);
1123 realParams.setSwl(epsInfo.Swl);
1124 realParams.finalize();
1128 case EclMultiplexerApproach::EclDefaultApproach: {
1129 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclDefaultApproach>();
1130 realParams.setGasOilParams(gasOilParams);
1131 realParams.setOilWaterParams(oilWaterParams);
1132 realParams.setSwl(epsInfo.Swl);
1133 realParams.finalize();
1137 case EclMultiplexerApproach::EclTwoPhaseApproach: {
1138 auto& realParams = materialParams.template getRealParams<EclMultiplexerApproach::EclTwoPhaseApproach>();
1139 realParams.setGasOilParams(gasOilParams);
1140 realParams.setOilWaterParams(oilWaterParams);
1141 realParams.setGasWaterParams(gasWaterParams);
1142 realParams.setApproach(twoPhaseApproach_);
1143 realParams.finalize();
1147 case EclMultiplexerApproach::EclOnePhaseApproach: {
1155 std::vector<double> normalizeKrValues_(
const double tolcrit,
1156 const TableColumn& krValues)
const
1158 auto kr = krValues.vectorCopy();
1159 std::transform(kr.begin(), kr.end(), kr.begin(),
1160 [tolcrit](
const double kri)
1162 return (kri > tolcrit) ? kri : 0.0;
1168 bool enableEndPointScaling_;
1169 std::shared_ptr<EclHysteresisConfig> hysteresisConfig_;
1171 std::shared_ptr<EclEpsConfig> oilWaterEclEpsConfig_;
1172 std::vector<EclEpsScalingPointsInfo<Scalar>> unscaledEpsInfo_;
1173 OilWaterScalingInfoVector oilWaterScaledEpsInfoDrainage_;
1175 std::shared_ptr<EclEpsConfig> gasWaterEclEpsConfig_;
1176 GasWaterScalingInfoVector gasWaterScaledEpsInfoDrainage_;
1178 GasOilScalingPointsVector gasOilUnscaledPointsVector_;
1179 OilWaterScalingPointsVector oilWaterUnscaledPointsVector_;
1180 GasWaterScalingPointsVector gasWaterUnscaledPointsVector_;
1182 GasOilEffectiveParamVector gasOilEffectiveParamVector_;
1183 OilWaterEffectiveParamVector oilWaterEffectiveParamVector_;
1184 GasWaterEffectiveParamVector gasWaterEffectiveParamVector_;
1186 EclMultiplexerApproach threePhaseApproach_ = EclMultiplexerApproach::EclDefaultApproach;
1188 enum EclTwoPhaseApproach twoPhaseApproach_ = EclTwoPhaseApproach::EclTwoPhaseGasOil;
1190 std::vector<std::shared_ptr<MaterialLawParams> > materialLawParams_;
1192 std::vector<int> satnumRegionArray_;
1193 std::vector<int> imbnumRegionArray_;
1194 std::vector<Scalar> stoneEtas;
1200 std::shared_ptr<EclEpsConfig> gasOilConfig;
1201 std::shared_ptr<EclEpsConfig> oilWaterConfig;
1202 std::shared_ptr<EclEpsConfig> gasWaterConfig;
Specifies the configuration used by the endpoint scaling code.
This material law takes a material law defined for unscaled saturation and converts it to a material ...
Specifies the configuration used by the ECL kr/pC hysteresis code.
This material law implements the hysteresis model of the ECL file format.
Implements a multiplexer class that provides all three phase capillary pressure laws used by the ECLi...
Implementation for the parameters required by the material law for two-phase simulations.
This file contains helper classes for the material laws.
Implementation of a tabulated, piecewise linear capillary pressure law.
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system assum...
Definition: EclEpsGridProperties.hpp:76
This material law takes a material law defined for unscaled saturation and converts it to a material ...
Definition: EclEpsTwoPhaseLaw.hpp:53
This material law implements the hysteresis model of the ECL file format.
Definition: EclHysteresisTwoPhaseLaw.hpp:41
Provides an simple way to create and manage the material law objects for a complete ECL deck.
Definition: EclMaterialLawManager.hpp:69
const MaterialLawParams & connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const
Returns a material parameter object for a given element and saturation region.
Definition: EclMaterialLawManager.hpp:538
Scalar applySwatinit(unsigned elemIdx, Scalar pcow, Scalar Sw)
Modify the initial condition according to the SWATINIT keyword.
Definition: EclMaterialLawManager.hpp:464
Implements a multiplexer class that provides all three phase capillary pressure laws used by the ECLi...
Definition: EclMultiplexerMaterial.hpp:58
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:135
static void updateHysteresis(Params ¶ms, const FluidState &fluidState)
Update the hysteresis parameters after a time step.
Definition: EclMultiplexerMaterial.hpp:545
Implementation of a tabulated, piecewise linear capillary pressure law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:51
ParamsT Params
The type of the parameter objects for this law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:59
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:60