GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/test/porousmediumflow/1pnc/dispersion/problem.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 40 47 85.1%
Functions: 8 14 57.1%
Branches: 51 94 54.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 OnePNCTests
10 * \brief Definition of a problem for the 1pnc problem:
11 * Component transport of nitrogen dissolved in the water phase.
12 */
13
14 #ifndef DUMUX_1P2C_TEST_PROBLEM_HH
15 #define DUMUX_1P2C_TEST_PROBLEM_HH
16
17 #include <dumux/common/properties.hh>
18 #include <dumux/common/parameters.hh>
19
20 #include <dumux/common/boundarytypes.hh>
21 #include <dumux/common/numeqvector.hh>
22 #include <dumux/porousmediumflow/problem.hh>
23
24
25 namespace Dumux {
26
27 /*!
28 * \ingroup OnePNCTests
29 * \brief Definition of a problem for the 1pnc problem:
30 * Component transport of nitrogen dissolved in the water phase.
31 *
32 * Nitrogen is dissolved in the water phase and is transported with the
33 * water flow from the left side to the right.
34 *
35 * The model domain is specified in the input file and
36 * we use homogeneous soil properties.
37 * Initially, the domain is filled with pure water.
38 *
39 * At the left side, a Dirichlet condition defines a nitrogen mole fraction.
40 * The water phase flows from the left side to the right if the applied pressure
41 * gradient is >0. The nitrogen is transported with the water flow
42 * and leaves the domain at theboundary, where again Dirichlet boundary
43 * conditions are applied.
44 *
45 * This problem uses the \ref OnePNCModel model.
46 */
47 template <class TypeTag>
48 class OnePNCDispersionProblem : public PorousMediumFlowProblem<TypeTag>
49 {
50 using ParentType = PorousMediumFlowProblem<TypeTag>;
51
52 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
53 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
54 using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
55 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
56 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
57 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
58 using Element = typename GridView::template Codim<0>::Entity;
59
60 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
61 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
62 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
63
64 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
65 using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView;
66 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
67
68 // copy some indices for convenience
69 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
70
71 enum
72 {
73 #if NONISOTHERMAL
74 energyEqIdx = Indices::energyEqIdx,
75 #endif
76 // indices of the primary variables
77 pressureIdx = Indices::pressureIdx,
78
79 // component indices
80 H2OIdx = FluidSystem::compIdx(FluidSystem::MultiPhaseFluidSystem::H2OIdx),
81 N2Idx = FluidSystem::compIdx(FluidSystem::MultiPhaseFluidSystem::N2Idx),
82 // indices of the equations
83 contiH2OEqIdx = Indices::conti0EqIdx + H2OIdx,
84 contiN2EqIdx = Indices::conti0EqIdx + N2Idx
85 };
86
87 //! Property that defines whether mole or mass fractions are used
88 static constexpr bool useMoles = getPropValue<TypeTag, Properties::UseMoles>();
89 static constexpr int numFluidComps = FluidSystem::numComponents;
90 static const int dimWorld = GridView::dimensionworld;
91 using GlobalPosition = typename SubControlVolumeFace::GlobalPosition;
92
93 public:
94 6 OnePNCDispersionProblem(std::shared_ptr<const GridGeometry> gridGeometry)
95
7/20
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✓ Branch 15 taken 6 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 6 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.
18 : ParentType(gridGeometry)
96 {
97 //initialize fluid system
98
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 FluidSystem::init();
99
100 // stating in the console whether mole or mass fractions are used
101 if constexpr (useMoles)
102
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
12 std::cout<<"problem uses mole fractions" << '\n';
103 else
104 std::cout<<"problem uses mass fractions" << '\n';
105
106
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 boundaryConcentration_ = getParam<Scalar>("Problem.BoundaryConcentration");
107
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 temperatureDifference_ = getParam<Scalar>("Problem.BoundaryTemperatureDifference");
108
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 counterFlowRate_ = getParam<Scalar>("Problem.CounterFlowRate");
109
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 pressure_ = getParam<Scalar>("Problem.Pressure");
110
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 problemName_ = getParam<std::string>("Problem.Name");
111 6 }
112
113 /*!
114 * \brief The problem name.
115 */
116 const std::string& name() const
117
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 { return problemName_; }
118
119 /*!
120 * \brief Specifies which kind of boundary condition should be
121 * used for which equation on a given boundary segment.
122 */
123 138996 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
124 {
125 138996 BoundaryTypes values;
126
127 138996 values.setAllDirichlet();
128
129 484704 if (isRightBoundary_(globalPos) ||
130 276210 isLowerBoundary_(globalPos) ||
131 isUpperBoundary_(globalPos) )
132 values.setAllNeumann();
133
134 138996 return values;
135 }
136
137 /*!
138 * \brief Evaluate the boundary conditions for a dirichlet
139 * boundary segment.
140 *
141 * For this method, the \a values parameter stores primary variables.
142 */
143 33858 PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
144 {
145 33858 PrimaryVariables values = initialAtPos(globalPos);
146
147 67716 if (isLeftBoundary_(globalPos))
148 {
149 48716 values[contiN2EqIdx] = boundaryConcentration_;
150 #if NONISOTHERMAL
151 57000 values[energyEqIdx] = this->spatialParams().temperatureAtPos(globalPos) + temperatureDifference_;
152 #endif
153 }
154
155 33858 return values;
156 }
157
158 /*!
159 * \brief Evaluates the boundary conditions for a neumann
160 * boundary segment (implementation for the box scheme).
161 *
162 * This is the method for the case where the Neumann condition is
163 * potentially solution dependent and requires some quantities that
164 * are specific to the fully-implicit method.
165 *
166 * \param element The finite element
167 * \param fvGeometry The finite-volume geometry
168 * \param elemVolVars All volume variables for the element
169 * \param elemFluxVarsCache Flux variables caches for all faces in stencil
170 * \param scvf The sub-control volume face
171 *
172 * For this method, the \a values parameter stores the flux
173 * in normal direction of each phase. Negative values mean influx.
174 * E.g. for the mass balance that would be the mass flux in \f$ [ kg / (m^2 \cdot s)] \f$.
175 */
176 NumEqVector neumann(const Element& element,
177 const FVElementGeometry& fvGeometry,
178 const ElementVolumeVariables& elemVolVars,
179 const ElementFluxVariablesCache& elemFluxVarsCache,
180 const SubControlVolumeFace& scvf) const
181 {
182 const auto globalPos = element.geometry().corner(scvf.insideScvIdx());
183 NumEqVector values(0.0);
184 if (isRightBoundary_(globalPos))
185 values[contiH2OEqIdx] = -1.0 * counterFlowRate_;
186 return values;
187 }
188
189 /*!
190 * \brief Evaluates the source term for all phases within a given
191 * sub-control volume.
192 *
193 * For this method, the \a priVars parameter stores the rate mass
194 * of a component is generated or annihilated per volume
195 * unit. Positive values mean that mass is created, negative ones
196 * mean that it vanishes.
197 *
198 * The units must be according to either using mole or mass fractions (mole/(m^3*s) or kg/(m^3*s)).
199 */
200 NumEqVector sourceAtPos(const GlobalPosition &globalPos) const
201 11715200 { return NumEqVector(0.0); }
202
203 //#### initial value for a control volume
204 36504 PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
205 {
206 36504 PrimaryVariables values;
207
208 36504 GetPropType<TypeTag, Properties::FluidState> fluidState;
209 73008 fluidState.setTemperature(this->spatialParams().temperatureAtPos(globalPos));
210 36504 fluidState.setPressure(0, pressure_);
211 36504 Scalar density = FluidSystem::density(fluidState, 0);
212 182520 const Scalar depth = this->gridGeometry().bBoxMax()[1] - globalPos[1];
213 146016 const Scalar gravity = this->spatialParams().gravity(globalPos)[1];
214
215 73008 values[Indices::pressureIdx] = pressure_ - (density * gravity * depth); //initial condition for the pressure
216 73008 values[contiN2EqIdx] = 0.0; //initial condition for the molefraction
217 #if NONISOTHERMAL
218 60969 values[energyEqIdx] = this->spatialParams().temperatureAtPos(globalPos);
219 #endif
220 36504 return values;
221 }
222
223 private:
224 bool isLeftBoundary_(const GlobalPosition& globalPos) const
225
5/10
✓ Branch 0 taken 33858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33858 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33858 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33858 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33858 times.
✗ Branch 9 not taken.
169290 { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; }
226
227 bool isRightBoundary_(const GlobalPosition& globalPos) const
228
10/20
✗ 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 taken 103356 times.
✓ Branch 11 taken 35640 times.
✓ Branch 12 taken 103356 times.
✓ Branch 13 taken 35640 times.
✓ Branch 14 taken 103356 times.
✓ Branch 15 taken 35640 times.
✓ Branch 16 taken 103356 times.
✓ Branch 17 taken 35640 times.
✓ Branch 18 taken 103356 times.
✓ Branch 19 taken 35640 times.
694980 { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; }
229
230 bool isLowerBoundary_(const GlobalPosition& globalPos) const
231
10/10
✓ Branch 0 taken 34749 times.
✓ Branch 1 taken 68607 times.
✓ Branch 2 taken 34749 times.
✓ Branch 3 taken 68607 times.
✓ Branch 4 taken 34749 times.
✓ Branch 5 taken 68607 times.
✓ Branch 6 taken 34749 times.
✓ Branch 7 taken 68607 times.
✓ Branch 8 taken 34749 times.
✓ Branch 9 taken 68607 times.
516780 { return globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_; }
232
233 bool isUpperBoundary_(const GlobalPosition& globalPos) const
234
10/10
✓ Branch 0 taken 34749 times.
✓ Branch 1 taken 33858 times.
✓ Branch 2 taken 34749 times.
✓ Branch 3 taken 33858 times.
✓ Branch 4 taken 34749 times.
✓ Branch 5 taken 33858 times.
✓ Branch 6 taken 34749 times.
✓ Branch 7 taken 33858 times.
✓ Branch 8 taken 34749 times.
✓ Branch 9 taken 33858 times.
343035 { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; }
235
236 static constexpr Scalar eps_ = 1e-6;
237 Scalar pressure_;
238 Scalar counterFlowRate_;
239 Scalar temperatureDifference_;
240 Scalar boundaryConcentration_;
241 std::string problemName_;
242 };
243
244 } // end namespace Dumux
245
246 #endif
247