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 in a rough channel with limited | ||
11 | * Nikuradse friction. | ||
12 | */ | ||
13 | #ifndef DUMUX_ROUGH_CHANNEL_TEST_PROBLEM_HH | ||
14 | #define DUMUX_ROUGH_CHANNEL_TEST_PROBLEM_HH | ||
15 | |||
16 | #include <dumux/common/boundarytypes.hh> | ||
17 | #include <dumux/common/parameters.hh> | ||
18 | #include <dumux/common/properties.hh> | ||
19 | #include <dumux/common/numeqvector.hh> | ||
20 | |||
21 | #include <dumux/freeflow/shallowwater/problem.hh> | ||
22 | #include <dumux/freeflow/shallowwater/boundaryfluxes.hh> | ||
23 | |||
24 | namespace Dumux { | ||
25 | |||
26 | /*! | ||
27 | * \ingroup ShallowWaterTests | ||
28 | * \brief A simple flow in a rough channel with friction law after Nikuradse with | ||
29 | * limiting. | ||
30 | * | ||
31 | * This is a synthetic test to check if the limiting of friction laws works. | ||
32 | * Therefore a parameter RoughnessHeight is used to ensure that the maximum | ||
33 | * calculated shear stress of the friction law is limited. An artificial water | ||
34 | * depth is added to the actual water depth if the water depth is smaller than | ||
35 | * two times the RoughnessHeight to limit the shear stress. | ||
36 | * | ||
37 | * At the left border a discharge boundary condition is applied and at the right | ||
38 | * border a water depth boundary condition. All other boundaries are set to | ||
39 | * no-flow. | ||
40 | * | ||
41 | * This problem uses the \ref ShallowWaterModel | ||
42 | */ | ||
43 | template <class TypeTag> | ||
44 | class RoughChannelProblem : public ShallowWaterProblem<TypeTag> | ||
45 | { | ||
46 | using ParentType = ShallowWaterProblem<TypeTag>; | ||
47 | |||
48 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
49 | using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; | ||
50 | using NumEqVector = Dumux::NumEqVector<PrimaryVariables>; | ||
51 | using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>; | ||
52 | using NeumannFluxes = NumEqVector; | ||
53 | using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; | ||
54 | |||
55 | using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; | ||
56 | using GridView = typename GridGeometry::GridView; | ||
57 | using Element = typename GridView::template Codim<0>::Entity; | ||
58 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
59 | using FVElementGeometry = typename GridGeometry::LocalView; | ||
60 | using SubControlVolume = typename FVElementGeometry::SubControlVolume; | ||
61 | using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; | ||
62 | |||
63 | using GridVariables = GetPropType<TypeTag, Properties::GridVariables>; | ||
64 | using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; | ||
65 | using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView; | ||
66 | |||
67 | public: | ||
68 | 1 | RoughChannelProblem(std::shared_ptr<const GridGeometry> gridGeometry) | |
69 |
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) |
70 | { | ||
71 |
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"); |
72 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | bedSlope_ = getParam<Scalar>("Problem.BedSlope"); |
73 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | discharge_ = getParam<Scalar>("Problem.Discharge"); |
74 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | hBoundary_ = getParam<Scalar>("Problem.WaterDepthOutflow"); |
75 | 1 | } | |
76 | |||
77 | /*! | ||
78 | * \brief The problem name | ||
79 | * | ||
80 | * This is used as a prefix for files generated by the simulation. | ||
81 | */ | ||
82 | const std::string& name() const | ||
83 | { | ||
84 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | return name_; |
85 | } | ||
86 | |||
87 | /*! | ||
88 | * \brief Evaluate the source term for all balance equations within a given | ||
89 | * sub-control-volume. | ||
90 | * | ||
91 | * This is the method for the case where the source term is | ||
92 | * potentially solution dependent and requires some quantities that | ||
93 | * are specific to the fully-implicit method. | ||
94 | * | ||
95 | * \param element The finite element | ||
96 | * \param fvGeometry The finite-volume geometry | ||
97 | * \param elemVolVars All volume variables for the element | ||
98 | * \param scv The sub control volume | ||
99 | * | ||
100 | * For this method, the values parameter stores the conserved quantity rate | ||
101 | * generated or annihilate per volume unit. Positive values mean | ||
102 | * that the conserved quantity is created, negative ones mean that it vanishes. | ||
103 | * E.g. for the mass balance that would be a mass rate in \f$ [ kg / (m^3 \cdot s)] \f$. | ||
104 | */ | ||
105 | 1070877 | NumEqVector source(const Element& element, | |
106 | const FVElementGeometry& fvGeometry, | ||
107 | const ElementVolumeVariables& elemVolVars, | ||
108 | const SubControlVolume &scv) const | ||
109 | { | ||
110 | |||
111 | 1070877 | NumEqVector source (0.0); | |
112 | 1070877 | source += bottomFrictionSource(element, fvGeometry, elemVolVars, scv); | |
113 | 1070877 | return source; | |
114 | } | ||
115 | |||
116 | /*! | ||
117 | * \brief Compute the source term due to bottom friction | ||
118 | */ | ||
119 | 1070877 | NumEqVector bottomFrictionSource(const Element& element, | |
120 | const FVElementGeometry& fvGeometry, | ||
121 | const ElementVolumeVariables& elemVolVars, | ||
122 | const SubControlVolume &scv) const | ||
123 | { | ||
124 | 1070877 | NumEqVector bottomFrictionSource(0.0); | |
125 | |||
126 | 1070877 | const auto& volVars = elemVolVars[scv]; | |
127 | 1070877 | Dune::FieldVector<Scalar, 2> bottomShearStress = | |
128 | 3212631 | this->spatialParams().frictionLaw(element, scv).bottomShearStress(volVars); | |
129 | |||
130 | 2141754 | bottomFrictionSource[0] = 0.0; | |
131 | 4283508 | bottomFrictionSource[1] = -bottomShearStress[0] / volVars.density(); | |
132 | 4283508 | bottomFrictionSource[2] = -bottomShearStress[1] / volVars.density(); | |
133 | |||
134 | 1070877 | return bottomFrictionSource; | |
135 | } | ||
136 | |||
137 | /*! | ||
138 | * \brief Specifies which kind of boundary condition should be | ||
139 | * used for which equation on a given boundary segment. | ||
140 | * | ||
141 | * \param globalPos The position for which the boundary type is set | ||
142 | */ | ||
143 | ✗ | BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const | |
144 | { | ||
145 | 544701 | BoundaryTypes bcTypes; | |
146 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 112110 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 432591 times.
|
544701 | bcTypes.setAllNeumann(); |
147 | ✗ | return bcTypes; | |
148 | } | ||
149 | |||
150 | /*! | ||
151 | * \brief Specifies the Neumann boundary | ||
152 | * | ||
153 | * We need the Riemann invariants to compute the values depending of the boundary type. | ||
154 | * Since we use a weak imposition we do not have a Dirichlet value. We impose fluxes | ||
155 | * based on q, h, etc. computed with the Riemann invariants | ||
156 | */ | ||
157 | 432591 | NeumannFluxes neumann(const Element& element, | |
158 | const FVElementGeometry& fvGeometry, | ||
159 | const ElementVolumeVariables& elemVolVars, | ||
160 | const ElementFluxVariablesCache& elemFluxVarsCache, | ||
161 | const SubControlVolumeFace& scvf) const | ||
162 | { | ||
163 | 432591 | NeumannFluxes values(0.0); | |
164 | |||
165 | 865182 | const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); | |
166 | 432591 | const auto& insideVolVars = elemVolVars[insideScv]; | |
167 | 432591 | const auto& nxy = scvf.unitOuterNormal(); | |
168 | 865182 | const auto gravity = this->spatialParams().gravity(scvf.center()); | |
169 | 432591 | const auto boundaryStateVariables = [&]() -> std::array<Scalar, 3> | |
170 | { | ||
171 | // impose discharge at the left side | ||
172 |
10/10✓ Branch 0 taken 2106 times.
✓ Branch 1 taken 430485 times.
✓ Branch 2 taken 2106 times.
✓ Branch 3 taken 430485 times.
✓ Branch 4 taken 2106 times.
✓ Branch 5 taken 430485 times.
✓ Branch 6 taken 2106 times.
✓ Branch 7 taken 430485 times.
✓ Branch 8 taken 2106 times.
✓ Branch 9 taken 430485 times.
|
2162955 | if (scvf.center()[0] < this->gridGeometry().bBoxMin()[0] + eps_) |
173 | { | ||
174 | 2106 | return ShallowWater::fixedDischargeBoundary(discharge_, | |
175 | 4212 | insideVolVars.waterDepth(), insideVolVars.velocity(0), insideVolVars.velocity(1), | |
176 | 2106 | gravity, nxy | |
177 | 2106 | ); | |
178 | } | ||
179 | |||
180 | // impose water depth at the right side | ||
181 |
12/12✓ Branch 0 taken 2160 times.
✓ Branch 1 taken 428325 times.
✓ Branch 2 taken 2160 times.
✓ Branch 3 taken 428325 times.
✓ Branch 4 taken 2160 times.
✓ Branch 5 taken 428325 times.
✓ Branch 6 taken 2160 times.
✓ Branch 7 taken 428325 times.
✓ Branch 8 taken 2160 times.
✓ Branch 9 taken 428325 times.
✓ Branch 10 taken 2160 times.
✓ Branch 11 taken 428325 times.
|
2582910 | else if (scvf.center()[0] > this->gridGeometry().bBoxMax()[0] - eps_) |
182 | { | ||
183 | 8640 | return ShallowWater::fixedWaterDepthBoundary(hBoundary_, | |
184 | insideVolVars.waterDepth(), insideVolVars.velocity(0), insideVolVars.velocity(1), | ||
185 | gravity, nxy | ||
186 | 2160 | ); | |
187 | } | ||
188 | |||
189 | // no flow boundary | ||
190 | else | ||
191 | { | ||
192 | return {{ | ||
193 | insideVolVars.waterDepth(), | ||
194 | 856650 | -insideVolVars.velocity(0), | |
195 | 856650 | -insideVolVars.velocity(1) | |
196 | 1713300 | }}; | |
197 | } | ||
198 |
2/2✓ Branch 1 taken 2106 times.
✓ Branch 2 taken 430485 times.
|
865182 | }(); |
199 | |||
200 | 432591 | const auto riemannFlux = ShallowWater::riemannProblem( | |
201 | 865182 | insideVolVars.waterDepth(), boundaryStateVariables[0], | |
202 | 865182 | insideVolVars.velocity(0), boundaryStateVariables[1], | |
203 | 865182 | insideVolVars.velocity(1), boundaryStateVariables[2], | |
204 | insideVolVars.bedSurface(), insideVolVars.bedSurface(), | ||
205 | gravity, nxy | ||
206 | ); | ||
207 | |||
208 | 1297773 | values[Indices::massBalanceIdx] = riemannFlux[0]; | |
209 | 1297773 | values[Indices::velocityXIdx] = riemannFlux[1]; | |
210 | 1297773 | values[Indices::velocityYIdx] = riemannFlux[2]; | |
211 | |||
212 | 432591 | return values; | |
213 | } | ||
214 | |||
215 | /*! | ||
216 | * \brief Evaluate the initial values for a control volume | ||
217 | */ | ||
218 | ✗ | PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const | |
219 | { | ||
220 | 2500 | PrimaryVariables values(0.0); | |
221 | |||
222 | 5000 | values[0] = hBoundary_; | |
223 | 7500 | values[1] = abs(discharge_)/hBoundary_ *0.9; | |
224 | 5000 | values[2] = 0.0; | |
225 | |||
226 | ✗ | return values; | |
227 | }; | ||
228 | |||
229 | private: | ||
230 | Scalar hBoundary_; | ||
231 | Scalar bedSlope_; | ||
232 | Scalar discharge_; // discharge at the inflow boundary | ||
233 | static constexpr Scalar eps_ = 1.0e-6; | ||
234 | std::string name_; | ||
235 | }; | ||
236 | |||
237 | } // end namespace Dumux | ||
238 | |||
239 | #endif | ||
240 |