Peano
posteriori-limiting-landslide.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 import peano4
4 import exahype2
5 
6 project = exahype2.Project(
7  ["tests", "exahype2", "aderdg"], ".", executable="ADERDG-Limiting"
8 )
9 
10 parser = exahype2.ArgumentParser("ExaHyPE 2 - ADER-DG Limiting Testing Script")
11 parser.set_defaults(
12  min_depth=3,
13  degrees_of_freedom=6,
14 )
15 args = parser.parse_args()
16 
17 use_aderdg = True
18 use_fv = True
19 use_limiting = use_aderdg and use_fv
20 with_limiting = 1 # 0 - all ADER, 1 - limit, 2 - all FV
21 
22 dimensions = 2
23 order = args.degrees_of_freedom - 1
24 end_time = 2.0
25 plot_interval = 0.00 # 0.05
26 CFL = 0.5
27 unknowns = {"h": 1, "hu": 1, "hv": 1, "z": 1}
28 auxiliary = {}
29 
30 size = [1.58, 1.58, 1.58][0:dimensions]
31 offset = [0.0, 0.0, 0.0][0:dimensions]
32 max_h = 1.1 * min(size) / (3.0**args.min_depth)
33 min_h = max_h / (3.0**args.amr_levels)
34 
35 g = 9.81
36 hThreshold = 1e-5
37 number_of_dmp_observables = 0
38 dmp_differences_scaling = 0.01 # 0.01 how the diff is scaled
39 dmp_relaxation_parameter = 0.02 # the diff scaling
40 
41 landslide_zoo = {
42  # avalanche-down-the-W
43  "DownTheWForm": """
44  const tarch::la::Vector<DIMENSIONS, double>& granularMaterialCenter = {{ {initCenterX}, {initCenterY} }};
45  const bool nearCentre = tarch::la::norm2(x - granularMaterialCenter) < {initRadius};
46  Q[0] = (nearCentre ? {initHeight} : 0.0); // Granular material height (h)
47  Q[1] = 0.0;
48  Q[2] = 0.0;
49  Q[3] = (0.5 + (0.5 * DomainSize[0] - x[0]) * (0.5 * DomainSize[0] - x[0]) / ((0.5 * DomainSize[0] - DomainSize[0]) * (0.5 * DomainSize[0] - DomainSize[0]))) * {amplitude} * std::cos({frequency} * x[0]);
50 """.format_map(
51  {
52  "initCenterX": 0.15,
53  "initCenterY": 0.79,
54  "amplitude": 0.75,
55  "frequency": 8.0,
56  "initRadius": 0.10,
57  "initHeight": 0.008,
58  }
59  ),
60  # avalanche-down-the-hyperbolic-par
61  "DownTheHyperbolicPar": """
62  const tarch::la::Vector<DIMENSIONS, double>& granularMaterialCenter = {{ {initCenterX}, {initCenterY} }};
63  const bool nearCentre = tarch::la::norm2(x - granularMaterialCenter) < {initRadius};
64  Q[0] = (nearCentre ? {initHeight} : 0.0); // Granular material height (h)
65  Q[1] = 0.0;
66  Q[2] = 0.0;
67  Q[3] = {initElevationParA} * (x[0] - {initElevationCenterX}) * (x[0] - {initElevationCenterX}) - {initElevationParB} * (x[1] - {initElevationCenterY}) * (x[1] - {initElevationCenterY});
68 """.format_map(
69  {
70  "initCenterX": 0.15,
71  "initCenterY": 0.79,
72  "initElevationCenterX": 0.79,
73  "initElevationCenterY": 0.79,
74  "initElevationParA": 1.0,
75  "initElevationParB": 1.0,
76  "initRadius": 0.10,
77  "initHeight": 0.008,
78  }
79  ),
80  # avalanche-down-the-revolve-par
81  "DownTheRevolvePar": """
82  const tarch::la::Vector<DIMENSIONS, double>& granularMaterialCenter = {{ {initCenterX}, {initCenterY} }};
83  const bool nearCentre = tarch::la::norm2(x - granularMaterialCenter) < {initRadius};
84  Q[0] = (nearCentre ? {initHeight} : 0.0); // Granular material height (h)
85  Q[1] = 0.0;
86  Q[2] = 0.0;
87  Q[3] = {initElevationParA} * (x[0] - {initElevationCenterX}) * (x[0] - {initElevationCenterX}) + {initElevationParB} * (x[1] - {initElevationCenterY}) * (x[1] - {initElevationCenterY});
88 """.format_map(
89  {
90  "initCenterX": 0.15,
91  "initCenterY": 0.79,
92  "initElevationCenterX": 0.79,
93  "initElevationCenterY": 0.79,
94  "initElevationParA": 1.0,
95  "initElevationParB": 1.0,
96  "initRadius": 0.10,
97  "initHeight": 0.008,
98  }
99  ),
100  # avalanche-down-the-slope-with-jump
101  "DownTheSlopeWithJump": """
102  const tarch::la::Vector<DIMENSIONS, double>& granularMaterialCenter = {{ {initCenterX}, {initCenterY} }};
103  const bool nearCentre = tarch::la::norm2(x - granularMaterialCenter) < {initRadius};
104  const double zeta{{ {initZetaDegree} * tarch::la::PI / 180.0}}; // translation from degrees to radians
105  Q[0] = (nearCentre ? {initHeight} : 0.0); // Granular material height (h)
106  Q[1] = 0.0;
107  Q[2] = 0.0;
108  Q[3] = (DomainSize[0] - x[0]) * std::tan(zeta);
109  if (tarch::la::greater({jumpX}, x[0])) {{
110  Q[3] += {jumpSize};
111  }}
112  """.format_map(
113  {
114  "initCenterX": 0.15,
115  "initCenterY": 0.79,
116  "jumpSize": 1.0,
117  "jumpX": 0.79,
118  "initZetaDegree": 35,
119  "initHeight": 0.008,
120  "initRadius": 0.10,
121  }
122  ),
123  # avalanche-down-the-slope-with-plateau
124  "DownTheSlopeWithPlateau": """
125  const tarch::la::Vector<DIMENSIONS, double>& granularMaterialCenter = {{ {initCenterX}, {initCenterY} }};
126  const bool nearCentre = tarch::la::norm2(x - granularMaterialCenter) < {initRadius};
127  const double zeta{{{initZetaDegree} * tarch::la::PI / 180.0}}; // translation from degrees to radians
128  Q[0] = (nearCentre ? {initHeight} : 0.0); // Granular material height (h)
129  Q[1] = 0.0;
130  Q[2] = 0.0;
131  if (tarch::la::greater({plateauStartX}, x[0])) {{
132  Q[3] = (DomainSize[0] - x[0]) * std::tan(zeta);
133  }}
134  else
135  if (tarch::la::greater({plateauEndX}, x[0])) {{
136  Q[3] = (DomainSize[0] - {plateauStartX}) * std::tan(zeta);
137  }}
138  else {{
139  Q[3] = (DomainSize[0] - (x[0] - {plateauEndX} + {plateauStartX})) * std::tan(zeta);
140  }}
141 """.format_map(
142  {
143  "initCenterX": 0.15,
144  "initCenterY": 0.79,
145  "initElevationCenterX": 0.79,
146  "initElevationCenterY": 0.79,
147  "plateauStartX": 0.395,
148  "plateauEndX": 1.185,
149  "initZetaDegree": 35,
150  "initHeight": 0.008,
151  "initRadius": 0.10,
152  }
153  ),
154  # avalanche-down-the-slope
155  "DownTheSlope": """
156  const tarch::la::Vector<DIMENSIONS, double>& granularMaterialCenter = {{ {initCenterX}, {initCenterY} }};
157  const bool nearCentre = tarch::la::norm2(x - granularMaterialCenter) < {initRadius};
158  const double zeta{{{initZetaDegree} * tarch::la::PI / 180.0}}; // translation from degrees to radians
159  Q[0] = (nearCentre ? {initHeight} : 0.0); // Granular material height (h)
160  Q[1] = 0.0;
161  Q[2] = 0.0;
162  Q[3] = (DomainSize[0] - x[0]) * std::tan(zeta);
163 """.format_map(
164  {
165  "initCenterX": 0.15,
166  "initCenterY": 0.79,
167  "initZetaDegree": 35,
168  "initHeight": 0.008,
169  "initRadius": 0.10,
170  }
171  ),
172 }
173 
174 landslide_case = "DownTheSlope"
175 initial_conditions = landslide_zoo[landslide_case]
176 
177 boundary_conditions = f"""
178  std::copy_n(Qinside, 4, Qoutside);
179  Qoutside[1] = -Qoutside[1];
180  Qoutside[2] = -Qoutside[2];
181 """
182 
183 flux = f"""
184  constexpr double g = {g};
185  constexpr double hThreshold = {hThreshold};
186  if (Q[0] > hThreshold) {{
187  const double un = Q[1 + normal] / Q[0];
188  F[0] = Q[1 + normal];
189  F[1] = un * Q[1];
190  F[2] = un * Q[2];
191  F[3] = 0.0;
192  F[1 + normal] += 0.5 * g * Q[0] * Q[0];
193  }}
194  else {{
195  F[0] = 0.0;
196  F[1] = 0.0;
197  F[2] = 0.0;
198  F[3] = 0.0;
199  }}
200 """
201 
202 ncp = f"""
203  constexpr double g = {g};
204  constexpr double hThreshold = {hThreshold};
205  if (Q[0] > hThreshold) {{
206  BTimesDeltaQ[0] = 0.0;
207  BTimesDeltaQ[1] = 0.0;
208  BTimesDeltaQ[2] = 0.0;
209  BTimesDeltaQ[3] = 0.0;
210  BTimesDeltaQ[1 + normal] = g * Q[0] * deltaQ[3];
211  }} else {{
212  BTimesDeltaQ[0] = 0.0;
213  BTimesDeltaQ[1] = 0.0;
214  BTimesDeltaQ[2] = 0.0;
215  BTimesDeltaQ[3] = 0.0;
216  }}
217 """
218 
219 source_term = f"""
220  S[0] = 0.0;
221  S[1] = 0.0;
222  S[2] = 0.0;
223  S[3] = 0.0;
224 """
225 
226 eigenvalues = f"""
227  constexpr double g = {g};
228  constexpr double hThreshold = {hThreshold};
229  if(Q[0] > hThreshold) {{
230  const double un = Q[normal+1] / Q[0];
231  const double c = std::sqrt(g * Q[0]);
232  return std::max(std::abs(un - c), std::abs(un + c));
233  }}
234  return 0.0;
235 """
236 
237 adjust_solution = f"""
238  constexpr double hThreshold = {hThreshold};
239  if (Q[0] < hThreshold) {{
240  Q[0] = 0.0;
241  Q[1] = 0.0;
242  Q[2] = 0.0;
243  }}
244 """
245 
246 riemann_solver_aderdg = f"""
247  double smax = 0.0;
248  constexpr double g = {g};
249  constexpr double hThreshold = {hThreshold};
250  for(int xy=0; xy<Order+1; xy++){{
251  smax = std::max(smax, maxEigenvalue(&QL[xy*{len(unknowns)}], x, h, t, dt, direction));
252  smax = std::max(smax, maxEigenvalue(&QR[xy*{len(unknowns)}], x, h, t, dt, direction));
253  }}
254 
255  for(int xy=0; xy<Order+1; xy++){{
256  double fluxLeft[{len(unknowns)}];
257  double fluxRight[{len(unknowns)}];
258 
259  flux(&QL[xy*{len(unknowns)}], x, h, t, dt, direction, fluxLeft);
260  flux(&QR[xy*{len(unknowns)}], x, h, t, dt, direction, fluxRight);
261  for (int varId = 0; varId < {len(unknowns) - 1}; ++varId) {{
262  FL[xy*{len(unknowns)}+varId] = 0.5*(fluxLeft[varId]+fluxRight[varId] + smax*(QL[xy*{len(unknowns)}+varId]-QR[xy*{len(unknowns)}+varId]));
263  }}
264 
265  for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
266  FR[xy*{len(unknowns)}+varId] = FL[xy*{len(unknowns)}+varId];
267  }}
268 
269  //Contribution from NCP
270  double AveragedQ[{len(unknowns)}];
271  double DeltaQ[{len(unknowns)}];
272  for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
273  AveragedQ[varId] = 0.5 * (QL[xy*{len(unknowns)} + varId] + QR[xy*{len(unknowns)} + varId]);
274  DeltaQ[varId] = QR[xy*{len(unknowns)} + varId] - QL[xy*{len(unknowns)} + varId];
275  }}
276  double ncp[{len(unknowns)}];
277  nonconservativeProduct(AveragedQ, DeltaQ, x, h, t, dt, direction, ncp);
278  for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
279  FL[xy*{len(unknowns)}+varId] += 0.5 * ncp[varId];
280  FR[xy*{len(unknowns)}+varId] -= 0.5 * ncp[varId];
281  }}
282  FL[xy*{len(unknowns)}+{len(unknowns) - 1}] = 0.0;
283  FR[xy*{len(unknowns)}+{len(unknowns) - 1}] = 0.0;
284  }}
285 """
286 
287 riemann_solver_fv = f"""
288  double smax = 0.0;
289  constexpr double g = {g};
290  constexpr double hThreshold = {hThreshold};
291  smax = std::max(smax, maxEigenvalue(QL, x, h, t, dt, normal));
292  smax = std::max(smax, maxEigenvalue(QR, x, h, t, dt, normal));
293 
294  double fluxLeft[{len(unknowns)}];
295  double fluxRight[{len(unknowns)}];
296  flux(QL, x, h, t, dt, normal, fluxLeft);
297  flux(QR, x, h, t, dt, normal, fluxRight);
298  for (int varId = 0; varId < {len(unknowns) - 1}; ++varId) {{
299  FL[varId] = 0.5*(fluxLeft[varId]+fluxRight[varId] + smax*(QL[varId]-QR[varId]));
300  }}
301 
302  for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
303  FR[varId] = FL[varId];
304  }}
305 
306  //Contribution from NCP
307  double AveragedQ[{len(unknowns)}];
308  double DeltaQ[{len(unknowns)}];
309  for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
310  AveragedQ[varId] = 0.5 * (QL[varId] + QR[varId]);
311  DeltaQ[varId] = QR[varId]-QL[varId];
312  }}
313  double ncp[{len(unknowns)}];
314  nonconservativeProduct(AveragedQ, DeltaQ, x, h, t, dt, normal, ncp);
315  for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
316  FL[varId] += 0.5 * ncp[varId];
317  FR[varId] -= 0.5 * ncp[varId];
318  }}
319 
320  // the elevation should be constant
321  FL[{len(unknowns) - 1}] = 0.0;
322  FR[{len(unknowns) - 1}] = 0.0;
323  return smax;
324 """
325 
326 isPhysicallyAdmissible = "return true;"
327 if with_limiting == 0:
328  isPhysicallyAdmissible = "return true; //all ADERDG"
329 elif with_limiting == 1:
330  isPhysicallyAdmissible = f"""
331  // If h is close to zero, it is assumed that limiting is not required.
332  // It allows to reduce the computational intensity, avoiding recalculation
333  // cells with zero heights on the FV layer
334  if (std::abs(Q[0]) < {hThreshold}) {{
335  return true;
336  }}
337 
338  // Height must be positive!
339  if (Q[0] < {hThreshold}) {{
340  return false;
341  }}
342 
343  // If non-physical oscillations occur, the wave speed might receive a negative value under the square root.
344  // It results in eigenvalue becoming NaN, which are not marked as TROUBLED, if no isfinte check is performed.
345  for (int i = 0; i < {len(unknowns)}; ++i) {{
346  if (!std::isfinite(Q[i])) {{
347  return false;
348  }}
349  }}
350 
351  // Limit close to boundaries
352  if (std::abs(x[0] - DomainOffset[0]) < h[0]
353  || std::abs(x[0] - DomainOffset[0] - DomainSize[0]) < h[0]
354  || std::abs(x[1] - DomainOffset[1]) < h[1]
355  || std::abs(x[1] - DomainOffset[1] - DomainSize[1]) < h[1]
356  ) {{
357  return false;
358  }}
359  return true;
360  """
361 else:
362  isPhysicallyAdmissible = "return false; //all FV"
363 
364 if use_aderdg:
365  aderdg_solver = exahype2.solvers.aderdg.GlobalAdaptiveTimeStep(
366  name="ADERDGSolver",
367  order=order,
368  unknowns=unknowns,
369  auxiliary_variables=auxiliary,
370  min_cell_h=min_h,
371  max_cell_h=max_h,
372  time_step_relaxation=CFL,
373  )
374  aderdg_solver.set_implementation(
375  flux=flux,
376  max_eigenvalue=eigenvalues,
377  initial_conditions=initial_conditions,
378  boundary_conditions=boundary_conditions,
379  ncp=ncp,
380  source_term=source_term,
381  riemann_solver=riemann_solver_aderdg
382  )
383  project.add_solver(aderdg_solver)
384 
385 if use_fv:
386  fv_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
387  name="FVSolver",
388  patch_size=2 * order + 1,
389  unknowns=unknowns,
390  auxiliary_variables=auxiliary,
391  min_volume_h=min_h,
392  max_volume_h=max_h,
393  time_step_relaxation=CFL,
394  )
395  fv_solver.set_implementation(
396  flux=flux,
397  max_eigenvalue=eigenvalues,
398  initial_conditions=initial_conditions,
399  boundary_conditions=boundary_conditions,
400  ncp=ncp,
401  source_term=source_term,
402  riemann_solver=riemann_solver_fv,
403  adjust_solution=adjust_solution,
404  )
405  project.add_solver(fv_solver)
406 
407 if use_limiting:
408  limiter = exahype2.solvers.limiting.PosterioriLimiting(
409  name="LimitingSolver",
410  regular_solver=aderdg_solver,
411  limiting_solver=fv_solver,
412  number_of_dmp_observables=number_of_dmp_observables,
413  dmp_relaxation_parameter=dmp_relaxation_parameter,
414  dmp_differences_scaling=dmp_differences_scaling,
415  physical_admissibility_criterion=isPhysicallyAdmissible,
416  )
417  project.add_solver(limiter)
418 
419 project.set_output_path("solutions")
420 project.set_global_simulation_parameters(
421  dimensions=dimensions,
422  offset=offset[0:dimensions],
423  size=size[0:dimensions],
424  min_end_time=end_time,
425  max_end_time=end_time,
426  first_plot_time_stamp=0.0,
427  time_in_between_plots=plot_interval,
428  periodic_BC=[False, False, False][0:dimensions],
429 )
430 
431 project.set_load_balancer("new ::exahype2::LoadBalancingConfiguration")
432 project.set_Peano4_installation("../../../", mode=peano4.output.string_to_mode(args.build_mode))
433 project = project.generate_Peano4_project(verbose=False)
434 project.set_fenv_handler(False)
435 project.build()
static double min(double const x, double const y)