opm-common
OilPvtThermal.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_OIL_PVT_THERMAL_HPP
28 #define OPM_OIL_PVT_THERMAL_HPP
29 
31 
32 #include <cstddef>
33 
34 namespace Opm {
35 
36 class EclipseState;
37 class Schedule;
38 
39 template <class Scalar, bool enableThermal>
40 class OilPvtMultiplexer;
41 
48 template <class Scalar>
50 {
51 public:
53  using IsothermalPvt = OilPvtMultiplexer<Scalar, /*enableThermal=*/false>;
54 
55  OilPvtThermal() = default;
56 
57  OilPvtThermal(IsothermalPvt* isothermalPvt,
58  const std::vector<TabulatedOneDFunction>& oilvisctCurves,
59  const std::vector<Scalar>& viscrefPress,
60  const std::vector<Scalar>& viscrefRs,
61  const std::vector<Scalar>& viscRef,
62  const std::vector<Scalar>& oildentRefTemp,
63  const std::vector<Scalar>& oildentCT1,
64  const std::vector<Scalar>& oildentCT2,
65  const std::vector<Scalar>& oilJTRefPres,
66  const std::vector<Scalar>& oilJTC,
67  const std::vector<TabulatedOneDFunction>& internalEnergyCurves,
69  bool enableJouleThomson,
71  bool enableInternalEnergy)
72  : isothermalPvt_(isothermalPvt)
73  , oilvisctCurves_(oilvisctCurves)
74  , viscrefPress_(viscrefPress)
75  , viscrefRs_(viscrefRs)
76  , viscRef_(viscRef)
77  , oildentRefTemp_(oildentRefTemp)
78  , oildentCT1_(oildentCT1)
79  , oildentCT2_(oildentCT2)
80  , oilJTRefPres_(oilJTRefPres)
81  , oilJTC_(oilJTC)
82  , internalEnergyCurves_(internalEnergyCurves)
83  , enableThermalDensity_(enableThermalDensity)
84  , enableJouleThomson_(enableJouleThomson)
85  , enableThermalViscosity_(enableThermalViscosity)
86  , enableInternalEnergy_(enableInternalEnergy)
87  { }
88 
89  OilPvtThermal(const OilPvtThermal& data)
90  { *this = data; }
91 
92  ~OilPvtThermal()
93  { delete isothermalPvt_; }
94 
98  void initFromState(const EclipseState& eclState, const Schedule& schedule);
99 
103  void setNumRegions(std::size_t numRegions);
104 
105  void setVapPars(const Scalar par1, const Scalar par2)
106  {
107  isothermalPvt_->setVapPars(par1, par2);
108  }
109 
113  void initEnd()
114  { }
115 
119  bool enableThermalDensity() const
120  { return enableThermalDensity_; }
121 
125  bool enableJouleThomson() const
126  { return enableJouleThomson_; }
127 
132  { return enableThermalViscosity_; }
133 
134  std::size_t numRegions() const
135  { return viscrefRs_.size(); }
136 
140  template <class Evaluation>
141  Evaluation internalEnergy(unsigned regionIdx,
142  const Evaluation& temperature,
143  const Evaluation& pressure,
144  const Evaluation& Rs) const
145  {
146  if (!enableInternalEnergy_) {
147  throw std::runtime_error("Requested the internal energy of oil but it is disabled");
148  }
149 
150  if (!enableJouleThomson_) {
151  // compute the specific internal energy for the specified tempature. We use linear
152  // interpolation here despite the fact that the underlying heat capacities are
153  // piecewise linear (which leads to a quadratic function)
154  return internalEnergyCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
155  }
156  else {
157  OpmLog::warning("Experimental code for jouleThomson: simulation will be slower");
158  Evaluation Tref = oildentRefTemp_[regionIdx];
159  Evaluation Pref = oilJTRefPres_[regionIdx];
160  Scalar JTC = oilJTC_[regionIdx]; // if JTC is default then JTC is calculated
161 
162  Evaluation invB = inverseFormationVolumeFactor(regionIdx, temperature, pressure, Rs);
163  Evaluation Cp = internalEnergyCurves_[regionIdx].eval(temperature, /*extrapolate=*/true)/temperature;
164  Evaluation density = invB * (oilReferenceDensity(regionIdx) + Rs * rhoRefG_[regionIdx]);
165 
166  Evaluation enthalpyPres;
167  if (JTC != 0) {
168  enthalpyPres = -Cp * JTC * (pressure - Pref);
169  }
170  else if (enableThermalDensity_) {
171  Scalar c1T = oildentCT1_[regionIdx];
172  Scalar c2T = oildentCT2_[regionIdx];
173 
174  Evaluation alpha = (c1T + 2 * c2T * (temperature - Tref)) /
175  (1 + c1T *(temperature - Tref) + c2T * (temperature - Tref) * (temperature - Tref));
176 
177  const int N = 100; // value is experimental
178  Evaluation deltaP = (pressure - Pref) / N;
179  Evaluation enthalpyPresPrev = 0;
180  for (std::size_t i = 0; i < N; ++i) {
181  Evaluation Pnew = Pref + i * deltaP;
182  Evaluation rho = inverseFormationVolumeFactor(regionIdx, temperature, Pnew, Rs) *
183  (oilReferenceDensity(regionIdx) + Rs * rhoRefG_[regionIdx]) ;
184  // see e.g.https://en.wikipedia.org/wiki/Joule-Thomson_effect for a derivation of the Joule-Thomson coeff.
185  Evaluation jouleThomsonCoefficient = -(1.0/Cp) * (1.0 - alpha * temperature)/rho;
186  Evaluation deltaEnthalpyPres = -Cp * jouleThomsonCoefficient * deltaP;
187  enthalpyPres = enthalpyPresPrev + deltaEnthalpyPres;
188  enthalpyPresPrev = enthalpyPres;
189  }
190  }
191  else {
192  throw std::runtime_error("Requested Joule-thomson calculation but thermal oil"
193  "density (OILDENT) is not provided");
194  }
195 
196  Evaluation enthalpy = Cp * (temperature - Tref) + enthalpyPres;
197 
198  return enthalpy - pressure/density;
199  }
200  }
201 
205  template <class Evaluation>
206  Evaluation viscosity(unsigned regionIdx,
207  const Evaluation& temperature,
208  const Evaluation& pressure,
209  const Evaluation& Rs) const
210  {
211  const auto& isothermalMu = isothermalPvt_->viscosity(regionIdx, temperature, pressure, Rs);
212  if (!enableThermalViscosity()) {
213  return isothermalMu;
214  }
215 
216  // compute the viscosity deviation due to temperature
217  const auto& muOilvisct = oilvisctCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
218  return muOilvisct / viscRef_[regionIdx] * isothermalMu;
219  }
220 
224  template <class Evaluation>
225  Evaluation saturatedViscosity(unsigned regionIdx,
226  const Evaluation& temperature,
227  const Evaluation& pressure) const
228  {
229  const auto& isothermalMu = isothermalPvt_->saturatedViscosity(regionIdx, temperature, pressure);
230  if (!enableThermalViscosity()) {
231  return isothermalMu;
232  }
233 
234  // compute the viscosity deviation due to temperature
235  const auto& muOilvisct = oilvisctCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
236  return muOilvisct / viscRef_[regionIdx] * isothermalMu;
237  }
238 
242  template <class Evaluation>
243  Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
244  const Evaluation& temperature,
245  const Evaluation& pressure,
246  const Evaluation& Rs) const
247  {
248  const auto& b =
249  isothermalPvt_->inverseFormationVolumeFactor(regionIdx, temperature, pressure, Rs);
250 
251  if (!enableThermalDensity()) {
252  return b;
253  }
254 
255  // we use the same approach as for the for water here, but with the OPM-specific
256  // OILDENT keyword.
257  Scalar TRef = oildentRefTemp_[regionIdx];
258  Scalar cT1 = oildentCT1_[regionIdx];
259  Scalar cT2 = oildentCT2_[regionIdx];
260  const Evaluation& Y = temperature - TRef;
261 
262  return b / (1 + (cT1 + cT2 * Y) * Y);
263  }
264 
268  template <class FluidState, class LhsEval = typename FluidState::ValueType>
269  std::pair<LhsEval, LhsEval>
270  inverseFormationVolumeFactorAndViscosity(const FluidState& fluidState, unsigned regionIdx)
271  {
272  auto [b, mu] = isothermalPvt_->inverseFormationVolumeFactorAndViscosity(fluidState, regionIdx);
273  const LhsEval& temperature = decay<LhsEval>(fluidState.temperature(FluidState::oilPhaseIdx));
274  if (enableThermalDensity()) {
275  // we use the same approach as for the for water here, but with the OPM-specific
276  // OILDENT keyword.
277  Scalar TRef = oildentRefTemp_[regionIdx];
278  Scalar cT1 = oildentCT1_[regionIdx];
279  Scalar cT2 = oildentCT2_[regionIdx];
280  const LhsEval Y = temperature - TRef;
281  b /= (1.0 + (cT1 + cT2 * Y) * Y);
282  }
283  if (enableThermalViscosity()) {
284  // compute the viscosity deviation due to temperature
285  const auto muOilvisct = oilvisctCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
286  mu *= (muOilvisct / viscRef_[regionIdx]);
287  }
288  return { b, mu };
289  }
290 
294  template <class Evaluation>
295  Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
296  const Evaluation& temperature,
297  const Evaluation& pressure) const
298  {
299  const auto& b =
300  isothermalPvt_->saturatedInverseFormationVolumeFactor(regionIdx, temperature, pressure);
301 
302  if (!enableThermalDensity()) {
303  return b;
304  }
305 
306  // we use the same approach as for the for water here, but with the OPM-specific
307  // OILDENT keyword.
308  Scalar TRef = oildentRefTemp_[regionIdx];
309  Scalar cT1 = oildentCT1_[regionIdx];
310  Scalar cT2 = oildentCT2_[regionIdx];
311  const Evaluation& Y = temperature - TRef;
312 
313  return b / (1 + (cT1 + cT2 * Y) * Y);
314  }
315 
323  template <class Evaluation>
324  Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
325  const Evaluation& temperature,
326  const Evaluation& pressure) const
327  { return isothermalPvt_->saturatedGasDissolutionFactor(regionIdx, temperature, pressure); }
328 
336  template <class Evaluation>
337  Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
338  const Evaluation& temperature,
339  const Evaluation& pressure,
340  const Evaluation& oilSaturation,
341  const Evaluation& maxOilSaturation) const
342  { return isothermalPvt_->saturatedGasDissolutionFactor(regionIdx, temperature, pressure, oilSaturation, maxOilSaturation); }
343 
351  template <class Evaluation>
352  Evaluation saturationPressure(unsigned regionIdx,
353  const Evaluation& temperature,
354  const Evaluation& pressure) const
355  { return isothermalPvt_->saturationPressure(regionIdx, temperature, pressure); }
356 
357  template <class Evaluation>
358  Evaluation diffusionCoefficient(const Evaluation& temperature,
359  const Evaluation& pressure,
360  unsigned compIdx) const
361  {
362  return isothermalPvt_->diffusionCoefficient(temperature, pressure, compIdx);
363  }
364 
365  const IsothermalPvt* isoThermalPvt() const
366  { return isothermalPvt_; }
367 
368  Scalar oilReferenceDensity(unsigned regionIdx) const
369  { return isothermalPvt_->oilReferenceDensity(regionIdx); }
370 
371  Scalar hVap(unsigned regionIdx) const
372  { return this->hVap_[regionIdx]; }
373 
374  const std::vector<TabulatedOneDFunction>& oilvisctCurves() const
375  { return oilvisctCurves_; }
376 
377  const std::vector<Scalar>& viscrefPress() const
378  { return viscrefPress_; }
379 
380  const std::vector<Scalar>& viscrefRs() const
381  { return viscrefRs_; }
382 
383  const std::vector<Scalar>& viscRef() const
384  { return viscRef_; }
385 
386  const std::vector<Scalar>& oildentRefTemp() const
387  { return oildentRefTemp_; }
388 
389  const std::vector<Scalar>& oildentCT1() const
390  { return oildentCT1_; }
391 
392  const std::vector<Scalar>& oildentCT2() const
393  { return oildentCT2_; }
394 
395  const std::vector<TabulatedOneDFunction>& internalEnergyCurves() const
396  { return internalEnergyCurves_; }
397 
398  bool enableInternalEnergy() const
399  { return enableInternalEnergy_; }
400 
401  const std::vector<Scalar>& oilJTRefPres() const
402  { return oilJTRefPres_; }
403 
404  const std::vector<Scalar>& oilJTC() const
405  { return oilJTC_; }
406 
407  bool operator==(const OilPvtThermal<Scalar>& data) const;
408 
409  OilPvtThermal<Scalar>& operator=(const OilPvtThermal<Scalar>& data);
410 
411 private:
412  IsothermalPvt* isothermalPvt_{nullptr};
413 
414  // The PVT properties needed for temperature dependence of the viscosity. We need
415  // to store one value per PVT region.
416  std::vector<TabulatedOneDFunction> oilvisctCurves_{};
417  std::vector<Scalar> viscrefPress_{};
418  std::vector<Scalar> viscrefRs_{};
419  std::vector<Scalar> viscRef_{};
420 
421  // The PVT properties needed for temperature dependence of the density.
422  std::vector<Scalar> oildentRefTemp_{};
423  std::vector<Scalar> oildentCT1_{};
424  std::vector<Scalar> oildentCT2_{};
425 
426  std::vector<Scalar> oilJTRefPres_{};
427  std::vector<Scalar> oilJTC_{};
428 
429  std::vector<Scalar> rhoRefG_{};
430  std::vector<Scalar> hVap_{};
431 
432  // piecewise linear curve representing the internal energy of oil
433  std::vector<TabulatedOneDFunction> internalEnergyCurves_{};
434 
435  bool enableThermalDensity_{false};
436  bool enableJouleThomson_{false};
437  bool enableThermalViscosity_{false};
438  bool enableInternalEnergy_{false};
439 };
440 
441 } // namespace Opm
442 
443 #endif
void setNumRegions(std::size_t numRegions)
Set the number of PVT-regions considered by this object.
Definition: OilPvtThermal.cpp:181
Evaluation saturationPressure(unsigned regionIdx, const Evaluation &temperature, const Evaluation &Rs) const
Returns the saturation pressure [Pa] of oil given the mass fraction of the gas component in the oil p...
Definition: OilPvtMultiplexer.hpp:247
Evaluation saturatedViscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: OilPvtThermal.hpp:225
void initFromState(const EclipseState &eclState, const Schedule &schedule)
Implement the temperature part of the oil PVT properties.
Definition: OilPvtThermal.cpp:41
Evaluation saturatedViscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: OilPvtMultiplexer.hpp:187
Definition: Schedule.hpp:100
bool enableThermalViscosity() const
Returns true iff the viscosity of the oil phase is temperature dependent.
Definition: OilPvtThermal.hpp:131
Evaluation saturationPressure(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the saturation pressure of the oil phase [Pa].
Definition: OilPvtThermal.hpp:352
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the formation volume factor [-] of the fluid phase.
Definition: OilPvtMultiplexer.hpp:214
Scalar oilReferenceDensity(unsigned regionIdx) const
Return the reference density which are considered by this PVT-object.
Definition: OilPvtMultiplexer.cpp:130
Definition: EclipseState.hpp:66
std::pair< LhsEval, LhsEval > inverseFormationVolumeFactorAndViscosity(const FluidState &fluidState, unsigned regionIdx)
Returns the formation volume factor [-] and viscosity [Pa s] of the fluid phase.
Definition: OilPvtMultiplexer.hpp:207
Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the formation volume factor [-] of gas-saturated oil phase.
Definition: OilPvtThermal.hpp:295
This class represents the Pressure-Volume-Temperature relations of the oil phase in the black-oil mod...
Definition: OilPvtMultiplexer.hpp:109
bool enableThermalDensity() const
Returns true iff the density of the oil phase is temperature dependent.
Definition: OilPvtThermal.hpp:119
Evaluation viscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: OilPvtThermal.hpp:206
Implements a linearly interpolated scalar function that depends on one variable.
Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &oilSaturation, const Evaluation &maxOilSaturation) const
Returns the gas dissolution factor [m^3/m^3] of the oil phase.
Definition: OilPvtThermal.hpp:337
This class implements temperature dependence of the PVT properties of oil.
Definition: OilPvtThermal.hpp:49
Evaluation diffusionCoefficient(const Evaluation &temperature, const Evaluation &pressure, unsigned compIdx) const
Calculate the binary molecular diffusion coefficient for a component in a fluid phase [mol^2 * s / (k...
Definition: OilPvtMultiplexer.hpp:256
Implements a linearly interpolated scalar function that depends on one variable.
Definition: Tabulated1DFunction.hpp:50
Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the gas dissolution factor [m^3/m^3] of saturated oil.
Definition: OilPvtMultiplexer.hpp:223
Evaluation viscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: OilPvtMultiplexer.hpp:177
Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the gas dissolution factor [m^3/m^3] of the oil phase.
Definition: OilPvtThermal.hpp:324
void initEnd()
Finish initializing the thermal part of the oil phase PVT properties.
Definition: OilPvtThermal.hpp:113
Evaluation internalEnergy(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs) const
Returns the specific internal energy [J/kg] of oil given a set of parameters.
Definition: OilPvtThermal.hpp:141
Evaluation inverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs) const
Returns the formation volume factor [-] of the fluid phase.
Definition: OilPvtMultiplexer.hpp:196
Evaluation inverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs) const
Returns the formation volume factor [-] of the fluid phase.
Definition: OilPvtThermal.hpp:243
std::pair< LhsEval, LhsEval > inverseFormationVolumeFactorAndViscosity(const FluidState &fluidState, unsigned regionIdx)
Returns the formation volume factor [-] and viscosity [Pa s] of the fluid phase.
Definition: OilPvtThermal.hpp:270
bool enableJouleThomson() const
Returns true iff Joule-Thomson effect for the oil phase is active.
Definition: OilPvtThermal.hpp:125