GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/test/porousmediumflow/2pncmin/nonisothermal/problem.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 129 138 93.5%
Functions: 12 12 100.0%
Branches: 88 152 57.9%

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-FileCopyrightText: 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 TwoPNCMinTests
10 * \brief Problem where brine is evaporating at the top boundary. The system is closed at the remaining boundaries.
11 */
12 #ifndef DUMUX_SALINIZATION_PROBLEM_HH
13 #define DUMUX_SALINIZATION_PROBLEM_HH
14
15 #include <dune/common/exceptions.hh>
16
17 #include <dumux/common/boundarytypes.hh>
18 #include <dumux/common/properties.hh>
19 #include <dumux/common/parameters.hh>
20 #include <dumux/common/numeqvector.hh>
21 #include <dumux/common/math.hh>
22
23 #include <dumux/discretization/method.hh>
24
25 #include <dumux/porousmediumflow/problem.hh>
26 #include <dumux/io/gnuplotinterface.hh>
27
28 namespace Dumux {
29
30 /*!
31 * \ingroup TwoPNCMinTests
32 * \brief Problem where water is evaporating at the top of a porous media filled container saturated with brine and air, which causes precipitation at the top.
33 *
34 */
35 template <class TypeTag>
36 class SalinizationProblem : public PorousMediumFlowProblem<TypeTag>
37 {
38 using ParentType = PorousMediumFlowProblem<TypeTag>;
39 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
40 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
41 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
42 using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>;
43 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
44 using SolidSystem = GetPropType<TypeTag, Properties::SolidSystem>;
45
46 enum
47 {
48 // primary variable indices
49 pressureIdx = Indices::pressureIdx,
50 switchIdx = Indices::switchIdx,
51
52 // component indices
53 // TODO: using xwNaClIdx as privaridx works here, but
54 // looks like magic. Can this be done differently??
55 xwNaClIdx = FluidSystem::NaClIdx,
56 precipNaClIdx = FluidSystem::numComponents,
57
58 // Indices of the components
59 H2OIdx = FluidSystem::H2OIdx,
60 NaClIdx = FluidSystem::NaClIdx,
61 AirIdx = FluidSystem::AirIdx,
62
63 // Indices of the phases
64 liquidPhaseIdx = FluidSystem::liquidPhaseIdx,
65 gasPhaseIdx = FluidSystem::gasPhaseIdx,
66
67 // index of the solid phase
68 sPhaseIdx = SolidSystem::comp0Idx,
69
70
71 // Index of the primary component of G and L phase
72 conti0EqIdx = Indices::conti0EqIdx, //water component
73 conti1EqIdx = Indices::conti0EqIdx + 1, //air component
74 precipNaClEqIdx = Indices::conti0EqIdx + FluidSystem::numComponents,
75 energyEqIdx = Indices::energyEqIdx,
76
77 // Phase State
78 bothPhases = Indices::bothPhases,
79
80 // Grid and world dimension
81 dim = GridView::dimension,
82 dimWorld = GridView::dimensionworld,
83 };
84
85 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
86 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
87 using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
88 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
89 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
90 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
91 using Element = typename GridView::template Codim<0>::Entity;
92 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
93 using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
94 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
95 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
96 using GlobalPosition = typename SubControlVolume::GlobalPosition;
97 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
98 using FluidState = GetPropType<TypeTag, Properties::FluidState>;
99 using ThermalConductivityModel = GetPropType<TypeTag, Properties::ThermalConductivityModel>;
100
101 public:
102 2 SalinizationProblem(std::shared_ptr<const GridGeometry> gridGeometry)
103
5/10
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
6 : ParentType(gridGeometry)
104 {
105 //Fluidsystem
106
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 nTemperature_ = getParam<int>("FluidSystem.NTemperature");
107
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 nPressure_ = getParam<int>("FluidSystem.NPressure");
108
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 pressureLow_ = getParam<Scalar>("FluidSystem.PressureLow");
109
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 pressureHigh_ = getParam<Scalar>("FluidSystem.PressureHigh");
110
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 temperatureLow_ = getParam<Scalar>("FluidSystem.TemperatureLow");
111
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 temperatureHigh_ = getParam<Scalar>("FluidSystem.TemperatureHigh");
112
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 name_ = getParam<std::string>("Problem.Name");
113
114 //problem
115
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 name_ = getParam<std::string>("Problem.Name");
116
117 //initial conditions
118
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 initPressure_ = getParam<Scalar>("Problem.InitialPressure");
119
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 initGasSaturation_ = getParam<Scalar>("Problem.InitialGasSaturation");
120
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 initSalinity_ = getParam<Scalar>("Problem.InitialSalinity");
121
122 2 unsigned int codim = GetPropType<TypeTag, Properties::GridGeometry>::discMethod == DiscretizationMethods::box ? dim : 0;
123
124
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 permeability_.resize(gridGeometry->gridView().size(codim));
125 2 FluidSystem::init(/*Tmin=*/temperatureLow_,
126 /*Tmax=*/temperatureHigh_,
127 2 /*nT=*/nTemperature_,
128 /*pmin=*/pressureLow_,
129 /*pmax=*/pressureHigh_,
130
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 /*np=*/nPressure_);
131 2 }
132
133 /*!
134 * \brief The current time.
135 */
136 84 void setTime( Scalar time )
137 {
138
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 time_ = time;
139 }
140
141 /*!
142 * \brief The time step size.
143 *
144 * This is used to calculate the source term.
145 */
146 84 void setTimeStepSize( Scalar timeStepSize )
147 {
148
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 timeStepSize_ = timeStepSize;
149 }
150
151
152 /*!
153 * \brief The problem name.
154 *
155 * This is used as a prefix for files generated by the simulation.
156 */
157 2 const std::string& name() const
158
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 { return name_; }
159
160 /*!
161 * \brief Specifies which kind of boundary condition should be
162 * used for which equation on a given boundary segment.
163 */
164 27328 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
165 {
166
2/2
✓ Branch 0 taken 136640 times.
✓ Branch 1 taken 27328 times.
163968 BoundaryTypes bcTypes;
167
168 // default to Neumann
169 27328 bcTypes.setAllNeumann();
170
171 27328 return bcTypes;
172 }
173
174 /*!
175 * \brief Evaluates the boundary conditions for a Dirichlet boundary segment.
176 */
177 PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
178 {
179 PrimaryVariables priVars(0.0);
180 priVars.setState(bothPhases);
181
182 return priVars;
183 }
184
185
186 /*!
187 * \brief Evaluate the boundary conditions for a neumann
188 * boundary segment.
189 *
190 * This is the method for the case where the Neumann condition is
191 * potentially solution dependent
192 *
193 * \param element The finite element
194 * \param fvGeometry The finite-volume geometry
195 * \param elemVolVars All volume variables for the element
196 * \param elemFluxVarsCache Flux variables caches for all faces in stencil
197 * \param scvf The sub control volume face
198 *
199 * Negative values mean influx.
200 * E.g. for the mass balance that would be the mass flux in \f$ [ kg / (m^2 \cdot s)] \f$.
201 */
202 118384 NumEqVector neumann(const Element& element,
203 const FVElementGeometry& fvGeometry,
204 const ElementVolumeVariables& elemVolVars,
205 const ElementFluxVariablesCache& elemFluxVarsCache,
206 const SubControlVolumeFace& scvf) const
207 {
208
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102899 times.
236768 PrimaryVariables values(0.0);
209
210
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102899 times.
118384 const auto& globalPos = scvf.ipGlobal();
211
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102899 times.
118384 const auto& volVars = elemVolVars[scvf.insideScvIdx()];
212
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 118382 times.
118384 const Scalar hmax = this->gridGeometry().bBoxMax()[1];
213
214
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 118382 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
118384 static const Scalar temperatureRef = getParam<Scalar>("FreeFlow.RefTemperature");
215
216
2/2
✓ Branch 0 taken 16912 times.
✓ Branch 1 taken 101472 times.
118384 if (globalPos[1] > hmax - eps_)
217 {
218 // get free-flow properties:
219
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
16912 static const Scalar densityRefAir = getParam<Scalar>("FreeFlow.RefDensityAir");
220
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
16912 static const Scalar molarDensityRefAir = densityRefAir / FluidSystem::molarMass(AirIdx);
221
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
16912 static const Scalar moleFracRefH2O = getParam<Scalar>("FreeFlow.RefMoleFracH2O");
222
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
16912 static const Scalar massFracRefH2O = refMoleToRefMassFrac_(moleFracRefH2O);
223
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
16912 static const Scalar boundaryLayerThickness = getParam<Scalar>("FreeFlow.BoundaryLayerThickness");
224
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
16912 static const Scalar massTransferCoefficient = getParam<Scalar>("FreeFlow.MassTransferCoefficient");
225
226 // calculate mass fluxes
227 // liquid phase
228 // calculate transmissibilities for diffusive mass exchange of component water in gaseous phase
229 16912 const Scalar massTransmissibilityFF = massTransferCoefficient
230 16912 * volVars.diffusionCoefficient(gasPhaseIdx, AirIdx, H2OIdx)
231 16912 * molarDensityRefAir
232 16912 / boundaryLayerThickness;
233
234 21336 const Scalar avgMassTransmissibility = [&]
235 {
236 if constexpr (GridGeometry::discMethod == DiscretizationMethods::cctpfa)
237 {
238 // take mean between porous medium and free-flow transmissibility
239
1/2
✓ Branch 0 taken 2212 times.
✗ Branch 1 not taken.
4424 const auto& scv = fvGeometry.scv(scvf.insideScvIdx());
240 4424 const Scalar distancePmToInterface = (globalPos - scv.dofPosition()).two_norm();
241 2212 const Scalar molarDensityPM = volVars.molarDensity(gasPhaseIdx);
242 2212 const Scalar massTransmissibilityPM = massTransferCoefficient
243 2212 * volVars.diffusionCoefficient(gasPhaseIdx, AirIdx, H2OIdx)
244 2212 * molarDensityPM
245 / distancePmToInterface;
246 // t_12=t1+t2/(t1*t2) results from equality of of fluxes on both sides of the interface
247 // (j1=t1(x1-xi), j2=t2(xi-x2), j=j1=j2) and elimination of unknown xi at interface
248
1/2
✓ Branch 0 taken 2212 times.
✗ Branch 1 not taken.
2212 return 1.0/2.0 * Dumux::harmonicMean(massTransmissibilityPM,massTransmissibilityFF);
249 }
250
251 // box-scheme -> no mean value needed as dof lies directly on the interface
252 else if (GridGeometry::discMethod == DiscretizationMethods::box)
253 return massTransmissibilityFF;
254
255 DUNE_THROW(Dune::NotImplemented,
256 "Average transmissibility for " << GridGeometry::discMethod.name());
257 16912 }();
258
259 16912 const Scalar massFracH2OInside = volVars.massFraction(gasPhaseIdx, H2OIdx);
260 16912 const Scalar evaporationRateMole = avgMassTransmissibility
261 16912 * (massFracH2OInside - massFracRefH2O);
262
263
1/2
✓ Branch 0 taken 16912 times.
✗ Branch 1 not taken.
16912 values[conti0EqIdx] = evaporationRateMole;
264
265 // gas phase
266 // gas flows out of porous medium domain
267
1/2
✓ Branch 0 taken 16912 times.
✗ Branch 1 not taken.
16912 if (volVars.pressure(gasPhaseIdx) - 1e5 > 0) {
268
1/2
✓ Branch 0 taken 2212 times.
✗ Branch 1 not taken.
33824 values[conti1EqIdx] = (volVars.pressure(gasPhaseIdx) - 1e5)
269
1/2
✓ Branch 0 taken 2212 times.
✗ Branch 1 not taken.
36036 /(globalPos - fvGeometry.scv(scvf.insideScvIdx()).center()).two_norm()
270 16912 *volVars.mobility(gasPhaseIdx)
271 16912 *volVars.permeability()
272 16912 *volVars.molarDensity(gasPhaseIdx)
273 16912 *volVars.moleFraction(gasPhaseIdx, AirIdx);
274 }
275 // gas flows into porous medium domain
276 else
277 {
278 values[conti1EqIdx] = (volVars.pressure(gasPhaseIdx) - 1e5)
279 /(globalPos - fvGeometry.scv(scvf.insideScvIdx()).center()).two_norm()
280 *volVars.mobility(gasPhaseIdx)
281 *volVars.permeability()
282 *volVars.molarDensity(gasPhaseIdx)
283 *(1-moleFracRefH2O);
284 }
285
286 // energy fluxes
287 // convective energy fluxes
288 16912 values[energyEqIdx] = FluidSystem::componentEnthalpy(volVars.fluidState(), gasPhaseIdx, H2OIdx) * values[conti0EqIdx] * FluidSystem::molarMass(H2OIdx);
289
290 16912 values[energyEqIdx] += FluidSystem::componentEnthalpy(volVars.fluidState(), gasPhaseIdx, AirIdx) * values[conti1EqIdx] * FluidSystem::molarMass(AirIdx);
291
292 // conductive energy fluxes
293 // calculate transmissibilities for conductive energy exchange between porous medium and free-flow
294 16912 const Scalar thermalConductivityFF = FluidSystem::thermalConductivity(elemVolVars[scvf.insideScvIdx()].fluidState(), gasPhaseIdx);
295 21336 const Scalar avgThermalTransmissibility = [&]
296 {
297 if constexpr (GridGeometry::discMethod == DiscretizationMethods::cctpfa)
298 {
299 // take mean between porous medium and free-flow transmissibility
300
1/2
✓ Branch 0 taken 2212 times.
✗ Branch 1 not taken.
4424 const auto& scv = fvGeometry.scv(scvf.insideScvIdx());
301 4424 const Scalar distancePmToInterface = (globalPos - scv.dofPosition()).two_norm();
302 2212 const Scalar thermalConductivityPM = ThermalConductivityModel::effectiveThermalConductivity(volVars);
303 2212 const Scalar thermalTransmissibilityPM = thermalConductivityPM/distancePmToInterface;
304
1/2
✓ Branch 0 taken 2212 times.
✗ Branch 1 not taken.
2212 const Scalar thermalTransmissibilityFF = thermalConductivityFF/boundaryLayerThickness;
305 // t_12=t1+t2/(t1*t2) results from the equality of fluxes on both sides of the interface
306 // (j1=t1(x1-xi), j2=t2(xi-x2), j=j1=j2) and elimination of unknown xi at interface
307 2212 return 1.0/2.0 * Dumux::harmonicMean(thermalTransmissibilityPM, thermalTransmissibilityFF);
308 }
309
310 // box-scheme -> no mean value needed as dof lies directly on the interface
311 else if (GridGeometry::discMethod == DiscretizationMethods::box)
312 14700 return thermalConductivityFF/boundaryLayerThickness;
313
314 DUNE_THROW(Dune::NotImplemented,
315 "Average transmissibility for " << GridGeometry::discMethod.name());
316 16912 }();
317 16912 values[energyEqIdx] += avgThermalTransmissibility * (volVars.temperature() - temperatureRef);
318 }
319 118384 return values;
320 }
321
322 /*!
323 * \brief Evaluates the initial value for a control volume.
324 *
325 * \param globalPos The global position
326 *
327 * For this method, the \a values parameter stores primary
328 * variables.
329 */
330 28 PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const
331 {
332 28 PrimaryVariables priVars(0.0);
333 28 priVars.setState(bothPhases);
334 28 Scalar density = 1000.00; //FluidSystem::density(, liquidPhaseIdx);
335
336 28 priVars[pressureIdx] = initPressure_ - density*9.81*globalPos[dimWorld-1];
337 28 priVars[switchIdx] = initGasSaturation_; // Sg primary variable
338 28 priVars[xwNaClIdx] = massToMoleFrac_(initSalinity_); // mole fraction
339 28 priVars[precipNaClIdx] = 0.0; // [kg/m^3]
340 28 priVars[energyEqIdx] = this->spatialParams().temperature(); // [K]
341
342 return priVars;
343 }
344
345 /*!
346 * \brief Evaluates the source term for all phases within a given
347 * sub-controlvolume.
348 *
349 * This is the method for the case where the source term is
350 * potentially solution dependent and requires some quantities that
351 * are specific to the fully-implicit method.
352 *
353 * \param element The finite element
354 * \param fvGeometry The finite-volume geometry
355 * \param elemVolVars All volume variables for the element
356 * \param scv The subcontrolvolume
357 *
358 * Positive values mean that the conserved quantity is created, negative ones mean that it vanishes.
359 * E.g. for the mass balance that would be a mass rate in \f$ [ kg / (m^3 \cdot s)] \f$.
360 */
361 157200 NumEqVector source(const Element &element,
362 const FVElementGeometry& fvGeometry,
363 const ElementVolumeVariables& elemVolVars,
364 const SubControlVolume &scv) const
365 {
366 157200 NumEqVector source(0.0);
367
368 157200 const auto& volVars = elemVolVars[scv];
369
370 157200 Scalar moleFracNaCl_wPhase = volVars.moleFraction(liquidPhaseIdx, NaClIdx);
371 157200 Scalar massFracNaCl_Max_wPhase = this->spatialParams().solubilityLimit();
372 157200 Scalar moleFracNaCl_Max_wPhase = massToMoleFrac_(massFracNaCl_Max_wPhase);
373 157200 Scalar saltPorosity = this->spatialParams().minimalPorosity(element, scv);
374
375 // precipitation of amount of salt which hexeeds the solubility limit
376 using std::abs;
377 157200 Scalar precipSalt = volVars.porosity() * volVars.molarDensity(liquidPhaseIdx)
378
2/2
✓ Branch 0 taken 154620 times.
✓ Branch 1 taken 2580 times.
157200 * volVars.saturation(liquidPhaseIdx)
379
2/2
✓ Branch 0 taken 154620 times.
✓ Branch 1 taken 2580 times.
157200 * abs(moleFracNaCl_wPhase - moleFracNaCl_Max_wPhase)
380 157200 / timeStepSize_;
381
2/2
✓ Branch 0 taken 154620 times.
✓ Branch 1 taken 2580 times.
157200 if (moleFracNaCl_wPhase < moleFracNaCl_Max_wPhase)
382 154620 precipSalt *= -1;
383
384 // make sure we don't dissolve more salt than previously precipitated
385
2/2
✓ Branch 1 taken 154620 times.
✓ Branch 2 taken 2580 times.
157200 if (precipSalt*timeStepSize_ + volVars.solidVolumeFraction(sPhaseIdx)* volVars.solidComponentMolarDensity(sPhaseIdx)< 0)
386 154620 precipSalt = -volVars.solidVolumeFraction(sPhaseIdx)* volVars.solidComponentMolarDensity(sPhaseIdx)/timeStepSize_;
387
388 // make sure there is still pore space available for precipitation
389
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157200 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157200 if (volVars.solidVolumeFraction(sPhaseIdx) >= this->spatialParams().referencePorosity(element, scv) - saltPorosity && precipSalt > 0)
390 precipSalt = 0;
391
392 157200 source[conti0EqIdx + NaClIdx] += -precipSalt;
393 157200 source[precipNaClEqIdx] += precipSalt;
394 157200 return source;
395 }
396
397 /*!
398 * \brief Adds additional VTK output data to the VTKWriter.
399 *
400 * Function is called by the output module on every write.
401 */
402
403 2 const std::vector<Scalar>& getPermeability()
404 {
405
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 return permeability_;
406 }
407
408 86 void updateVtkOutput(const SolutionVector& curSol)
409 {
410
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
86 auto fvGeometry = localView(this->gridGeometry());
411
3/6
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 946 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 430 times.
✗ Branch 8 not taken.
2666 for (const auto& element : elements(this->gridGeometry().gridView()))
412 {
413
2/3
✓ Branch 2 taken 430 times.
✗ Branch 3 not taken.
✓ Branch 1 taken 430 times.
860 const auto elemSol = elementSolution(element, curSol, this->gridGeometry());
414
1/2
✓ Branch 1 taken 430 times.
✗ Branch 2 not taken.
1290 fvGeometry.bindElement(element);
415
2/2
✓ Branch 1 taken 2150 times.
✓ Branch 2 taken 860 times.
3010 for (auto&& scv : scvs(fvGeometry))
416 {
417 2150 VolumeVariables volVars;
418
1/2
✓ Branch 1 taken 2150 times.
✗ Branch 2 not taken.
2150 volVars.update(elemSol, *this, element, scv);
419 2150 const auto dofIdxGlobal = scv.dofIndex();
420 2150 permeability_[dofIdxGlobal] = volVars.permeability();
421 }
422 }
423 86 }
424
425 private:
426
427 /*!
428 * \brief Returns the molality of NaCl (mol NaCl / kg water) for a given mole fraction.
429 *
430 * \param massFracNaClInWater The mass fraction of NaCl in liquid phase water [kg NaCl / kg solution]
431 */
432 157200 static Scalar massToMoleFrac_(Scalar massFracNaClInWater)
433 {
434 157228 const Scalar molarMassWater = FluidSystem::molarMass(H2OIdx); /* molecular weight of water [kg/mol] */
435 157228 const Scalar molarMassNaCl = FluidSystem::molarMass(NaClIdx); /* molecular weight of NaCl [kg/mol] */
436
437 157200 const auto moleFracNaClInWater = -molarMassWater * massFracNaClInWater / ((molarMassNaCl - molarMassWater) * massFracNaClInWater - molarMassNaCl);
438 return moleFracNaClInWater;
439 }
440
441 /*!
442 * \brief Returns the mass fraction of H2O in the gaseous phase for a given mole fraction.
443 *
444 * \param moleFracH2OInGasRef The reference mole fraction of H2O in the gaseous phase.
445 */
446 2 static Scalar refMoleToRefMassFrac_(Scalar moleFracH2OInGasRef)
447 {
448 2 const Scalar molarMassWater = FluidSystem::molarMass(H2OIdx); // in kg/mol
449 2 const Scalar molarMassAir = FluidSystem::molarMass(AirIdx); // in kg/mol
450
451 2 auto massFracH2OInGasRef = molarMassWater * moleFracH2OInGasRef / (molarMassWater * moleFracH2OInGasRef + molarMassAir * (1 - moleFracH2OInGasRef));
452 return massFracH2OInGasRef;
453 }
454
455
456 std::string name_;
457
458 Scalar initPressure_;
459 Scalar initGasSaturation_;
460 Scalar initSalinity_;
461
462 Scalar pressureLow_, pressureHigh_;
463 Scalar temperatureLow_, temperatureHigh_;
464 int nTemperature_;
465 int nPressure_;
466
467 Scalar time_ = 0.0;
468 Scalar timeStepSize_ = 0.0;
469 static constexpr Scalar eps_ = 1e-6;
470
471 std::vector<Scalar> permeability_;
472
473 Dumux::GnuplotInterface<Scalar> gnuplot_;
474 Dumux::GnuplotInterface<Scalar> gnuplot2_;
475 std::vector<Scalar> x_;
476 std::vector<Scalar> y_;
477 std::vector<Scalar> y2_;
478 };
479
480 } // end namespace Dumux
481
482 #endif
483