GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/examples/2pinfiltration/problem.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 41 41 100.0%
Functions: 5 5 100.0%
Branches: 72 98 73.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 #ifndef DUMUX_EXAMPLE_TWOP_INFILTRATION_PROBLEM_HH
9 #define DUMUX_EXAMPLE_TWOP_INFILTRATION_PROBLEM_HH
10
11 // ## The file `problem.hh`
12 // [[content]]
13 //
14 // ### Includes
15 // We start with includes for `PorousMediumFlowProblem`, `readFileToContainer`,
16 // `BoundaryTypes`, `GetPropType` and `NumEqVector` (used below).
17 #include <dumux/porousmediumflow/problem.hh>
18 #include <dumux/io/container.hh>
19 #include <dumux/common/boundarytypes.hh>
20 #include <dumux/common/properties.hh>
21 #include <dumux/common/numeqvector.hh>
22
23 // ### Problem class
24 // The problem class `PointSourceProblem` implements boundary and initial conditions.
25 // It derives from the `PorousMediumFlowProblem` class.
26 namespace Dumux {
27
28 template <class TypeTag>
29 class PointSourceProblem : public PorousMediumFlowProblem<TypeTag>
30 {
31 // The class implementation starts with some alias declarations and index definitions for convenience
32 // [[details]] local alias declarations and indices
33 using ParentType = PorousMediumFlowProblem<TypeTag>;
34 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
35 using GridView = typename GridGeometry::GridView;
36 using Element = typename GridView::template Codim<0>::Entity;
37 using Vertex = typename GridView::template Codim<GridView::dimensionworld>::Entity;
38 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
39 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
40 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
41 using PointSource = GetPropType<TypeTag, Properties::PointSource>;
42 using BoundaryTypes = Dumux::BoundaryTypes<PrimaryVariables::size()>;
43 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
44 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
45 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
46
47 enum {
48 pressureH2OIdx = Indices::pressureIdx,
49 saturationDNAPLIdx = Indices::saturationIdx,
50 contiDNAPLEqIdx = Indices::conti0EqIdx + FluidSystem::comp1Idx,
51 waterPhaseIdx = FluidSystem::phase0Idx,
52 dnaplPhaseIdx = FluidSystem::phase1Idx
53 };
54 // [[/details]]
55 //
56 // In the constructor of the class, we call the parent type's constructor
57 // and read the initial values for the primary variables from a text file.
58 // The function `readFileToContainer` is implemented in the header `dumux/io/container.hh`.
59 public:
60 1 PointSourceProblem(std::shared_ptr<const GridGeometry> gridGeometry)
61
7/20
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 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.
3 : ParentType(gridGeometry)
62 {
63
5/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
3 initialValues_ = readFileToContainer<std::vector<PrimaryVariables>>("initialsolutioncc.txt");
64 1 }
65
66 // #### Boundary types
67 // We define the type of boundary conditions depending on the location. Two types of boundary conditions
68 // can be specified: Dirichlet or Neumann boundary conditions. On a Dirichlet boundary, the values of the
69 // primary variables need to be fixed. On a Neumann boundary condition, values for derivatives need to be fixed.
70 // Depending on the chosen discretization scheme, mixed boundary conditions (different types for different equations
71 // on the same boundary) may not be accepted.
72 // [[codeblock]]
73 33924 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
74 {
75 33924 BoundaryTypes values;
76 // Dirichlet boundaries on the left and right hand side of the domain
77 124688 if (onLeftBoundary_(globalPos) || onRightBoundary_(globalPos))
78 values.setAllDirichlet();
79 // and Neumann boundaries otherwise (top and bottom of the domain)
80 else
81 values.setAllNeumann();
82 33924 return values;
83 }
84 // [[/codeblock]]
85
86 // #### Dirichlet boundaries
87 // We specify the values for the Dirichlet boundaries, depending on location.
88 // We need to fix values for the two primary variables: the water pressure
89 // and the DNAPL saturation.
90 // [[codeblock]]
91 2880 PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
92 {
93 // To determine the density of water for a given state, we build a fluid state with the given conditions:
94 2880 PrimaryVariables values;
95 2880 GetPropType<TypeTag, Properties::FluidState> fluidState;
96 5760 fluidState.setTemperature(this->spatialParams().temperatureAtPos({}));
97 5760 fluidState.setPressure(waterPhaseIdx, /*pressure=*/1e5);
98 5760 fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5);
99
100 // The density is then calculated by the fluid system:
101 5760 const Scalar densityW = FluidSystem::density(fluidState, waterPhaseIdx);
102
103 // The water phase pressure is the hydrostatic pressure, scaled with a factor:
104 20160 const Scalar height = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1];
105 14400 const Scalar depth = this->gridGeometry().bBoxMax()[1] - globalPos[1];
106 2880 const Scalar alpha = 1 + 1.5/height;
107 20160 const Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0];
108 5760 const Scalar factor = (width*alpha + (1.0 - alpha)*globalPos[0])/width;
109
110 14400 values[pressureH2OIdx] = 1e5 - factor*densityW*this->spatialParams().gravity(globalPos)[1]*depth;
111 // The saturation of the DNAPL Trichlorethene is zero on our Dirichlet boundary:
112 5760 values[saturationDNAPLIdx] = 0.0;
113
114 2880 return values;
115 }
116 // [[/codeblock]]
117
118 // #### Neumann boundaries
119 // In our case, we need to specify mass fluxes for our two liquid phases.
120 // Negative sign means influx and the unit of the boundary flux is $`kg/(m^2 s)`$.
121 // On the inlet area, we set a DNAPL influx of $`0.04 kg/(m^2 s)`$. On all other
122 // Neumann boundaries, the boundary flux is zero.
123 // [[codeblock]]
124 17259 NumEqVector neumannAtPos(const GlobalPosition &globalPos) const
125 {
126 17259 NumEqVector values(0.0);
127 20995 if (onInlet_(globalPos))
128 7472 values[contiDNAPLEqIdx] = -0.04;
129
130 17259 return values;
131 }
132 // [[/codeblock]]
133
134 // #### Initial conditions
135 // The initial condition needs to be set for all primary variables.
136 // Here, we take the data from the file that we read in previously.
137 // [[codeblock]]
138 6144 PrimaryVariables initial(const Element& element) const
139 {
140 // The input data is written for a uniform grid with discretization length delta.
141 // Accordingly, we need to find the index of our cells, depending on the x and y coordinates,
142 // that corresponds to the indices of the input data set.
143 6144 const auto delta = 0.0625;
144 18432 const unsigned int cellsX = this->gridGeometry().bBoxMax()[0]/delta;
145
1/2
✓ Branch 2 taken 6144 times.
✗ Branch 3 not taken.
6144 const auto globalPos = element.geometry().center();
146
147 12288 const unsigned int dataIdx = std::trunc(globalPos[1]/delta) * cellsX + std::trunc(globalPos[0]/delta);
148 12288 return initialValues_[dataIdx];
149 }
150 // [[/codeblock]]
151
152 // #### Point source
153 // In this scenario, we set a point source (e.g. modeling a well). The point source value can be solution dependent.
154 // Point sources are added by pushing them into the vector `pointSources`.
155 // The `PointSource` constructor takes two arguments.
156 // The first argument is a coordinate array containing the position in space,
157 // the second argument is an array of source value for each equation (in units of $`kg/s`$).
158 // Recall that the first equation is the water phase mass balance
159 // and the second equation is the DNAPL phase mass balance.
160 void addPointSources(std::vector<PointSource>& pointSources) const
161 {
162
5/10
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
32 pointSources.push_back(PointSource({0.502, 3.02}, {0, 0.1}));
163 }
164
165 // In the private part of the class, we define some helper functions for
166 // the boundary conditions and local variables.
167 // [[details]] private data members and functions
168 private:
169 bool onLeftBoundary_(const GlobalPosition &globalPos) const
170
10/10
✓ Branch 0 taken 28420 times.
✓ Branch 1 taken 5504 times.
✓ Branch 2 taken 28420 times.
✓ Branch 3 taken 5504 times.
✓ Branch 4 taken 28420 times.
✓ Branch 5 taken 5504 times.
✓ Branch 6 taken 28420 times.
✓ Branch 7 taken 5504 times.
✓ Branch 8 taken 28420 times.
✓ Branch 9 taken 5504 times.
169620 { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; }
171
172 bool onRightBoundary_(const GlobalPosition &globalPos) const
173
10/10
✓ Branch 0 taken 22916 times.
✓ Branch 1 taken 5504 times.
✓ Branch 2 taken 22916 times.
✓ Branch 3 taken 5504 times.
✓ Branch 4 taken 22916 times.
✓ Branch 5 taken 5504 times.
✓ Branch 6 taken 22916 times.
✓ Branch 7 taken 5504 times.
✓ Branch 8 taken 22916 times.
✓ Branch 9 taken 5504 times.
142100 { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; }
174
175 bool onUpperBoundary_(const GlobalPosition &globalPos) const
176
6/6
✓ Branch 0 taken 10907 times.
✓ Branch 1 taken 6352 times.
✓ Branch 2 taken 10907 times.
✓ Branch 3 taken 6352 times.
✓ Branch 4 taken 10907 times.
✓ Branch 5 taken 6352 times.
51777 { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; }
177
178 bool onInlet_(const GlobalPosition &globalPos) const
179 {
180
12/12
✓ Branch 0 taken 10907 times.
✓ Branch 1 taken 6352 times.
✓ Branch 2 taken 10907 times.
✓ Branch 3 taken 6352 times.
✓ Branch 4 taken 10907 times.
✓ Branch 5 taken 6352 times.
✓ Branch 6 taken 10907 times.
✓ Branch 7 taken 6352 times.
✓ Branch 8 taken 10907 times.
✓ Branch 9 taken 6352 times.
✓ Branch 10 taken 10907 times.
✓ Branch 11 taken 6352 times.
103554 Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0];
181
8/8
✓ Branch 0 taken 10907 times.
✓ Branch 1 taken 6352 times.
✓ Branch 2 taken 10907 times.
✓ Branch 3 taken 6352 times.
✓ Branch 4 taken 10907 times.
✓ Branch 5 taken 6352 times.
✓ Branch 6 taken 10907 times.
✓ Branch 7 taken 6352 times.
69036 Scalar lambda = (this->gridGeometry().bBoxMax()[0] - globalPos[0])/width;
182
8/8
✓ Branch 0 taken 10907 times.
✓ Branch 1 taken 6352 times.
✓ Branch 2 taken 10907 times.
✓ Branch 3 taken 6352 times.
✓ Branch 4 taken 6629 times.
✓ Branch 5 taken 4278 times.
✓ Branch 6 taken 3736 times.
✓ Branch 7 taken 2893 times.
34518 return onUpperBoundary_(globalPos) && 0.5 < lambda && lambda < 2.0/3.0;
183 }
184
185 static constexpr Scalar eps_ = 1e-6;
186 std::vector<PrimaryVariables> initialValues_;
187 };
188
189 } // end namespace Dumux
190 // [[/details]]
191 // [[/content]]
192 #endif
193