GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/test/freeflow/shallowwater/poiseuilleflow/vertical/problem.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 69 74 93.2%
Functions: 4 7 57.1%
Branches: 61 110 55.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_POISEUILLE_FLOW_VERTICAL_TEST_PROBLEM_HH
9 #define DUMUX_POISEUILLE_FLOW_VERTICAL_TEST_PROBLEM_HH
10
11 #include <algorithm>
12 #include <cctype>
13
14 #include <dumux/common/properties.hh>
15 #include <dumux/common/parameters.hh>
16 #include <dumux/common/numeqvector.hh>
17
18 #include <dumux/freeflow/shallowwater/problem.hh>
19 #include <dumux/freeflow/shallowwater/boundaryfluxes.hh>
20
21 namespace Dumux {
22
23 /*!
24 * \ingroup ShallowWaterTests
25 * \brief A simple test for the 2D flow in a channel with viscous bottom friction (plane Poiseuille flow).
26 * In comparison to the other Poiseuille flow test, here we assume a rectangular channel with zero friction walls
27 * but viscous friction due to bottom shear stress.
28 * The result is a parabolic velocity profile \f$ U(z) \f$ over the height:
29 * \f[
30 * U(z) = 3u(z/h - 0.5(z/h)^2)
31 * \f]
32 * bottom shear stress
33 * \f[
34 * \tau = -\mu 3u/h
35 * \f]
36 * and mean velocity
37 * \f[
38 * u = \frac{1}{3} \frac{h^2 \rho g S}{\mu}
39 * \f]
40 * where \f$ S \f$ denotes the bed slope in m/m.
41 * Therefore, in difference to the other test, the heigh-averaged velocity is constant over the channel width
42 * and to model the bottom surface, we need to include the effect of the bottom shear stress.
43 * This problem uses the \ref ShallowWaterModel
44 */
45 template<class TypeTag>
46 class PoiseuilleFlowProblem
47 : public ShallowWaterProblem<TypeTag>
48 {
49 using ParentType = ShallowWaterProblem<TypeTag>;
50 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
51 using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
52 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
53 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
54 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
55 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
56 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
57 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
58 using VolumeVariables = typename ElementVolumeVariables::VolumeVariables;
59 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
60 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
61 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
62 using Element = typename GridView::template Codim<0>::Entity;
63 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
64 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
65 using NeumannFluxes = NumEqVector;
66 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
67 using FluidSystem = typename VolumeVariables::FluidSystem;
68
69 public:
70 1 PoiseuilleFlowProblem(std::shared_ptr<const GridGeometry> gridGeometry)
71
10/30
✓ 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 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
3 : ParentType(gridGeometry)
72 {
73 // assume box grid with flow in x-direction driven by gravity
74
6/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 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
6 channelWidth_ = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1];
75
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 name_ = getParam<std::string>("Problem.Name");
76
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 bedSlope_ = getParam<Scalar>("Problem.BedSlope");
77
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 waterDepthBoundary_ = getParam<Scalar>("Problem.WaterDepth");
78
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 dynamicViscosity_ = FluidSystem::viscosity(293.15, 1e5);
79
80
3/6
✓ 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.
2 exactWaterDepth_.resize(gridGeometry->numDofs(), 0.0);
81
3/6
✓ 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.
2 exactVelocityX_.resize(gridGeometry->numDofs(), 0.0);
82
3/8
✓ 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 9 not taken.
✗ Branch 10 not taken.
2 exactVelocityY_.resize(gridGeometry->numDofs(), 0.0);
83 1 }
84
85 const std::string& name() const
86
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { return name_; }
87
88 /*!
89 * \brief Specifies which kind of boundary condition should be
90 * used for which equation on a given boundary segment.
91 *
92 * \param globalPos The position for which the boundary type is set
93 */
94 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
95 {
96 440 BoundaryTypes bcTypes;
97
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 352 times.
440 bcTypes.setAllNeumann();
98 return bcTypes;
99 }
100
101 /*!
102 * \brief Specifies the neumann boundary
103 *
104 * We need the Riemann invariants to compute the values depending of the boundary type.
105 * Since we use a weak imposition we do not have a dirichlet value. We impose fluxes
106 * based on q, h, etc. computed with the Riemann invariants
107 */
108 352 NeumannFluxes neumann(const Element& element,
109 const FVElementGeometry& fvGeometry,
110 const ElementVolumeVariables& elemVolVars,
111 const ElementFluxVariablesCache& elemFluxVarsCache,
112 const SubControlVolumeFace& scvf) const
113 {
114 352 NeumannFluxes values(0.0);
115
116 352 const auto& globalPos = scvf.ipGlobal();
117 704 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
118 352 const auto& insideVolVars = elemVolVars[insideScv];
119
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 160 times.
352 const auto& unitNormal = scvf.unitOuterNormal();
120
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 160 times.
352 const auto gravity = this->spatialParams().gravity(globalPos);
121 std::array<Scalar, 3> boundaryStateVariables;
122
123
8/8
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 192 times.
✓ Branch 3 taken 160 times.
✓ Branch 4 taken 192 times.
✓ Branch 5 taken 160 times.
✓ Branch 6 taken 192 times.
✓ Branch 7 taken 160 times.
1408 if (globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_
124
12/12
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 160 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 160 times.
✓ Branch 7 taken 32 times.
✓ Branch 8 taken 160 times.
✓ Branch 9 taken 32 times.
✓ Branch 10 taken 160 times.
✓ Branch 11 taken 32 times.
352 || globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_)
125 {
126 // full slip for tangential part and reflection (no-flow) for normal part
127 1280 const Scalar insideVelocityNormalWall = insideVolVars.velocity(0)*unitNormal[0] + insideVolVars.velocity(1)*unitNormal[1];
128 1280 const Scalar insideVelocityTangentWall = -insideVolVars.velocity(0)*unitNormal[1] + insideVolVars.velocity(1)*unitNormal[0];
129 320 const Scalar outsideVelocityNormalWall = -insideVelocityNormalWall;
130 320 const Scalar outsideVelocityTangentWall = insideVelocityTangentWall;
131 640 const Scalar outsideVelocityXWall = outsideVelocityNormalWall*unitNormal[0] - outsideVelocityTangentWall*unitNormal[1];
132 640 const Scalar outsideVelocityYWall = outsideVelocityNormalWall*unitNormal[1] + outsideVelocityTangentWall*unitNormal[0];
133 640 boundaryStateVariables = { insideVolVars.waterDepth(), outsideVelocityXWall, outsideVelocityYWall };
134 }
135 else
136 {
137 // for inlet and outlet, the same water depth is prescribed
138 96 boundaryStateVariables = ShallowWater::fixedWaterDepthBoundary(
139 32 waterDepthBoundary_,
140 insideVolVars.waterDepth(), insideVolVars.velocity(0), insideVolVars.velocity(1),
141 gravity, unitNormal
142 );
143 }
144
145 352 auto riemannFlux = ShallowWater::riemannProblem(
146 704 insideVolVars.waterDepth(), boundaryStateVariables[0],
147 704 insideVolVars.velocity(0), boundaryStateVariables[1],
148 704 insideVolVars.velocity(1), boundaryStateVariables[2],
149 insideVolVars.bedSurface(), insideVolVars.bedSurface(),
150 gravity, unitNormal
151 );
152
153 1056 values[Indices::massBalanceIdx] = riemannFlux[0];
154 1056 values[Indices::velocityXIdx] = riemannFlux[1];
155 1056 values[Indices::velocityYIdx] = riemannFlux[2];
156
157 // zero viscous part of the flux since we assume full slip on the walls
158
159 352 return values;
160 }
161
162 // bottom friction source
163 320 NumEqVector source(const Element &element,
164 const FVElementGeometry& fvGeometry,
165 const ElementVolumeVariables& elemVolVars,
166 const SubControlVolume& scv) const
167 {
168 320 NumEqVector bottomFrictionSource(0.0);
169
170 320 const auto& volVars = elemVolVars[scv];
171 320 Dune::FieldVector<Scalar, 2> bottomShearStress =
172 960 this->spatialParams().frictionLaw(element, scv).bottomShearStress(volVars);
173
174 640 bottomFrictionSource[0] = 0.0;
175 1280 bottomFrictionSource[1] = -bottomShearStress[0] / volVars.density();
176 1280 bottomFrictionSource[2] = -bottomShearStress[1] / volVars.density();
177
178 320 return bottomFrictionSource;
179 }
180
181 // Set initial sol to the exact solution
182 PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const
183 {
184 80 return exactSol_(globalPos);
185 };
186
187 //! Update the analytical solution
188 1 void updateAnalyticalSolution()
189 {
190
1/2
✓ Branch 3 taken 41 times.
✗ Branch 4 not taken.
83 for (const auto& element : elements(this->gridGeometry().gridView()))
191 {
192 120 const auto eIdx = this->gridGeometry().elementMapper().index(element);
193 40 const auto& globalPos = element.geometry().center();
194 80 const auto sol = exactSol_(globalPos);
195 120 exactWaterDepth_[eIdx] = sol[Indices::waterdepthIdx];
196 120 exactVelocityX_[eIdx] = sol[Indices::velocityXIdx];
197 120 exactVelocityY_[eIdx] = sol[Indices::velocityYIdx];
198 }
199 1 }
200
201 //! Get the analytical water depth
202 const std::vector<Scalar>& getExactWaterDepth() const
203
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { return exactWaterDepth_; }
204
205 //! Get the analytical U-velocity
206 const std::vector<Scalar>& getExactVelocityX() const
207
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { return exactVelocityX_; }
208
209 //! Get the analytical V-velocity
210 const std::vector<Scalar>& getExactVelocityY() const
211
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { return exactVelocityY_; }
212
213 private:
214 PrimaryVariables exactSol_(const GlobalPosition& globalPos) const
215 {
216 80 PrimaryVariables values(0.0);
217 160 const auto gravity = this->spatialParams().gravity(globalPos);
218 80 const auto hSquared = waterDepthBoundary_*waterDepthBoundary_;
219 80 const auto pressureGradient = 1000.0*gravity*bedSlope_;
220 160 values[0] = waterDepthBoundary_;
221 160 values[1] = pressureGradient*hSquared/(3.0*dynamicViscosity_);
222 160 values[2] = 0.0;
223 return values;
224 }
225
226 std::vector<Scalar> exactWaterDepth_;
227 std::vector<Scalar> exactVelocityX_;
228 std::vector<Scalar> exactVelocityY_;
229
230 Scalar channelWidth_;
231 Scalar waterDepthBoundary_; // water level
232 Scalar bedSlope_; // bed slope (positive downwards)
233 Scalar dynamicViscosity_;
234
235 static constexpr Scalar eps_ = 1.0e-6;
236 std::string name_;
237 };
238
239 } //end namespace Dumux
240
241 #endif
242