GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/porousmediumflow/3p3c/volumevariables.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 152 257 59.1%
Functions: 6 18 33.3%
Branches: 72 210 34.3%

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 ThreePThreeCModel
10 * \brief Contains the quantities which are constant within a
11 * finite volume in the three-phase three-component model.
12 */
13 #ifndef DUMUX_3P3C_VOLUME_VARIABLES_HH
14 #define DUMUX_3P3C_VOLUME_VARIABLES_HH
15
16 #include <dumux/material/constants.hh>
17 #include <dumux/material/fluidstates/compositional.hh>
18 #include <dumux/material/constraintsolvers/computefromreferencephase.hh>
19 #include <dumux/material/constraintsolvers/misciblemultiphasecomposition.hh>
20
21 #include <dumux/porousmediumflow/volumevariables.hh>
22 #include <dumux/porousmediumflow/nonisothermal/volumevariables.hh>
23 #include <dumux/material/solidstates/updatesolidvolumefractions.hh>
24 #include <dumux/common/optionalscalar.hh>
25
26 #include "primaryvariableswitch.hh"
27
28 namespace Dumux {
29
30 namespace Detail {
31 // helper struct and function detecting if the fluid matrix interaction features a adsorptionModel() function
32 template <class FluidMatrixInteraction>
33 using AdsorptionModelDetector = decltype(std::declval<FluidMatrixInteraction>().adsorptionModel());
34
35 template<class FluidMatrixInteraction>
36 static constexpr bool hasAdsorptionModel()
37 { return Dune::Std::is_detected<AdsorptionModelDetector, FluidMatrixInteraction>::value; }
38
39 }
40
41 /*!
42 * \ingroup ThreePThreeCModel
43 * \brief Contains the quantities which are are constant within a
44 * finite volume in the three-phase three-component model.
45 */
46 template <class Traits>
47 2048886 class ThreePThreeCVolumeVariables
48 : public PorousMediumFlowVolumeVariables<Traits>
49 , public EnergyVolumeVariables<Traits, ThreePThreeCVolumeVariables<Traits> >
50 {
51 using ParentType = PorousMediumFlowVolumeVariables<Traits>;
52 using EnergyVolVars = EnergyVolumeVariables<Traits, ThreePThreeCVolumeVariables<Traits> >;
53
54 using Scalar = typename Traits::PrimaryVariables::value_type;
55 using PermeabilityType = typename Traits::PermeabilityType;
56
57 using FS = typename Traits::FluidSystem;
58 using MiscibleMultiPhaseComposition = Dumux::MiscibleMultiPhaseComposition<Scalar, FS>;
59 using ComputeFromReferencePhase = Dumux::ComputeFromReferencePhase<Scalar, FS>;
60
61 using ModelTraits = typename Traits::ModelTraits;
62 using Idx = typename ModelTraits::Indices;
63 static constexpr int numFluidComps = ParentType::numFluidComponents();
64 enum {
65 wCompIdx = FS::wCompIdx,
66 gCompIdx = FS::gCompIdx,
67 nCompIdx = FS::nCompIdx,
68
69 wPhaseIdx = FS::wPhaseIdx,
70 gPhaseIdx = FS::gPhaseIdx,
71 nPhaseIdx = FS::nPhaseIdx,
72
73 switch1Idx = Idx::switch1Idx,
74 switch2Idx = Idx::switch2Idx,
75 pressureIdx = Idx::pressureIdx
76 };
77
78 // present phases
79 enum {
80 threePhases = Idx::threePhases,
81 wPhaseOnly = Idx::wPhaseOnly,
82 gnPhaseOnly = Idx::gnPhaseOnly,
83 wnPhaseOnly = Idx::wnPhaseOnly,
84 gPhaseOnly = Idx::gPhaseOnly,
85 wgPhaseOnly = Idx::wgPhaseOnly
86 };
87
88 using EffDiffModel = typename Traits::EffectiveDiffusivityModel;
89 using DiffusionCoefficients = typename Traits::DiffusionType::DiffusionCoefficientsContainer;
90
91 public:
92 //! export fluid state type
93 using FluidState = typename Traits::FluidState;
94 //! export fluid system type
95 using FluidSystem = typename Traits::FluidSystem;
96 //! export the indices
97 using Indices = typename ModelTraits::Indices;
98 //! export type of solid state
99 using SolidState = typename Traits::SolidState;
100 //! export type of solid system
101 using SolidSystem = typename Traits::SolidSystem;
102 //! export the primary variable switch
103 using PrimaryVariableSwitch = ThreePThreeCPrimaryVariableSwitch;
104
105 /*!
106 * \brief Update all quantities for a given control volume
107 *
108 * \param elemSol A vector containing all primary variables connected to the element
109 * \param problem The object specifying the problem which ought to
110 * be simulated
111 * \param element An element which contains part of the control volume
112 * \param scv The sub control volume
113 */
114 template<class ElemSol, class Problem, class Element, class Scv>
115 4678725 void update(const ElemSol &elemSol,
116 const Problem &problem,
117 const Element &element,
118 const Scv& scv)
119 {
120 4678725 ParentType::update(elemSol, problem, element, scv);
121 4678725 const auto& priVars = elemSol[scv.localDofIndex()];
122 4678725 const auto phasePresence = priVars.state();
123
124 4475850 constexpr bool useConstraintSolver = ModelTraits::useConstraintSolver();
125
126 4678725 EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState_, solidState_);
127
128 /* first the saturations */
129
2/2
✓ Branch 0 taken 3496302 times.
✓ Branch 1 taken 1182423 times.
4678725 if (phasePresence == threePhases)
130 {
131 3496302 sw_ = priVars[switch1Idx];
132 3496302 sn_ = priVars[switch2Idx];
133 3496302 sg_ = 1. - sw_ - sn_;
134 }
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == wPhaseOnly)
136 {
137 sw_ = 1.;
138 sn_ = 0.;
139 sg_ = 0.;
140 }
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == gnPhaseOnly)
142 {
143 sw_ = 0.;
144 sn_ = priVars[switch2Idx];
145 sg_ = 1. - sn_;
146 }
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == wnPhaseOnly)
148 {
149 sn_ = priVars[switch2Idx];
150 sw_ = 1. - sn_;
151 sg_ = 0.;
152 }
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == gPhaseOnly)
154 {
155 sw_ = 0.;
156 sn_ = 0.;
157 sg_ = 1.;
158 }
159
1/2
✓ Branch 0 taken 1182423 times.
✗ Branch 1 not taken.
1182423 else if (phasePresence == wgPhaseOnly)
160 {
161 1182423 sw_ = priVars[switch1Idx];
162 1182423 sn_ = 0.;
163 1182423 sg_ = 1. - sw_;
164 }
165 else
166 DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
167
168
2/2
✓ Branch 0 taken 1207452 times.
✓ Branch 1 taken 3268398 times.
4678725 fluidState_.setSaturation(wPhaseIdx, sw_);
169
2/2
✓ Branch 0 taken 1207452 times.
✓ Branch 1 taken 3268398 times.
4678725 fluidState_.setSaturation(gPhaseIdx, sg_);
170
2/2
✓ Branch 0 taken 1207452 times.
✓ Branch 1 taken 3268398 times.
4678725 fluidState_.setSaturation(nPhaseIdx, sn_);
171
172 /* now the pressures */
173
2/2
✓ Branch 0 taken 1207452 times.
✓ Branch 1 taken 3268398 times.
4678725 pg_ = priVars[pressureIdx];
174
175 // calculate capillary pressures
176
177
4/4
✓ Branch 0 taken 1207452 times.
✓ Branch 1 taken 3268398 times.
✓ Branch 2 taken 1207452 times.
✓ Branch 3 taken 3268398 times.
9357450 const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol);
178 4678725 Scalar pcgw = fluidMatrixInteraction.pcgw(sw_, sn_);
179 4678725 Scalar pcnw = fluidMatrixInteraction.pcnw(sw_, sn_);
180 4678725 Scalar pcgn = fluidMatrixInteraction.pcgn(sw_, sn_);
181
182
2/2
✓ Branch 0 taken 3646834 times.
✓ Branch 1 taken 1031891 times.
4678725 const Scalar pcAlpha = fluidMatrixInteraction.pcAlpha(sw_, sn_);
183 4678725 const Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file
184
185 4678725 pn_ = pg_- pcAlpha * pcgn - (1.-pcAlpha)*(pcgw - pcNW1);
186 4678725 pw_ = pn_ - pcAlpha * pcnw - (1.-pcAlpha)*pcNW1;
187
188 4678725 fluidState_.setPressure(wPhaseIdx, pw_);
189 4678725 fluidState_.setPressure(gPhaseIdx, pg_);
190 4678725 fluidState_.setPressure(nPhaseIdx, pn_);
191
192 // calculate and set all fugacity coefficients. this is
193 // possible because we require all phases to be an ideal
194 // mixture, i.e. fugacity coefficients are not supposed to
195 // depend on composition!
196 typename FluidSystem::ParameterCache paramCache;
197 // assert(FluidSystem::isIdealGas(gPhaseIdx));
198
2/2
✓ Branch 0 taken 14036175 times.
✓ Branch 1 taken 4678725 times.
18714900 for (int phaseIdx = 0; phaseIdx < ModelTraits::numFluidPhases(); ++ phaseIdx) {
199 assert(FluidSystem::isIdealMixture(phaseIdx));
200
201
2/2
✓ Branch 0 taken 42108525 times.
✓ Branch 1 taken 14036175 times.
56144700 for (int compIdx = 0; compIdx < ModelTraits::numFluidComponents(); ++ compIdx) {
202 42108525 Scalar phi = FluidSystem::fugacityCoefficient(fluidState_, paramCache, phaseIdx, compIdx);
203 84217050 fluidState_.setFugacityCoefficient(phaseIdx, compIdx, phi);
204 }
205 }
206
207 // now comes the tricky part: calculate phase composition
208
2/2
✓ Branch 0 taken 3496302 times.
✓ Branch 1 taken 1182423 times.
4678725 if (phasePresence == threePhases) {
209 // all phases are present, phase compositions are a
210 // result of the the gas <-> liquid equilibrium. This is
211 // the job of the "MiscibleMultiPhaseComposition"
212 // constraint solver ...
213 if (useConstraintSolver) {
214 MiscibleMultiPhaseComposition::solve(fluidState_,
215 paramCache);
216 }
217 // ... or calculated explicitly this way ...
218 // please note that we experienced some problems with un-regularized
219 // partial pressures due to their calculation from fugacity coefficients -
220 // that's why they are regularized below "within physically meaningful bounds"
221 else {
222 3496302 Scalar partPressH2O = FluidSystem::fugacityCoefficient(fluidState_,
223 wPhaseIdx,
224 3496302 wCompIdx) * pw_;
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3496302 times.
3496302 if (partPressH2O > pg_) partPressH2O = pg_;
226 3496302 Scalar partPressNAPL = FluidSystem::fugacityCoefficient(fluidState_,
227 nPhaseIdx,
228 3496302 nCompIdx) * pn_;
229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3496302 times.
3496302 if (partPressNAPL > pg_) partPressNAPL = pg_;
230 3496302 Scalar partPressAir = pg_ - partPressH2O - partPressNAPL;
231
232 3496302 Scalar xgn = partPressNAPL/pg_;
233 3496302 Scalar xgw = partPressH2O/pg_;
234 3496302 Scalar xgg = partPressAir/pg_;
235
236 // actually, it's nothing else than Henry coefficient
237 3496302 Scalar xwn = partPressNAPL
238 3496302 / (FluidSystem::fugacityCoefficient(fluidState_,
239 wPhaseIdx,nCompIdx)
240 3496302 * pw_);
241 3496302 Scalar xwg = partPressAir
242 3496302 / (FluidSystem::fugacityCoefficient(fluidState_,
243 wPhaseIdx,gCompIdx)
244 3496302 * pw_);
245 3496302 Scalar xww = 1.-xwg-xwn;
246
247 3496302 Scalar xnn = 1.-2.e-10;
248 3496302 Scalar xna = 1.e-10;
249 3496302 Scalar xnw = 1.e-10;
250
251 3496302 fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
252 3496302 fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
253 3496302 fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
254 3496302 fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
255 3496302 fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
256 3496302 fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
257 3496302 fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
258 3496302 fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
259 3496302 fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
260
261 3496302 Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
262 3496302 Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
263 3496302 Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
264 3496302 Scalar rhoWMolar = FluidSystem::molarDensity(fluidState_, wPhaseIdx);
265 3496302 Scalar rhoGMolar = FluidSystem::molarDensity(fluidState_, gPhaseIdx);
266 3496302 Scalar rhoNMolar = FluidSystem::molarDensity(fluidState_, nPhaseIdx);
267
268 3496302 fluidState_.setDensity(wPhaseIdx, rhoW);
269 3496302 fluidState_.setDensity(gPhaseIdx, rhoG);
270 3496302 fluidState_.setDensity(nPhaseIdx, rhoN);
271 3496302 fluidState_.setMolarDensity(wPhaseIdx, rhoWMolar);
272 3496302 fluidState_.setMolarDensity(gPhaseIdx, rhoGMolar);
273 3496302 fluidState_.setMolarDensity(nPhaseIdx, rhoNMolar);
274 }
275 }
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == wPhaseOnly) {
277 // only the water phase is present, water phase composition is
278 // stored explicitly.
279
280 // extract mole fractions in the water phase
281 Scalar xwg = priVars[switch1Idx];
282 Scalar xwn = priVars[switch2Idx];
283 Scalar xww = 1 - xwg - xwn;
284
285 // write water mole fractions in the fluid state
286 fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
287 fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
288 fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
289
290 // calculate the composition of the remaining phases (as
291 // well as the densities of all phases). this is the job
292 // of the "ComputeFromReferencePhase" constraint solver ...
293 if (useConstraintSolver)
294 {
295 ComputeFromReferencePhase::solve(fluidState_,
296 paramCache,
297 wPhaseIdx);
298 }
299 // ... or calculated explicitly this way ...
300 else {
301 // note that the gas phase is actually not existing!
302 // thus, this is used as phase switch criterion
303 Scalar xgg = xwg * FluidSystem::fugacityCoefficient(fluidState_,
304 wPhaseIdx,gCompIdx)
305 * pw_ / pg_;
306 Scalar xgn = xwn * FluidSystem::fugacityCoefficient(fluidState_,
307 wPhaseIdx,nCompIdx)
308 * pw_ / pg_;
309 Scalar xgw = FluidSystem::fugacityCoefficient(fluidState_,
310 wPhaseIdx,wCompIdx)
311 * pw_ / pg_;
312
313
314 // note that the gas phase is actually not existing!
315 // thus, this is used as phase switch criterion
316 Scalar xnn = xwn * FluidSystem::fugacityCoefficient(fluidState_,
317 wPhaseIdx,nCompIdx)
318 * pw_;
319 Scalar xna = 1.e-10;
320 Scalar xnw = 1.e-10;
321
322 fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
323 fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
324 fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
325 fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
326 fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
327 fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
328
329 Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
330 Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
331 Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
332 Scalar rhoWMolar = FluidSystem::molarDensity(fluidState_, wPhaseIdx);
333 Scalar rhoGMolar = FluidSystem::molarDensity(fluidState_, gPhaseIdx);
334 Scalar rhoNMolar = FluidSystem::molarDensity(fluidState_, nPhaseIdx);
335
336 fluidState_.setDensity(wPhaseIdx, rhoW);
337 fluidState_.setDensity(gPhaseIdx, rhoG);
338 fluidState_.setDensity(nPhaseIdx, rhoN);
339 fluidState_.setMolarDensity(wPhaseIdx, rhoWMolar);
340 fluidState_.setMolarDensity(gPhaseIdx, rhoGMolar);
341 fluidState_.setMolarDensity(nPhaseIdx, rhoNMolar);
342 }
343 }
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == gnPhaseOnly) {
345 // only gas and NAPL phases are present
346 // we have all (partly hypothetical) phase pressures
347 // and temperature and the mole fraction of water in
348 // the gas phase
349
350 // we have all (partly hypothetical) phase pressures
351 // and temperature and the mole fraction of water in
352 // the gas phase
353 Scalar partPressNAPL = fluidState_.fugacityCoefficient(nPhaseIdx, nCompIdx)*pn_;
354 if (partPressNAPL > pg_) partPressNAPL = pg_;
355
356 Scalar xgw = priVars[switch1Idx];
357 Scalar xgn = partPressNAPL/pg_;
358 Scalar xgg = 1.-xgw-xgn;
359
360 // write mole fractions in the fluid state
361 fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
362 fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
363 fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
364
365 // calculate the composition of the remaining phases (as
366 // well as the densities of all phases). this is the job
367 // of the "ComputeFromReferencePhase" constraint solver
368 ComputeFromReferencePhase::solve(fluidState_,
369 paramCache,
370 gPhaseIdx);
371 }
372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == wnPhaseOnly) {
373 // only water and NAPL phases are present
374 Scalar partPressNAPL = fluidState_.fugacityCoefficient(nPhaseIdx,nCompIdx)*pn_;
375 if (partPressNAPL > pg_) partPressNAPL = pg_;
376 Scalar henryC = fluidState_.fugacityCoefficient(wPhaseIdx,nCompIdx)*pw_;
377
378 Scalar xwg = priVars[switch1Idx];
379 Scalar xwn = partPressNAPL/henryC;
380 Scalar xww = 1.-xwg-xwn;
381
382 // write mole fractions in the fluid state
383 fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
384 fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
385 fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
386
387 // calculate the composition of the remaining phases (as
388 // well as the densities of all phases). this is the job
389 // of the "ComputeFromReferencePhase" constraint solver
390 ComputeFromReferencePhase::solve(fluidState_,
391 paramCache,
392 wPhaseIdx);
393 }
394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 else if (phasePresence == gPhaseOnly) {
395 // only the gas phase is present, gas phase composition is
396 // stored explicitly here below.
397
398 const Scalar xgw = priVars[switch1Idx];
399 const Scalar xgn = priVars[switch2Idx];
400 Scalar xgg = 1 - xgw - xgn;
401
402 // write mole fractions in the fluid state
403 fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
404 fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
405 fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
406
407 // calculate the composition of the remaining phases (as
408 // well as the densities of all phases). this is the job
409 // of the "ComputeFromReferencePhase" constraint solver ...
410 if (useConstraintSolver)
411 {
412 ComputeFromReferencePhase::solve(fluidState_,
413 paramCache,
414 gPhaseIdx);
415 }
416 // ... or calculated explicitly this way ...
417 else {
418
419 // note that the water phase is actually not existing!
420 // thus, this is used as phase switch criterion
421 Scalar xww = xgw * pg_
422 / (FluidSystem::fugacityCoefficient(fluidState_,
423 wPhaseIdx,wCompIdx)
424 * pw_);
425 Scalar xwn = 1.e-10;
426 Scalar xwg = 1.e-10;
427
428 // note that the NAPL phase is actually not existing!
429 // thus, this is used as phase switch criterion
430 Scalar xnn = xgn * pg_
431 / (FluidSystem::fugacityCoefficient(fluidState_,
432 nPhaseIdx,nCompIdx)
433 * pn_);
434 Scalar xna = 1.e-10;
435 Scalar xnw = 1.e-10;
436
437 fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
438 fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
439 fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
440 fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
441 fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
442 fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
443
444 Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
445 Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
446 Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
447 Scalar rhoWMolar = FluidSystem::molarDensity(fluidState_, wPhaseIdx);
448 Scalar rhoGMolar = FluidSystem::molarDensity(fluidState_, gPhaseIdx);
449 Scalar rhoNMolar = FluidSystem::molarDensity(fluidState_, nPhaseIdx);
450
451 fluidState_.setDensity(wPhaseIdx, rhoW);
452 fluidState_.setDensity(gPhaseIdx, rhoG);
453 fluidState_.setDensity(nPhaseIdx, rhoN);
454 fluidState_.setMolarDensity(wPhaseIdx, rhoWMolar);
455 fluidState_.setMolarDensity(gPhaseIdx, rhoGMolar);
456 fluidState_.setMolarDensity(nPhaseIdx, rhoNMolar);
457 }
458 }
459
1/2
✓ Branch 0 taken 1182423 times.
✗ Branch 1 not taken.
1182423 else if (phasePresence == wgPhaseOnly) {
460 // only water and gas phases are present
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 Scalar xgn = priVars[switch2Idx];
462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 Scalar partPressH2O = fluidState_.fugacityCoefficient(wPhaseIdx, wCompIdx)*pw_;
463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182423 times.
1182423 if (partPressH2O > pg_) partPressH2O = pg_;
464
465 1182423 Scalar xgw = partPressH2O/pg_;
466 1182423 Scalar xgg = 1.-xgn-xgw;
467
468 // write mole fractions in the fluid state
469 1182423 fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
470 1182423 fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
471 1182423 fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
472
473 // calculate the composition of the remaining phases (as
474 // well as the densities of all phases). this is the job
475 // of the "ComputeFromReferencePhase" constraint solver ...
476 if (useConstraintSolver)
477 {
478 ComputeFromReferencePhase::solve(fluidState_,
479 paramCache,
480 gPhaseIdx);
481 }
482 // ... or calculated explicitly this way ...
483 else {
484 // actually, it's nothing else than Henry coefficient
485 2364846 Scalar xwn = xgn * pg_
486 1182423 / (FluidSystem::fugacityCoefficient(fluidState_,
487 wPhaseIdx,nCompIdx)
488 1182423 * pw_);
489 2364846 Scalar xwg = xgg * pg_
490 1182423 / (FluidSystem::fugacityCoefficient(fluidState_,
491 wPhaseIdx,gCompIdx)
492 1182423 * pw_);
493 1182423 Scalar xww = 1.-xwg-xwn;
494
495 // note that the NAPL phase is actually not existing!
496 // thus, this is used as phase switch criterion
497 2364846 Scalar xnn = xgn * pg_
498 1182423 / (FluidSystem::fugacityCoefficient(fluidState_,
499 nPhaseIdx,nCompIdx)
500 1182423 * pn_);
501 1182423 Scalar xna = 1.e-10;
502 1182423 Scalar xnw = 1.e-10;
503
504 1182423 fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
505 1182423 fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
506 1182423 fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
507 1182423 fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
508 1182423 fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
509 1182423 fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
510
511 1182423 Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
512 1182423 Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
513 1182423 Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
514 1182423 Scalar rhoWMolar = FluidSystem::molarDensity(fluidState_, wPhaseIdx);
515 1182423 Scalar rhoGMolar = FluidSystem::molarDensity(fluidState_, gPhaseIdx);
516 1182423 Scalar rhoNMolar = FluidSystem::molarDensity(fluidState_, nPhaseIdx);
517
518 1182423 fluidState_.setDensity(wPhaseIdx, rhoW);
519 1182423 fluidState_.setDensity(gPhaseIdx, rhoG);
520 1182423 fluidState_.setDensity(nPhaseIdx, rhoN);
521 1182423 fluidState_.setMolarDensity(wPhaseIdx, rhoWMolar);
522 1182423 fluidState_.setMolarDensity(gPhaseIdx, rhoGMolar);
523 1182423 fluidState_.setMolarDensity(nPhaseIdx, rhoNMolar);
524 }
525 }
526 else
527 DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
528
529
2/2
✓ Branch 0 taken 14036175 times.
✓ Branch 1 taken 4678725 times.
18714900 for (int phaseIdx = 0; phaseIdx < ModelTraits::numFluidPhases(); ++phaseIdx)
530 {
531 // mobilities
532 const Scalar mu =
533 14036175 FluidSystem::viscosity(fluidState_,
534 paramCache,
535 phaseIdx);
536 14036175 fluidState_.setViscosity(phaseIdx,mu);
537
538 42108525 const Scalar kr = fluidMatrixInteraction.kr(phaseIdx,
539 fluidState_.saturation(wPhaseIdx),
540 fluidState_.saturation(nPhaseIdx));
541 14036175 mobility_[phaseIdx] = kr / mu;
542 }
543
544 // material dependent parameters for NAPL adsorption (only if law is provided)
545 if constexpr (Detail::hasAdsorptionModel<std::decay_t<decltype(fluidMatrixInteraction)>>())
546 1179193 bulkDensTimesAdsorpCoeff_ = fluidMatrixInteraction.adsorptionModel().bulkDensTimesAdsorpCoeff();
547
548 /* compute the diffusion coefficient
549 * \note This is the part of the diffusion coefficient determined by the fluid state, e.g.
550 * important if they are tabularized. In the diffusive flux computation (e.g. Fick's law)
551 * this gets converted into an efficient coefficient depending on saturation and porosity.
552 * We can then add a normalized tensorial component
553 * e.g. obtained from DTI from the spatial params (currently not implemented)
554 */
555
556 4678725 auto getEffectiveDiffusionCoefficient = [&](int phaseIdx, int compIIdx, int compJIdx)
557 {
558 28072350 return EffDiffModel::effectiveDiffusionCoefficient(*this, phaseIdx, compIIdx, compJIdx);
559 };
560
561 // porosity & permeabilty
562 4678725 updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, numFluidComps);
563
564 4678725 effectiveDiffCoeff_.update(getEffectiveDiffusionCoefficient);
565
566 4678725 EnergyVolVars::updateSolidEnergyParams(elemSol, problem, element, scv, solidState_);
567
4/4
✓ Branch 0 taken 3010933 times.
✓ Branch 1 taken 1667792 times.
✓ Branch 2 taken 3010933 times.
✓ Branch 3 taken 1667792 times.
9357450 permeability_ = problem.spatialParams().permeability(element, scv, elemSol);
568 4678725 EnergyVolVars::updateEffectiveThermalConductivity();
569
570 // compute and set the enthalpy
571
2/2
✓ Branch 0 taken 14036175 times.
✓ Branch 1 taken 4678725 times.
18714900 for (int phaseIdx = 0; phaseIdx < ModelTraits::numFluidPhases(); ++phaseIdx)
572 {
573 14036175 Scalar h = EnergyVolVars::enthalpy(fluidState_, paramCache, phaseIdx);
574 28072350 fluidState_.setEnthalpy(phaseIdx, h);
575 }
576 4678725 }
577
578 /*!
579 * \brief Returns the phase state for the control volume.
580 */
581 const FluidState &fluidState() const
582 148603092 { return fluidState_; }
583
584 /*!
585 * \brief Returns the phase state for the control volume.
586 */
587 const SolidState &solidState() const
588 4475850 { return solidState_; }
589
590 /*!
591 * \brief Returns the average molar mass \f$\mathrm{[kg/mol]}\f$ of the fluid phase.
592 *
593 * \param phaseIdx The phase index
594 */
595 Scalar averageMolarMass(int phaseIdx) const
596 { return fluidState_.averageMolarMass(phaseIdx); }
597
598 /*!
599 * \brief Returns the effective saturation of a given phase within
600 * the control volume.
601 *
602 * \param phaseIdx The phase index
603 */
604 Scalar saturation(const int phaseIdx) const
605
21/48
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 268 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 268 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 156144 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 156412 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 268 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 156144 times.
✓ Branch 16 taken 14 times.
✓ Branch 17 taken 156398 times.
✓ Branch 18 taken 14 times.
✓ Branch 19 taken 254 times.
✓ Branch 20 taken 9 times.
✓ Branch 21 taken 156135 times.
✓ Branch 22 taken 9 times.
✓ Branch 23 taken 156135 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 8127 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 8127 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 34791 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 42918 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 8127 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 34791 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 34791 times.
552063494 { return fluidState_.saturation(phaseIdx); }
606
607 /*!
608 * \brief Returns the mass fraction of a given component in a
609 * given phase within the control volume in \f$[-]\f$.
610 *
611 * \param phaseIdx The phase index
612 * \param compIdx The component index
613 */
614 Scalar massFraction(const int phaseIdx, const int compIdx) const
615 187190940 { return fluidState_.massFraction(phaseIdx, compIdx); }
616
617 /*!
618 * \brief Returns the mole fraction of a given component in a
619 * given phase within the control volume in \f$[-]\f$.
620 *
621 * \param phaseIdx The phase index
622 * \param compIdx The component index
623 */
624 Scalar moleFraction(const int phaseIdx, const int compIdx) const
625
4/44
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 39 times.
✓ Branch 41 taken 42879 times.
✓ Branch 42 taken 39 times.
✓ Branch 43 taken 42879 times.
885414262 { return fluidState_.moleFraction(phaseIdx, compIdx); }
626
627 /*!
628 * \brief Returns the mass density of a given phase within the
629 * control volume.
630 *
631 * \param phaseIdx The phase index
632 */
633 Scalar density(const int phaseIdx) const
634 798739326 { return fluidState_.density(phaseIdx); }
635
636 /*!
637 * \brief Returns the molar density of a given phase within the
638 * control volume.
639 *
640 * \param phaseIdx The phase index
641 */
642 Scalar molarDensity(const int phaseIdx) const
643 885328380 { return fluidState_.molarDensity(phaseIdx); }
644
645 /*!
646 * \brief Returns the effective pressure of a given phase within
647 * the control volume.
648 *
649 * \param phaseIdx The phase index
650 */
651 Scalar pressure(const int phaseIdx) const
652 294984660 { return fluidState_.pressure(phaseIdx); }
653
654 /*!
655 * \brief Returns temperature inside the sub-control volume.
656 *
657 * Note that we assume thermodynamic equilibrium, i.e. the
658 * temperatures of the rock matrix and of all fluid phases are
659 * identical.
660 */
661 Scalar temperature() const
662
2/4
✓ Branch 0 taken 2195127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2195127 times.
✗ Branch 3 not taken.
94443228 { return fluidState_.temperature(/*phaseIdx=*/0); }
663
664 /*!
665 * \brief Returns the effective mobility of a given phase within
666 * the control volume.
667 *
668 * \param phaseIdx The phase index
669 */
670 Scalar mobility(const int phaseIdx) const
671 319953672 { return mobility_[phaseIdx]; }
672
673 /*!
674 * \brief Returns the effective capillary pressure within the control volume.
675 */
676 Scalar capillaryPressure() const
677 { return fluidState_.capillaryPressure(); }
678
679 /*!
680 * \brief Returns the average porosity within the control volume.
681 */
682 Scalar porosity() const
683
0/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
542627220 { return solidState_.porosity(); }
684
685 /*!
686 * \brief Returns the adsorption information.
687 */
688 Scalar bulkDensTimesAdsorpCoeff() const
689 {
690 if (bulkDensTimesAdsorpCoeff_)
691 return bulkDensTimesAdsorpCoeff_.value();
692 else
693 DUNE_THROW(Dune::NotImplemented, "Your spatialParams do not provide an adsorption model");
694 }
695
696 /*!
697 * \brief Returns the average permeability within the control volume in \f$[m^2]\f$.
698 */
699 const PermeabilityType& permeability() const
700 { return permeability_; }
701
702 /*
703 * \brief Returns the binary diffusion coefficients for a phase in \f$[m^2/s]\f$.
704 */
705 Scalar diffusionCoefficient(int phaseIdx, int compIIdx, int compJIdx) const
706 {
707 typename FluidSystem::ParameterCache paramCache;
708 paramCache.updatePhase(fluidState_, phaseIdx);
709 return FluidSystem::diffusionCoefficient(fluidState_, paramCache, phaseIdx, compJIdx);
710 }
711
712 /*!
713 * \brief Returns the effective diffusion coefficients for a phase in \f$[m^2/s]\f$.
714 */
715 Scalar effectiveDiffusionCoefficient(int phaseIdx, int compIIdx, int compJIdx) const
716 76038808 { return effectiveDiffCoeff_(phaseIdx, compIIdx, compJIdx); }
717
718 protected:
719 FluidState fluidState_;
720 SolidState solidState_;
721
722
723 private:
724 Scalar sw_, sg_, sn_, pg_, pw_, pn_;
725
726 Scalar moleFrac_[ModelTraits::numFluidPhases()][ModelTraits::numFluidComponents()];
727 Scalar massFrac_[ModelTraits::numFluidPhases()][ModelTraits::numFluidComponents()];
728
729 PermeabilityType permeability_; //!< Effective permeability within the control volume
730 Scalar mobility_[ModelTraits::numFluidPhases()]; //!< Effective mobility within the control volume
731 OptionalScalar<Scalar> bulkDensTimesAdsorpCoeff_; //!< the basis for calculating adsorbed NAPL
732
733 DiffusionCoefficients effectiveDiffCoeff_;
734 };
735
736 } // end namespace Dumux
737
738 #endif
739