opm-common
Loading...
Searching...
No Matches
WaterPvtThermal.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_WATER_PVT_THERMAL_HPP
28#define OPM_WATER_PVT_THERMAL_HPP
29
31
32#include <cstddef>
33
34namespace Opm {
35
36class EclipseState;
37class Schedule;
38
39template <class Scalar, bool enableThermal, bool enableBrine>
41
48template <class Scalar, bool enableBrine>
49class WaterPvtThermal
50{
51public:
52 using TabulatedOneDFunction = Tabulated1DFunction<Scalar>;
53 using IsothermalPvt = WaterPvtMultiplexer<Scalar, /*enableThermal=*/false, enableBrine>;
54
55 WaterPvtThermal() = default;
56
57 WaterPvtThermal(IsothermalPvt* isothermalPvt,
58 const std::vector<Scalar>& viscrefPress,
59 const std::vector<Scalar>& watdentRefTemp,
60 const std::vector<Scalar>& watdentCT1,
61 const std::vector<Scalar>& watdentCT2,
62 const std::vector<Scalar>& watJTRefPres,
63 const std::vector<Scalar>& watJTC,
64 const std::vector<Scalar>& pvtwRefPress,
65 const std::vector<Scalar>& pvtwRefB,
66 const std::vector<Scalar>& pvtwCompressibility,
67 const std::vector<Scalar>& pvtwViscosity,
68 const std::vector<Scalar>& pvtwViscosibility,
69 const std::vector<Scalar>& referenceSaltConcentration,
70 const std::vector<TabulatedOneDFunction>& watvisctCurves,
71 const std::vector<TabulatedOneDFunction>& internalEnergyCurves,
75 bool enableInternalEnergy,
76 bool enableBrineViscosity)
77 : isothermalPvt_(isothermalPvt)
78 , viscrefPress_(viscrefPress)
79 , watdentRefTemp_(watdentRefTemp)
80 , watdentCT1_(watdentCT1)
81 , watdentCT2_(watdentCT2)
82 , watJTRefPres_(watJTRefPres)
83 , watJTC_(watJTC)
84 , pvtwRefPress_(pvtwRefPress)
85 , pvtwRefB_(pvtwRefB)
86 , pvtwCompressibility_(pvtwCompressibility)
87 , pvtwViscosity_(pvtwViscosity)
88 , pvtwViscosibility_(pvtwViscosibility)
89 , referenceSaltConcentration_(referenceSaltConcentration)
90 , watvisctCurves_(watvisctCurves)
91 , internalEnergyCurves_(internalEnergyCurves)
92 , enableThermalDensity_(enableThermalDensity)
93 , enableJouleThomson_(enableJouleThomson)
94 , enableThermalViscosity_(enableThermalViscosity)
95 , enableInternalEnergy_(enableInternalEnergy)
96 , enableBrineViscosity_(enableBrineViscosity)
97 { }
98
99 WaterPvtThermal(const WaterPvtThermal& data)
100 { *this = data; }
101
102 ~WaterPvtThermal()
103 { delete isothermalPvt_; }
104
108 void initFromState(const EclipseState& eclState, const Schedule& schedule);
109
113 void setNumRegions(std::size_t numRegions);
114
115 void setVapPars(const Scalar par1, const Scalar par2)
116 {
117 isothermalPvt_->setVapPars(par1, par2);
118 }
119
123 void initEnd()
124 { }
125
130 { return enableThermalDensity_; }
131
136 { return enableJouleThomson_; }
137
142 { return enableThermalViscosity_; }
143
144 Scalar hVap(unsigned regionIdx) const
145 { return this->hVap_[regionIdx]; }
146
147 std::size_t numRegions() const
148 { return pvtwRefPress_.size(); }
149
153 template <class Evaluation>
154 Evaluation internalEnergy(unsigned regionIdx,
155 const Evaluation& temperature,
156 const Evaluation& pressure,
157 const Evaluation& Rsw,
158 const Evaluation& saltconcentration) const
159 {
160 if (!enableInternalEnergy_) {
161 throw std::runtime_error("Requested the internal energy of water but it is disabled");
162 }
163
164 if (!enableJouleThomson_) {
165 // compute the specific internal energy for the specified tempature. We use linear
166 // interpolation here despite the fact that the underlying heat capacities are
167 // piecewise linear (which leads to a quadratic function)
168 return internalEnergyCurves_[regionIdx].eval(temperature, /*extrapolate=*/true);
169 }
170 else {
171 Evaluation Tref = watdentRefTemp_[regionIdx];
172 Evaluation Pref = watJTRefPres_[regionIdx];
173 Scalar JTC = watJTC_[regionIdx]; // if JTC is default then JTC is calculated
174
175 Evaluation invB = inverseFormationVolumeFactor(regionIdx, temperature, pressure, Rsw, saltconcentration);
176 Evaluation Cp = internalEnergyCurves_[regionIdx].eval(temperature, /*extrapolate=*/true)/temperature;
177 Evaluation density = invB * waterReferenceDensity(regionIdx);
178
179 Evaluation enthalpyPres;
180 if (JTC != 0) {
181 enthalpyPres = -Cp * JTC * (pressure - Pref);
182 }
183 else if (enableThermalDensity_) {
184 Scalar c1T = watdentCT1_[regionIdx];
185 Scalar c2T = watdentCT2_[regionIdx];
186
187 Evaluation alpha = (c1T + 2 * c2T * (temperature - Tref)) /
188 (1 + c1T *(temperature - Tref) + c2T * (temperature - Tref) * (temperature - Tref));
189
190 constexpr const int N = 100; // value is experimental
191 Evaluation deltaP = (pressure - Pref) / N;
192 Evaluation enthalpyPresPrev = 0;
193 for (std::size_t i = 0; i < N; ++i) {
194 Evaluation Pnew = Pref + i * deltaP;
195 Evaluation rho = inverseFormationVolumeFactor(regionIdx, temperature,
196 Pnew, Rsw, saltconcentration) *
197 waterReferenceDensity(regionIdx);
198 Evaluation jouleThomsonCoefficient = -(1.0 / Cp) * (1.0 - alpha * temperature) / rho;
199 Evaluation deltaEnthalpyPres = -Cp * jouleThomsonCoefficient * deltaP;
200 enthalpyPres = enthalpyPresPrev + deltaEnthalpyPres;
201 enthalpyPresPrev = enthalpyPres;
202 }
203 }
204 else {
205 throw std::runtime_error("Requested Joule-thomson calculation but "
206 "thermal water density (WATDENT) is not provided");
207 }
208
209 Evaluation enthalpy = Cp * (temperature - Tref) + enthalpyPres;
210
211 return enthalpy - pressure/density;
212 }
213 }
214
218 template <class Evaluation>
219 Evaluation viscosity(unsigned regionIdx,
220 const Evaluation& temperature,
221 const Evaluation& pressure,
222 const Evaluation& Rsw,
223 const Evaluation& saltconcentration) const
224 {
225 const auto& isothermalMu = isothermalPvt_->viscosity(regionIdx, temperature,
226 pressure, Rsw, saltconcentration);
227 if (!enableThermalViscosity()) {
228 return isothermalMu;
229 }
230
231 const auto& muWatvisct = watvisctCurves_[regionIdx].eval(temperature, true);
232 if (enableBrineViscosity()) {
233 auto muRef = isothermalPvt_->viscosity(regionIdx, temperature, Evaluation(viscrefPress_[regionIdx]), Rsw, Evaluation(referenceSaltConcentration_[regionIdx]));
234 return isothermalMu * muWatvisct / muRef;
235 } else {
236 Scalar x = -pvtwViscosibility_[regionIdx] * (viscrefPress_[regionIdx] - pvtwRefPress_[regionIdx]);
237 Scalar muRef = pvtwViscosity_[regionIdx] / (1.0 + x + 0.5 * x * x);
238 return isothermalMu * muWatvisct / muRef;
239 }
240 }
241
245 template <class Evaluation>
246 Evaluation saturatedViscosity(unsigned regionIdx,
247 const Evaluation& temperature,
248 const Evaluation& pressure,
249 const Evaluation& saltconcentration) const
250 {
251 const auto& isothermalMu = isothermalPvt_->saturatedViscosity(regionIdx, temperature,
252 pressure, saltconcentration);
253 if (!enableThermalViscosity()) {
254 return isothermalMu;
255 }
256
257 Scalar x = -pvtwViscosibility_[regionIdx] * (viscrefPress_[regionIdx] -
258 pvtwRefPress_[regionIdx]);
259 Scalar muRef = pvtwViscosity_[regionIdx] / (1.0 + x + 0.5 * x * x);
260
261 // compute the viscosity deviation due to temperature
262 const auto& muWatvisct = watvisctCurves_[regionIdx].eval(temperature, true);
263 return isothermalMu * muWatvisct / muRef;
264 }
265
269 template <class Evaluation>
270 Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
271 const Evaluation& temperature,
272 const Evaluation& pressure,
273 const Evaluation& saltconcentration) const
274 {
275 Evaluation Rsw = 0.0;
276 return inverseFormationVolumeFactor(regionIdx, temperature, pressure,
277 Rsw, saltconcentration);
278 }
279
282 template <class Evaluation>
283 Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
284 const Evaluation& temperature,
285 const Evaluation& pressure,
286 const Evaluation& Rsw,
287 const Evaluation& saltconcentration) const
288 {
289 if (!enableThermalDensity()) {
290 return isothermalPvt_->inverseFormationVolumeFactor(regionIdx, temperature,
291 pressure, Rsw, saltconcentration);
292 }
293
294 Scalar BwRef = pvtwRefB_[regionIdx];
295 Scalar TRef = watdentRefTemp_[regionIdx];
296 const Evaluation& X = pvtwCompressibility_[regionIdx] * (pressure -
297 pvtwRefPress_[regionIdx]);
298 Scalar cT1 = watdentCT1_[regionIdx];
299 Scalar cT2 = watdentCT2_[regionIdx];
300 const Evaluation& Y = temperature - TRef;
301
302 // this is inconsistent with the density calculation of water in the isothermal
303 // case (it misses the quadratic pressure term), but it is the equation given in
304 // the documentation.
305 return 1.0 / (((1 - X) * (1 + cT1 * Y + cT2 * Y * Y)) * BwRef);
306 }
307
311 template <class FluidState, class LhsEval = typename FluidState::ValueType>
312 std::pair<LhsEval, LhsEval>
313 inverseFormationVolumeFactorAndViscosity(const FluidState& fluidState, unsigned regionIdx)
314 {
315 auto [b, mu] = isothermalPvt_->inverseFormationVolumeFactorAndViscosity(fluidState, regionIdx);
316 const LhsEval& pressure = decay<LhsEval>(fluidState.pressure(FluidState::waterPhaseIdx));
317 const LhsEval& temperature = decay<LhsEval>(fluidState.temperature(FluidState::waterPhaseIdx));
318 if (enableThermalDensity()) {
319 Scalar BwRef = pvtwRefB_[regionIdx];
320 Scalar TRef = watdentRefTemp_[regionIdx];
321 const LhsEval X = pvtwCompressibility_[regionIdx] * (pressure - pvtwRefPress_[regionIdx]);
322 Scalar cT1 = watdentCT1_[regionIdx];
323 Scalar cT2 = watdentCT2_[regionIdx];
324 const LhsEval Y = temperature - TRef;
325 // this is inconsistent with the density calculation of water in the isothermal
326 // case (it misses the quadratic pressure term), but it is the equation given in
327 // the documentation.
328 // Note assignment to 'b', not multiplying the isothermal 'b' by a factor!
329 b = 1.0 / (((1 - X) * (1 + cT1 * Y + cT2 * Y * Y)) * BwRef);
330 }
332 Scalar x = -pvtwViscosibility_[regionIdx] * (viscrefPress_[regionIdx] - pvtwRefPress_[regionIdx]);
333 Scalar muRef = pvtwViscosity_[regionIdx] / (1.0 + x + 0.5 * x * x);
334 // compute the viscosity deviation due to temperature
335 const auto muWatvisct = watvisctCurves_[regionIdx].eval(temperature, true);
336 // Split operations to get same order of operations as in the viscosity() function.
337 mu *= muWatvisct;
338 mu /= muRef;
339 }
340 return { b, mu };
341 }
342
350 template <class Evaluation>
351 Evaluation saturationPressure(unsigned /*regionIdx*/,
352 const Evaluation& /*temperature*/,
353 const Evaluation& /*Rs*/,
354 const Evaluation& /*saltconcentration*/) const
355 { return 0.0; /* this is dead water, so there isn't any meaningful saturation pressure! */ }
356
360 template <class Evaluation>
361 Evaluation saturatedGasDissolutionFactor(unsigned /*regionIdx*/,
362 const Evaluation& /*temperature*/,
363 const Evaluation& /*pressure*/,
364 const Evaluation& /*saltconcentration*/) const
365 { return 0.0; /* this is dead water! */ }
366
367 template <class Evaluation>
368 Evaluation diffusionCoefficient(const Evaluation& /*temperature*/,
369 const Evaluation& /*pressure*/,
370 unsigned /*compIdx*/,
371 unsigned /*regionIdx*/ = 0) const
372 {
373 throw std::runtime_error("Not implemented: The PVT model does not provide "
374 "a diffusionCoefficient()");
375 }
376
377 const IsothermalPvt* isoThermalPvt() const
378 { return isothermalPvt_; }
379
380 Scalar waterReferenceDensity(unsigned regionIdx) const
381 { return isothermalPvt_->waterReferenceDensity(regionIdx); }
382
383 const std::vector<Scalar>& viscrefPress() const
384 { return viscrefPress_; }
385
386 const std::vector<Scalar>& watdentRefTemp() const
387 { return watdentRefTemp_; }
388
389 const std::vector<Scalar>& watdentCT1() const
390 { return watdentCT1_; }
391
392 const std::vector<Scalar>& watdentCT2() const
393 { return watdentCT2_; }
394
395 const std::vector<Scalar>& pvtwRefPress() const
396 { return pvtwRefPress_; }
397
398 const std::vector<Scalar>& pvtwRefB() const
399 { return pvtwRefB_; }
400
401 const std::vector<Scalar>& pvtwCompressibility() const
402 { return pvtwCompressibility_; }
403
404 const std::vector<Scalar>& pvtwViscosity() const
405 { return pvtwViscosity_; }
406
407 const std::vector<Scalar>& pvtwViscosibility() const
408 { return pvtwViscosibility_; }
409
410 const std::vector<Scalar>& referenceSaltConcentration() const
411 { return referenceSaltConcentration_; }
412
413 const std::vector<TabulatedOneDFunction>& watvisctCurves() const
414 { return watvisctCurves_; }
415
416 const std::vector<TabulatedOneDFunction>& internalEnergyCurves() const
417 { return internalEnergyCurves_; }
418
419 bool enableInternalEnergy() const
420 { return enableInternalEnergy_; }
421
422 bool enableBrineViscosity() const
423 { return enableBrineViscosity_; }
424
425 const std::vector<Scalar>& watJTRefPres() const
426 { return watJTRefPres_; }
427
428 const std::vector<Scalar>& watJTC() const
429 { return watJTC_; }
430
431 bool operator==(const WaterPvtThermal<Scalar, enableBrine>& data) const;
432
433 WaterPvtThermal<Scalar, enableBrine>&
434 operator=(const WaterPvtThermal<Scalar, enableBrine>& data);
435
436private:
437 IsothermalPvt* isothermalPvt_{nullptr};
438
439 // The PVT properties needed for temperature dependence. We need to store one
440 // value per PVT region.
441 std::vector<Scalar> viscrefPress_{};
442
443 std::vector<Scalar> watdentRefTemp_{};
444 std::vector<Scalar> watdentCT1_{};
445 std::vector<Scalar> watdentCT2_{};
446
447 std::vector<Scalar> watJTRefPres_{};
448 std::vector<Scalar> watJTC_{};
449
450 std::vector<Scalar> pvtwRefPress_{};
451 std::vector<Scalar> pvtwRefB_{};
452 std::vector<Scalar> pvtwCompressibility_{};
453 std::vector<Scalar> pvtwViscosity_{};
454 std::vector<Scalar> pvtwViscosibility_{};
455 std::vector<Scalar> referenceSaltConcentration_{};
456
457 std::vector<TabulatedOneDFunction> watvisctCurves_{};
458
459 // piecewise linear curve representing the internal energy of water
460 std::vector<TabulatedOneDFunction> internalEnergyCurves_{};
461 std::vector<Scalar> hVap_{};
462
463 bool enableThermalDensity_{false};
464 bool enableJouleThomson_{false};
465 bool enableThermalViscosity_{false};
466 bool enableInternalEnergy_{false};
467 bool enableBrineViscosity_{false};
468};
469
470} // namespace Opm
471
472#endif
Implements a linearly interpolated scalar function that depends on one variable.
Definition EclipseState.hpp:66
Definition Schedule.hpp:101
Implements a linearly interpolated scalar function that depends on one variable.
Definition Tabulated1DFunction.hpp:51
This class represents the Pressure-Volume-Temperature relations of the water phase in the black-oil m...
Definition WaterPvtMultiplexer.hpp:88
Scalar waterReferenceDensity(unsigned regionIdx) const
Return the reference density which are considered by this PVT-object.
Definition WaterPvtMultiplexer.cpp:109
bool enableThermalViscosity() const
Returns true iff the viscosity of the water phase is temperature dependent.
Definition WaterPvtThermal.hpp:141
Evaluation saturationPressure(unsigned, const Evaluation &, const Evaluation &, const Evaluation &) const
Returns the saturation pressure of the water phase [Pa] depending on its mass fraction of the gas com...
Definition WaterPvtThermal.hpp:351
Evaluation viscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rsw, const Evaluation &saltconcentration) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition WaterPvtThermal.hpp:219
void initEnd()
Finish initializing the thermal part of the water phase PVT properties.
Definition WaterPvtThermal.hpp:123
Evaluation inverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rsw, const Evaluation &saltconcentration) const
Returns the formation volume factor [-] of the fluid phase.
Definition WaterPvtThermal.hpp:283
bool enableThermalDensity() const
Returns true iff the density of the water phase is temperature dependent.
Definition WaterPvtThermal.hpp:129
void initFromState(const EclipseState &eclState, const Schedule &schedule)
Implement the temperature part of the water PVT properties.
Definition WaterPvtThermal.cpp:41
Evaluation saturatedGasDissolutionFactor(unsigned, const Evaluation &, const Evaluation &, const Evaluation &) const
Returns the gas dissolution factor [m^3/m^3] of the water phase.
Definition WaterPvtThermal.hpp:361
Evaluation internalEnergy(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rsw, const Evaluation &saltconcentration) const
Returns the specific internal energy [J/kg] of water given a set of parameters.
Definition WaterPvtThermal.hpp:154
Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &saltconcentration) const
Returns the formation volume factor [-] of the fluid phase.
Definition WaterPvtThermal.hpp:270
bool enableJouleThomson() const
Returns true iff Joule-Thomson effect for the water phase is active.
Definition WaterPvtThermal.hpp:135
Evaluation saturatedViscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &saltconcentration) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition WaterPvtThermal.hpp:246
void setNumRegions(std::size_t numRegions)
Set the number of PVT-regions considered by this object.
Definition WaterPvtThermal.cpp:198
std::pair< LhsEval, LhsEval > inverseFormationVolumeFactorAndViscosity(const FluidState &fluidState, unsigned regionIdx)
Returns the formation volume factor [-] and viscosity [Pa s] of the fluid phase.
Definition WaterPvtThermal.hpp:313
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30