GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/test/freeflow/shallowwater/roughchannel/problem.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 60 66 90.9%
Functions: 5 8 62.5%
Branches: 56 92 60.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-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 ShallowWaterTests
10 * \brief A test for the Shallow water model (rough channel).
11 */
12 #ifndef DUMUX_ROUGH_CHANNEL_TEST_PROBLEM_HH
13 #define DUMUX_ROUGH_CHANNEL_TEST_PROBLEM_HH
14
15 #include <dumux/common/boundarytypes.hh>
16 #include <dumux/common/parameters.hh>
17 #include <dumux/common/properties.hh>
18 #include <dumux/common/numeqvector.hh>
19
20 #include <dumux/freeflow/shallowwater/problem.hh>
21 #include <dumux/freeflow/shallowwater/boundaryfluxes.hh>
22
23 namespace Dumux {
24
25 /*!
26 * \ingroup ShallowWaterTests
27 * \brief A simple flow in a rough channel with friction law after Manning.
28 *
29 * At the left border a discharge
30 * boundary condition is applied and at the right border a water depth boundary condition.
31 * All other boundaries are set to no-flow. Normal flow is assumed, therefore the water depth
32 * at the right border can be calculated with the formular of Gaukler-Manning-Strickler.
33 *
34 * \f[
35 * v_m = 1/n * R_{hy}^{2/3} * I_s^{1/2}
36 * \f]
37 *
38 * With the mean velocity
39 * \f[
40 * v_m = \frac{q}/{h}
41 * \f]
42 * the friction value n after Manning
43 * the hydraulic radius R_{hy} equal to the water depth h (because normal flow is assumed)
44 * the bed slope I_s and the unity inflow discharge q.
45 *
46 * Therefore h can be calculated with
47 *
48 * \f[
49 * h = \left(\frac{n*q}{\sqrt{I_s}} \right)^{3/5}
50 * \f]
51 *
52 * The formula of Gaukler Manning and Strickler is also used to calculate the analytic solution.
53 *
54 * This problem uses the \ref ShallowWaterModel
55 */
56 template <class TypeTag>
57 class RoughChannelProblem : public ShallowWaterProblem<TypeTag>
58 {
59 using ParentType = ShallowWaterProblem<TypeTag>;
60 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
61 using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
62 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
63 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
64 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
65 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
66 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
67 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
68 using VolumeVariables = typename ElementVolumeVariables::VolumeVariables;
69 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
70 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
71 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
72 using Element = typename GridView::template Codim<0>::Entity;
73 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
74 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
75 using NeumannFluxes = NumEqVector;
76 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
77
78 public:
79 1 RoughChannelProblem(std::shared_ptr<const GridGeometry> gridGeometry)
80
9/26
✓ 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 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
3 : ParentType(gridGeometry)
81 {
82
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");
83
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);
84
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 exactVelocityX_.resize(gridGeometry->numDofs(), 0.0);
85
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 constManningN_ = getParam<Scalar>("Problem.ManningN");
86
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 bedSlope_ = getParam<Scalar>("Problem.BedSlope");
87
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 discharge_ = getParam<Scalar>("Problem.Discharge");
88 1 hBoundary_ = this->gauklerManningStrickler(discharge_,constManningN_,bedSlope_);
89 1 }
90
91 //! Get the analytical water depth
92 const std::vector<Scalar>& getExactWaterDepth()
93 {
94
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return exactWaterDepth_;
95 }
96
97 //! Get the analytical velocity
98 const std::vector<Scalar>& getExactVelocityX()
99 {
100
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return exactVelocityX_;
101 }
102
103 //! Calculate the water depth with Gaukler-Manning-Strickler
104 Scalar gauklerManningStrickler(Scalar discharge, Scalar manningN, Scalar bedSlope)
105 {
106 using std::pow;
107 using std::abs;
108 using std::sqrt;
109
110 return pow(abs(discharge)*manningN/sqrt(bedSlope), 0.6);
111 }
112
113 //! Update the analytical solution
114 24 void updateAnalyticalSolution()
115 {
116 using std::abs;
117
118
1/2
✓ Branch 3 taken 60024 times.
✗ Branch 4 not taken.
120072 for (const auto& element : elements(this->gridGeometry().gridView()))
119 {
120 60000 const Scalar h = this->gauklerManningStrickler(discharge_,constManningN_,bedSlope_);
121 60000 const Scalar u = abs(discharge_)/h;
122
123 180000 const auto eIdx = this->gridGeometry().elementMapper().index(element);
124 120000 exactWaterDepth_[eIdx] = h;
125 120000 exactVelocityX_[eIdx] = u;
126 }
127 24 }
128
129 /*!
130 * \name Problem parameters
131 */
132 // \{
133
134 /*!
135 * \brief The problem name
136 *
137 * This is used as a prefix for files generated by the simulation.
138 */
139 const std::string& name() const
140 {
141
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return name_;
142 }
143
144 /*!
145 * \brief Evaluate the source term for all balance equations within a given
146 * sub-control-volume.
147 *
148 * This is the method for the case where the source term is
149 * potentially solution dependent and requires some quantities that
150 * are specific to the fully-implicit method.
151 *
152 * \param element The finite element
153 * \param fvGeometry The finite-volume geometry
154 * \param elemVolVars All volume variables for the element
155 * \param scv The sub control volume
156 *
157 * For this method, the \a values parameter stores the conserved quantity rate
158 * generated or annihilate per volume unit. Positive values mean
159 * that the conserved quantity is created, negative ones mean that it vanishes.
160 * E.g. for the mass balance that would be a mass rate in \f$ [ kg / (m^3 \cdot s)] \f$.
161 */
162 523835 NumEqVector source(const Element& element,
163 const FVElementGeometry& fvGeometry,
164 const ElementVolumeVariables& elemVolVars,
165 const SubControlVolume &scv) const
166 {
167
168 523835 NumEqVector source (0.0);
169
170 523835 source += bottomFrictionSource(element, fvGeometry, elemVolVars, scv);
171
172 523835 return source;
173 }
174
175 /*!
176 * \brief Compute the source term due to bottom friction
177 *
178 * \param element The finite element
179 * \param fvGeometry The finite-volume geometry
180 * \param elemVolVars All volume variables for the element
181 * \param scv The sub control volume
182 *
183 * \return source
184 */
185 523835 NumEqVector bottomFrictionSource(const Element& element,
186 const FVElementGeometry& fvGeometry,
187 const ElementVolumeVariables& elemVolVars,
188 const SubControlVolume &scv) const
189 {
190 523835 NumEqVector bottomFrictionSource(0.0);
191
192 523835 const auto& volVars = elemVolVars[scv];
193 1571505 Dune::FieldVector<Scalar, 2> bottomShearStress = this->spatialParams().frictionLaw(element, scv).bottomShearStress(volVars);
194
195 1047670 bottomFrictionSource[0] = 0.0;
196 2095340 bottomFrictionSource[1] = -bottomShearStress[0] / volVars.density();
197 2095340 bottomFrictionSource[2] = -bottomShearStress[1] / volVars.density();
198
199 523835 return bottomFrictionSource;
200 }
201
202 // \}
203
204 /*!
205 * \name Boundary conditions
206 */
207 // \{
208
209 /*!
210 * \brief Specifies which kind of boundary condition should be
211 * used for which equation on a given boundary segment.
212 *
213 * \param globalPos The position for which the boundary type is set
214 */
215 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
216 {
217 268256 BoundaryTypes bcTypes;
218
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 56560 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 211696 times.
268256 bcTypes.setAllNeumann();
219 return bcTypes;
220 }
221
222 /*!
223 * \brief Specifies the neumann boundary
224 *
225 * We need the Riemann invariants to compute the values depending of the boundary type.
226 * Since we use a weak imposition we do not have a dirichlet value. We impose fluxes
227 * based on q, h, etc. computed with the Riemann invariants
228 *
229 * \param element
230 * \param fvGeometry
231 * \param elemVolVars
232 * \param elemFluxVarsCache
233 * \param scvf
234 */
235 211696 NeumannFluxes neumann(const Element& element,
236 const FVElementGeometry& fvGeometry,
237 const ElementVolumeVariables& elemVolVars,
238 const ElementFluxVariablesCache& elemFluxVarsCache,
239 const SubControlVolumeFace& scvf) const
240 {
241 211696 NeumannFluxes values(0.0);
242
243 423392 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
244 211696 const auto& insideVolVars = elemVolVars[insideScv];
245
2/2
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 210651 times.
211696 const auto& nxy = scvf.unitOuterNormal();
246
4/4
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 210651 times.
✓ Branch 2 taken 1045 times.
✓ Branch 3 taken 210651 times.
423392 const auto gravity = this->spatialParams().gravity(scvf.center());
247 std::array<Scalar, 3> boundaryStateVariables;
248
249 // impose discharge at the left side
250
12/12
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 210651 times.
✓ Branch 2 taken 1045 times.
✓ Branch 3 taken 210651 times.
✓ Branch 4 taken 1045 times.
✓ Branch 5 taken 210651 times.
✓ Branch 6 taken 1045 times.
✓ Branch 7 taken 210651 times.
✓ Branch 8 taken 1045 times.
✓ Branch 9 taken 210651 times.
✓ Branch 10 taken 1045 times.
✓ Branch 11 taken 210651 times.
1270176 if (scvf.center()[0] < this->gridGeometry().bBoxMin()[0] + eps_)
251 {
252 4180 boundaryStateVariables = ShallowWater::fixedDischargeBoundary(discharge_,
253 insideVolVars.waterDepth(),
254 insideVolVars.velocity(0),
255 insideVolVars.velocity(1),
256 gravity,
257 nxy);
258 }
259 // impose water depth at the right side
260
12/12
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 209531 times.
✓ Branch 2 taken 1120 times.
✓ Branch 3 taken 209531 times.
✓ Branch 4 taken 1120 times.
✓ Branch 5 taken 209531 times.
✓ Branch 6 taken 1120 times.
✓ Branch 7 taken 209531 times.
✓ Branch 8 taken 1120 times.
✓ Branch 9 taken 209531 times.
✓ Branch 10 taken 1120 times.
✓ Branch 11 taken 209531 times.
1263906 else if (scvf.center()[0] > this->gridGeometry().bBoxMax()[0] - eps_)
261 {
262 4480 boundaryStateVariables = ShallowWater::fixedWaterDepthBoundary(hBoundary_,
263 insideVolVars.waterDepth(),
264 insideVolVars.velocity(0),
265 insideVolVars.velocity(1),
266 gravity,
267 nxy);
268 }
269 // no flow boundary
270 else
271 {
272 419062 boundaryStateVariables[0] = insideVolVars.waterDepth();
273 419062 boundaryStateVariables[1] = -insideVolVars.velocity(0);
274 628593 boundaryStateVariables[2] = -insideVolVars.velocity(1);
275 }
276
277 211696 auto riemannFlux = ShallowWater::riemannProblem(insideVolVars.waterDepth(),
278 423392 boundaryStateVariables[0],
279 insideVolVars.velocity(0),
280 423392 boundaryStateVariables[1],
281 insideVolVars.velocity(1),
282 423392 boundaryStateVariables[2],
283 insideVolVars.bedSurface(),
284 insideVolVars.bedSurface(),
285 gravity,
286 nxy);
287
288 635088 values[Indices::massBalanceIdx] = riemannFlux[0];
289 635088 values[Indices::velocityXIdx] = riemannFlux[1];
290 635088 values[Indices::velocityYIdx] = riemannFlux[2];
291
292 211696 return values;
293 }
294
295 // \}
296
297 /*!
298 * \name Volume terms
299 */
300 // \{
301
302 /*!
303 * \brief Evaluate the initial values for a control volume.
304 *
305 * For this method, the \a values parameter stores primary
306 * variables.
307 *
308 * \param globalPos The position for which the boundary type is set
309 */
310 PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
311 {
312 2500 PrimaryVariables values(0.0);
313
314 5000 values[0] = hBoundary_;
315 7500 values[1] = abs(discharge_)/hBoundary_;
316 5000 values[2] = 0.0;
317
318 return values;
319 };
320
321 // \}
322
323 private:
324 std::vector<Scalar> exactWaterDepth_;
325 std::vector<Scalar> exactVelocityX_;
326 Scalar hBoundary_;
327 Scalar constManningN_; // analytic solution is only available for const friction.
328 Scalar bedSlope_;
329 Scalar discharge_; // discharge at the inflow boundary
330 static constexpr Scalar eps_ = 1.0e-6;
331 std::string name_;
332 };
333
334 } //end namespace Dumux
335
336 #endif
337