Peano
FWave.py
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 
4 fWave = r"""
5  /**
6  ****
7  **** F-Wave Riemann Solver for the Shallow Water Equation
8  ****
9  * Note:
10  * This solver does not support inundation. For dry cells, we assume an infinitely high solid wall
11  * at the shore-line, which is equivalent to reflecting boundary conditions. Thus no water is
12  * able to pass the shoreline, and we have to assure that the particle velocity at the boundary is
13  * zero.
14  *
15  * Literature:
16  *
17  * @article{bale2002wave,
18  * title={A wave propagation method for conservation laws and balance laws with spatially varying flux functions},
19  * author={Bale, D.S. and LeVeque, R.J. and Mitran, S. and Rossmanith, J.A.}, journal={SIAM Journal on Scientific Computing},
20  * volume={24},
21  * number={3},
22  * pages={955--978},
23  * year={2002},
24  * publisher={Citeseer}}
25  *
26  * @book{leveque2002finite,
27  * Author = {LeVeque, R. J.},
28  * Date-Added = {2011-09-13 14:09:31 +0000},
29  * Date-Modified = {2011-10-31 09:46:40 +0000},
30  * Publisher = {Cambridge University Press},
31  * Title = {Finite Volume Methods for Hyperbolic Problems},
32  * Volume = {31},
33  * Year = {2002}}
34  *
35  * @webpage{levequeclawpack,
36  * Author = {LeVeque, R. J.},
37  * Lastchecked = {January, 05, 2011},
38  * Title = {Clawpack Sofware},
39  * Url = {https://github.com/clawpack/clawpack-4.x/blob/master/geoclaw/2d/lib}}
40  ****
41  */
42 
43  enum class WetDryState {
44  DryDry, /**< Both cells are dry. */
45  WetWet, /**< Both cells are wet. */
46  WetDryInundation, /**< 1st cell: wet, 2nd cell: dry. 1st cell lies higher than the 2nd one. */
47  WetDryWall, /**< 1st cell: wet, 2nd cell: dry. 1st cell lies lower than the 2nd one. Momentum is not large enough to overcome the difference. */
48  WetDryWallInundation, /**< 1st cell: wet, 2nd cell: dry. 1st cell lies lower than the 2nd one. Momentum is large enough to overcome the difference. */
49  DryWetInundation, /**< 1st cell: dry, 2nd cell: wet. 1st cell lies lower than the 2nd one. */
50  DryWetWall, /**< 1st cell: dry, 2nd cell: wet. 1st cell lies higher than the 2nd one. Momentum is not large enough to overcome the difference. */
51  DryWetWallInundation /**< 1st cell: dry, 2nd cell: wet. 1st cell lies higher than the 2nd one. Momentum is large enough to overcome the difference. */
52  };
53 
54  // Set speeds to zero (will be determined later)
55  double uLeft = 0.0;
56  double uRight = 0.0;
57 
58  // Not const here as they may get reassigned due to boundary conditions
59  double hLeft = QL[Shortcuts::h];
60  double hRight = QR[Shortcuts::h];
61  double huLeft = QL[Shortcuts::hu + normal];
62  double huRight = QR[Shortcuts::hu + normal];
63  double bLeft = QL[Shortcuts::z];
64  double bRight = QR[Shortcuts::z];
65 
66  //! Wet/dry state of our Riemann-problem
67  WetDryState wetDryState = WetDryState::WetWet; // Assume everything is wet
68 
69  // Determine the wet/dry state
70  if (hLeft <= hThreshold && hRight <= hThreshold) { // Both cells are dry
71  wetDryState = WetDryState::DryDry;
72  } else if (hLeft <= hThreshold) { // Left cell dry, right cell wet
73  uRight = huRight / hRight;
74  // Set wall boundary conditions (inundation is not supported!)
75  hLeft = hRight;
76  bLeft = bRight;
77  huLeft = -huRight;
78  uLeft = -uRight;
79  wetDryState = WetDryState::DryWetWall;
80  } else if (hRight <= hThreshold) { // Left cell wet, right cell dry
81  uLeft = huLeft / hLeft;
82  hRight = hLeft;
83  bRight = bLeft;
84  huRight = -huLeft;
85  uRight = -uLeft;
86  wetDryState = WetDryState::WetDryWall;
87  } else {
88  uLeft = huLeft / hLeft;
89  uRight = huRight / hRight;
90  wetDryState = WetDryState::WetWet;
91  }
92 
93  // Zero updates in the beginning
94  for (int i = 0; i < 3; i++) {
95  FL[i] = 0.0;
96  FR[i] = 0.0;
97  }
98 
99  // Return in the case of dry cells
100  if (wetDryState == WetDryState::DryDry) {
101  return 0.0;
102  }
103 
104  // Compute eigenvalues of the Jacobian matrices in states Q_{i-1} and Q_{i}
105  const double hRoe = 0.5 * (hRight + hLeft);
106  const double uRoe = (uLeft * std::sqrt(hLeft) + uRight * std::sqrt(hRight)) / (std::sqrt(hLeft) + std::sqrt(hRight));
107  const double roeSpeeds[2] = {uRoe - std::sqrt(g * hRoe), uRoe + std::sqrt(g * hRoe)};
108  const double characteristicSpeeds[2] = {uLeft - std::sqrt(g * hLeft), uRight + std::sqrt(g * hRight)};
109  const double einfeldtSpeeds[2] = {std::fmin(characteristicSpeeds[0], roeSpeeds[0]), std::fmax(characteristicSpeeds[1], roeSpeeds[1])};
110 
111  // Set wave speeds (lambda Roe)
112  //! Wave speeds of the f-waves
113  const double waveSpeeds[2] {einfeldtSpeeds[0], einfeldtSpeeds[1]};
114  const double deltaLambda = waveSpeeds[1] - waveSpeeds[0];
115 
116 #if !defined(WITH_GPU)
117  // Wave speed of the 1st wave family should be less than the speed of the 2nd wave family.
118  assertion(waveSpeeds[0] < waveSpeeds[1]);
119  assertion(std::fabs(deltaLambda) > 0); // Make sure we do not divide by 0
120 #endif
121 
122  const double inverseDeltaLambda = 1.0 / deltaLambda;
123 
124  // Compute the inverse matrix R^{-1} to obtain Eigencoefficients (alpha)
125  //
126  // 1 1 ^-1
127  //
128  // \lambda_{1} \lambda_{2}
129  //
130  // Inverse: https://mathworld.wolfram.com/MatrixInverse.html
131  //
132  // 1 \lambda_{2} -1
133  // ____________
134  // deltaLambda -\lambda_{1} 1
135  const double Rinv[2][2] {
136  { inverseDeltaLambda * waveSpeeds[1], -inverseDeltaLambda },
137  { inverseDeltaLambda * -waveSpeeds[0], inverseDeltaLambda }
138  };
139 
140  // Right hand side
141  const double fluxLeft[2] {huLeft, huLeft * uLeft + 0.5 * g * hLeft * hLeft};
142  const double fluxRight[2] {huRight, huRight * uRight + 0.5 * g * hRight * hRight};
143 
144  // Add source term (bathymetry) into the decomposition of the jump in the flux function
145  const double deltaxPsi = -g * (bRight - bLeft) * hRoe;
146  // Calculate flux difference f(Q_i) - f(Q_{i-1})
147  const double deltaFlux[2] {fluxRight[0] - fluxLeft[0], fluxRight[1] - fluxLeft[1] - deltaxPsi};
148 
149  // Solve linear equations
150  const double alpha[2] {
151  Rinv[0][0] * deltaFlux[0] + Rinv[0][1] * deltaFlux[1],
152  Rinv[1][0] * deltaFlux[0] + Rinv[1][1] * deltaFlux[1]
153  };
154 
155  // Z
156  const double fWaves[2][2] {
157  { alpha[0], alpha[0] * waveSpeeds[0] },
158  { alpha[1], alpha[1] * waveSpeeds[1] }
159  };
160 
161  // Compute the net-updates
162  double hUpdateLeft = 0.0;
163  double hUpdateRight = 0.0;
164  double huUpdateLeft = 0.0;
165  double huUpdateRight = 0.0;
166 
167  constexpr double ZERO_TOL = std::numeric_limits<double>::epsilon();
168  // 1st wave family
169  if (waveSpeeds[0] < ZERO_TOL) { // Left going
170  hUpdateLeft += fWaves[0][0];
171  huUpdateLeft += fWaves[0][1];
172  } else if (waveSpeeds[0] > ZERO_TOL) { // Right going
173  hUpdateRight -= fWaves[0][0];
174  huUpdateRight -= fWaves[0][1];
175  } else { // Split waves
176  hUpdateLeft += 0.5 * fWaves[0][0];
177  huUpdateLeft += 0.5 * fWaves[0][1];
178  hUpdateRight -= 0.5 * fWaves[0][0];
179  huUpdateRight -= 0.5 * fWaves[0][1];
180  }
181 
182  // 2nd wave family
183  if (waveSpeeds[1] < ZERO_TOL) { // Left going
184  hUpdateLeft += fWaves[1][0];
185  huUpdateLeft += fWaves[1][1];
186  } else if (waveSpeeds[1] > ZERO_TOL) { // Right going
187  hUpdateRight -= fWaves[1][0];
188  huUpdateRight -= fWaves[1][1];
189  } else { // Split waves
190  hUpdateLeft += 0.5 * fWaves[1][0];
191  huUpdateLeft += 0.5 * fWaves[1][1];
192  hUpdateRight -= 0.5 * fWaves[1][0];
193  huUpdateRight -= 0.5 * fWaves[1][1];
194  }
195 
196  // Zero ghost updates (wall boundary)
197  if (wetDryState == WetDryState::WetDryWall) {
198  hUpdateRight = 0;
199  huUpdateRight = 0;
200  } else if (wetDryState == WetDryState::DryWetWall) {
201  hUpdateLeft = 0;
202  huUpdateLeft = 0;
203  }
204 
205  // Compute maximum wave speed (-> CFL-condition)
206  const double maxWaveSpeed = std::fmax(std::fabs(waveSpeeds[0]), std::fabs(waveSpeeds[1]));
207 
208 #if !defined(WITH_GPU)
209  assertion(!std::isnan(hUpdateLeft));
210  assertion(!std::isnan(hUpdateRight));
211  assertion(!std::isnan(huUpdateLeft));
212  assertion(!std::isnan(huUpdateRight));
213  assertion(!std::isnan(maxWaveSpeed));
214 #endif
215 
216  // Set net-updates
217  FL[Shortcuts::h] = hUpdateLeft;
218  FR[Shortcuts::h] = hUpdateRight;
219  FL[normal + 1] = huUpdateLeft;
220  FR[normal + 1] = huUpdateRight;
221 
222  return maxWaveSpeed;
223 """