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 ShallowWaterModels | ||
10 | * \brief Compute boundary conditions for the Riemann Solver | ||
11 | * | ||
12 | * The boundary conditions are given at the the outer face of the | ||
13 | * the boundary cells. In this form the boundary condition can't be | ||
14 | * processed by the riemann Solver, because it needs two cell states, one at | ||
15 | * each side of a face. Therefore the Riemann invariants are used to | ||
16 | * calculate a virtual outer state. | ||
17 | */ | ||
18 | #ifndef DUMUX_SHALLOWWATER_BOUNDARYFLUXES_HH | ||
19 | #define DUMUX_SHALLOWWATER_BOUNDARYFLUXES_HH | ||
20 | |||
21 | #include <array> | ||
22 | #include <cmath> | ||
23 | #include <algorithm> | ||
24 | |||
25 | namespace Dumux::ShallowWater { | ||
26 | |||
27 | /*! | ||
28 | * \brief Compute the outer cell state for fixed water depth boundary. | ||
29 | * | ||
30 | * \param waterDepthBoundary Water depth at the boundary face [m^2/s] | ||
31 | * \param waterDepthInside Water depth in the inner cell [m] | ||
32 | * \param velocityXInside Velocity in x-direction in the inner cell [m/s] | ||
33 | * \param velocityYInside Velocity in y-direction in the inner cell [m/s] | ||
34 | * \param gravity Gravity constant [m/s^2] | ||
35 | * \param nxy Normal vector of the boundary face | ||
36 | * | ||
37 | * \return cellStateOutside The outer cell state | ||
38 | */ | ||
39 | template<class Scalar, class GlobalPosition> | ||
40 | 23418 | std::array<Scalar, 3> fixedWaterDepthBoundary(const Scalar waterDepthBoundary, | |
41 | const Scalar waterDepthInside, | ||
42 | const Scalar velocityXInside, | ||
43 | const Scalar velocityYInside, | ||
44 | const Scalar gravity, | ||
45 | const GlobalPosition& nxy) | ||
46 | |||
47 | { | ||
48 | std::array<Scalar, 3> cellStateOutside; | ||
49 | 46836 | cellStateOutside[0] = waterDepthBoundary; | |
50 | |||
51 | using std::sqrt; | ||
52 | 70254 | const auto uboundIn = nxy[0] * velocityXInside + nxy[1] * velocityYInside; | |
53 | 46836 | const auto uboundQut = uboundIn + 2.0 * sqrt(gravity * waterDepthInside) - 2.0 * sqrt(gravity * cellStateOutside[0]); | |
54 | |||
55 | 70254 | cellStateOutside[1] = (nxy[0] * uboundQut); // we only use the normal part | |
56 | 70254 | cellStateOutside[2] = (nxy[1] * uboundQut); // we only use the normal part | |
57 | |||
58 | 23418 | return cellStateOutside; | |
59 | } | ||
60 | |||
61 | /*! | ||
62 | * \brief Compute the outer cell state for a fixed discharge boundary. | ||
63 | * | ||
64 | * \param dischargeBoundary Discharge per meter at the boundary face [m^2/s] | ||
65 | * \param waterDepthInside Water depth in the inner cell [m] | ||
66 | * \param velocityXInside Velocity in x-direction in the inner cell [m/s] | ||
67 | * \param velocityYInside Velocity in y-direction in the inner cell [m/s] | ||
68 | * \param gravity Gravity constant [m/s^2] | ||
69 | * \param nxy Normal vector of the boundary face | ||
70 | * | ||
71 | * \return cellStateOutside The outer cell state | ||
72 | */ | ||
73 | template<class Scalar, class GlobalPosition> | ||
74 | 23143 | std::array<Scalar, 3> fixedDischargeBoundary(const Scalar dischargeBoundary, | |
75 | const Scalar waterDepthInside, | ||
76 | const Scalar velocityXInside, | ||
77 | const Scalar velocityYInside, | ||
78 | const Scalar gravity, | ||
79 | const GlobalPosition& nxy) | ||
80 | { | ||
81 | std::array<Scalar, 3> cellStateOutside; | ||
82 | using std::abs; | ||
83 | using std::sqrt; | ||
84 | using std::max; | ||
85 | |||
86 | // only impose if abs(q) > 0 | ||
87 |
2/4✓ Branch 0 taken 23143 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23143 times.
✗ Branch 3 not taken.
|
46286 | if (abs(dischargeBoundary) > 1.0e-9) |
88 | { | ||
89 | 46286 | const auto uboundIn = nxy[0]*velocityXInside + nxy[1]*velocityYInside; | |
90 | 23143 | const auto alphal = uboundIn + 2.0*sqrt(gravity * waterDepthInside); | |
91 | |||
92 | //initial guess for hstar solved with newton | ||
93 | 23143 | constexpr Scalar tol_hstar = 1.0E-12; | |
94 | 23143 | constexpr Scalar ink_hstar = 1.0E-9; | |
95 | 23143 | constexpr int maxstep_hstar = 30; | |
96 | |||
97 | 23143 | Scalar hstar = 0.1; | |
98 |
1/2✓ Branch 0 taken 228064 times.
✗ Branch 1 not taken.
|
228064 | for (int i = 0; i < maxstep_hstar; ++i) |
99 | { | ||
100 | 228064 | Scalar f_hstar = alphal - dischargeBoundary/hstar - 2 * sqrt(gravity * hstar); | |
101 | 228064 | Scalar df_hstar = (f_hstar -(alphal - dischargeBoundary/(hstar + ink_hstar) - 2 * sqrt(gravity * (hstar+ink_hstar))))/ink_hstar; | |
102 | 228064 | Scalar dx_hstar = -f_hstar/df_hstar; | |
103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 228064 times.
|
228064 | hstar = max(hstar - dx_hstar,0.001); |
104 | |||
105 |
2/2✓ Branch 0 taken 204921 times.
✓ Branch 1 taken 23143 times.
|
228064 | if (dx_hstar*dx_hstar < tol_hstar) |
106 | break; | ||
107 | } | ||
108 | |||
109 | 46286 | const auto qinner = (nxy[0] * waterDepthInside * velocityYInside) - (nxy[1] * waterDepthInside * velocityXInside); | |
110 | 23143 | cellStateOutside[0] = hstar; | |
111 | 69429 | cellStateOutside[1] = (nxy[0] * dischargeBoundary - nxy[1] * qinner)/hstar; | |
112 | 92572 | cellStateOutside[2] = (nxy[1] * dischargeBoundary + nxy[0] * qinner)/hstar; | |
113 | } | ||
114 | |||
115 | 23143 | return cellStateOutside; | |
116 | } | ||
117 | |||
118 | /*! | ||
119 | * \brief Compute the viscosity/diffusive flux at a rough wall boundary using no-slip formulation. | ||
120 | * | ||
121 | * \param alphaWall Roughness parameter: alphaWall=0.0 means full slip, alphaWall=1.0 means no slip, \f$0.0<\text{alphaWall}<1.0\f$ means partial slip [-] | ||
122 | * \param turbulentViscosity Turbulent viscosity [m^2/s] | ||
123 | * \param state Primary variables (water depth, velocities) | ||
124 | * \param cellCenterToBoundaryFaceCenter Cell-center to boundary distance | ||
125 | * \param unitNormal Normal vector of the boundary face | ||
126 | */ | ||
127 | template<class PrimaryVariables, class Scalar, class GlobalPosition> | ||
128 | 80173 | std::array<Scalar, 3> noslipWallBoundary(const Scalar alphaWall, | |
129 | const Scalar turbulentViscosity, | ||
130 | const PrimaryVariables& state, | ||
131 | const GlobalPosition& cellCenterToBoundaryFaceCenter, | ||
132 | const GlobalPosition& unitNormal) | ||
133 | { | ||
134 | // only impose if abs(alphaWall) > 0 | ||
135 | using std::abs; | ||
136 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 80173 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80173 times.
|
160346 | if (abs(alphaWall) <= 1.0e-9) |
137 | ✗ | return {}; | |
138 | |||
139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 80173 times.
|
80173 | const auto waterDepth = state[0]; |
140 | // regularization: Set gradients to zero for drying cell | ||
141 | // Use LET-limiter instead for differentiability? | ||
142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 80173 times.
|
80173 | if (waterDepth <= 0.001) |
143 | ✗ | return {}; | |
144 | |||
145 | 80173 | const auto xVelocity = state[1]; | |
146 | 80173 | const auto yVelocity = state[2]; | |
147 | 80173 | const auto distance = cellCenterToBoundaryFaceCenter.two_norm(); | |
148 | |||
149 | // Compute the velocity gradients | ||
150 | // Outside - inside cell: therefore the minus-sign | ||
151 | // Only when cell contains sufficient water. | ||
152 | 80173 | const auto gradU = -alphaWall * xVelocity/distance; | |
153 | 80173 | const auto gradV = -alphaWall * yVelocity/distance; | |
154 | |||
155 | // Factor that takes the direction of the unit vector into account | ||
156 | 80173 | const auto direction = (unitNormal*cellCenterToBoundaryFaceCenter)/distance; | |
157 | |||
158 | // Compute the viscosity/diffusive fluxes at the rough wall | ||
159 | return { | ||
160 | 0.0, | ||
161 | 80173 | -turbulentViscosity*waterDepth*gradU*direction, | |
162 | 80173 | -turbulentViscosity*waterDepth*gradV*direction | |
163 | 80173 | }; | |
164 | } | ||
165 | |||
166 | /*! | ||
167 | * \brief Compute the viscosity/diffusive flux at a rough wall boundary using Nikuradse formulation. | ||
168 | * | ||
169 | * \param ksWall Nikuradse roughness height for the wall [m] | ||
170 | * \param state the primary variable state (water depth, velocities) | ||
171 | * \param cellCenterToBoundaryFaceCenter Cell-center to boundary distance | ||
172 | * \param unitNormal Normal vector of the boundary face | ||
173 | */ | ||
174 | template<class PrimaryVariables, class Scalar, class GlobalPosition> | ||
175 | ✗ | std::array<Scalar, 3> nikuradseWallBoundary(const Scalar ksWall, | |
176 | const PrimaryVariables& state, | ||
177 | const GlobalPosition& cellCenterToBoundaryFaceCenter, | ||
178 | const GlobalPosition& unitNormal) | ||
179 | { | ||
180 | // only impose if abs(ksWall) > 0 | ||
181 | using std::abs; | ||
182 | ✗ | if (abs(ksWall) <= 1.0e-9) | |
183 | ✗ | return {}; | |
184 | |||
185 | using std::hypot; | ||
186 | ✗ | const Scalar xVelocity = state[1]; | |
187 | ✗ | const Scalar yVelocity = state[2]; | |
188 | ✗ | const Scalar velocityMagnitude = hypot(xVelocity, yVelocity); | |
189 | ✗ | const Scalar distance = cellCenterToBoundaryFaceCenter.two_norm(); | |
190 | ✗ | const Scalar y0w = ksWall/30.0; | |
191 | ✗ | constexpr Scalar kappa2 = 0.41*0.41; | |
192 | |||
193 | // should distance/y0w be limited to not become too small? | ||
194 | using std::log; using std::max; | ||
195 | ✗ | const auto logYPlus = log(distance/y0w+1.0); | |
196 | ✗ | const auto fac = kappa2*velocityMagnitude / max(1.0e-3,logYPlus*logYPlus); | |
197 | |||
198 | // Factor that takes the direction of the unit vector into account | ||
199 | ✗ | const auto direction = (unitNormal*cellCenterToBoundaryFaceCenter)/distance; | |
200 | |||
201 | // wall shear stress vector | ||
202 | ✗ | const auto tauWx = direction*fac*xVelocity; | |
203 | ✗ | const auto tauWy = direction*fac*yVelocity; | |
204 | |||
205 | // Compute the viscosity/diffusive fluxes at the rough wall | ||
206 | ✗ | const auto waterDepth = state[0]; | |
207 | ✗ | return {0.0, waterDepth*tauWx, waterDepth*tauWy}; | |
208 | } | ||
209 | |||
210 | } // end namespace Dumux::ShallowWater | ||
211 | |||
212 | #endif | ||
213 |