Peano
Loading...
Searching...
No Matches
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
3import peano4
4import exahype2
5
6project = exahype2.Project(
7 ["tests", "exahype2", "aderdg"], ".", executable="ADERDG-Limiting"
8)
9
10parser = exahype2.ArgumentParser("ExaHyPE 2 - ADER-DG Limiting Testing Script")
11parser.set_defaults(
12 min_depth=3,
13 degrees_of_freedom=6,
14)
15args = parser.parse_args()
16
17use_aderdg = True
18use_fv = True
19use_limiting = use_aderdg and use_fv
20with_limiting = 1 # 0 - all ADER, 1 - limit, 2 - all FV
21
22dimensions = 2
23order = args.degrees_of_freedom - 1
24end_time = 2.0
25plot_interval = 0.00 # 0.05
26CFL = 0.5
27unknowns = {"h": 1, "hu": 1, "hv": 1, "z": 1}
28auxiliary = {}
29
30size = [1.58, 1.58, 1.58][0:dimensions]
31offset = [0.0, 0.0, 0.0][0:dimensions]
32max_h = 1.1 * min(size) / (3.0**args.min_depth)
33min_h = max_h / (3.0**args.amr_levels)
34
35g = 9.81
36hThreshold = 1e-5
37number_of_dmp_observables = 0
38dmp_differences_scaling = 0.01 # 0.01 how the diff is scaled
39dmp_relaxation_parameter = 0.02 # the diff scaling
40
41landslide_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
174landslide_case = "DownTheSlope"
175initial_conditions = landslide_zoo[landslide_case]
176
177boundary_conditions = f"""
178 std::copy_n(Qinside, 4, Qoutside);
179 Qoutside[1] = -Qoutside[1];
180 Qoutside[2] = -Qoutside[2];
181"""
182
183flux = 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
202ncp = 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
219source_term = f"""
220 S[0] = 0.0;
221 S[1] = 0.0;
222 S[2] = 0.0;
223 S[3] = 0.0;
224"""
225
226eigenvalues = 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
237adjust_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
246riemann_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
287riemann_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/*
307 //Contribution from NCP
308 double AveragedQ[{len(unknowns)}];
309 double DeltaQ[{len(unknowns)}];
310 for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
311 AveragedQ[varId] = 0.5 * (QL[varId] + QR[varId]);
312 DeltaQ[varId] = QR[varId]-QL[varId];
313 }}
314 double ncp[{len(unknowns)}];
315 nonconservativeProduct(AveragedQ, DeltaQ, x, h, t, dt, normal, ncp);
316 for (int varId = 0; varId < {len(unknowns)}; ++varId) {{
317 FL[varId] += 0.5 * ncp[varId];
318 FR[varId] -= 0.5 * ncp[varId];
319 }}
320*/
321
322 // the elevation should be constant
323 FL[{len(unknowns) - 1}] = 0.0;
324 FR[{len(unknowns) - 1}] = 0.0;
325
326 return smax;
327"""
328
329isPhysicallyAdmissible = "return true;"
330if with_limiting == 0:
331 isPhysicallyAdmissible = "return true; //all ADERDG"
332elif with_limiting == 1:
333 isPhysicallyAdmissible = f"""
334 // If h is close to zero, it is assumed that limiting is not required.
335 // It allows to reduce the computational intensity, avoiding recalculation
336 // cells with zero heights on the FV layer
337 if (std::abs(Q[0]) < {hThreshold}) {{
338 return true;
339 }}
340
341 // Height must be positive!
342 if (Q[0] < {hThreshold}) {{
343 return false;
344 }}
345
346 // If non-physical oscillations occur, the wave speed might receive a negative value under the square root.
347 // It results in eigenvalue becoming NaN, which are not marked as TROUBLED, if no isfinte check is performed.
348 for (int i = 0; i < {len(unknowns)}; ++i) {{
349 if (!std::isfinite(Q[i])) {{
350 return false;
351 }}
352 }}
353
354 // Limit close to boundaries
355 if (std::abs(x[0] - DomainOffset[0]) < h[0]
356 || std::abs(x[0] - DomainOffset[0] - DomainSize[0]) < h[0]
357 || std::abs(x[1] - DomainOffset[1]) < h[1]
358 || std::abs(x[1] - DomainOffset[1] - DomainSize[1]) < h[1]
359 ) {{
360 return false;
361 }}
362 return true;
363 """
364else:
365 isPhysicallyAdmissible = "return false; //all FV"
366
367if use_aderdg:
368 aderdg_solver = exahype2.solvers.aderdg.GlobalAdaptiveTimeStep(
369 name="ADERDGSolver",
370 order=order,
371 unknowns=unknowns,
372 auxiliary_variables=auxiliary,
373 min_cell_h=min_h,
374 max_cell_h=max_h,
375 time_step_relaxation=CFL,
376 )
377 aderdg_solver.set_implementation(
378 flux=flux,
379 max_eigenvalue=eigenvalues,
380 initial_conditions=initial_conditions,
381 boundary_conditions=boundary_conditions,
382 ncp=ncp,
383 source_term=source_term,
384 riemann_solver=riemann_solver_aderdg
385 )
386 project.add_solver(aderdg_solver)
387
388if use_fv:
389 fv_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
390 name="FVSolver",
391 patch_size=2 * order + 1,
392 unknowns=unknowns,
393 auxiliary_variables=auxiliary,
394 min_volume_h=min_h,
395 max_volume_h=max_h,
396 time_step_relaxation=CFL,
397 )
398 fv_solver.set_implementation(
399 flux=flux,
400 max_eigenvalue=eigenvalues,
401 initial_conditions=initial_conditions,
402 boundary_conditions=boundary_conditions,
403 ncp=ncp,
404 source_term=source_term,
405 riemann_solver=riemann_solver_fv,
406 adjust_solution=adjust_solution,
407 )
408 project.add_solver(fv_solver)
409
410if use_limiting:
411 limiter = exahype2.solvers.limiting.PosterioriLimiting(
412 name="LimitingSolver",
413 regular_solver=aderdg_solver,
414 limiting_solver=fv_solver,
415 number_of_dmp_observables=number_of_dmp_observables,
416 dmp_relaxation_parameter=dmp_relaxation_parameter,
417 dmp_differences_scaling=dmp_differences_scaling,
418 physical_admissibility_criterion=isPhysicallyAdmissible,
419 )
420 project.add_solver(limiter)
421
422project.set_output_path("solutions")
423project.set_global_simulation_parameters(
424 dimensions=dimensions,
425 offset=offset[0:dimensions],
426 size=size[0:dimensions],
427 min_end_time=end_time,
428 max_end_time=end_time,
429 first_plot_time_stamp=0.0,
430 time_in_between_plots=plot_interval,
431 periodic_BC=[False, False, False][0:dimensions],
432)
433
434project.set_load_balancer("new ::exahype2::LoadBalancingConfiguration")
435project.set_Peano4_installation("../../../", mode=peano4.output.string_to_mode(args.build_mode))
436project = project.generate_Peano4_project(verbose=False)
437project.set_fenv_handler(False)
438project.build()