opm-common
LiveOilPvt.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 #ifndef OPM_LIVE_OIL_PVT_HPP
28 #define OPM_LIVE_OIL_PVT_HPP
29 
31 #include <opm/common/OpmLog/OpmLog.hpp>
32 
36 
37 #include <cstddef>
38 
39 namespace Opm {
40 
41 class EclipseState;
42 class Schedule;
43 class SimpleTable;
44 
49 template <class Scalar>
51 {
52  using SamplingPoints = std::vector<std::pair<Scalar, Scalar>>;
53 
54 public:
57 
61  void initFromState(const EclipseState& eclState, const Schedule& schedule);
62 
63 private:
64  void extendPvtoTable_(unsigned regionIdx,
65  unsigned xIdx,
66  const SimpleTable& curTable,
67  const SimpleTable& masterTable);
68 
69 public:
70  void setNumRegions(std::size_t numRegions);
71 
72  void setVapPars(const Scalar, const Scalar par2)
73  {
74  vapPar2_ = par2;
75  }
76 
80  void setReferenceDensities(unsigned regionIdx,
81  Scalar rhoRefOil,
82  Scalar rhoRefGas,
83  Scalar /*rhoRefWater*/);
84 
91  void setSaturatedOilGasDissolutionFactor(unsigned regionIdx,
92  const SamplingPoints& samplePoints)
93  { saturatedGasDissolutionFactorTable_[regionIdx].setContainerOfTuples(samplePoints); }
94 
104  void setSaturatedOilFormationVolumeFactor(unsigned regionIdx,
105  const SamplingPoints& samplePoints);
106 
119  void setInverseOilFormationVolumeFactor(unsigned regionIdx,
120  const TabulatedTwoDFunction& invBo)
121  { inverseOilBTable_[regionIdx] = invBo; }
122 
128  void setOilViscosity(unsigned regionIdx, const TabulatedTwoDFunction& muo)
129  { oilMuTable_[regionIdx] = muo; }
130 
138  void setSaturatedOilViscosity(unsigned regionIdx,
139  const SamplingPoints& samplePoints);
140 
144  void initEnd();
145 
149  unsigned numRegions() const
150  { return inverseOilBMuTable_.size(); }
151 
155  template <class Evaluation>
156  Evaluation internalEnergy(unsigned,
157  const Evaluation&,
158  const Evaluation&,
159  const Evaluation&) const
160  {
161  throw std::runtime_error("Requested the enthalpy of oil but the thermal "
162  "option is not enabled");
163  }
164 
165  Scalar hVap(unsigned) const
166  {
167  throw std::runtime_error("Requested the hvap of oil but the thermal "
168  "option is not enabled");
169  }
170 
174  template <class Evaluation>
175  Evaluation viscosity(unsigned regionIdx,
176  const Evaluation& /*temperature*/,
177  const Evaluation& pressure,
178  const Evaluation& Rs) const
179  {
180  // ATTENTION: Rs is the first axis!
181  const Evaluation& invBo = inverseOilBTable_[regionIdx].eval(Rs, pressure, /*extrapolate=*/true);
182  const Evaluation& invMuoBo = inverseOilBMuTable_[regionIdx].eval(Rs, pressure, /*extrapolate=*/true);
183 
184  return invBo / invMuoBo;
185  }
186 
190  template <class Evaluation>
191  Evaluation saturatedViscosity(unsigned regionIdx,
192  const Evaluation& /*temperature*/,
193  const Evaluation& pressure) const
194  {
195  // ATTENTION: Rs is the first axis!
196  const Evaluation& invBo = inverseSaturatedOilBTable_[regionIdx].eval(pressure, /*extrapolate=*/true);
197  const Evaluation& invMuoBo = inverseSaturatedOilBMuTable_[regionIdx].eval(pressure, /*extrapolate=*/true);
198 
199  return invBo / invMuoBo;
200  }
201 
205  template <class Evaluation>
206  Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
207  const Evaluation& /*temperature*/,
208  const Evaluation& pressure,
209  const Evaluation& Rs) const
210  {
211  // ATTENTION: Rs is represented by the _first_ axis!
212  return inverseOilBTable_[regionIdx].eval(Rs, pressure, /*extrapolate=*/true);
213  }
214 
218  template <class FluidState, class LhsEval = typename FluidState::ValueType>
219  std::pair<LhsEval, LhsEval>
220  inverseFormationVolumeFactorAndViscosity(const FluidState& fluidState, unsigned regionIdx)
221  {
222  const LhsEval& p = decay<LhsEval>(fluidState.pressure(FluidState::oilPhaseIdx));
223  const LhsEval& Rs = decay<LhsEval>(fluidState.Rs());
224 
225  const auto satSegIdx = this->saturatedGasDissolutionFactorTable_[regionIdx].findSegmentIndex(p, /*extrapolate=*/ true);
226  const auto RsSat = this->saturatedGasDissolutionFactorTable_[regionIdx].eval(p, SegmentIndex{satSegIdx});
227  const bool useSaturatedTables = (fluidState.saturation(FluidState::gasPhaseIdx) > 0.0) && (Rs >= (1.0 - 1e-10) * RsSat);
228 
229  if (useSaturatedTables) {
230  const LhsEval b = this->inverseSaturatedOilBTable_[regionIdx].eval(p, SegmentIndex{satSegIdx});
231  const LhsEval invBMu = this->inverseSaturatedOilBMuTable_[regionIdx].eval(p, SegmentIndex{satSegIdx});
232  const LhsEval mu = b / invBMu;
233  return { b, mu };
234  } else {
235  unsigned ii, jj1, jj2;
236  LhsEval alpha, beta1, beta2;
237  this->inverseOilBTable_[regionIdx].findPoints(ii, jj1, jj2, alpha, beta1, beta2, Rs, p, /*extrapolate =*/ true);
238  const LhsEval b = this->inverseOilBTable_[regionIdx].eval(ii, jj1, jj2, alpha, beta1, beta2);
239  const LhsEval invBMu = this->inverseOilBMuTable_[regionIdx].eval(ii, jj1, jj2, alpha, beta1, beta2);
240  const LhsEval mu = b / invBMu;
241  return { b, mu };
242  }
243  }
244 
248  template <class Evaluation>
249  Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
250  const Evaluation& /*temperature*/,
251  const Evaluation& pressure) const
252  {
253  // ATTENTION: Rs is represented by the _first_ axis!
254  return inverseSaturatedOilBTable_[regionIdx].eval(pressure, /*extrapolate=*/true);
255  }
256 
260  template <class Evaluation>
261  Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
262  const Evaluation& /*temperature*/,
263  const Evaluation& pressure) const
264  { return saturatedGasDissolutionFactorTable_[regionIdx].eval(pressure, /*extrapolate=*/true); }
265 
273  template <class Evaluation>
274  Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
275  const Evaluation& /*temperature*/,
276  const Evaluation& pressure,
277  const Evaluation& oilSaturation,
278  Evaluation maxOilSaturation) const
279  {
280  Evaluation tmp =
281  saturatedGasDissolutionFactorTable_[regionIdx].eval(pressure, /*extrapolate=*/true);
282 
283  // apply the vaporization parameters for the gas phase (cf. the Eclipse VAPPARS
284  // keyword)
285  maxOilSaturation = min(maxOilSaturation, Scalar(1.0));
286  if (vapPar2_ > 0.0 && maxOilSaturation > 0.01 && oilSaturation < maxOilSaturation) {
287  constexpr const Scalar eps = 0.001;
288  const Evaluation& So = max(oilSaturation, eps);
289  tmp *= max(1e-3, pow(So / maxOilSaturation, vapPar2_));
290  }
291 
292  return tmp;
293  }
294 
302  template <class Evaluation>
303  Evaluation saturationPressure(unsigned regionIdx,
304  const Evaluation&,
305  const Evaluation& Rs) const
306  {
307  using Toolbox = MathToolbox<Evaluation>;
308 
309  const auto& RsTable = saturatedGasDissolutionFactorTable_[regionIdx];
310  constexpr const Scalar eps = std::numeric_limits<typename Toolbox::Scalar>::epsilon() * 1e6;
311 
312  // use the saturation pressure function to get a pretty good initial value
313  Evaluation pSat = saturationPressure_[regionIdx].eval(Rs, /*extrapolate=*/true);
314 
315  // Newton method to do the remaining work. If the initial
316  // value is good, this should only take two to three
317  // iterations...
318  bool onProbation = false;
319  for (int i = 0; i < 20; ++i) {
320  const Evaluation& f = RsTable.eval(pSat, /*extrapolate=*/true) - Rs;
321  const Evaluation& fPrime = RsTable.evalDerivative(pSat, /*extrapolate=*/true);
322 
323  // If the derivative is "zero" Newton will not converge,
324  // so simply return our initial guess.
325  if (std::abs(scalarValue(fPrime)) < 1.0e-30) {
326  return pSat;
327  }
328 
329  const Evaluation& delta = f / fPrime;
330 
331  pSat -= delta;
332 
333  if (pSat < 0.0) {
334  // if the pressure is lower than 0 Pascals, we set it back to 0. if this
335  // happens twice, we give up and just return 0 Pa...
336  if (onProbation) {
337  return 0.0;
338  }
339 
340  onProbation = true;
341  pSat = 0.0;
342  }
343 
344  if (std::abs(scalarValue(delta)) < std::abs(scalarValue(pSat))*eps) {
345  return pSat;
346  }
347  }
348 
349  const std::string msg =
350  "Finding saturation pressure did not converge: "
351  " pSat = " + std::to_string(getValue(pSat)) +
352  ", Rs = " + std::to_string(getValue(Rs));
353  OpmLog::debug("Live oil saturation pressure", msg);
354  throw NumericalProblem(msg);
355  }
356 
357  template <class Evaluation>
358  Evaluation diffusionCoefficient(const Evaluation& /*temperature*/,
359  const Evaluation& /*pressure*/,
360  unsigned /*compIdx*/) const
361  {
362  throw std::runtime_error("Not implemented: The PVT model does not provide "
363  "a diffusionCoefficient()");
364  }
365 
366  Scalar gasReferenceDensity(unsigned regionIdx) const
367  { return gasReferenceDensity_[regionIdx]; }
368 
369  Scalar oilReferenceDensity(unsigned regionIdx) const
370  { return oilReferenceDensity_[regionIdx]; }
371 
372  const std::vector<TabulatedTwoDFunction>& inverseOilBTable() const
373  { return inverseOilBTable_; }
374 
375  const std::vector<TabulatedTwoDFunction>& oilMuTable() const
376  { return oilMuTable_; }
377 
378  const std::vector<TabulatedTwoDFunction>& inverseOilBMuTable() const
379  { return inverseOilBMuTable_; }
380 
381  const std::vector<TabulatedOneDFunction>& saturatedOilMuTable() const
382  { return saturatedOilMuTable_; }
383 
384  const std::vector<TabulatedOneDFunction>& inverseSaturatedOilBTable() const
385  { return inverseSaturatedOilBTable_; }
386 
387  const std::vector<TabulatedOneDFunction>& inverseSaturatedOilBMuTable() const
388  { return inverseSaturatedOilBMuTable_; }
389 
390  const std::vector<TabulatedOneDFunction>& saturatedGasDissolutionFactorTable() const
391  { return saturatedGasDissolutionFactorTable_; }
392 
393  const std::vector<TabulatedOneDFunction>& saturationPressure() const
394  { return saturationPressure_; }
395 
396  Scalar vapPar2() const
397  { return vapPar2_; }
398 
399 private:
400  void updateSaturationPressure_(unsigned regionIdx);
401 
402  std::vector<Scalar> gasReferenceDensity_{};
403  std::vector<Scalar> oilReferenceDensity_{};
404  std::vector<TabulatedTwoDFunction> inverseOilBTable_{};
405  std::vector<TabulatedTwoDFunction> oilMuTable_{};
406  std::vector<TabulatedTwoDFunction> inverseOilBMuTable_{};
407  std::vector<TabulatedOneDFunction> saturatedOilMuTable_{};
408  std::vector<TabulatedOneDFunction> inverseSaturatedOilBTable_{};
409  std::vector<TabulatedOneDFunction> inverseSaturatedOilBMuTable_{};
410  std::vector<TabulatedOneDFunction> saturatedGasDissolutionFactorTable_{};
411  std::vector<TabulatedOneDFunction> saturationPressure_{};
412 
413  Scalar vapPar2_ = 0.0;
414 };
415 
416 } // namespace Opm
417 
418 #endif
void initFromState(const EclipseState &eclState, const Schedule &schedule)
Initialize the oil parameters via the data specified by the PVTO ECL keyword.
Definition: LiveOilPvt.cpp:40
Evaluation saturationPressure(unsigned regionIdx, const Evaluation &, const Evaluation &Rs) const
Returns the saturation pressure of the oil phase [Pa] depending on its mass fraction of the gas compo...
Definition: LiveOilPvt.hpp:303
Definition: Exceptions.hpp:39
Evaluation viscosity(unsigned regionIdx, const Evaluation &, const Evaluation &pressure, const Evaluation &Rs) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: LiveOilPvt.hpp:175
A traits class which provides basic mathematical functions for arbitrary scalar floating point values...
Implements a scalar function that depends on two variables and which is sampled uniformly in the X di...
Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &, const Evaluation &pressure) const
Returns the formation volume factor [-] of the fluid phase.
Definition: LiveOilPvt.hpp:249
Definition: Schedule.hpp:102
Provides the OPM specific exception classes.
void setOilViscosity(unsigned regionIdx, const TabulatedTwoDFunction &muo)
Initialize the viscosity of the oil phase.
Definition: LiveOilPvt.hpp:128
std::pair< LhsEval, LhsEval > inverseFormationVolumeFactorAndViscosity(const FluidState &fluidState, unsigned regionIdx)
Returns the formation volume factor [-] and viscosity [Pa s] of the fluid phase.
Definition: LiveOilPvt.hpp:220
unsigned numRegions() const
Return the number of PVT regions which are considered by this PVT-object.
Definition: LiveOilPvt.hpp:149
Evaluation inverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &, const Evaluation &pressure, const Evaluation &Rs) const
Returns the formation volume factor [-] of the fluid phase.
Definition: LiveOilPvt.hpp:206
Implements a scalar function that depends on two variables and which is sampled uniformly in the X di...
Definition: UniformXTabulated2DFunction.hpp:55
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
void initEnd()
Finish initializing the oil phase PVT properties.
Definition: LiveOilPvt.cpp:296
Definition: EclipseState.hpp:66
Definition: SimpleTable.hpp:36
Evaluation internalEnergy(unsigned, const Evaluation &, const Evaluation &, const Evaluation &) const
Returns the specific enthalpy [J/kg] of oil given a set of parameters.
Definition: LiveOilPvt.hpp:156
This class represents the Pressure-Volume-Temperature relations of the oil phas with dissolved gas...
Definition: LiveOilPvt.hpp:50
Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &, const Evaluation &pressure) const
Returns the gas dissolution factor [m^3/m^3] of the oil phase.
Definition: LiveOilPvt.hpp:261
void setReferenceDensities(unsigned regionIdx, Scalar rhoRefOil, Scalar rhoRefGas, Scalar)
Initialize the reference densities of all fluids for a given PVT region.
Definition: LiveOilPvt.cpp:231
void setSaturatedOilViscosity(unsigned regionIdx, const SamplingPoints &samplePoints)
Initialize the phase viscosity for gas saturated oil.
Definition: LiveOilPvt.cpp:269
void setSaturatedOilFormationVolumeFactor(unsigned regionIdx, const SamplingPoints &samplePoints)
Initialize the function for the oil formation volume factor.
Definition: LiveOilPvt.cpp:242
void setSaturatedOilGasDissolutionFactor(unsigned regionIdx, const SamplingPoints &samplePoints)
Initialize the function for the gas dissolution factor .
Definition: LiveOilPvt.hpp:91
Definition: MathToolbox.hpp:50
void setInverseOilFormationVolumeFactor(unsigned regionIdx, const TabulatedTwoDFunction &invBo)
Initialize the function for the oil formation volume factor.
Definition: LiveOilPvt.hpp:119
Implements a linearly interpolated scalar function that depends on one variable.
Implements a linearly interpolated scalar function that depends on one variable.
Definition: Tabulated1DFunction.hpp:51
Definition: Tabulated1DFunction.hpp:42
Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &, const Evaluation &pressure, const Evaluation &oilSaturation, Evaluation maxOilSaturation) const
Returns the gas dissolution factor [m^3/m^3] of the oil phase.
Definition: LiveOilPvt.hpp:274
Evaluation saturatedViscosity(unsigned regionIdx, const Evaluation &, const Evaluation &pressure) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: LiveOilPvt.hpp:191