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