GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/test/porousmediumflow/mpnc/obstacle/problem.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 54 58 93.1%
Functions: 6 14 42.9%
Branches: 46 76 60.5%

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 MPNCTests
10 * \brief Problem where liquid water is injected which has to go
11 * around an obstacle with \f$10^3\f$ lower permeability.
12 *
13 * The water is injected by means of a Dirichlet condition on the lower
14 * right of the domain.
15 */
16 #ifndef DUMUX_OBSTACLEPROBLEM_HH
17 #define DUMUX_OBSTACLEPROBLEM_HH
18
19 #include <dumux/common/properties.hh>
20 #include <dumux/common/parameters.hh>
21 #include <dumux/common/boundarytypes.hh>
22 #include <dumux/common/numeqvector.hh>
23
24 #include <dumux/porousmediumflow/problem.hh>
25 #include <dumux/porousmediumflow/mpnc/initialconditionhelper.hh>
26
27 namespace Dumux {
28
29 /*!
30 * \ingroup MPNCTests
31 * \brief Problem where liquid water is injected which has to go
32 * around an obstacle with \f$10^3\f$ lower permeability.
33 *
34 * The water is injected by means of a Dirichlet condition on the lower
35 * right of the domain.
36 *
37 * The domain is sized 60m times 40m and consists of two media, a
38 * moderately permeable soil (\f$ K_0=10e-12 m^2\f$) and an obstacle
39 * at \f$[10; 20]m \times [0; 35]m \f$ with a lower permeablility of
40 * \f$ K_1=K_0/1000\f$.
41 *
42 * Initially, the whole domain is filled with nitrogen, the temperature
43 * is \f$25\symbol{23}C\f$ in the whole domain. The gas pressure in the
44 * domain is 1 bar, except on the inlet (lower 10 meters of right hand
45 * boundary) where the pressure is 2 bar.
46 *
47 * The boundary is no-flow except on the lower 10 meters of the left
48 * and the right boundary which are Dirichlet conditions with the same
49 * values as the initial condition.
50 *
51 * This problem uses the \ref MPNCModel.
52 */
53 template <class TypeTag>
54 class ObstacleProblem
55 : public PorousMediumFlowProblem<TypeTag>
56 {
57 using ParentType = PorousMediumFlowProblem<TypeTag>;
58 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
59 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
60 using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
61 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
62 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
63 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
64 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
65 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
66 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
67 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
68 using Element = typename GridView::template Codim<0>::Entity;
69 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
70 using FluidState = GetPropType<TypeTag, Properties::FluidState>;
71
72 using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>;
73 using Indices = typename ModelTraits::Indices;
74
75 enum { dimWorld = GridView::dimensionworld };
76 enum { numPhases = ModelTraits::numFluidPhases() };
77 enum { numComponents = ModelTraits::numFluidComponents() };
78 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
79 enum { liquidPhaseIdx = FluidSystem::liquidPhaseIdx };
80 enum { H2OIdx = FluidSystem::H2OIdx };
81 enum { N2Idx = FluidSystem::N2Idx };
82 enum { fug0Idx = Indices::fug0Idx };
83 enum { s0Idx = Indices::s0Idx };
84 enum { p0Idx = Indices::p0Idx };
85
86 using GlobalPosition = typename SubControlVolume::GlobalPosition;
87 using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
88
89 public:
90 2 ObstacleProblem(std::shared_ptr<const GridGeometry> gridGeometry)
91
7/20
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
6 : ParentType(gridGeometry)
92 {
93
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const auto temperature = getParam<Scalar>("SpatialParams.Temperature");
94
95 // initialize the tables of the fluid system
96 2 Scalar Tmin = temperature - 1.0;
97 2 Scalar Tmax = temperature + 1.0;
98 2 int nT = 3;
99
100 2 Scalar pmin = 1.0e5 * 0.75;
101 2 Scalar pmax = 2.0e5 * 1.25;
102 2 int np = 1000;
103
104
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 FluidSystem::init(Tmin, Tmax, nT, pmin, pmax, np);
105
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 name_ = getParam<std::string>("Problem.Name");
106 2 }
107
108 /*!
109 * \name Problem parameters
110 */
111 // \{
112
113 /*!
114 * \brief Returns the problem name
115 *
116 * This is used as a prefix for files generated by the simulation.
117 */
118 const std::string name() const
119
2/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 { return name_; }
120
121 // \}
122
123 /*!
124 * \name Boundary conditions
125 */
126 // \{
127 /*!
128 * \brief Specifies which kind of boundary condition should be
129 * used for which equation on a given boundary segment
130 *
131 * \param globalPos The global position
132 */
133 28308 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
134 {
135 28308 BoundaryTypes bcTypes;
136 55149 if (onInlet_(globalPos) || onOutlet_(globalPos))
137 bcTypes.setAllDirichlet();
138 else
139 bcTypes.setAllNeumann();
140 28308 return bcTypes;
141 }
142
143 /*!
144 * \brief Evaluates the boundary conditions for a Dirichlet boundary segment.
145 *
146 * \param globalPos The global position
147 */
148 PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
149 {
150 1134 return initial_(globalPos);
151 }
152
153 /*!
154 * \brief Evaluates the boundary conditions for a Neumann boundary segment.
155 */
156 NumEqVector neumannAtPos(const GlobalPosition& globalPos) const
157 {
158
1/2
✓ Branch 0 taken 16200 times.
✗ Branch 1 not taken.
237080 return NumEqVector(0.0);
159 }
160
161 // \}
162
163 /*!
164 * \name Volume terms
165 */
166 // \{
167
168 /*!
169 * \brief Evaluates the source term for all balance equations within a given
170 * sub-control volume.
171 *
172 * \param element The finite element
173 * \param fvGeometry The finite volume geometry of the element
174 * \param elemVolVars The volume variables of the element
175 * \param scv The sub-control volume
176 *
177 * Positive values mean that mass is created, negative ones mean that it vanishes.
178 */
179 NumEqVector source(const Element &element,
180 const FVElementGeometry& fvGeometry,
181 const ElementVolumeVariables& elemVolVars,
182 const SubControlVolume &scv) const
183 {
184 1209216 return NumEqVector(0.0);
185 }
186
187 /*!
188 * \brief Evaluates the initial value for a control volume.
189 *
190 * \param globalPos The center of the finite volume which ought to be set.
191 *
192 * For this method, the \a values parameter stores primary
193 * variables.
194 */
195 PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
196 {
197 809 return initial_(globalPos);
198 }
199
200 // \}
201
202 private:
203 // the internal method for the initial condition
204 1943 PrimaryVariables initial_(const GlobalPosition &globalPos) const
205 {
206 int refPhaseIdx, otherPhaseIdx;
207 Scalar refPhasePressure, refPhaseSaturation;
208
209 1943 FluidState fs;
210 3886 fs.setTemperature(this->spatialParams().temperatureAtPos(globalPos));
211 3886 if (onInlet_(globalPos))
212 {
213 // only liquid on inlet
214 572 refPhaseIdx = liquidPhaseIdx;
215 572 otherPhaseIdx = gasPhaseIdx;
216 572 refPhasePressure = 2e5;
217 572 refPhaseSaturation = 1.0;
218
219 572 fs.setSaturation(liquidPhaseIdx, refPhaseSaturation);
220 572 fs.setPressure(liquidPhaseIdx, refPhasePressure);
221 572 fs.setMoleFraction(liquidPhaseIdx, N2Idx, 0.0);
222 572 fs.setMoleFraction(liquidPhaseIdx, H2OIdx, 1.0);
223 }
224 else {
225 // elsewhere, only gas
226 1371 refPhaseIdx = gasPhaseIdx;
227 1371 otherPhaseIdx = liquidPhaseIdx;
228 1371 refPhasePressure = 1e5;
229 1371 refPhaseSaturation = 1.0;
230
231 1371 fs.setSaturation(gasPhaseIdx, refPhaseSaturation);
232 1371 fs.setPressure(gasPhaseIdx, refPhasePressure);
233 1371 fs.setMoleFraction(gasPhaseIdx, N2Idx, 0.99);
234 1371 fs.setMoleFraction(gasPhaseIdx, H2OIdx, 0.01);
235 }
236
237 1943 fs.setSaturation(otherPhaseIdx, 1.0 - refPhaseSaturation);
238 3886 const auto fluidMatrixInteraction = this->spatialParams().fluidMatrixInteractionAtPos(globalPos);
239 1943 const int wPhaseIdx = this->spatialParams().template wettingPhaseAtPos<FluidSystem>(globalPos);
240 1943 const auto pc = fluidMatrixInteraction.capillaryPressures(fs, wPhaseIdx);
241 5829 fs.setPressure(otherPhaseIdx, refPhasePressure + (pc[otherPhaseIdx] - pc[refPhaseIdx]));
242
243 MPNCInitialConditionHelper<PrimaryVariables, FluidSystem, ModelTraits> helper;
244 1943 helper.solve(fs, MPNCInitialConditions::NotAllPhasesPresent{.refPhaseIdx = refPhaseIdx});
245 1943 return helper.getPrimaryVariables(fs);
246 }
247
248 bool onInlet_(const GlobalPosition &globalPos) const
249 {
250
6/6
✓ Branch 0 taken 4320 times.
✓ Branch 1 taken 17280 times.
✓ Branch 2 taken 1376 times.
✓ Branch 3 taken 5332 times.
✓ Branch 4 taken 584 times.
✓ Branch 5 taken 1359 times.
30251 Scalar x = globalPos[0];
251
6/6
✓ Branch 0 taken 4320 times.
✓ Branch 1 taken 17280 times.
✓ Branch 2 taken 1376 times.
✓ Branch 3 taken 5332 times.
✓ Branch 4 taken 584 times.
✓ Branch 5 taken 1359 times.
30251 Scalar y = globalPos[1];
252
12/12
✓ Branch 0 taken 4320 times.
✓ Branch 1 taken 17280 times.
✓ Branch 2 taken 3240 times.
✓ Branch 3 taken 1080 times.
✓ Branch 4 taken 1376 times.
✓ Branch 5 taken 5332 times.
✓ Branch 6 taken 989 times.
✓ Branch 7 taken 387 times.
✓ Branch 8 taken 584 times.
✓ Branch 9 taken 1359 times.
✓ Branch 10 taken 572 times.
✓ Branch 11 taken 12 times.
30251 return x >= 60 - eps_ && y <= 10 + eps_;
253 }
254
255 bool onOutlet_(const GlobalPosition &globalPos) const
256 {
257
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 5696 times.
✓ Branch 3 taken 21145 times.
26841 Scalar x = globalPos[0];
258
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 5696 times.
✓ Branch 3 taken 21145 times.
26841 Scalar y = globalPos[1];
259
4/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5696 times.
✓ Branch 5 taken 21145 times.
✓ Branch 6 taken 4229 times.
✓ Branch 7 taken 1467 times.
26841 return x < eps_ && y <= 10 + eps_;
260 }
261
262 static constexpr Scalar eps_ = 1e-6;
263 std::string name_;
264 };
265 } // end namespace Dumux
266
267 #endif
268