opm-common
Loading...
Searching...
No Matches
GasPvtThermal.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_GAS_PVT_THERMAL_HPP
28#define OPM_GAS_PVT_THERMAL_HPP
29
31
32#include <cstddef>
33
34namespace Opm {
35
36class EclipseState;
37class Schedule;
38
39template <class Scalar, bool enableThermal>
41
48template <class Scalar>
49class GasPvtThermal
50{
51public:
52 using IsothermalPvt = GasPvtMultiplexer<Scalar, /*enableThermal=*/false>;
53 using TabulatedOneDFunction = Tabulated1DFunction<Scalar>;
54
55 GasPvtThermal() = default;
56
57 GasPvtThermal(IsothermalPvt* isothermalPvt,
58 const std::vector<TabulatedOneDFunction>& gasvisctCurves,
59 const std::vector<Scalar>& viscrefPress,
60 const std::vector<Scalar>& viscRef,
61 const std::vector<Scalar>& gasdentRefTemp,
62 const std::vector<Scalar>& gasdentCT1,
63 const std::vector<Scalar>& gasdentCT2,
64 const std::vector<Scalar>& gasJTRefPres,
65 const std::vector<Scalar>& gasJTC,
66 const std::vector<TabulatedOneDFunction>& internalEnergyCurves,
70 bool enableInternalEnergy)
71 : isothermalPvt_(isothermalPvt)
72 , gasvisctCurves_(gasvisctCurves)
73 , viscrefPress_(viscrefPress)
74 , viscRef_(viscRef)
75 , gasdentRefTemp_(gasdentRefTemp)
76 , gasdentCT1_(gasdentCT1)
77 , gasdentCT2_(gasdentCT2)
78 , gasJTRefPres_(gasJTRefPres)
79 , gasJTC_(gasJTC)
80 , internalEnergyCurves_(internalEnergyCurves)
81 , enableThermalDensity_(enableThermalDensity)
82 , enableJouleThomson_(enableJouleThomson)
83 , enableThermalViscosity_(enableThermalViscosity)
84 , enableInternalEnergy_(enableInternalEnergy)
85 { }
86
87 GasPvtThermal(const GasPvtThermal& data)
88 { *this = data; }
89
90 ~GasPvtThermal()
91 { delete isothermalPvt_; }
92
96 void initFromState(const EclipseState& eclState, const Schedule& schedule);
97
101 void setNumRegions(std::size_t numRegions);
102
103 void setVapPars(const Scalar par1, const Scalar par2)
104 {
105 isothermalPvt_->setVapPars(par1, par2);
106 }
107
111 void initEnd()
112 { }
113
118 { return enableThermalDensity_; }
119
124 { return enableJouleThomson_; }
125
130 { return enableThermalViscosity_; }
131
132 std::size_t numRegions() const
133 { return viscrefPress_.size(); }
134
138 template <class Evaluation>
139 Evaluation internalEnergy(unsigned regionIdx,
140 const Evaluation& temperature,
141 const Evaluation& pressure,
142 const Evaluation& Rv,
143 [[maybe_unused]] const Evaluation& RvW) const
144 {
145 if (!enableInternalEnergy_) {
146 throw std::runtime_error("Requested the internal energy of gas but it is disabled");
147 }
148
149 if (!enableJouleThomson_) {
150 // compute the specific internal energy for the specified tempature. We use linear
151 // interpolation here despite the fact that the underlying heat capacities are
152 // piecewise linear (which leads to a quadratic function)
153 return internalEnergyCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
154 }
155 else {
156 // NB should probably be revisited with adding more or restrict to linear internal energy
157 OpmLog::warning("Experimental code for jouleThomson: simulation will be slower");
158 Evaluation Tref = gasdentRefTemp_[regionIdx];
159 Evaluation Pref = gasJTRefPres_[regionIdx];
160 Scalar JTC = gasJTC_[regionIdx]; // if JTC is default then JTC is calculaited
161 Evaluation Rvw = 0.0;
162
163 Evaluation invB = inverseFormationVolumeFactor(regionIdx, temperature, pressure, Rv, Rvw);
164 // NB this assumes internalEnergyCurve(0) = 0 derivative should be used add Cp table ??
165 Evaluation Cp = (internalEnergyCurves_[regionIdx].eval(temperature, /*extrapolate=*/true))/temperature;
166 Evaluation density = invB * (gasReferenceDensity(regionIdx) + Rv * rhoRefO_[regionIdx]);
167
168 Evaluation enthalpyPres;
169 if (JTC != 0) {
170 enthalpyPres = -Cp * JTC * (pressure -Pref);
171 }
172 else if (enableThermalDensity_) {
173 Scalar c1T = gasdentCT1_[regionIdx];
174 Scalar c2T = gasdentCT2_[regionIdx];
175
176 Evaluation alpha = (c1T + 2 * c2T * (temperature - Tref)) /
177 (1 + c1T *(temperature - Tref) + c2T * (temperature - Tref) * (temperature - Tref));
178
179 constexpr const int N = 100; // value is experimental
180 Evaluation deltaP = (pressure - Pref)/N;
181 Evaluation enthalpyPresPrev = 0;
182 for (std::size_t i = 0; i < N; ++i) {
183 Evaluation Pnew = Pref + i * deltaP;
184 Evaluation rho = inverseFormationVolumeFactor(regionIdx, temperature, Pnew, Rv, Rvw) *
185 (gasReferenceDensity(regionIdx) + Rv * rhoRefO_[regionIdx]);
186 // see e.g.https://en.wikipedia.org/wiki/Joule-Thomson_effect for a derivation of the Joule-Thomson coeff.
187 Evaluation jouleThomsonCoefficient = -(1.0/Cp) * (1.0 - alpha * temperature)/rho;
188 Evaluation deltaEnthalpyPres = -Cp * jouleThomsonCoefficient * deltaP;
189 enthalpyPres = enthalpyPresPrev + deltaEnthalpyPres;
190 enthalpyPresPrev = enthalpyPres;
191 }
192 }
193 else {
194 throw std::runtime_error("Requested Joule-thomson calculation but thermal "
195 "gas density (GASDENT) is not provided");
196 }
197
198 Evaluation enthalpy = Cp * (temperature - Tref) + enthalpyPres;
199
200 return enthalpy - pressure/density;
201 }
202 }
203
207 template <class Evaluation>
208 Evaluation viscosity(unsigned regionIdx,
209 const Evaluation& temperature,
210 const Evaluation& pressure,
211 const Evaluation& Rv,
212 const Evaluation& Rvw) const
213 {
214 const auto& isothermalMu = isothermalPvt_->viscosity(regionIdx, temperature, pressure, Rv, Rvw);
216 return isothermalMu;
217
218 // compute the viscosity deviation due to temperature
219 const auto& muGasvisct = gasvisctCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
220 return muGasvisct/viscRef_[regionIdx]*isothermalMu;
221 }
222
226 template <class Evaluation>
227 Evaluation saturatedViscosity(unsigned regionIdx,
228 const Evaluation& temperature,
229 const Evaluation& pressure) const
230 {
231 const auto& isothermalMu = isothermalPvt_->saturatedViscosity(regionIdx, temperature, pressure);
233 return isothermalMu;
234
235 // compute the viscosity deviation due to temperature
236 const auto& muGasvisct = gasvisctCurves_[regionIdx].eval(temperature, true);
237 return muGasvisct/viscRef_[regionIdx]*isothermalMu;
238 }
239
243 template <class Evaluation>
244 Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
245 const Evaluation& temperature,
246 const Evaluation& pressure,
247 const Evaluation& Rv,
248 const Evaluation& /*Rvw*/) const
249 {
250 const Evaluation& Rvw = 0.0;
251 const auto& b =
252 isothermalPvt_->inverseFormationVolumeFactor(regionIdx, temperature,
253 pressure, Rv, Rvw);
254
255 if (!enableThermalDensity()) {
256 return b;
257 }
258
259 // we use the same approach as for the for water here, but with the OPM-specific
260 // GASDENT keyword.
261 //
262 // TODO: Since gas is quite a bit more compressible than water, it might be
263 // necessary to make GASDENT to a table keyword. If the current temperature
264 // is relatively close to the reference temperature, the current approach
265 // should be good enough, though.
266 Scalar TRef = gasdentRefTemp_[regionIdx];
267 Scalar cT1 = gasdentCT1_[regionIdx];
268 Scalar cT2 = gasdentCT2_[regionIdx];
269 const Evaluation& Y = temperature - TRef;
270
271 return b / (1 + (cT1 + cT2 * Y) * Y);
272 }
273
277 template <class FluidState, class LhsEval = typename FluidState::ValueType>
278 std::pair<LhsEval, LhsEval>
279 inverseFormationVolumeFactorAndViscosity(const FluidState& fluidState, unsigned regionIdx)
280 {
281 auto [b, mu] = isothermalPvt_->inverseFormationVolumeFactorAndViscosity(fluidState, regionIdx);
282 const LhsEval& temperature = decay<LhsEval>(fluidState.temperature(FluidState::gasPhaseIdx));
283 if (enableThermalDensity()) {
284 // we use the same approach as for the for water here, but with the OPM-specific
285 // GASDENT keyword.
286 //
287 // TODO: Since gas is quite a bit more compressible than water, it might be
288 // necessary to make GASDENT to a table keyword. If the current temperature
289 // is relatively close to the reference temperature, the current approach
290 // should be good enough, though.
291 Scalar TRef = gasdentRefTemp_[regionIdx];
292 Scalar cT1 = gasdentCT1_[regionIdx];
293 Scalar cT2 = gasdentCT2_[regionIdx];
294 const LhsEval& Y = temperature - TRef;
295 b /= (1.0 + (cT1 + cT2 * Y) * Y);
296 }
298 // compute the viscosity deviation due to temperature
299 const auto& muGasvisct = gasvisctCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
300 mu *= (muGasvisct / viscRef_[regionIdx]);
301 }
302 return { b, mu };
303 }
304
308 template <class Evaluation>
309 Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
310 const Evaluation& temperature,
311 const Evaluation& pressure) const
312 {
313 const auto& b =
314 isothermalPvt_->saturatedInverseFormationVolumeFactor(regionIdx, temperature, pressure);
315
316 if (!enableThermalDensity()) {
317 return b;
318 }
319
320 // we use the same approach as for the for water here, but with the OPM-specific
321 // GASDENT keyword.
322 //
323 // TODO: Since gas is quite a bit more compressible than water, it might be
324 // necessary to make GASDENT to a table keyword. If the current temperature
325 // is relatively close to the reference temperature, the current approach
326 // should be good enough, though.
327 Scalar TRef = gasdentRefTemp_[regionIdx];
328 Scalar cT1 = gasdentCT1_[regionIdx];
329 Scalar cT2 = gasdentCT2_[regionIdx];
330 const Evaluation& Y = temperature - TRef;
331
332 return b / (1 + (cT1 + cT2 * Y) * Y);
333 }
334
338 template <class Evaluation>
339 Evaluation saturatedWaterVaporizationFactor(unsigned /*regionIdx*/,
340 const Evaluation& /*temperature*/,
341 const Evaluation& /*pressure*/) const
342 { return 0.0; }
343
347 template <class Evaluation = Scalar>
348 Evaluation saturatedWaterVaporizationFactor(unsigned /*regionIdx*/,
349 const Evaluation& /*temperature*/,
350 const Evaluation& /*pressure*/,
351 const Evaluation& /*saltConcentration*/) const
352 { return 0.0; }
353
361 template <class Evaluation>
362 Evaluation saturatedOilVaporizationFactor(unsigned regionIdx,
363 const Evaluation& temperature,
364 const Evaluation& pressure) const
365 { return isothermalPvt_->saturatedOilVaporizationFactor(regionIdx, temperature, pressure); }
366
374 template <class Evaluation>
375 Evaluation saturatedOilVaporizationFactor(unsigned regionIdx,
376 const Evaluation& temperature,
377 const Evaluation& pressure,
378 const Evaluation& oilSaturation,
379 const Evaluation& maxOilSaturation) const
380 {
381 return isothermalPvt_->saturatedOilVaporizationFactor(regionIdx, temperature,
382 pressure, oilSaturation,
383 maxOilSaturation);
384 }
385
393 template <class Evaluation>
394 Evaluation saturationPressure(unsigned regionIdx,
395 const Evaluation& temperature,
396 const Evaluation& pressure) const
397 { return isothermalPvt_->saturationPressure(regionIdx, temperature, pressure); }
398
399 template <class Evaluation>
400 Evaluation diffusionCoefficient(const Evaluation& temperature,
401 const Evaluation& pressure,
402 unsigned compIdx) const
403 {
404 return isothermalPvt_->diffusionCoefficient(temperature, pressure, compIdx);
405 }
406 const IsothermalPvt* isoThermalPvt() const
407 { return isothermalPvt_; }
408
409 Scalar gasReferenceDensity(unsigned regionIdx) const
410 { return isothermalPvt_->gasReferenceDensity(regionIdx); }
411
412 Scalar hVap(unsigned regionIdx) const
413 { return this->hVap_[regionIdx]; }
414
415 const std::vector<TabulatedOneDFunction>& gasvisctCurves() const
416 { return gasvisctCurves_; }
417
418 const std::vector<Scalar>& viscrefPress() const
419 { return viscrefPress_; }
420
421 const std::vector<Scalar>& viscRef() const
422 { return viscRef_; }
423
424 const std::vector<Scalar>& gasdentRefTemp() const
425 { return gasdentRefTemp_; }
426
427 const std::vector<Scalar>& gasdentCT1() const
428 { return gasdentCT1_; }
429
430 const std::vector<Scalar>& gasdentCT2() const
431 { return gasdentCT2_; }
432
433 const std::vector<TabulatedOneDFunction>& internalEnergyCurves() const
434 { return internalEnergyCurves_; }
435
436 bool enableInternalEnergy() const
437 { return enableInternalEnergy_; }
438
439 const std::vector<Scalar>& gasJTRefPres() const
440 { return gasJTRefPres_; }
441
442 const std::vector<Scalar>& gasJTC() const
443 { return gasJTC_; }
444
445 bool operator==(const GasPvtThermal<Scalar>& data) const;
446
447 GasPvtThermal<Scalar>& operator=(const GasPvtThermal<Scalar>& data);
448
449private:
450 IsothermalPvt* isothermalPvt_{nullptr};
451
452 // The PVT properties needed for temperature dependence of the viscosity. We need
453 // to store one value per PVT region.
454 std::vector<TabulatedOneDFunction> gasvisctCurves_{};
455 std::vector<Scalar> viscrefPress_{};
456 std::vector<Scalar> viscRef_{};
457
458 std::vector<Scalar> gasdentRefTemp_{};
459 std::vector<Scalar> gasdentCT1_{};
460 std::vector<Scalar> gasdentCT2_{};
461
462 std::vector<Scalar> gasJTRefPres_{};
463 std::vector<Scalar> gasJTC_{};
464
465 std::vector<Scalar> rhoRefO_{};
466 std::vector<Scalar> hVap_{};
467
468 // piecewise linear curve representing the internal energy of gas
469 std::vector<TabulatedOneDFunction> internalEnergyCurves_{};
470
471 bool enableThermalDensity_{false};
472 bool enableJouleThomson_{false};
473 bool enableThermalViscosity_{false};
474 bool enableInternalEnergy_{false};
475};
476
477} // namespace Opm
478
479#endif
Implements a linearly interpolated scalar function that depends on one variable.
Definition EclipseState.hpp:66
This class represents the Pressure-Volume-Temperature relations of the gas phase in the black-oil mod...
Definition GasPvtMultiplexer.hpp:109
Scalar gasReferenceDensity(unsigned regionIdx) const
Return the reference density which are considered by this PVT-object.
Definition GasPvtMultiplexer.cpp:57
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 GasPvtMultiplexer.hpp:279
bool enableThermalDensity() const
Returns true iff the density of the gas phase is temperature dependent.
Definition GasPvtThermal.hpp:117
Evaluation viscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rv, const Evaluation &Rvw) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition GasPvtThermal.hpp:208
Evaluation saturatedOilVaporizationFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &oilSaturation, const Evaluation &maxOilSaturation) const
Returns the oil vaporization factor [m^3/m^3] of the gas phase.
Definition GasPvtThermal.hpp:375
Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the formation volume factor [-] of oil-saturated gas.
Definition GasPvtThermal.hpp:309
Evaluation saturatedOilVaporizationFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the oil vaporization factor [m^3/m^3] of the gas phase.
Definition GasPvtThermal.hpp:362
Evaluation saturatedWaterVaporizationFactor(unsigned, const Evaluation &, const Evaluation &, const Evaluation &) const
Returns the water vaporization factor [m^3/m^3] of water saturated gas.
Definition GasPvtThermal.hpp:348
Evaluation internalEnergy(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rv, const Evaluation &RvW) const
Returns the specific internal energy [J/kg] of gas given a set of parameters.
Definition GasPvtThermal.hpp:139
void setNumRegions(std::size_t numRegions)
Set the number of PVT-regions considered by this object.
Definition GasPvtThermal.cpp:191
void initEnd()
Finish initializing the thermal part of the gas phase PVT properties.
Definition GasPvtThermal.hpp:111
Evaluation inverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rv, const Evaluation &) const
Returns the formation volume factor [-] of the fluid phase.
Definition GasPvtThermal.hpp:244
bool enableJouleThomson() const
Returns true iff Joule-Thomson effect for the gas phase is active.
Definition GasPvtThermal.hpp:123
bool enableThermalViscosity() const
Returns true iff the viscosity of the gas phase is temperature dependent.
Definition GasPvtThermal.hpp:129
Evaluation saturatedWaterVaporizationFactor(unsigned, const Evaluation &, const Evaluation &) const
Returns the water vaporization factor [m^3/m^3] of the water phase.
Definition GasPvtThermal.hpp:339
std::pair< LhsEval, LhsEval > inverseFormationVolumeFactorAndViscosity(const FluidState &fluidState, unsigned regionIdx)
Returns the formation volume factor [-] and viscosity [Pa s] of the fluid phase.
Definition GasPvtThermal.hpp:279
Evaluation saturatedViscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the dynamic viscosity [Pa s] of the oil-saturated gas phase given a set of parameters.
Definition GasPvtThermal.hpp:227
Evaluation saturationPressure(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the saturation pressure of the gas phase [Pa].
Definition GasPvtThermal.hpp:394
void initFromState(const EclipseState &eclState, const Schedule &schedule)
Implement the temperature part of the gas PVT properties.
Definition GasPvtThermal.cpp:42
Definition Schedule.hpp:101
Implements a linearly interpolated scalar function that depends on one variable.
Definition Tabulated1DFunction.hpp:51
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30