Line | Branch | Exec | Source |
---|---|---|---|
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 | // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder | ||
5 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
6 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup FluidSystems | ||
10 | * \brief @copybrief Dumux::Spe5ParameterCache | ||
11 | */ | ||
12 | #ifndef SPE5_PARAMETER_CACHE_HH | ||
13 | #define SPE5_PARAMETER_CACHE_HH | ||
14 | |||
15 | #include <cassert> | ||
16 | |||
17 | #include <dumux/material/components/h2o.hh> | ||
18 | #include <dumux/material/fluidsystems/parametercachebase.hh> | ||
19 | |||
20 | #include <dumux/material/eos/pengrobinson.hh> | ||
21 | #include <dumux/material/eos/pengrobinsonparamsmixture.hh> | ||
22 | |||
23 | namespace Dumux { | ||
24 | |||
25 | /*! | ||
26 | * \ingroup FluidSystems | ||
27 | * \brief Specifies the parameters required by the SPE5 problem which | ||
28 | * are despondent on the thermodynamic state. | ||
29 | */ | ||
30 | template <class Scalar, class FluidSystem> | ||
31 | class Spe5ParameterCache | ||
32 | : public ParameterCacheBase<Spe5ParameterCache<Scalar, FluidSystem> > | ||
33 | { | ||
34 | using ThisType = Spe5ParameterCache<Scalar, FluidSystem>; | ||
35 | using ParentType = ParameterCacheBase<ThisType>; | ||
36 | |||
37 | using PengRobinson = Dumux::PengRobinson<Scalar>; | ||
38 | |||
39 | enum { numPhases = FluidSystem::numPhases }; | ||
40 | |||
41 | enum { wPhaseIdx = FluidSystem::wPhaseIdx }; | ||
42 | enum { oPhaseIdx = FluidSystem::oPhaseIdx }; | ||
43 | enum { gPhaseIdx = FluidSystem::gPhaseIdx }; | ||
44 | |||
45 | public: | ||
46 | // types of the parameter objects for each phase | ||
47 | using OilPhaseParams = PengRobinsonParamsMixture<Scalar, FluidSystem, oPhaseIdx, /*useSpe5=*/true>; | ||
48 | using GasPhaseParams = PengRobinsonParamsMixture<Scalar, FluidSystem, gPhaseIdx, /*useSpe5=*/true>; | ||
49 | |||
50 | /*! | ||
51 | * \brief The constructor | ||
52 | */ | ||
53 | 53 | Spe5ParameterCache() | |
54 | { | ||
55 |
4/4✓ Branch 0 taken 156 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
|
212 | for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) |
56 | 159 | VmUpToDate_[phaseIdx] = false; | |
57 | } | ||
58 | |||
59 | /*! | ||
60 | * \brief Update all parameters required by the fluid system to | ||
61 | * calculate some quantities for the phase. | ||
62 | * \param fs An arbitrary fluid state | ||
63 | * \param phaseIdx The index of the fluid phase to consider | ||
64 | * \param except The except quantity | ||
65 | */ | ||
66 | template <class FluidState> | ||
67 | 22111 | void updatePhase(const FluidState &fs, | |
68 | int phaseIdx, | ||
69 | int except = ParentType::None) | ||
70 | { | ||
71 | 22111 | updateEosParams(fs, phaseIdx, except); | |
72 | |||
73 | // if we don't need to recalculate the molar volume, we exit | ||
74 | // here | ||
75 |
2/2✓ Branch 0 taken 22108 times.
✓ Branch 1 taken 3 times.
|
22111 | if (VmUpToDate_[phaseIdx]) |
76 | return; | ||
77 | |||
78 | // update the phase's molar volume | ||
79 | 22108 | updateMolarVolume_(fs, phaseIdx); | |
80 | } | ||
81 | |||
82 | /*! | ||
83 | * \brief Update all cached parameters of a specific fluid phase | ||
84 | * which depend on the mole fraction of a single component | ||
85 | * | ||
86 | * \b Only use this method if just a single component's | ||
87 | * concentration changed between two \p update() calls. If more than | ||
88 | * one concentration changed, call updatePhaseComposition() of | ||
89 | * updatePhase()! | ||
90 | |||
91 | * \param fs An arbitrary fluid state | ||
92 | * \param compIdx The index of the component to consider | ||
93 | * \param phaseIdx The index of the fluid phase to consider | ||
94 | */ | ||
95 | template <class FluidState> | ||
96 | ✗ | void updateSingleMoleFraction(const FluidState &fs, | |
97 | int phaseIdx, | ||
98 | int compIdx) | ||
99 | { | ||
100 | ✗ | if (phaseIdx == oPhaseIdx) | |
101 | ✗ | oilPhaseParams_.updateSingleMoleFraction(fs, compIdx); | |
102 | ✗ | else if (phaseIdx == gPhaseIdx) | |
103 | ✗ | gasPhaseParams_.updateSingleMoleFraction(fs, compIdx); | |
104 | |||
105 | // update the phase's molar volume | ||
106 | ✗ | updateMolarVolume_(fs, phaseIdx); | |
107 | ✗ | } | |
108 | |||
109 | /*! | ||
110 | * \brief The Peng-Robinson attractive parameter for a phase. | ||
111 | * \param phaseIdx The index of the fluid phase to consider | ||
112 | */ | ||
113 | 619919 | Scalar a(int phaseIdx) const | |
114 | { | ||
115 |
2/3✓ Branch 0 taken 297845 times.
✓ Branch 1 taken 322074 times.
✗ Branch 2 not taken.
|
619919 | switch (phaseIdx) |
116 | { | ||
117 | 297845 | case oPhaseIdx: return oilPhaseParams_.a(); | |
118 | 322074 | case gPhaseIdx: return gasPhaseParams_.a(); | |
119 | ✗ | default: | |
120 | ✗ | DUNE_THROW(Dune::InvalidStateException, | |
121 | "The a() parameter is only defined for " | ||
122 | "oil and gas phases"); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | /*! | ||
127 | * \brief The Peng-Robinson co-volume for a phase. | ||
128 | * \param phaseIdx The index of the fluid phase to consider | ||
129 | */ | ||
130 | 619919 | Scalar b(int phaseIdx) const | |
131 | { | ||
132 |
2/3✓ Branch 0 taken 297845 times.
✓ Branch 1 taken 322074 times.
✗ Branch 2 not taken.
|
619919 | switch (phaseIdx) |
133 | { | ||
134 | 297845 | case oPhaseIdx: return oilPhaseParams_.b(); | |
135 | 322074 | case gPhaseIdx: return gasPhaseParams_.b(); | |
136 | ✗ | default: | |
137 | ✗ | DUNE_THROW(Dune::InvalidStateException, | |
138 | "The b() parameter is only defined for " | ||
139 | "oil and gas phases"); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | /*! | ||
144 | * \brief The Peng-Robinson attractive parameter for a pure | ||
145 | * component given the same temperature and pressure of the | ||
146 | * phase. | ||
147 | * \param compIdx The index of the component to consider | ||
148 | * \param phaseIdx The index of the fluid phase to consider | ||
149 | */ | ||
150 | 2121728 | Scalar aPure(int phaseIdx, int compIdx) const | |
151 | { | ||
152 |
2/3✓ Branch 0 taken 1060864 times.
✓ Branch 1 taken 1060864 times.
✗ Branch 2 not taken.
|
2121728 | switch (phaseIdx) |
153 | { | ||
154 | 2121728 | case oPhaseIdx: return oilPhaseParams_.pureParams(compIdx).a(); | |
155 | 2121728 | case gPhaseIdx: return gasPhaseParams_.pureParams(compIdx).a(); | |
156 | ✗ | default: | |
157 | ✗ | DUNE_THROW(Dune::InvalidStateException, | |
158 | "The a() parameter is only defined for " | ||
159 | "oil and gas phases"); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /*! | ||
164 | * \brief The Peng-Robinson co-volume for a pure component given | ||
165 | * the same temperature and pressure of the phase. | ||
166 | * \param compIdx The index of the component to consider | ||
167 | * \param phaseIdx The index of the fluid phase to consider | ||
168 | */ | ||
169 | 265216 | Scalar bPure(int phaseIdx, int compIdx) const | |
170 | { | ||
171 |
2/3✓ Branch 0 taken 132608 times.
✓ Branch 1 taken 132608 times.
✗ Branch 2 not taken.
|
265216 | switch (phaseIdx) |
172 | { | ||
173 | 265216 | case oPhaseIdx: return oilPhaseParams_.pureParams(compIdx).b(); | |
174 | 265216 | case gPhaseIdx: return gasPhaseParams_.pureParams(compIdx).b(); | |
175 | ✗ | default: | |
176 | ✗ | DUNE_THROW(Dune::InvalidStateException, | |
177 | "The b() parameter is only defined for " | ||
178 | "oil and gas phases"); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /*! | ||
183 | * \brief Returns the molar volume of a phase \f$\mathrm{[m^3/mol]}\f$ | ||
184 | * \param phaseIdx The index of the fluid phase to consider | ||
185 | */ | ||
186 | Scalar molarVolume(int phaseIdx) const | ||
187 | { | ||
188 |
7/16✗ Branch 0 not taken.
✓ Branch 1 taken 5000 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9972 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 34905 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 265205 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6966 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 56827 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
|
378876 | assert(VmUpToDate_[phaseIdx]); |
189 |
2/2✓ Branch 0 taken 23268 times.
✓ Branch 1 taken 11634 times.
|
322046 | return Vm_[phaseIdx]; |
190 | } | ||
191 | |||
192 | |||
193 | /*! | ||
194 | * \brief Returns the Peng-Robinson mixture parameters for the oil | ||
195 | * phase. | ||
196 | */ | ||
197 | const OilPhaseParams &oilPhaseParams() const | ||
198 | { return oilPhaseParams_; } | ||
199 | |||
200 | /*! | ||
201 | * \brief Returns the Peng-Robinson mixture parameters for the gas | ||
202 | * phase. | ||
203 | */ | ||
204 | const GasPhaseParams &gasPhaseParams() const | ||
205 | { return gasPhaseParams_; } | ||
206 | |||
207 | /*! | ||
208 | * \brief Update all parameters required by the equation of state to | ||
209 | * calculate some quantities for the phase. | ||
210 | */ | ||
211 | template <class FluidState> | ||
212 | 22111 | void updateEosParams(const FluidState &fs, | |
213 | int phaseIdx, | ||
214 | int exceptQuantities = ParentType::None) | ||
215 | { | ||
216 |
2/2✓ Branch 0 taken 22105 times.
✓ Branch 1 taken 6 times.
|
22111 | if (!(exceptQuantities & ParentType::Temperature)) |
217 | { | ||
218 | 22105 | updatePure_(fs, phaseIdx); | |
219 | 22105 | updateMix_(fs, phaseIdx); | |
220 | 22105 | VmUpToDate_[phaseIdx] = false; | |
221 | } | ||
222 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | else if (!(exceptQuantities & ParentType::Composition)) |
223 | { | ||
224 | 3 | updateMix_(fs, phaseIdx); | |
225 | 3 | VmUpToDate_[phaseIdx] = false; | |
226 | } | ||
227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | else if (!(exceptQuantities & ParentType::Pressure)) { |
228 | ✗ | VmUpToDate_[phaseIdx] = false; | |
229 | } | ||
230 | 22111 | } | |
231 | |||
232 | protected: | ||
233 | /*! | ||
234 | * \brief Update all parameters of a phase which only depend on | ||
235 | * temperature and/or pressure. | ||
236 | * | ||
237 | * This usually means the parameters for the pure components. | ||
238 | */ | ||
239 | template <class FluidState> | ||
240 | 22105 | void updatePure_(const FluidState &fs, int phaseIdx) | |
241 | { | ||
242 |
3/3✓ Branch 0 taken 7361 times.
✓ Branch 1 taken 7360 times.
✓ Branch 2 taken 7360 times.
|
22105 | Scalar T = fs.temperature(phaseIdx); |
243 |
3/3✓ Branch 0 taken 7361 times.
✓ Branch 1 taken 7360 times.
✓ Branch 2 taken 7360 times.
|
22105 | Scalar p = fs.pressure(phaseIdx); |
244 | |||
245 |
3/3✓ Branch 0 taken 7369 times.
✓ Branch 1 taken 7368 times.
✓ Branch 2 taken 7368 times.
|
22105 | switch (phaseIdx) |
246 | { | ||
247 | 7369 | case oPhaseIdx: oilPhaseParams_.updatePure(T, p); break; | |
248 | 7368 | case gPhaseIdx: gasPhaseParams_.updatePure(T, p); break; | |
249 | } | ||
250 | 22105 | } | |
251 | |||
252 | /*! | ||
253 | * \brief Update all parameters of a phase which depend on the | ||
254 | * fluid composition. It is assumed that updatePure() has | ||
255 | * been called before this method. | ||
256 | * | ||
257 | * Here, the mixing rule kicks in. | ||
258 | */ | ||
259 | template <class FluidState> | ||
260 | 22108 | void updateMix_(const FluidState &fs, int phaseIdx) | |
261 | { | ||
262 |
3/3✓ Branch 0 taken 7370 times.
✓ Branch 1 taken 7369 times.
✓ Branch 2 taken 7369 times.
|
22108 | switch (phaseIdx) |
263 | { | ||
264 | 7370 | case oPhaseIdx: | |
265 | 7370 | oilPhaseParams_.updateMix(fs); | |
266 | 7370 | break; | |
267 | 7369 | case gPhaseIdx: | |
268 | 7369 | gasPhaseParams_.updateMix(fs); | |
269 | 7369 | break; | |
270 | case wPhaseIdx: | ||
271 | break; | ||
272 | } | ||
273 | 22108 | } | |
274 | |||
275 | template <class FluidState> | ||
276 | 57013 | void updateMolarVolume_(const FluidState &fs, | |
277 | int phaseIdx) | ||
278 | { | ||
279 | 57013 | VmUpToDate_[phaseIdx] = true; | |
280 | |||
281 | // calculate molar volume of the phase (we will need this for the | ||
282 | // fugacity coefficients and the density anyway) | ||
283 |
3/4✓ Branch 0 taken 19004 times.
✓ Branch 1 taken 19005 times.
✓ Branch 2 taken 19004 times.
✗ Branch 3 not taken.
|
57013 | switch (phaseIdx) { |
284 | 19004 | case gPhaseIdx: { | |
285 | // calculate molar volumes for the given composition. although | ||
286 | // this isn't a Peng-Robinson parameter strictly speaking, the | ||
287 | // molar volume appears in basically every quantity the fluid | ||
288 | // system can get queried, so it is okay to calculate it | ||
289 | // here... | ||
290 | 19004 | Vm_[gPhaseIdx] = | |
291 | 19004 | PengRobinson::computeMolarVolume(fs, | |
292 | *this, | ||
293 | phaseIdx, | ||
294 | /*isGasPhase=*/true); | ||
295 | 19004 | break; | |
296 | } | ||
297 | 19005 | case oPhaseIdx: { | |
298 | // calculate molar volumes for the given composition. although | ||
299 | // this isn't a Peng-Robinson parameter strictly speaking, the | ||
300 | // molar volume appears in basically every quantity the fluid | ||
301 | // system can get queried, so it is okay to calculate it | ||
302 | // here... | ||
303 | 19005 | Vm_[oPhaseIdx] = | |
304 | 19005 | PengRobinson::computeMolarVolume(fs, | |
305 | *this, | ||
306 | phaseIdx, | ||
307 | /*isGasPhase=*/false); | ||
308 | 19005 | break; | |
309 | } | ||
310 | 19004 | case wPhaseIdx: { | |
311 | // Density of water in the stock tank (i.e. atmospheric | ||
312 | // pressure) is specified as 62.4 lb/ft^3 by the SPE-5 | ||
313 | // paper. Also 1 lb = 0.4535923 and 1 ft = 0.3048 m. | ||
314 | 19004 | const Scalar stockTankWaterDensity = 62.4 * 0.45359237 / 0.028316847; | |
315 | // Water compressibility is specified as 3.3e-6 per psi | ||
316 | // overpressure, where 1 psi = 6894.7573 Pa | ||
317 | 19004 | Scalar overPressure = fs.pressure(wPhaseIdx) - 1.013e5; // [Pa] | |
318 | 19004 | Scalar waterDensity = | |
319 | 19004 | stockTankWaterDensity * (1 + 3.3e-6*overPressure/6894.7573); | |
320 | |||
321 | // convert water density [kg/m^3] to molar volume [m^3/mol] | ||
322 | 19004 | Vm_[wPhaseIdx] = fs.averageMolarMass(wPhaseIdx)/waterDensity; | |
323 | 19004 | break; | |
324 | } | ||
325 | ✗ | default: | |
326 | ✗ | DUNE_THROW(Dune::InvalidStateException, "invalid phaseIdx " << phaseIdx); | |
327 | } | ||
328 | 57013 | } | |
329 | |||
330 | bool VmUpToDate_[numPhases]; | ||
331 | Scalar Vm_[numPhases]; | ||
332 | |||
333 | OilPhaseParams oilPhaseParams_; | ||
334 | GasPhaseParams gasPhaseParams_; | ||
335 | }; | ||
336 | |||
337 | } // end namespace Dumux | ||
338 | |||
339 | #endif | ||
340 |