EclMaterialLawManager.hpp
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
27 #if ! HAVE_OPM_PARSER
28 #error "The opm-parser module is required to use the ECL material manager!"
29 #endif
30 
31 #ifndef OPM_ECL_MATERIAL_LAW_MANAGER_HPP
32 #define OPM_ECL_MATERIAL_LAW_MANAGER_HPP
33 
44 
45 #include <opm/common/Exceptions.hpp>
46 #include <opm/common/ErrorMacros.hpp>
47 
48 #include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
49 #include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
50 #include <opm/parser/eclipse/Deck/Deck.hpp>
51 
52 #include <algorithm>
53 
54 
55 namespace Opm {
56 
63 template <class TraitsT>
65 {
66 private:
67  typedef TraitsT Traits;
68  typedef typename Traits::Scalar Scalar;
69  enum { waterPhaseIdx = Traits::wettingPhaseIdx };
70  enum { oilPhaseIdx = Traits::nonWettingPhaseIdx };
71  enum { gasPhaseIdx = Traits::gasPhaseIdx };
72  enum { numPhases = Traits::numPhases };
73 
76 
77  // the two-phase material law which is defined on effective (unscaled) saturations
80  typedef typename GasOilEffectiveTwoPhaseLaw::Params GasOilEffectiveTwoPhaseParams;
81  typedef typename OilWaterEffectiveTwoPhaseLaw::Params OilWaterEffectiveTwoPhaseParams;
82 
83  // the two-phase material law which is defined on absolute (scaled) saturations
86  typedef typename GasOilEpsTwoPhaseLaw::Params GasOilEpsTwoPhaseParams;
87  typedef typename OilWaterEpsTwoPhaseLaw::Params OilWaterEpsTwoPhaseParams;
88 
89  // the scaled two-phase material laws with hystersis
92  typedef typename GasOilTwoPhaseLaw::Params GasOilTwoPhaseHystParams;
93  typedef typename OilWaterTwoPhaseLaw::Params OilWaterTwoPhaseHystParams;
94 
95 public:
96  // the three-phase material law used by the simulation
98  typedef typename MaterialLaw::Params MaterialLawParams;
99 
100 private:
101  // internal typedefs
102  typedef std::vector<std::shared_ptr<GasOilEffectiveTwoPhaseParams> > GasOilEffectiveParamVector;
103  typedef std::vector<std::shared_ptr<OilWaterEffectiveTwoPhaseParams> > OilWaterEffectiveParamVector;
104  typedef std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar> > > GasOilScalingPointsVector;
105  typedef std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar> > > OilWaterScalingPointsVector;
106  typedef std::vector<std::shared_ptr<EclEpsScalingPointsInfo<Scalar> > > GasOilScalingInfoVector;
107  typedef std::vector<std::shared_ptr<EclEpsScalingPointsInfo<Scalar> > > OilWaterScalingInfoVector;
108  typedef std::vector<std::shared_ptr<GasOilTwoPhaseHystParams> > GasOilParamVector;
109  typedef std::vector<std::shared_ptr<OilWaterTwoPhaseHystParams> > OilWaterParamVector;
110  typedef std::vector<std::shared_ptr<MaterialLawParams> > MaterialLawParamsVector;
111 
112 public:
114  {}
115 
116  void initFromDeck(const Opm::Deck& deck,
117  const Opm::EclipseState& eclState,
118  const std::vector<int>& compressedToCartesianElemIdx)
119  {
120  // get the number of saturation regions and the number of cells in the deck
121  const size_t numSatRegions = eclState.runspec().tabdims().getNumSatTables();
122  size_t numCompressedElems = compressedToCartesianElemIdx.size();
123 
124  // copy the SATNUM grid property. in some cases this is not necessary, but it
125  // should not require much memory anyway...
126  satnumRegionArray_.resize(numCompressedElems);
127  if (eclState.get3DProperties().hasDeckIntGridProperty("SATNUM")) {
128  const auto& satnumRawData = eclState.get3DProperties().getIntGridProperty("SATNUM").getData();
129  for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
130  unsigned cartesianElemIdx = static_cast<unsigned>(compressedToCartesianElemIdx[elemIdx]);
131  satnumRegionArray_[elemIdx] = satnumRawData[cartesianElemIdx] - 1;
132  }
133  }
134  else
135  std::fill(satnumRegionArray_.begin(), satnumRegionArray_.end(), 0);
136 
137  readGlobalEpsOptions_(deck, eclState);
138  readGlobalHysteresisOptions_(deck);
139  readGlobalThreePhaseOptions_(deck);
140 
141  unscaledEpsInfo_.resize(numSatRegions);
142  for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx)
143  unscaledEpsInfo_[satRegionIdx].extractUnscaled(deck, eclState, satRegionIdx);
144 
145  initParamsForElements_(deck, eclState, compressedToCartesianElemIdx, satnumRegionArray_);
146  }
147 
156  Scalar applySwatinit(unsigned elemIdx,
157  Scalar pcow,
158  Scalar Sw)
159  {
160  auto& elemScaledEpsInfo = *oilWaterScaledEpsInfoDrainage_[elemIdx];
161 
162  // TODO: Mixed wettability systems - see ecl kw OPTIONS switch 74
163 
164  if (pcow < 0.0)
165  Sw = elemScaledEpsInfo.Swu;
166  else {
167 
168  if (Sw <= elemScaledEpsInfo.Swl)
169  Sw = elemScaledEpsInfo.Swl;
170 
171  // specify a fluid state which only stores the saturations
172  typedef Opm::SimpleModularFluidState<Scalar,
173  numPhases,
174  /*numComponents=*/0,
175  /*FluidSystem=*/void, /* -> don't care */
176  /*storePressure=*/false,
177  /*storeTemperature=*/false,
178  /*storeComposition=*/false,
179  /*storeFugacity=*/false,
180  /*storeSaturation=*/true,
181  /*storeDensity=*/false,
182  /*storeViscosity=*/false,
183  /*storeEnthalpy=*/false> FluidState;
184  FluidState fs;
185  fs.setSaturation(waterPhaseIdx, Sw);
186  fs.setSaturation(gasPhaseIdx, 0);
187  fs.setSaturation(oilPhaseIdx, 0);
188  Scalar pc[numPhases] = { 0 };
189  MaterialLaw::capillaryPressures(pc, materialLawParams(elemIdx), fs);
190 
191  Scalar pcowAtSw = pc[oilPhaseIdx] - pc[waterPhaseIdx];
192  if (pcowAtSw > 0.0) {
193  elemScaledEpsInfo.maxPcow *= pcow/pcowAtSw;
194  auto& elemEclEpsScalingPoints = oilWaterScaledEpsPointsDrainage(elemIdx);
195  elemEclEpsScalingPoints.init(elemScaledEpsInfo, *oilWaterEclEpsConfig_, Opm::EclOilWaterSystem);
196  }
197  }
198 
199  return Sw;
200  }
201 
202  bool enableEndPointScaling() const
203  { return enableEndPointScaling_; }
204 
205  bool enableHysteresis() const
206  { return hysteresisConfig_->enableHysteresis(); }
207 
208  MaterialLawParams& materialLawParams(unsigned elemIdx)
209  {
210  assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
211  return *materialLawParams_[elemIdx];
212  }
213 
214  const MaterialLawParams& materialLawParams(unsigned elemIdx) const
215  {
216  assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
217  return *materialLawParams_[elemIdx];
218  }
219 
228  const MaterialLawParams& connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const
229  {
230  MaterialLawParams& mlp = *materialLawParams_[elemIdx];
231 
232  if (enableHysteresis()) {
233  OPM_MESSAGE("Warning: Using non-defautl satnum regions for conenction is not tested in combination with hysteresis");
234  }
235  // Currently we don't support COMPIMP. I.e. use the same table lookup for the hysteresis curves.
236  // unsigned impRegionIdx = satRegionIdx;
237 
238  // change the sat table it points to.
239  switch (mlp.approach()) {
240  case EclStone1Approach: {
241  auto& realParams = mlp.template getRealParams<Opm::EclStone1Approach>();
242 
243  realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
244  realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
245  realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
246  realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
247 // if (enableHysteresis()) {
248 // realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
249 // realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
250 // realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
251 // realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
252 // }
253  }
254  break;
255 
256  case EclStone2Approach: {
257  auto& realParams = mlp.template getRealParams<Opm::EclStone2Approach>();
258  realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
259  realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
260  realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
261  realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
262 // if (enableHysteresis()) {
263 // realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
264 // realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
265 // realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
266 // realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
267 // }
268  }
269  break;
270 
271  case EclDefaultApproach: {
272  auto& realParams = mlp.template getRealParams<Opm::EclDefaultApproach>();
273  realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
274  realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
275  realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
276  realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
277 // if (enableHysteresis()) {
278 // realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
279 // realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
280 // realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
281 // realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
282 // }
283  }
284  break;
285 
286  case EclTwoPhaseApproach: {
287  auto& realParams = mlp.template getRealParams<Opm::EclTwoPhaseApproach>();
288  realParams.oilWaterParams().drainageParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
289  realParams.oilWaterParams().drainageParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
290  realParams.gasOilParams().drainageParams().setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
291  realParams.gasOilParams().drainageParams().setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
292 // if (enableHysteresis()) {
293 // realParams.oilWaterParams().imbibitionParams().setUnscaledPoints(oilWaterUnscaledPointsVector_[impRegionIdx]);
294 // realParams.oilWaterParams().imbibitionParams().setEffectiveLawParams(oilWaterEffectiveParamVector_[impRegionIdx]);
295 // realParams.gasOilParams().imbibitionParams().setUnscaledPoints(gasOilUnscaledPointsVector_[impRegionIdx]);
296 // realParams.gasOilParams().imbibitionParams().setEffectiveLawParams(gasOilEffectiveParamVector_[impRegionIdx]);
297 // }
298  }
299  break;
300 
301  default:
302  OPM_THROW(std::logic_error, "Enum value for material approach unknown!");
303  }
304 
305  return mlp;
306  }
307 
308  int satnumRegionIdx(unsigned elemIdx) const {
309  return satnumRegionArray_[elemIdx];
310  }
311 
312  std::shared_ptr<MaterialLawParams>& materialLawParamsPointerReferenceHack(unsigned elemIdx)
313  {
314  assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
315  return materialLawParams_[elemIdx];
316  }
317 
318  template <class FluidState>
319  void updateHysteresis(const FluidState& fluidState, unsigned elemIdx)
320  {
321  if (!enableHysteresis())
322  return;
323 
324  auto threePhaseParams = materialLawParams_[elemIdx];
325  MaterialLaw::updateHysteresis(*threePhaseParams, fluidState);
326  }
327 
328  void oilWaterHysteresisParams(Scalar& pcSwMdc,
329  Scalar& krnSwMdc,
330  unsigned elemIdx) const
331  {
332  if (!enableHysteresis()) {
333  OPM_THROW(std::runtime_error, "Cannot get hysteresis parameters if hysteresis not enabled.");
334  }
335  const auto& params = materialLawParams(elemIdx);
336  MaterialLaw::oilWaterHysteresisParams(pcSwMdc, krnSwMdc, params);
337  }
338 
339  void setOilWaterHysteresisParams(const Scalar& pcSwMdc,
340  const Scalar& krnSwMdc,
341  unsigned elemIdx)
342  {
343  if (!enableHysteresis()) {
344  OPM_THROW(std::runtime_error, "Cannot set hysteresis parameters if hysteresis not enabled.");
345  }
346  auto& params = materialLawParams(elemIdx);
347  MaterialLaw::setOilWaterHysteresisParams(pcSwMdc, krnSwMdc, params);
348  }
349 
350  void gasOilHysteresisParams(Scalar& pcSwMdc,
351  Scalar& krnSwMdc,
352  unsigned elemIdx) const
353  {
354  if (!enableHysteresis()) {
355  OPM_THROW(std::runtime_error, "Cannot get hysteresis parameters if hysteresis not enabled.");
356  }
357  const auto& params = materialLawParams(elemIdx);
358  MaterialLaw::gasOilHysteresisParams(pcSwMdc, krnSwMdc, params);
359  }
360 
361  void setGasOilHysteresisParams(const Scalar& pcSwMdc,
362  const Scalar& krnSwMdc,
363  unsigned elemIdx)
364  {
365  if (!enableHysteresis()) {
366  OPM_THROW(std::runtime_error, "Cannot set hysteresis parameters if hysteresis not enabled.");
367  }
368  auto& params = materialLawParams(elemIdx);
369  MaterialLaw::setGasOilHysteresisParams(pcSwMdc, krnSwMdc, params);
370  }
371 
372  EclEpsScalingPoints<Scalar>& oilWaterScaledEpsPointsDrainage(unsigned elemIdx)
373  {
374  auto& materialParams = *materialLawParams_[elemIdx];
375  switch (materialParams.approach()) {
376  case EclStone1Approach: {
377  auto& realParams = materialParams.template getRealParams<Opm::EclStone1Approach>();
378  return realParams.oilWaterParams().drainageParams().scaledPoints();
379  }
380 
381  case EclStone2Approach: {
382  auto& realParams = materialParams.template getRealParams<Opm::EclStone2Approach>();
383  return realParams.oilWaterParams().drainageParams().scaledPoints();
384  }
385 
386  case EclDefaultApproach: {
387  auto& realParams = materialParams.template getRealParams<Opm::EclDefaultApproach>();
388  return realParams.oilWaterParams().drainageParams().scaledPoints();
389  }
390 
391  case EclTwoPhaseApproach: {
392  auto& realParams = materialParams.template getRealParams<Opm::EclTwoPhaseApproach>();
393  return realParams.oilWaterParams().drainageParams().scaledPoints();
394  }
395  default:
396  OPM_THROW(std::logic_error, "Enum value for material approach unknown!");
397  }
398  }
399 
400  const Opm::EclEpsScalingPointsInfo<Scalar>& oilWaterScaledEpsInfoDrainage(size_t elemIdx) const
401  {
402  return *oilWaterScaledEpsInfoDrainage_[elemIdx];
403  }
404 
405  std::shared_ptr<EclEpsScalingPointsInfo<Scalar> >& oilWaterScaledEpsInfoDrainagePointerReferenceHack(unsigned elemIdx)
406  {
407  return oilWaterScaledEpsInfoDrainage_[elemIdx];
408  }
409 private:
410  void readGlobalEpsOptions_(const Opm::Deck& deck, const Opm::EclipseState& eclState)
411  {
412  oilWaterEclEpsConfig_ = std::make_shared<Opm::EclEpsConfig>();
413  oilWaterEclEpsConfig_-> initFromDeck(deck, eclState, Opm::EclOilWaterSystem);
414 
415  enableEndPointScaling_ = deck.hasKeyword("ENDSCALE");
416  }
417 
418  void readGlobalHysteresisOptions_(const Opm::Deck& deck)
419  {
420  hysteresisConfig_ = std::make_shared<Opm::EclHysteresisConfig>();
421  hysteresisConfig_->initFromDeck(deck);
422  }
423 
424  void readGlobalThreePhaseOptions_(const Opm::Deck& deck)
425  {
426  bool gasEnabled = deck.hasKeyword("GAS");
427  bool oilEnabled = deck.hasKeyword("OIL");
428  bool waterEnabled = deck.hasKeyword("WATER");
429 
430  int numEnabled =
431  (gasEnabled?1:0)
432  + (oilEnabled?1:0)
433  + (waterEnabled?1:0);
434 
435  if (numEnabled < 2)
436  OPM_THROW(std::runtime_error,
437  "At least two fluid phases must be enabled. (Is: " << numEnabled << ")");
438 
439  if (numEnabled == 2) {
440  threePhaseApproach_ = Opm::EclTwoPhaseApproach;
441  if (!gasEnabled)
442  twoPhaseApproach_ = Opm::EclTwoPhaseOilWater;
443  else if (!oilEnabled)
444  twoPhaseApproach_ = Opm::EclTwoPhaseGasWater;
445  else if (!waterEnabled)
446  twoPhaseApproach_ = Opm::EclTwoPhaseGasOil;
447  }
448  else {
449  assert(numEnabled == 3);
450 
451  threePhaseApproach_ = Opm::EclDefaultApproach;
452  if (deck.hasKeyword("STONE") || deck.hasKeyword("STONE2"))
453  threePhaseApproach_ = Opm::EclStone2Approach;
454  else if (deck.hasKeyword("STONE1"))
455  threePhaseApproach_ = Opm::EclStone1Approach;
456  }
457  }
458 
459  void initParamsForElements_(const Deck& deck, const EclipseState& eclState,
460  const std::vector<int>& compressedToCartesianElemIdx,
461  const std::vector<int>& satnumRegionArray)
462  {
463  const size_t numSatRegions = eclState.runspec().tabdims().getNumSatTables();
464  unsigned numCompressedElems = static_cast<unsigned>(compressedToCartesianElemIdx.size());
465 
466  // read the end point scaling configuration. this needs to be done only once per
467  // deck.
468  auto gasOilConfig = std::make_shared<Opm::EclEpsConfig>();
469  auto oilWaterConfig = std::make_shared<Opm::EclEpsConfig>();
470  gasOilConfig->initFromDeck(deck, eclState, Opm::EclGasOilSystem);
471  oilWaterConfig->initFromDeck(deck, eclState, Opm::EclOilWaterSystem);
472 
473  // read the saturation region specific parameters from the deck
474  gasOilUnscaledPointsVector_.resize(numSatRegions);
475  oilWaterUnscaledPointsVector_.resize(numSatRegions);
476  gasOilEffectiveParamVector_.resize(numSatRegions);
477  oilWaterEffectiveParamVector_.resize(numSatRegions);
478  for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
479  // unscaled points for end-point scaling
480  readGasOilUnscaledPoints_(gasOilUnscaledPointsVector_, gasOilConfig, deck, eclState, satRegionIdx);
481  readOilWaterUnscaledPoints_(oilWaterUnscaledPointsVector_, oilWaterConfig, deck, eclState, satRegionIdx);
482 
483  // the parameters for the effective two-phase matererial laws
484  readGasOilEffectiveParameters_(gasOilEffectiveParamVector_, deck, eclState, satRegionIdx);
485  readOilWaterEffectiveParameters_(oilWaterEffectiveParamVector_, deck, eclState, satRegionIdx);
486 
487  // read the end point scaling info for the saturation region
488  unscaledEpsInfo_[satRegionIdx].extractUnscaled(deck, eclState, satRegionIdx);
489 
490  }
491 
492  // read the scaled end point scaling parameters which are specific for each
493  // element
494  GasOilScalingInfoVector gasOilScaledInfoVector(numCompressedElems);
495  oilWaterScaledEpsInfoDrainage_.resize(numCompressedElems);
496  GasOilScalingInfoVector gasOilScaledImbInfoVector;
497  OilWaterScalingInfoVector oilWaterScaledImbInfoVector;
498 
499  GasOilScalingPointsVector gasOilScaledPointsVector(numCompressedElems);
500  GasOilScalingPointsVector oilWaterScaledEpsPointsDrainage(numCompressedElems);
501  GasOilScalingPointsVector gasOilScaledImbPointsVector;
502  OilWaterScalingPointsVector oilWaterScaledImbPointsVector;
503 
504  if (enableHysteresis()) {
505  gasOilScaledImbInfoVector.resize(numCompressedElems);
506  gasOilScaledImbPointsVector.resize(numCompressedElems);
507  oilWaterScaledImbInfoVector.resize(numCompressedElems);
508  oilWaterScaledImbPointsVector.resize(numCompressedElems);
509  }
510 
511  EclEpsGridProperties epsGridProperties, epsImbGridProperties;
512  epsGridProperties.initFromDeck(deck, eclState, /*imbibition=*/false);
513  if (enableHysteresis())
514  epsImbGridProperties.initFromDeck(deck, eclState, /*imbibition=*/true);
515  for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
516  unsigned cartElemIdx = static_cast<unsigned>(compressedToCartesianElemIdx[elemIdx]);
517  readGasOilScaledPoints_(gasOilScaledInfoVector,
518  gasOilScaledPointsVector,
519  gasOilConfig,
520  eclState,
521  epsGridProperties,
522  elemIdx,
523  cartElemIdx);
524  readOilWaterScaledPoints_(oilWaterScaledEpsInfoDrainage_,
525  oilWaterScaledEpsPointsDrainage,
526  oilWaterConfig,
527  eclState,
528  epsGridProperties,
529  elemIdx,
530  cartElemIdx);
531 
532  if (enableHysteresis()) {
533  readGasOilScaledPoints_(gasOilScaledImbInfoVector,
534  gasOilScaledImbPointsVector,
535  gasOilConfig,
536  eclState,
537  epsImbGridProperties,
538  elemIdx,
539  cartElemIdx);
540  readOilWaterScaledPoints_(oilWaterScaledImbInfoVector,
541  oilWaterScaledImbPointsVector,
542  oilWaterConfig,
543  eclState,
544  epsImbGridProperties,
545  elemIdx,
546  cartElemIdx);
547  }
548  }
549 
550  // create the parameter objects for the two-phase laws
551  GasOilParamVector gasOilParams(numCompressedElems);
552  OilWaterParamVector oilWaterParams(numCompressedElems);
553  GasOilParamVector gasOilImbParams;
554  OilWaterParamVector oilWaterImbParams;
555 
556  if (enableHysteresis()) {
557  gasOilImbParams.resize(numCompressedElems);
558  oilWaterImbParams.resize(numCompressedElems);
559  }
560 
561  bool hasGas = deck.hasKeyword("GAS");
562  bool hasOil = deck.hasKeyword("OIL");
563  bool hasWater = deck.hasKeyword("WATER");
564 
565  const auto& imbnumData = eclState.get3DProperties().getIntGridProperty("IMBNUM").getData();
566  assert(numCompressedElems == satnumRegionArray.size());
567  for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
568  unsigned satRegionIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
569 
570  gasOilParams[elemIdx] = std::make_shared<GasOilTwoPhaseHystParams>();
571  oilWaterParams[elemIdx] = std::make_shared<OilWaterTwoPhaseHystParams>();
572 
573  gasOilParams[elemIdx]->setConfig(hysteresisConfig_);
574  oilWaterParams[elemIdx]->setConfig(hysteresisConfig_);
575 
576  if (hasGas && hasOil) {
577  auto gasOilDrainParams = std::make_shared<GasOilEpsTwoPhaseParams>();
578  gasOilDrainParams->setConfig(gasOilConfig);
579  gasOilDrainParams->setUnscaledPoints(gasOilUnscaledPointsVector_[satRegionIdx]);
580  gasOilDrainParams->setScaledPoints(gasOilScaledPointsVector[elemIdx]);
581  gasOilDrainParams->setEffectiveLawParams(gasOilEffectiveParamVector_[satRegionIdx]);
582  gasOilDrainParams->finalize();
583 
584  gasOilParams[elemIdx]->setDrainageParams(gasOilDrainParams,
585  *gasOilScaledInfoVector[elemIdx],
586  EclGasOilSystem);
587  }
588 
589  if (hasOil && hasWater) {
590  auto oilWaterDrainParams = std::make_shared<OilWaterEpsTwoPhaseParams>();
591  oilWaterDrainParams->setConfig(oilWaterConfig);
592  oilWaterDrainParams->setUnscaledPoints(oilWaterUnscaledPointsVector_[satRegionIdx]);
593  oilWaterDrainParams->setScaledPoints(oilWaterScaledEpsPointsDrainage[elemIdx]);
594  oilWaterDrainParams->setEffectiveLawParams(oilWaterEffectiveParamVector_[satRegionIdx]);
595  oilWaterDrainParams->finalize();
596 
597  oilWaterParams[elemIdx]->setDrainageParams(oilWaterDrainParams,
598  *oilWaterScaledEpsInfoDrainage_[elemIdx],
599  EclOilWaterSystem);
600  }
601 
602  if (enableHysteresis()) {
603  unsigned imbRegionIdx = static_cast<unsigned>(imbnumData[elemIdx]) - 1;
604 
605  if (hasGas && hasOil) {
606  auto gasOilImbParamsHyst = std::make_shared<GasOilEpsTwoPhaseParams>();
607  gasOilImbParamsHyst->setConfig(gasOilConfig);
608  gasOilImbParamsHyst->setUnscaledPoints(gasOilUnscaledPointsVector_[imbRegionIdx]);
609  gasOilImbParamsHyst->setScaledPoints(gasOilScaledImbPointsVector[elemIdx]);
610  gasOilImbParamsHyst->setEffectiveLawParams(gasOilEffectiveParamVector_[imbRegionIdx]);
611  gasOilImbParamsHyst->finalize();
612 
613  gasOilParams[elemIdx]->setImbibitionParams(gasOilImbParamsHyst,
614  *gasOilScaledImbInfoVector[elemIdx],
615  EclGasOilSystem);
616  }
617 
618  if (hasOil && hasWater) {
619  auto oilWaterImbParamsHyst = std::make_shared<OilWaterEpsTwoPhaseParams>();
620  oilWaterImbParamsHyst->setConfig(oilWaterConfig);
621  oilWaterImbParamsHyst->setUnscaledPoints(oilWaterUnscaledPointsVector_[imbRegionIdx]);
622  oilWaterImbParamsHyst->setScaledPoints(oilWaterScaledImbPointsVector[elemIdx]);
623  oilWaterImbParamsHyst->setEffectiveLawParams(oilWaterEffectiveParamVector_[imbRegionIdx]);
624  oilWaterImbParamsHyst->finalize();
625 
626  oilWaterParams[elemIdx]->setImbibitionParams(oilWaterImbParamsHyst,
627  *gasOilScaledImbInfoVector[elemIdx],
628  EclGasOilSystem);
629  }
630  }
631 
632  if (hasGas && hasOil)
633  gasOilParams[elemIdx]->finalize();
634 
635  if (hasOil && hasWater)
636  oilWaterParams[elemIdx]->finalize();
637  }
638 
639  // create the parameter objects for the three-phase law
640  materialLawParams_.resize(numCompressedElems);
641  for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
642  materialLawParams_[elemIdx] = std::make_shared<MaterialLawParams>();
643  unsigned satRegionIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
644 
645  initThreePhaseParams_(deck,
646  eclState,
647  *materialLawParams_[elemIdx],
648  satRegionIdx,
649  *oilWaterScaledEpsInfoDrainage_[elemIdx],
650  oilWaterParams[elemIdx],
651  gasOilParams[elemIdx]);
652 
653  materialLawParams_[elemIdx]->finalize();
654  }
655  }
656 
657  // The saturation function family.
658  // If SWOF and SGOF are specified in the deck it return FamilyI
659  // If SWFN, SGFN and SOF3 are specified in the deck it return FamilyII
660  // If keywords are missing or mixed, an error is given.
661  enum SaturationFunctionFamily {
662  noFamily,
663  FamilyI,
664  FamilyII
665  };
666 
667  SaturationFunctionFamily getSaturationFunctionFamily(const Opm::Deck& deck, const Opm::EclipseState& eclState) const
668  {
669  const auto& tableManager = eclState.getTableManager();
670  const TableContainer& swofTables = tableManager.getSwofTables();
671  const TableContainer& slgofTables= tableManager.getSlgofTables();
672  const TableContainer& sgofTables = tableManager.getSgofTables();
673  const TableContainer& swfnTables = tableManager.getSwfnTables();
674  const TableContainer& sgfnTables = tableManager.getSgfnTables();
675  const TableContainer& sof3Tables = tableManager.getSof3Tables();
676 
677  bool hasGas = deck.hasKeyword("GAS");
678  bool hasOil = deck.hasKeyword("OIL");
679  bool hasWater = deck.hasKeyword("WATER");
680 
681  bool family1 = false;
682  bool family2 = false;
683  if (!hasGas) {
684  // oil-water case
685  family1 = !swofTables.empty();
686  if (!family1)
687  throw std::runtime_error("only SWOF is supporeted for oil-water two-phase simulations");
688  //family2 = !swfnTables.empty() && !sof2Tables.empty();
689  }
690  else if (!hasWater) {
691  // oil-gas case
692  family1 = !sgofTables.empty();
693  if (!family1)
694  throw std::runtime_error("only SGOF is supporeted for oil-gas two-phase simulations");
695  //family2 = !sgfnTables.empty() && !sof2Tables.empty();
696  }
697  else if (!hasOil) {
698  // water-gas case
699  throw std::runtime_error("water-gas two-phase simulations are currently not supported");
700  }
701  else {
702  // three-phase case
703  family1 = (!sgofTables.empty() || !slgofTables.empty()) && !swofTables.empty();
704  family2 = !swfnTables.empty() && !sgfnTables.empty() && !sof3Tables.empty();
705  }
706 
707  if (family1 && family2) {
708  throw std::invalid_argument("Saturation families should not be mixed \n"
709  "Use either SGOF and SWOF or SGFN, SWFN and SOF3");
710  }
711 
712  if (!family1 && !family2) {
713  throw std::invalid_argument("Saturations function must be specified using either "
714  "family 1 or family 2 keywords \n"
715  "Use either SGOF and SWOF or SGFN, SWFN and SOF3" );
716  }
717 
718  if (family1 && !family2)
719  return SaturationFunctionFamily::FamilyI;
720  else if (family2 && !family1)
721  return SaturationFunctionFamily::FamilyII;
722  return SaturationFunctionFamily::noFamily; // no family or two families
723  }
724 
725  template <class Container>
726  void readGasOilEffectiveParameters_(Container& dest,
727  const Opm::Deck& deck,
728  const Opm::EclipseState& eclState,
729  unsigned satRegionIdx)
730  {
731  bool hasGas = deck.hasKeyword("GAS");
732  bool hasOil = deck.hasKeyword("OIL");
733 
734  if (!hasGas || !hasOil)
735  // we don't read anything if either the gas or the oil phase is not active
736  return;
737 
738  dest[satRegionIdx] = std::make_shared<GasOilEffectiveTwoPhaseParams>();
739 
740  auto& effParams = *dest[satRegionIdx];
741 
742  // the situation for the gas phase is complicated that all saturations are
743  // shifted by the connate water saturation.
744  Scalar Swco = unscaledEpsInfo_[satRegionIdx].Swl;
745  const auto& tableManager = eclState.getTableManager();
746 
747  switch (getSaturationFunctionFamily(deck, eclState)) {
748  case FamilyI:
749  {
750  const TableContainer& sgofTables = tableManager.getSgofTables();
751  const TableContainer& slgofTables = tableManager.getSlgofTables();
752  if (!sgofTables.empty())
753  readGasOilEffectiveParametersSgof_(effParams,
754  Swco,
755  sgofTables.getTable<SgofTable>(satRegionIdx));
756  else if (!slgofTables.empty())
757  readGasOilEffectiveParametersSlgof_(effParams,
758  Swco,
759  slgofTables.getTable<SlgofTable>(satRegionIdx));
760  break;
761  }
762 
763  case FamilyII:
764  {
765  const Sof3Table& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>( satRegionIdx );
766  const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
767  readGasOilEffectiveParametersFamily2_(effParams,
768  Swco,
769  sof3Table,
770  sgfnTable);
771  break;
772  }
773 
774  //default:
775  case noFamily:
776  throw std::domain_error("No valid saturation keyword family specified");
777 
778  }
779  }
780 
781  void readGasOilEffectiveParametersSgof_(GasOilEffectiveTwoPhaseParams& effParams,
782  Scalar Swco,
783  const Opm::SgofTable& sgofTable)
784  {
785  // convert the saturations of the SGOF keyword from gas to oil saturations
786  std::vector<double> SoSamples(sgofTable.numRows());
787  std::vector<double> SoKroSamples(sgofTable.numRows());
788  for (size_t sampleIdx = 0; sampleIdx < sgofTable.numRows(); ++ sampleIdx) {
789  SoSamples[sampleIdx] = 1 - sgofTable.get("SG", sampleIdx);
790  SoKroSamples[sampleIdx] = SoSamples[sampleIdx] - Swco;
791  }
792 
793  effParams.setKrwSamples(SoKroSamples, sgofTable.getColumn("KROG").vectorCopy());
794  effParams.setKrnSamples(SoSamples, sgofTable.getColumn("KRG").vectorCopy());
795  effParams.setPcnwSamples(SoSamples, sgofTable.getColumn("PCOG").vectorCopy());
796  effParams.finalize();
797  }
798 
799  void readGasOilEffectiveParametersSlgof_(GasOilEffectiveTwoPhaseParams& effParams,
800  Scalar Swco,
801  const Opm::SlgofTable& slgofTable)
802  {
803  // convert the saturations of the SLGOF keyword from "liquid" to oil saturations
804  std::vector<double> SoSamples(slgofTable.numRows());
805  std::vector<double> SoKroSamples(slgofTable.numRows());
806  for (size_t sampleIdx = 0; sampleIdx < slgofTable.numRows(); ++ sampleIdx) {
807  SoSamples[sampleIdx] = slgofTable.get("SL", sampleIdx);
808  SoKroSamples[sampleIdx] = slgofTable.get("SL", sampleIdx) - Swco;
809  }
810 
811  effParams.setKrwSamples(SoKroSamples, slgofTable.getColumn("KROG").vectorCopy());
812  effParams.setKrnSamples(SoSamples, slgofTable.getColumn("KRG").vectorCopy());
813  effParams.setPcnwSamples(SoSamples, slgofTable.getColumn("PCOG").vectorCopy());
814  effParams.finalize();
815  }
816 
817  void readGasOilEffectiveParametersFamily2_(GasOilEffectiveTwoPhaseParams& effParams,
818  Scalar /* Swco */,
819  const Opm::Sof3Table& sof3Table,
820  const Opm::SgfnTable& sgfnTable)
821  {
822  // convert the saturations of the SGFN keyword from gas to oil saturations
823  std::vector<double> SoSamples(sgfnTable.numRows());
824  std::vector<double> SoColumn = sof3Table.getColumn("SO").vectorCopy();
825  for (size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) {
826  SoSamples[sampleIdx] = 1 - sgfnTable.get("SG", sampleIdx);
827  }
828 
829  effParams.setKrwSamples(SoColumn, sof3Table.getColumn("KROG").vectorCopy());
830  effParams.setKrnSamples(SoSamples, sgfnTable.getColumn("KRG").vectorCopy());
831  effParams.setPcnwSamples(SoSamples, sgfnTable.getColumn("PCOG").vectorCopy());
832  effParams.finalize();
833  }
834 
835  template <class Container>
836  void readOilWaterEffectiveParameters_(Container& dest,
837  const Opm::Deck& deck,
838  const Opm::EclipseState& eclState,
839  unsigned satRegionIdx)
840  {
841  bool hasWater = deck.hasKeyword("WATER");
842  bool hasOil = deck.hasKeyword("OIL");
843 
844  if (!hasOil || !hasWater)
845  // we don't read anything if either the water or the oil phase is not active
846  return;
847 
848  dest[satRegionIdx] = std::make_shared<OilWaterEffectiveTwoPhaseParams>();
849 
850  const auto& tableManager = eclState.getTableManager();
851  auto& effParams = *dest[satRegionIdx];
852 
853  switch (getSaturationFunctionFamily(deck, eclState)) {
854  case FamilyI: {
855  const auto& swofTable = tableManager.getSwofTables().getTable<SwofTable>(satRegionIdx);
856  std::vector<double> SwColumn = swofTable.getColumn("SW").vectorCopy();
857 
858  effParams.setKrwSamples(SwColumn, swofTable.getColumn("KRW").vectorCopy());
859  effParams.setKrnSamples(SwColumn, swofTable.getColumn("KROW").vectorCopy());
860  effParams.setPcnwSamples(SwColumn, swofTable.getColumn("PCOW").vectorCopy());
861  effParams.finalize();
862  break;
863  }
864  case FamilyII:
865  {
866  const auto& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>(satRegionIdx);
867  const auto& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>(satRegionIdx);
868  std::vector<double> SwColumn = swfnTable.getColumn("SW").vectorCopy();
869 
870  // convert the saturations of the SOF3 keyword from oil to water saturations
871  std::vector<double> SwSamples(sof3Table.numRows());
872  for (size_t sampleIdx = 0; sampleIdx < sof3Table.numRows(); ++ sampleIdx)
873  SwSamples[sampleIdx] = 1 - sof3Table.get("SO", sampleIdx);
874 
875  effParams.setKrwSamples(SwColumn, swfnTable.getColumn("KRW").vectorCopy());
876  effParams.setKrnSamples(SwSamples, sof3Table.getColumn("KROW").vectorCopy());
877  effParams.setPcnwSamples(SwColumn, swfnTable.getColumn("PCOW").vectorCopy());
878  effParams.finalize();
879  break;
880  }
881 
882  case noFamily:
883  //default:
884  throw std::domain_error("No valid saturation keyword family specified");
885 
886  }
887  }
888 
889 
890  template <class Container>
891  void readGasOilUnscaledPoints_(Container& dest,
892  std::shared_ptr<EclEpsConfig> config,
893  const Opm::Deck& deck,
894  const Opm::EclipseState& /* eclState */,
895  unsigned satRegionIdx)
896  {
897  bool hasGas = deck.hasKeyword("GAS");
898  bool hasOil = deck.hasKeyword("OIL");
899 
900  if (!hasGas || !hasOil)
901  // we don't read anything if either the gas or the oil phase is not active
902  return;
903 
904  dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
905  dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclGasOilSystem);
906  }
907 
908  template <class Container>
909  void readOilWaterUnscaledPoints_(Container& dest,
910  std::shared_ptr<EclEpsConfig> config,
911  const Opm::Deck& deck,
912  const Opm::EclipseState& /* eclState */,
913  unsigned satRegionIdx)
914  {
915  bool hasWater = deck.hasKeyword("WATER");
916  bool hasOil = deck.hasKeyword("OIL");
917 
918  if (!hasOil || !hasWater)
919  // we don't read anything if either the water or the oil phase is not active
920  return;
921 
922  dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
923  dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclOilWaterSystem);
924  }
925 
926  template <class InfoContainer, class PointsContainer>
927  void readGasOilScaledPoints_(InfoContainer& destInfo,
928  PointsContainer& destPoints,
929  std::shared_ptr<EclEpsConfig> config,
930  const Opm::EclipseState& eclState,
931  const EclEpsGridProperties& epsGridProperties,
932  unsigned elemIdx,
933  unsigned cartElemIdx)
934  {
935  unsigned satRegionIdx = static_cast<unsigned>((*epsGridProperties.satnum)[cartElemIdx]) - 1; // ECL uses Fortran indices!
936 
937  destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
938  destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, cartElemIdx);
939 
940  destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
941  destPoints[elemIdx]->init(*destInfo[elemIdx], *config, EclGasOilSystem);
942  }
943 
944  template <class InfoContainer, class PointsContainer>
945  void readOilWaterScaledPoints_(InfoContainer& destInfo,
946  PointsContainer& destPoints,
947  std::shared_ptr<EclEpsConfig> config,
948  const Opm::EclipseState& eclState,
949  const EclEpsGridProperties& epsGridProperties,
950  unsigned elemIdx,
951  unsigned cartElemIdx)
952  {
953  unsigned satRegionIdx = static_cast<unsigned>((*epsGridProperties.satnum)[cartElemIdx]) - 1; // ECL uses Fortran indices!
954 
955  destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
956  destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, cartElemIdx);
957 
958  destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
959  destPoints[elemIdx]->init(*destInfo[elemIdx], *config, EclOilWaterSystem);
960  }
961 
962  void initThreePhaseParams_(const Opm::Deck& deck,
963  const Opm::EclipseState& /* eclState */,
964  MaterialLawParams& materialParams,
965  unsigned satRegionIdx,
966  const EclEpsScalingPointsInfo<Scalar>& epsInfo,
967  std::shared_ptr<OilWaterTwoPhaseHystParams> oilWaterParams,
968  std::shared_ptr<GasOilTwoPhaseHystParams> gasOilParams)
969  {
970  materialParams.setApproach(threePhaseApproach_);
971 
972  switch (materialParams.approach()) {
973  case EclStone1Approach: {
974  auto& realParams = materialParams.template getRealParams<Opm::EclStone1Approach>();
975  realParams.setGasOilParams(gasOilParams);
976  realParams.setOilWaterParams(oilWaterParams);
977  realParams.setSwl(epsInfo.Swl);
978 
979  if (deck.hasKeyword("STONE1EX")) {
980  Scalar eta =
981  deck.getKeyword("STONE1EX").getRecord(satRegionIdx).getItem(0).getSIDouble(0);
982  realParams.setEta(eta);
983  }
984  else
985  realParams.setEta(1.0);
986  realParams.finalize();
987  break;
988  }
989 
990  case EclStone2Approach: {
991  auto& realParams = materialParams.template getRealParams<Opm::EclStone2Approach>();
992  realParams.setGasOilParams(gasOilParams);
993  realParams.setOilWaterParams(oilWaterParams);
994  realParams.setSwl(epsInfo.Swl);
995  realParams.finalize();
996  break;
997  }
998 
999  case EclDefaultApproach: {
1000  auto& realParams = materialParams.template getRealParams<Opm::EclDefaultApproach>();
1001  realParams.setGasOilParams(gasOilParams);
1002  realParams.setOilWaterParams(oilWaterParams);
1003  realParams.setSwl(epsInfo.Swl);
1004  realParams.finalize();
1005  break;
1006  }
1007 
1008  case EclTwoPhaseApproach: {
1009  auto& realParams = materialParams.template getRealParams<Opm::EclTwoPhaseApproach>();
1010  realParams.setGasOilParams(gasOilParams);
1011  realParams.setOilWaterParams(oilWaterParams);
1012  realParams.setApproach(twoPhaseApproach_);
1013  realParams.finalize();
1014  break;
1015  }
1016  }
1017  }
1018 
1019  bool enableEndPointScaling_;
1020  std::shared_ptr<EclHysteresisConfig> hysteresisConfig_;
1021 
1022  std::shared_ptr<EclEpsConfig> oilWaterEclEpsConfig_;
1023  std::vector<Opm::EclEpsScalingPointsInfo<Scalar>> unscaledEpsInfo_;
1024  OilWaterScalingInfoVector oilWaterScaledEpsInfoDrainage_;
1025 
1026  GasOilScalingPointsVector gasOilUnscaledPointsVector_;
1027  OilWaterScalingPointsVector oilWaterUnscaledPointsVector_;
1028  GasOilEffectiveParamVector gasOilEffectiveParamVector_;
1029  OilWaterEffectiveParamVector oilWaterEffectiveParamVector_;
1030 
1031  Opm::EclMultiplexerApproach threePhaseApproach_;
1032  // this attribute only makes sense for twophase simulations!
1033  enum EclTwoPhaseApproach twoPhaseApproach_;
1034 
1035  std::vector<std::shared_ptr<MaterialLawParams> > materialLawParams_;
1036 
1037  std::vector<int> satnumRegionArray_;
1038 };
1039 } // namespace Opm
1040 
1041 #endif
This material law implements the hysteresis model of the ECL file format.
This material law implements the hysteresis model of the ECL file format.
Definition: EclHysteresisTwoPhaseLaw.hpp:40
static void capillaryPressures(ContainerT &values, const Params &params, const FluidState &fluidState)
Implements the multiplexer three phase capillary pressure law used by the ECLipse simulator...
Definition: EclMultiplexerMaterial.hpp:131
ParamsT Params
The type of the parameter objects for this law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:61
Implementation of a tabulated, piecewise linear capillary pressure law.
static void updateHysteresis(Params &params, const FluidState &fluidState)
Update the hysteresis parameters after a time step.
Definition: EclMultiplexerMaterial.hpp:453
Scalar applySwatinit(unsigned elemIdx, Scalar pcow, Scalar Sw)
Modify the initial condition according to the SWATINIT keyword.
Definition: EclMaterialLawManager.hpp:156
Definition: Air_Mesitylene.hpp:33
const MaterialLawParams & connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const
Returns a material parameter object for a given element and saturation region.
Definition: EclMaterialLawManager.hpp:228
This file contains helper classes for the material laws.
Implementation of a tabulated, piecewise linear capillary pressure law.
Definition: PiecewiseLinearTwoPhaseMaterial.hpp:52
This structure represents all values which can be possibly used as scaling points in the endpoint sca...
Definition: EclEpsScalingPoints.hpp:154
Implements a multiplexer class that provides all three phase capillary pressure laws used by the ECLi...
Definition: EclMultiplexerMaterial.hpp:57
This material law takes a material law defined for unscaled saturation and converts it to a material ...
Specifies the configuration used by the endpoint scaling code.
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system assum...
Definition: SimpleModularFluidState.hpp:77
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system assum...
This material law takes a material law defined for unscaled saturation and converts it to a material ...
Definition: EclEpsTwoPhaseLaw.hpp:50
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.
Provides an simple way to create and manage the material law objects for a complete ECL deck...
Definition: EclMaterialLawManager.hpp:64
Specifies the configuration used by the ECL kr/pC hysteresis code.
A generic traits class for two-phase material laws.
Definition: MaterialTraits.hpp:59