opm-common
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 */
28 #ifndef OPM_ECL_MATERIAL_LAW_MANAGER_HPP
29 #define OPM_ECL_MATERIAL_LAW_MANAGER_HPP
30 
31 #include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
32 #include <opm/input/eclipse/EclipseState/WagHysteresisConfig.hpp>
33 
42 
43 #include <cassert>
44 #include <functional>
45 #include <memory>
46 #include <vector>
47 
48 namespace Opm {
49 
50 class EclipseState;
51 class EclEpsGridProperties;
52 template<class Scalar> class EclEpsScalingPoints;
53 template<class Scalar> struct EclEpsScalingPointsInfo;
54 class EclHysteresisConfig;
55 enum class EclTwoPhaseSystemType;
56 class FieldPropsManager;
57 class Runspec;
58 class SgfnTable;
59 class SgofTable;
60 class SlgofTable;
61 class TableColumn;
62 
63 }
64 
65 namespace Opm::EclMaterialLaw {
66 
67 template<class Traits> class InitParams;
68 
75 template <class TraitsT>
76 class Manager
77 {
78  using Traits = TraitsT;
79  using Scalar = typename Traits::Scalar;
80  static constexpr int gasPhaseIdx = Traits::gasPhaseIdx;
81  static constexpr int oilPhaseIdx = Traits::nonWettingPhaseIdx;
82  static constexpr int waterPhaseIdx = Traits::wettingPhaseIdx;
83  static constexpr int numPhases = Traits::numPhases;
84  using GasOilEffectiveParamVector = typename EclMaterialLaw::TwoPhaseTypes<Traits>::GasOilEffectiveParamVector;
85  using GasWaterEffectiveParamVector = typename EclMaterialLaw::TwoPhaseTypes<Traits>::GasWaterEffectiveParamVector;
86  using OilWaterEffectiveParamVector = typename EclMaterialLaw::TwoPhaseTypes<Traits>::OilWaterEffectiveParamVector;
87 
88 public:
89  // the three-phase material law used by the simulation
90  using MaterialLaw = EclMultiplexerMaterial<Traits,
91  typename EclMaterialLaw::TwoPhaseTypes<Traits>::GasOilLaw,
92  typename EclMaterialLaw::TwoPhaseTypes<Traits>::OilWaterLaw,
93  typename EclMaterialLaw::TwoPhaseTypes<Traits>::GasWaterLaw>;
94  using MaterialLawParams = typename MaterialLaw::Params;
95  using DirectionalMaterialLawParamsPtr = std::unique_ptr<DirectionalMaterialLawParams<MaterialLawParams>>;
96 
97 private:
98  using GasOilScalingPointsVector = std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar>>>;
99  using OilWaterScalingPointsVector = std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar>>>;
100  using GasWaterScalingPointsVector = std::vector<std::shared_ptr<EclEpsScalingPoints<Scalar>>>;
101  using OilWaterScalingInfoVector = std::vector<EclEpsScalingPointsInfo<Scalar>>;
102  using MaterialLawParamsVector = std::vector<std::shared_ptr<MaterialLawParams>>;
103 
104 public:
105  struct Params
106  {
107  OilWaterScalingInfoVector oilWaterScaledEpsInfoDrainage{};
108  GasOilEffectiveParamVector gasOilEffectiveParamVector{};
109  OilWaterEffectiveParamVector oilWaterEffectiveParamVector{};
110  GasWaterEffectiveParamVector gasWaterEffectiveParamVector{};
111  GasOilScalingPointsVector gasOilUnscaledPointsVector{};
112  OilWaterScalingPointsVector oilWaterUnscaledPointsVector{};
113  GasWaterScalingPointsVector gasWaterUnscaledPointsVector{};
114  std::vector<int> krnumXArray{};
115  std::vector<int> krnumYArray{};
116  std::vector<int> krnumZArray{};
117  std::vector<int> imbnumXArray{};
118  std::vector<int> imbnumYArray{};
119  std::vector<int> imbnumZArray{};
120  std::vector<int> satnumRegionArray{};
121  std::vector<int> imbnumRegionArray{};
122  std::vector<MaterialLawParams> materialLawParams{};
123  DirectionalMaterialLawParamsPtr dirMaterialLawParams{};
124  bool onlyPiecewiseLinear = true;
125 
126  bool hasDirectionalRelperms() const
127  {
128  return !krnumXArray.empty() ||
129  !krnumYArray.empty() ||
130  !krnumZArray.empty();
131  }
132 
133  bool hasDirectionalImbnum() const
134  {
135  return !imbnumXArray.empty() ||
136  !imbnumYArray.empty() ||
137  !imbnumZArray.empty();
138  }
139  };
140 
141  void initFromState(const EclipseState& eclState);
142 
143  // \brief Function argument 'fieldPropIntOnLeadAssigner' needed to lookup
144  // field properties of cells on the leaf grid view for CpGrid with local grid refinement.
145  // Function argument 'lookupIdxOnLevelZeroAssigner' is added to lookup, for each
146  // leaf gridview cell with index 'elemIdx', its 'lookupIdx' (index of the parent/equivalent cell on level zero).
147  void initParamsForElements(const EclipseState& eclState, size_t numCompressedElems,
148  const std::function<std::vector<int>(const FieldPropsManager&, const std::string&, bool)>&
149  fieldPropIntOnLeafAssigner,
150  const std::function<unsigned(unsigned)>& lookupIdxOnLevelZeroAssigner);
151 
160  std::pair<Scalar, bool>
161  applySwatinit(unsigned elemIdx,
162  Scalar pcow,
163  Scalar Sw);
164 
173  void applyRestartSwatInit(const unsigned elemIdx, const Scalar maxPcow);
174 
175  bool enableEndPointScaling() const
176  { return enableEndPointScaling_; }
177 
178  bool enablePpcwmax() const
179  { return enablePpcwmax_; }
180 
181  const EclHysteresisConfig& hysteresisConfig() const
182  { return hysteresisConfig_; }
183 
184  bool enableHysteresis() const
185  { return hysteresisConfig_.enableHysteresis(); }
186 
187  bool enablePCHysteresis() const
188  { return hysteresisConfig_.enablePCHysteresis(); }
189 
190  bool enableWettingHysteresis() const
191  { return hysteresisConfig_.enableWettingHysteresis(); }
192 
193  bool enableNonWettingHysteresis() const
194  { return hysteresisConfig_.enableNonWettingHysteresis(); }
195 
196  bool hasGas() const
197  { return hasGas_; }
198 
199  bool hasOil() const
200  { return hasOil_; }
201 
202  bool hasWater() const
203  { return hasWater_; }
204 
205  const EclEpsScalingPointsInfo<Scalar>& unscaledEpsInfo(unsigned satRegionIdx) const
206  { return unscaledEpsInfo_[satRegionIdx]; }
207 
208  std::shared_ptr<WagHysteresisConfig::WagHysteresisConfigRecord>
209  wagHystersisConfig(unsigned satRegionIdx) const
210  { return wagHystersisConfig_[satRegionIdx]; }
211 
212  const EclEpsConfig& gasOilConfig() const
213  { return gasOilConfig_; }
214 
215  const EclEpsConfig& gasWaterConfig() const
216  { return gasWaterConfig_; }
217 
218  const EclEpsConfig& oilWaterConfig() const
219  { return oilWaterConfig_; }
220 
221  MaterialLawParams& materialLawParams(unsigned elemIdx)
222  {
223  assert(elemIdx < params_.materialLawParams.size());
224  return params_.materialLawParams[elemIdx];
225  }
226 
227  const MaterialLawParams& materialLawParams(unsigned elemIdx) const
228  {
229  assert(elemIdx < params_.materialLawParams.size());
230  return params_.materialLawParams[elemIdx];
231  }
232 
233  const MaterialLawParams& materialLawParams(unsigned elemIdx, FaceDir::DirEnum facedir) const
234  { return materialLawParamsFunc_(elemIdx, facedir); }
235 
236  MaterialLawParams& materialLawParams(unsigned elemIdx, FaceDir::DirEnum facedir)
237  { return const_cast<MaterialLawParams&>(materialLawParamsFunc_(elemIdx, facedir)); }
238 
247  const MaterialLawParams& connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const;
248 
249  int satnumRegionIdx(unsigned elemIdx) const
250  { return params_.satnumRegionArray[elemIdx]; }
251 
252  int getKrnumSatIdx(unsigned elemIdx, FaceDir::DirEnum facedir) const;
253 
254  bool hasDirectionalRelperms() const
255  { return params_.hasDirectionalRelperms(); }
256 
257  bool hasDirectionalImbnum() const
258  { return params_.hasDirectionalImbnum(); }
259 
260  int imbnumRegionIdx(unsigned elemIdx) const
261  { return params_.imbnumRegionArray[elemIdx]; }
262 
263  EclMultiplexerApproach threePhaseApproach() const
264  { return threePhaseApproach_; }
265 
266  EclTwoPhaseApproach twoPhaseApproach() const
267  { return twoPhaseApproach_; }
268 
269  const std::vector<Scalar>& stoneEtas() const
270  { return stoneEtas_; }
271 
272  template <class FluidState>
273  bool updateHysteresis(const FluidState& fluidState, unsigned elemIdx)
274  {
275  OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
276  if (!enableHysteresis())
277  return false;
278  bool changed = MaterialLaw::updateHysteresis(materialLawParams(elemIdx), fluidState);
279  if (hasDirectionalRelperms() || hasDirectionalImbnum()) {
280  using Dir = FaceDir::DirEnum;
281  constexpr int ndim = 3;
282  const Dir facedirs[] = {Dir::XPlus, Dir::YPlus, Dir::ZPlus};
283  for (int i = 0; i<ndim; i++) {
284  const bool ischanged =
285  MaterialLaw::updateHysteresis(materialLawParams(elemIdx, facedirs[i]), fluidState);
286  changed = changed || ischanged;
287  }
288  }
289  return changed;
290  }
291 
292  void oilWaterHysteresisParams(Scalar& soMax,
293  Scalar& swMax,
294  Scalar& swMin,
295  unsigned elemIdx) const;
296 
297  void setOilWaterHysteresisParams(const Scalar& soMax,
298  const Scalar& swMax,
299  const Scalar& swMin,
300  unsigned elemIdx);
301 
302  void gasOilHysteresisParams(Scalar& sgmax,
303  Scalar& shmax,
304  Scalar& somin,
305  unsigned elemIdx) const;
306 
307  void setGasOilHysteresisParams(const Scalar& sgmax,
308  const Scalar& shmax,
309  const Scalar& somin,
310  unsigned elemIdx);
311 
312  EclEpsScalingPoints<Scalar>& oilWaterScaledEpsPointsDrainage(unsigned elemIdx);
313 
314  const EclEpsScalingPointsInfo<Scalar>& oilWaterScaledEpsInfoDrainage(size_t elemIdx) const
315  { return params_.oilWaterScaledEpsInfoDrainage[elemIdx]; }
316 
317  template<class Serializer>
318  void serializeOp(Serializer& serializer)
319  {
320  // This is for restart serialization.
321  // Only dynamic state in the parameters need to be stored.
322  // For that reason we do not serialize the vector
323  // as that would recreate the objects inside.
324  for (auto& mat : params_.materialLawParams) {
325  serializer(mat);
326  }
327  }
328 
329  bool satCurveIsAllPiecewiseLinear() const
330  {
331  return this->params_.onlyPiecewiseLinear;
332  }
333 
334 private:
335  const MaterialLawParams& materialLawParamsFunc_(unsigned elemIdx, FaceDir::DirEnum facedir) const;
336 
337  void readGlobalEpsOptions_(const EclipseState& eclState);
338 
339  void readGlobalHysteresisOptions_(const EclipseState& state);
340 
341  void readGlobalThreePhaseOptions_(const Runspec& runspec);
342 
343  bool enableEndPointScaling_{false};
344  EclHysteresisConfig hysteresisConfig_;
345  std::vector<std::shared_ptr<WagHysteresisConfig::WagHysteresisConfigRecord>> wagHystersisConfig_;
346 
347  std::vector<EclEpsScalingPointsInfo<Scalar>> unscaledEpsInfo_;
348 
349  Params params_;
350 
351  EclMultiplexerApproach threePhaseApproach_ = EclMultiplexerApproach::Default;
352  // this attribute only makes sense for twophase simulations!
353  EclTwoPhaseApproach twoPhaseApproach_ = EclTwoPhaseApproach::GasOil;
354 
355  std::vector<Scalar> stoneEtas_;
356 
357  bool enablePpcwmax_{false};
358  std::vector<Scalar> maxAllowPc_;
359  std::vector<bool> modifySwl_;
360 
361  bool hasGas_{true};
362  bool hasOil_{true};
363  bool hasWater_{true};
364 
365  EclEpsConfig gasOilConfig_;
366  EclEpsConfig oilWaterConfig_;
367  EclEpsConfig gasWaterConfig_;
368 };
369 
370 } // namespace Opm::EclMaterialLaw
371 
372 #endif
This material law implements the hysteresis model of the ECL file format.
EclTwoPhaseSystemType
Specified which fluids are involved in a given twophase material law for endpoint scaling...
Definition: EclEpsConfig.hpp:40
static bool updateHysteresis(Params &params, const FluidState &fluidState)
Update the hysteresis parameters after a time step.
Definition: EclMultiplexerMaterial.hpp:555
Definition: EclMaterialLawHystParams.cpp:28
This file contains definitions related to directional material law parameters.
Definition: FieldPropsManager.hpp:42
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
This file contains helper classes for the material laws.
Definition: EclipseState.hpp:66
This material law takes a material law defined for unscaled saturation and converts it to a material ...
const MaterialLawParams & connectionMaterialLawParams(unsigned satRegionIdx, unsigned elemIdx) const
Returns a material parameter object for a given element and saturation region.
Definition: EclMaterialLawManager.cpp:244
Specifies the configuration used by the ECL kr/pC hysteresis code.
Definition: EclHysteresisConfig.hpp:39
Specifies the configuration used by the endpoint scaling code.
std::pair< Scalar, bool > applySwatinit(unsigned elemIdx, Scalar pcow, Scalar Sw)
Modify the initial condition according to the SWATINIT keyword.
Definition: EclMaterialLawManager.cpp:136
bool enableHysteresis() const
Returns whether hysteresis is enabled.
Definition: EclHysteresisConfig.hpp:51
Implements a multiplexer class that provides all three phase capillary pressure laws used by the ECLi...
void applyRestartSwatInit(const unsigned elemIdx, const Scalar maxPcow)
Apply SWATINIT-like scaling of oil/water capillary pressure curve at simulation restart.
Definition: EclMaterialLawManager.cpp:211
Definition: EclMaterialLawManager.hpp:105
Implements a multiplexer class that provides LET curves and piecewise linear saturation functions...