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_TEST_PROBLEM_HH | ||
9 | #define DUMUX_POISEUILLE_FLOW_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 rough side walls (Poiseuille flow). | ||
26 | * | ||
27 | * The initial water depth corresponds to the analytical solution: | ||
28 | * having a slope equal to \f$ ib = d \Theta / L \f$ , where \f$ d \Theta \f$ is the water level difference between upstream and downstream and \f$ L \f$ is the domain length. | ||
29 | * At the west/left (inflow) boundary a discharge is prescribed of \f$ Q_{in} \f$ or \f$ q_{in} \f$ per meter. | ||
30 | * At the east/right (outflow) boundary a fixed water level is prescribed of \f$ \Theta \f$. | ||
31 | * The south and north boundaries are set to roughwall type boundaries, | ||
32 | * with a coefficient alphaWall = 1.0, where: | ||
33 | * alphaWall = 0.0: full slip (smooth wall) | ||
34 | * 0.0 <alphaWall < 1.0: partial slip (partially-rough wall) | ||
35 | * alphaWall = 1.0: no slip (fully-rough wall) | ||
36 | * Additionally these (south and north) boundaries are (automatically) set to no-flow boundaries. | ||
37 | |||
38 | * The flow in the channel experiences two forces: | ||
39 | * 1) the pressure gradient, driving the flow downstream | ||
40 | * 2) the wall roughness, | ||
41 | |||
42 | * It can be verified that this force balance reduces the momentum equation in X-direction to: | ||
43 | * | ||
44 | \f[ | ||
45 | \frac{\partial p}{\partial x} = \nu_T \frac{\partial^2 u}{\partial y^2} | ||
46 | \f] | ||
47 | * where \f$ \nu_T \f$ is the turbulent viscosity. | ||
48 | * | ||
49 | * This ordinary differential equation can be solved (applying the boundary conditions to obtain the integration constants), | ||
50 | * resulting in a parabolic velocity profile in lateral direction (over the width of the channel): | ||
51 | * | ||
52 | \f[ | ||
53 | u(y) = \frac{g d \Theta}{8 \nu_T L} \left(4y^2 - W^2\right) | ||
54 | \f] | ||
55 | * | ||
56 | * where y the coordinate in lateral direction. | ||
57 | * The velocity has a maximum value at y = 0: | ||
58 | \f[ | ||
59 | u_{max} = \frac{g d \Theta W^2}{8 \nu_T L} | ||
60 | \f] | ||
61 | * | ||
62 | The formula for \f$ u(y) \f$ is also used to calculate the analytic solution. | ||
63 | * It should be noted that u = f(x) and that v = 0 in the whole domain (in the final steady state). | ||
64 | * Therefore the momentum advection/convection terms should be zero for this test, as: | ||
65 | * \f$ u \partial u / \partial x = v \partial u / \partial y = u \partial v / \partial x = v \partial v / \partial y = 0 \f$ | ||
66 | * | ||
67 | * This problem uses the \ref ShallowWaterModel | ||
68 | */ | ||
69 | template<class TypeTag> | ||
70 | class PoiseuilleFlowProblem | ||
71 | : public ShallowWaterProblem<TypeTag> | ||
72 | { | ||
73 | using ParentType = ShallowWaterProblem<TypeTag>; | ||
74 | using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; | ||
75 | using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>; | ||
76 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
77 | using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; | ||
78 | using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; | ||
79 | using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView; | ||
80 | using GridVariables = GetPropType<TypeTag, Properties::GridVariables>; | ||
81 | using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; | ||
82 | using VolumeVariables = typename ElementVolumeVariables::VolumeVariables; | ||
83 | using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView; | ||
84 | using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; | ||
85 | using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView; | ||
86 | using Element = typename GridView::template Codim<0>::Entity; | ||
87 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
88 | using NumEqVector = Dumux::NumEqVector<PrimaryVariables>; | ||
89 | using NeumannFluxes = NumEqVector; | ||
90 | using SubControlVolume = typename FVElementGeometry::SubControlVolume; | ||
91 | |||
92 | public: | ||
93 | 6 | PoiseuilleFlowProblem(std::shared_ptr<const GridGeometry> gridGeometry) | |
94 |
11/34✓ 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 21 taken 6 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 6 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 6 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 6 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
|
18 | : ParentType(gridGeometry) |
95 | { | ||
96 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
|
6 | name_ = getParam<std::string>("Problem.Name"); |
97 |
4/7✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
12 | exactWaterDepth_.resize(gridGeometry->numDofs(), 0.0); |
98 |
4/7✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
12 | exactVelocityX_.resize(gridGeometry->numDofs(), 0.0); |
99 |
4/10✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
12 | exactVelocityY_.resize(gridGeometry->numDofs(), 0.0); |
100 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | bedSlope_ = getParam<Scalar>("Problem.BedSlope"); |
101 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | discharge_ = getParam<Scalar>("Problem.Discharge"); |
102 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | hBoundary_ = getParam<Scalar>("Problem.HBoundary"); |
103 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | alphaWall_ = getParam<Scalar>("Problem.AlphaWall"); |
104 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | turbViscosity_ = getParam<Scalar>("ShallowWater.TurbulentViscosity"); |
105 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | ksWall_ = getParam<Scalar>("Problem.KsWall"); |
106 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
|
6 | wallFrictionLawType_ = getParam<std::string>("Problem.WallFrictionLaw"); |
107 | // Make the wallFrictionLawType_ lower case | ||
108 | 60 | std::transform(wallFrictionLawType_.begin(), wallFrictionLawType_.end(), wallFrictionLawType_.begin(), [](unsigned char c){ return std::tolower(c); }); | |
109 | 6 | } | |
110 | |||
111 | //! Get the analytical water depth | ||
112 | const std::vector<Scalar>& getExactWaterDepth() const | ||
113 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | { return exactWaterDepth_; } |
114 | |||
115 | //! Get the analytical U-velocity | ||
116 | const std::vector<Scalar>& getExactVelocityX() const | ||
117 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | { return exactVelocityX_; } |
118 | |||
119 | //! Get the analytical V-velocity | ||
120 | const std::vector<Scalar>& getExactVelocityY() const | ||
121 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | { return exactVelocityY_; } |
122 | |||
123 | //! Update the analytical solution | ||
124 | 219 | void updateAnalyticalSolution() | |
125 | { | ||
126 |
4/4✓ Branch 3 taken 74674 times.
✓ Branch 4 taken 111 times.
✓ Branch 5 taken 44326 times.
✓ Branch 6 taken 111 times.
|
149789 | for (const auto& element : elements(this->gridGeometry().gridView())) |
127 | { | ||
128 | 223698 | const auto eIdx = this->gridGeometry().elementMapper().index(element); | |
129 | 118892 | const auto& globalPos = element.geometry().center(); | |
130 | 104806 | const auto gravity = this->spatialParams().gravity(globalPos); | |
131 | 104806 | const Scalar y = globalPos[1]; | |
132 | 477636 | const Scalar width = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; | |
133 | 74566 | const Scalar h = hBoundary_; | |
134 | 74566 | const Scalar u = -(gravity*bedSlope_/(8.0*turbViscosity_)) * (4.0*y*y - width*width); | |
135 | 104806 | exactWaterDepth_[eIdx] = h; | |
136 | 104806 | exactVelocityX_[eIdx] = u; | |
137 | 149132 | exactVelocityY_[eIdx] = 0.0; | |
138 | } | ||
139 | 219 | } | |
140 | |||
141 | const std::string& name() const | ||
142 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | { return name_; } |
143 | |||
144 | /*! | ||
145 | * \name Boundary conditions | ||
146 | */ | ||
147 | // \{ | ||
148 | |||
149 | /*! | ||
150 | * \brief Specifies which kind of boundary condition should be | ||
151 | * used for which equation on a given boundary segment. | ||
152 | * | ||
153 | * \param globalPos The position for which the boundary type is set | ||
154 | */ | ||
155 | ✗ | BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const | |
156 | { | ||
157 | 148431 | BoundaryTypes bcTypes; | |
158 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 31760 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 116671 times.
|
148431 | bcTypes.setAllNeumann(); |
159 | ✗ | return bcTypes; | |
160 | } | ||
161 | |||
162 | /*! | ||
163 | * \brief Specifies the neumann boundary | ||
164 | * | ||
165 | * We need the Riemann invariants to compute the values depending of the boundary type. | ||
166 | * Since we use a weak imposition we do not have a dirichlet value. We impose fluxes | ||
167 | * based on q, h, etc. computed with the Riemann invariants | ||
168 | */ | ||
169 | 116671 | NeumannFluxes neumann(const Element& element, | |
170 | const FVElementGeometry& fvGeometry, | ||
171 | const ElementVolumeVariables& elemVolVars, | ||
172 | const ElementFluxVariablesCache& elemFluxVarsCache, | ||
173 | const SubControlVolumeFace& scvf) const | ||
174 | { | ||
175 | 116671 | NeumannFluxes values(0.0); | |
176 | |||
177 | 233342 | const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); | |
178 | 116671 | const auto& insideVolVars = elemVolVars[insideScv]; | |
179 |
2/2✓ Branch 0 taken 18192 times.
✓ Branch 1 taken 98479 times.
|
116671 | const auto& unitNormal = scvf.unitOuterNormal(); |
180 |
4/4✓ Branch 0 taken 18192 times.
✓ Branch 1 taken 98479 times.
✓ Branch 2 taken 18192 times.
✓ Branch 3 taken 98479 times.
|
233342 | const auto gravity = this->spatialParams().gravity(scvf.center()); |
181 | std::array<Scalar, 3> boundaryStateVariables; | ||
182 | |||
183 | // impose discharge at the left side | ||
184 |
12/12✓ Branch 0 taken 18192 times.
✓ Branch 1 taken 98479 times.
✓ Branch 2 taken 18192 times.
✓ Branch 3 taken 98479 times.
✓ Branch 4 taken 18192 times.
✓ Branch 5 taken 98479 times.
✓ Branch 6 taken 18192 times.
✓ Branch 7 taken 98479 times.
✓ Branch 8 taken 18192 times.
✓ Branch 9 taken 98479 times.
✓ Branch 10 taken 18192 times.
✓ Branch 11 taken 98479 times.
|
700026 | if (scvf.center()[0] < this->gridGeometry().bBoxMin()[0] + eps_) |
185 | { | ||
186 | // Prescribe the exact q-distribution long the inflow boundaryStateVariables | ||
187 | // based on the parabolic u-profile: | ||
188 | // q(y) = (g*H*ib/(8*nu_T)) * (4*y^2^-W^2) | ||
189 | // Note the opposite sign to the velocity u, due to the fact that it is an inflow discharge | ||
190 | 36384 | const auto y = scvf.center()[1]; | |
191 | 109152 | const auto width = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; | |
192 | 18192 | const auto h = hBoundary_; | |
193 | // Now compute a weighted average between the constant q (from input) and the parabolic q from the analytical solution | ||
194 | // based on the prescribed alphaWall | ||
195 | 18192 | const auto q_in0 = (gravity*h*bedSlope_/(8.0*turbViscosity_)) * (4.0*y*y - width*width); | |
196 | 18192 | const auto q_in1 = discharge_; | |
197 | 18192 | const auto q_in = (1.0-alphaWall_)*q_in1 + alphaWall_*q_in0; | |
198 | 72768 | boundaryStateVariables = ShallowWater::fixedDischargeBoundary(q_in, | |
199 | insideVolVars.waterDepth(), | ||
200 | insideVolVars.velocity(0), | ||
201 | insideVolVars.velocity(1), | ||
202 | gravity, | ||
203 | unitNormal); | ||
204 | } | ||
205 | // impose water depth at the right side | ||
206 |
12/12✓ Branch 0 taken 18306 times.
✓ Branch 1 taken 80173 times.
✓ Branch 2 taken 18306 times.
✓ Branch 3 taken 80173 times.
✓ Branch 4 taken 18306 times.
✓ Branch 5 taken 80173 times.
✓ Branch 6 taken 18306 times.
✓ Branch 7 taken 80173 times.
✓ Branch 8 taken 18306 times.
✓ Branch 9 taken 80173 times.
✓ Branch 10 taken 18306 times.
✓ Branch 11 taken 80173 times.
|
590874 | else if (scvf.center()[0] > this->gridGeometry().bBoxMax()[0] - eps_) |
207 | { | ||
208 | 73224 | boundaryStateVariables = ShallowWater::fixedWaterDepthBoundary(hBoundary_, | |
209 | insideVolVars.waterDepth(), | ||
210 | insideVolVars.velocity(0), | ||
211 | insideVolVars.velocity(1), | ||
212 | gravity, | ||
213 | unitNormal); | ||
214 | } | ||
215 | // no flow boundary | ||
216 | else | ||
217 | { | ||
218 | // For the rough side walls of type no-slip we prescribe a slip condition based on alphaWall | ||
219 | // for smooth closed walls we prescribed a full-slip condition (zero-roughness) | ||
220 | |||
221 | // Get inside velocity components in cell face coordinates (t,n) using normal vector unitNormal | ||
222 | // Note that the first component is the normal component | ||
223 | // since we are rotating to the normal vector coordinate system | ||
224 |
8/8✓ Branch 0 taken 40109 times.
✓ Branch 1 taken 40064 times.
✓ Branch 2 taken 40109 times.
✓ Branch 3 taken 40064 times.
✓ Branch 4 taken 40109 times.
✓ Branch 5 taken 40064 times.
✓ Branch 6 taken 40109 times.
✓ Branch 7 taken 40064 times.
|
320692 | const Scalar insideVelocityNWall = insideVolVars.velocity(0)*unitNormal[0] + insideVolVars.velocity(1)*unitNormal[1]; |
225 |
8/8✓ Branch 0 taken 40109 times.
✓ Branch 1 taken 40064 times.
✓ Branch 2 taken 40109 times.
✓ Branch 3 taken 40064 times.
✓ Branch 4 taken 40109 times.
✓ Branch 5 taken 40064 times.
✓ Branch 6 taken 40109 times.
✓ Branch 7 taken 40064 times.
|
320692 | const Scalar insideVelocityTWall = -insideVolVars.velocity(0)*unitNormal[1] + insideVolVars.velocity(1)*unitNormal[0]; |
226 | |||
227 | // Initialisation of outside velocities | ||
228 | 80173 | auto outsideVelocityNWall = insideVelocityNWall; | |
229 | 80173 | auto outsideVelocityTWall = insideVelocityTWall; | |
230 | |||
231 | // Now set the outside (ghost cell) velocities based on the chosen slip condition | ||
232 |
19/28✓ Branch 0 taken 40109 times.
✓ Branch 1 taken 40064 times.
✓ Branch 2 taken 40109 times.
✓ Branch 3 taken 40064 times.
✓ Branch 4 taken 40109 times.
✓ Branch 5 taken 40064 times.
✓ Branch 6 taken 40109 times.
✓ Branch 7 taken 40064 times.
✓ Branch 8 taken 40109 times.
✓ Branch 9 taken 40064 times.
✓ Branch 10 taken 40109 times.
✓ Branch 11 taken 40064 times.
✓ Branch 12 taken 40109 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 40109 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 40109 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 40109 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 40109 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 40109 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 80173 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
481038 | if ((scvf.center()[1] < this->gridGeometry().bBoxMin()[1] + eps_ || scvf.center()[1] > this->gridGeometry().bBoxMax()[1] - eps_) && (wallFrictionLawType_ == "noslip" || wallFrictionLawType_ == "nikuradse")) |
233 | { | ||
234 | // Set the outside state using the no-slip wall roughness conditions based on alphaWall | ||
235 | // alphaWall = 0.0: full slip (wall tangential velocity equals inside tangential velocity) | ||
236 | // alphaWall = 1.0: no slip (wall tangential velocity=0.0: point mirroring of the velocity) | ||
237 | // 0.0 < alphaWall < 1.0: 'partial' slip. | ||
238 | // e.g. for alphaWall = 0.5 the wall tangential velocity is half the inside tangential velocity. | ||
239 | 80173 | outsideVelocityNWall = -insideVelocityNWall; | |
240 | 80173 | outsideVelocityTWall = (1.0 - 2.0*alphaWall_)*insideVelocityTWall; | |
241 | } | ||
242 | else | ||
243 | { | ||
244 | // Set the outside state using the full-slip wall roughness conditions (line mirroring in the boundary face) | ||
245 | // Only mirror the normal component | ||
246 | ✗ | outsideVelocityNWall = -insideVelocityNWall; | |
247 | ✗ | outsideVelocityTWall = insideVelocityTWall; | |
248 | } | ||
249 | // Rotate back to cartesian coordinate system | ||
250 | 160346 | const Scalar outsideVelocityXWall = outsideVelocityNWall*unitNormal[0] - outsideVelocityTWall*unitNormal[1]; | |
251 | 160346 | const Scalar outsideVelocityYWall = outsideVelocityNWall*unitNormal[1] + outsideVelocityTWall*unitNormal[0]; | |
252 | |||
253 | 160346 | boundaryStateVariables[0] = insideVolVars.waterDepth(); | |
254 | 80173 | boundaryStateVariables[1] = outsideVelocityXWall; | |
255 | 160346 | boundaryStateVariables[2] = outsideVelocityYWall; | |
256 | |||
257 | } | ||
258 | |||
259 | 116671 | auto riemannFlux = ShallowWater::riemannProblem(insideVolVars.waterDepth(), | |
260 | 233342 | boundaryStateVariables[0], | |
261 | insideVolVars.velocity(0), | ||
262 | 233342 | boundaryStateVariables[1], | |
263 | insideVolVars.velocity(1), | ||
264 | 233342 | boundaryStateVariables[2], | |
265 | insideVolVars.bedSurface(), | ||
266 | insideVolVars.bedSurface(), | ||
267 | gravity, | ||
268 | unitNormal); | ||
269 | |||
270 |
4/4✓ Branch 0 taken 76607 times.
✓ Branch 1 taken 40064 times.
✓ Branch 2 taken 76607 times.
✓ Branch 3 taken 40064 times.
|
233342 | values[Indices::massBalanceIdx] = riemannFlux[0]; |
271 |
4/4✓ Branch 0 taken 76607 times.
✓ Branch 1 taken 40064 times.
✓ Branch 2 taken 76607 times.
✓ Branch 3 taken 40064 times.
|
233342 | values[Indices::velocityXIdx] = riemannFlux[1]; |
272 |
4/4✓ Branch 0 taken 76607 times.
✓ Branch 1 taken 40064 times.
✓ Branch 2 taken 76607 times.
✓ Branch 3 taken 40064 times.
|
233342 | values[Indices::velocityYIdx] = riemannFlux[2]; |
273 | |||
274 | // Addition of viscosity/diffusive flux rough wall boundaries | ||
275 | // No-slip wall (with coefficient alphaWall): | ||
276 | // Compute wall shear stress using turbulent viscosity and local velocity gradient | ||
277 | // Assume velocity gradient (in cell adjacent to wall) equal to alphaWall*(0 - u_c) | ||
278 | 116671 | std::array<Scalar, 3> roughWallFlux{}; | |
279 |
24/24✓ Branch 0 taken 76607 times.
✓ Branch 1 taken 40064 times.
✓ Branch 2 taken 76607 times.
✓ Branch 3 taken 40064 times.
✓ Branch 4 taken 76607 times.
✓ Branch 5 taken 40064 times.
✓ Branch 6 taken 76607 times.
✓ Branch 7 taken 40064 times.
✓ Branch 8 taken 76607 times.
✓ Branch 9 taken 40064 times.
✓ Branch 10 taken 76607 times.
✓ Branch 11 taken 40064 times.
✓ Branch 12 taken 40109 times.
✓ Branch 13 taken 36498 times.
✓ Branch 14 taken 40109 times.
✓ Branch 15 taken 36498 times.
✓ Branch 16 taken 40109 times.
✓ Branch 17 taken 36498 times.
✓ Branch 18 taken 40109 times.
✓ Branch 19 taken 36498 times.
✓ Branch 20 taken 40109 times.
✓ Branch 21 taken 36498 times.
✓ Branch 22 taken 40109 times.
✓ Branch 23 taken 36498 times.
|
700026 | if (scvf.center()[1] < this->gridGeometry().bBoxMin()[1] + eps_ || scvf.center()[1] > this->gridGeometry().bBoxMax()[1] - eps_) |
280 | { | ||
281 | // Distance vector between the inside cell center and the boundary face center | ||
282 | 240519 | const auto& cellCenterToBoundaryFaceCenter = scvf.center() - insideScv.center(); | |
283 | |||
284 | // The left (inside) state vector | ||
285 | 80173 | const auto& leftState = insideVolVars.priVars(); | |
286 | |||
287 |
1/2✓ Branch 1 taken 80173 times.
✗ Branch 2 not taken.
|
80173 | if (wallFrictionLawType_ == "noslip") |
288 | { | ||
289 | 80173 | roughWallFlux = ShallowWater::noslipWallBoundary(alphaWall_, | |
290 | 80173 | turbViscosity_, | |
291 | leftState, | ||
292 | cellCenterToBoundaryFaceCenter, | ||
293 | unitNormal); | ||
294 | } | ||
295 | ✗ | else if (wallFrictionLawType_ == "nikuradse") | |
296 | { | ||
297 | ✗ | roughWallFlux = ShallowWater::nikuradseWallBoundary(ksWall_, | |
298 | leftState, | ||
299 | cellCenterToBoundaryFaceCenter, | ||
300 | unitNormal); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | 350013 | values[Indices::massBalanceIdx] += roughWallFlux[0]; | |
305 | 350013 | values[Indices::velocityXIdx] += roughWallFlux[1]; | |
306 | 350013 | values[Indices::velocityYIdx] += roughWallFlux[2]; | |
307 | |||
308 | 116671 | return values; | |
309 | } | ||
310 | |||
311 | // \} | ||
312 | |||
313 | /*! | ||
314 | * \brief Evaluate the initial values for a control volume. | ||
315 | * \param globalPos The position for which the boundary type is set | ||
316 | */ | ||
317 | 2038 | PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const | |
318 | { | ||
319 | 2038 | PrimaryVariables values(0.0); | |
320 | |||
321 | // Set the initial values to the analytical solution | ||
322 | 4076 | const auto gravity = this->spatialParams().gravity(globalPos); | |
323 | 14266 | const auto width = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; | |
324 | |||
325 | 4076 | values[0] = hBoundary_; | |
326 | 8152 | values[1] = -(gravity*bedSlope_/(8.0*turbViscosity_)) * (4.0*globalPos[1]*globalPos[1] - width*width); | |
327 | 4076 | values[2] = 0.0; | |
328 | |||
329 | 2038 | return values; | |
330 | }; | ||
331 | |||
332 | private: | ||
333 | |||
334 | std::vector<Scalar> exactWaterDepth_; | ||
335 | std::vector<Scalar> exactVelocityX_; | ||
336 | std::vector<Scalar> exactVelocityY_; | ||
337 | |||
338 | Scalar hBoundary_; // water level at the outflow boundary | ||
339 | Scalar bedSlope_; // bed slope (positive downwards) | ||
340 | Scalar discharge_; // discharge at the inflow boundary | ||
341 | Scalar alphaWall_; // wall roughness coefficient for no-slip type wall roughness | ||
342 | Scalar ksWall_; // Nikuradse wall roughness height for Nikuradse type wall roughness | ||
343 | Scalar turbViscosity_; // turbulent viscosity | ||
344 | std::string wallFrictionLawType_; // wall friction law type | ||
345 | |||
346 | static constexpr Scalar eps_ = 1.0e-6; | ||
347 | std::string name_; | ||
348 | }; | ||
349 | |||
350 | } //end namespace Dumux | ||
351 | |||
352 | #endif | ||
353 |