Peano
Loading...
Searching...
No Matches
FWaveRiemannSolver.cpph
Go to the documentation of this file.
1// This file is part of the ExaHyPE2 project. For conditions of distribution and
2// use, please see the copyright notice at www.peano-framework.org
3
4template <class T, class Shortcuts>
5static inline GPU_CALLABLE_METHOD double applications::exahype2::ShallowWater::fWaveRiemannSolver(
6 const T* const NOALIAS QL,
7 const T* const NOALIAS QR,
8 const tarch::la::Vector<DIMENSIONS, double>& x,
9 const tarch::la::Vector<DIMENSIONS, double>& h,
10 const double t,
11 const double dt,
12 const int normal,
13 T* const NOALIAS FL,
14 T* const NOALIAS FR
15) {
16 // Set speeds to zero (will be determined later)
17 T uLeft = 0.0;
18 T uRight = 0.0;
19
20 // Not const here as they may get reassigned due to boundary conditions
21 T hLeft = QL[Shortcuts::h];
22 T hRight = QR[Shortcuts::h];
23 T huLeft = QL[Shortcuts::hu + normal];
24 T huRight = QR[Shortcuts::hu + normal];
25 T zLeft = QL[Shortcuts::z];
26 T zRight = QR[Shortcuts::z];
27
29 WetDryState wetDryState = WetDryState::WetWet; // Assume everything is wet
30
31 // Determine the wet/dry state
32 if (hLeft <= hThreshold && hRight <= hThreshold) { // Both cells are dry
33 wetDryState = WetDryState::DryDry;
34 } else if (hLeft <= hThreshold) { // Left cell dry, right cell wet
35 uRight = huRight / hRight;
36 // Set wall boundary conditions (inundation is not supported!)
37 hLeft = hRight;
38 zLeft = zRight;
39 huLeft = -huRight;
40 uLeft = -uRight;
41 wetDryState = WetDryState::DryWetWall;
42 } else if (hRight <= hThreshold) { // Left cell wet, right cell dry
43 uLeft = huLeft / hLeft;
44 hRight = hLeft;
45 zRight = zLeft;
46 huRight = -huLeft;
47 uRight = -uLeft;
48 wetDryState = WetDryState::WetDryWall;
49 } else {
50 uLeft = huLeft / hLeft;
51 uRight = huRight / hRight;
52 wetDryState = WetDryState::WetWet;
53 }
54
55 // Zero updates in the beginning
56 for (int i = 0; i < 3; i++) {
57 FL[i] = 0.0;
58 FR[i] = 0.0;
59 }
60
61 // Return in the case of dry cells
62 if (wetDryState == WetDryState::DryDry) {
63 return 0.0;
64 }
65
66 // Compute eigenvalues of the Jacobian matrices in states Q_{i-1} and Q_{i}
67 const T hRoe = 0.5 * (hRight + hLeft);
68 const T uRoe = (uLeft * std::sqrt(hLeft) + uRight * std::sqrt(hRight)) / (std::sqrt(hLeft) + std::sqrt(hRight));
69 const T roeSpeeds[2] = {uRoe - std::sqrt(g * hRoe), uRoe + std::sqrt(g * hRoe)};
70 const T characteristicSpeeds[2] = {uLeft - std::sqrt(g * hLeft), uRight + std::sqrt(g * hRight)};
71 const T einfeldtSpeeds[2] = {
72 std::fmin(characteristicSpeeds[0], roeSpeeds[0]),
73 std::fmax(characteristicSpeeds[1], roeSpeeds[1])
74 };
75
76 // Set wave speeds (lambda Roe)
78 const T waveSpeeds[2]{einfeldtSpeeds[0], einfeldtSpeeds[1]};
79 const T deltaLambda = waveSpeeds[1] - waveSpeeds[0];
80
81#if !defined(WITH_GPU)
82 // Wave speed of the 1st wave family should be less than the speed of the 2nd wave family.
83 assertion(waveSpeeds[0] < waveSpeeds[1]);
84 assertion(std::fabs(deltaLambda) > 0); // Make sure we do not divide by 0
85#endif
86
87 const T inverseDeltaLambda = 1.0 / deltaLambda;
88
89 // Compute the inverse matrix R^{-1} to obtain Eigencoefficients (alpha)
90 //
91 // 1 1 ^-1
92 //
93 // \lambda_{1} \lambda_{2}
94 //
95 // Inverse: https://mathworld.wolfram.com/MatrixInverse.html
96 //
97 // 1 \lambda_{2} -1
98 // ____________
99 // deltaLambda -\lambda_{1} 1
100 const T Rinv[2][2]{
101 {inverseDeltaLambda * waveSpeeds[1], -inverseDeltaLambda},
102 {inverseDeltaLambda * -waveSpeeds[0], inverseDeltaLambda}
103 };
104
105 // Right hand side
106 const T fluxLeft[2]{huLeft, huLeft * uLeft + 0.5 * g * hLeft * hLeft};
107 const T fluxRight[2]{huRight, huRight * uRight + 0.5 * g * hRight * hRight};
108
109 // Add source term (bathymetry) into the decomposition of the jump in the flux function
110 const T deltaxPsi = -g * (zRight - zLeft) * hRoe;
111 // Calculate flux difference f(Q_i) - f(Q_{i-1})
112 const T deltaFlux[2]{fluxRight[0] - fluxLeft[0], fluxRight[1] - fluxLeft[1] - deltaxPsi};
113
114 // Solve linear equations
115 const T alpha[2]{
116 Rinv[0][0] * deltaFlux[0] + Rinv[0][1] * deltaFlux[1],
117 Rinv[1][0] * deltaFlux[0] + Rinv[1][1] * deltaFlux[1]
118 };
119
120 // Z
121 const T fWaves[2][2]{{alpha[0], alpha[0] * waveSpeeds[0]}, {alpha[1], alpha[1] * waveSpeeds[1]}};
122
123 // Compute the net-updates
124 T hUpdateLeft = 0.0;
125 T hUpdateRight = 0.0;
126 T huUpdateLeft = 0.0;
127 T huUpdateRight = 0.0;
128
129 constexpr T ZERO_TOL = std::numeric_limits<T>::epsilon();
130 // 1st wave family
131 if (waveSpeeds[0] < ZERO_TOL) { // Left going
132 hUpdateLeft += fWaves[0][0];
133 huUpdateLeft += fWaves[0][1];
134 } else if (waveSpeeds[0] > ZERO_TOL) { // Right going
135 hUpdateRight -= fWaves[0][0];
136 huUpdateRight -= fWaves[0][1];
137 } else { // Split waves
138 hUpdateLeft += 0.5 * fWaves[0][0];
139 huUpdateLeft += 0.5 * fWaves[0][1];
140 hUpdateRight -= 0.5 * fWaves[0][0];
141 huUpdateRight -= 0.5 * fWaves[0][1];
142 }
143
144 // 2nd wave family
145 if (waveSpeeds[1] < ZERO_TOL) { // Left going
146 hUpdateLeft += fWaves[1][0];
147 huUpdateLeft += fWaves[1][1];
148 } else if (waveSpeeds[1] > ZERO_TOL) { // Right going
149 hUpdateRight -= fWaves[1][0];
150 huUpdateRight -= fWaves[1][1];
151 } else { // Split waves
152 hUpdateLeft += 0.5 * fWaves[1][0];
153 huUpdateLeft += 0.5 * fWaves[1][1];
154 hUpdateRight -= 0.5 * fWaves[1][0];
155 huUpdateRight -= 0.5 * fWaves[1][1];
156 }
157
158 // Zero ghost updates (wall boundary)
159 if (wetDryState == WetDryState::WetDryWall) {
160 hUpdateRight = 0;
161 huUpdateRight = 0;
162 } else if (wetDryState == WetDryState::DryWetWall) {
163 hUpdateLeft = 0;
164 huUpdateLeft = 0;
165 }
166
167 // Compute maximum wave speed (-> CFL-condition)
168 const T maxWaveSpeed = std::fmax(std::fabs(waveSpeeds[0]), std::fabs(waveSpeeds[1]));
169
170#if !defined(WITH_GPU)
171 assertion(!std::isnan(hUpdateLeft));
172 assertion(!std::isnan(hUpdateRight));
173 assertion(!std::isnan(huUpdateLeft));
174 assertion(!std::isnan(huUpdateRight));
175 assertion(!std::isnan(maxWaveSpeed));
176#endif
177
178 // Set net-updates
179 FL[Shortcuts::h] = hUpdateLeft;
180 FR[Shortcuts::h] = hUpdateRight;
181 FL[normal + 1] = huUpdateLeft;
182 FR[normal + 1] = huUpdateRight;
183
184 return maxWaveSpeed;
185}
static GPU_CALLABLE_METHOD double fWaveRiemannSolver(const T *const NOALIAS QL, const T *const NOALIAS QR, const tarch::la::Vector< DIMENSIONS, double > &x, const tarch::la::Vector< DIMENSIONS, double > &h, const double t, const double dt, const int normal, T *const NOALIAS FL, T *const NOALIAS FR)
F-Wave Riemann Solver for the Shallow Water Equation.