Peano
Loading...
Searching...
No Matches
euler.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 argparse
4
5import peano4
6import exahype2
7
8
9class Euler:
10 _available_solvers = {
13
16
17 "RusanovGlobalFixedADERDG": exahype2.solvers.aderdg.GlobalFixedTimeStep,
18 "RusanovGlobalAdaptiveADERDG": exahype2.solvers.aderdg.GlobalAdaptiveTimeStep,
19
21 }
22
23 def setup_parser(self):
24 parser = argparse.ArgumentParser(
25 description="ExaHyPE 2 - Euler Application Script"
26 )
27
28 parser.add_argument(
29 "-s",
30 "--solver",
31 choices=self._available_solvers.keys(),
32 help="|".join(self._available_solvers.keys()),
33 )
34 parser.add_argument(
35 "-d",
36 "--dimensions",
37 type=int,
38 help="Number of space dimensions.",
39 )
40 parser.add_argument(
41 "-dt",
42 "--time-step-size",
43 type=float,
44 default=0.01,
45 help="Time step size for fixed time-stepping.",
46 )
47 parser.add_argument(
48 "-cfl",
49 "--time-step-relaxation",
50 type=float,
51 default=0.5,
52 help="Time step relaxation safety factor for adaptive time-stepping.",
53 )
54
55 parser.add_argument(
56 "-width",
57 "--width",
58 type=str,
59 help="Specify size of domain in meters as [x, y] as string (e.g. [10, 10], [7e6, 4e6]).",
60 )
61 parser.add_argument(
62 "-offset",
63 "--offset",
64 type=str,
65 help="Specify offset of domain in meters as [x, y] as string (e.g. [-10, -10], [-7e6, -4e6]).",
66 )
67
68 parser.add_argument(
69 "-stateless",
70 "--stateless",
71 action="store_true",
72 default=False,
73 help="Use stateless PDE terms for GPU offloading (requires a GPU enabled Peano build and an enclave solver).",
74 )
75
76 parser.add_argument(
77 "-o",
78 "--output",
79 type=str,
80 default="solution",
81 help="Output path for project solution output. The project will create a new folder at the given path. Default is 'solution'.",
82 )
83
84 parser.add_argument(
85 "-pbc-x",
86 "--periodic-boundary-conditions-x",
87 action="store_true",
88 help="Use periodic boundary conditions in the x-axis.",
89 )
90 parser.add_argument(
91 "-pbc-y",
92 "--periodic-boundary-conditions-y",
93 action="store_true",
94 help="Use periodic boundary conditions in the y-axis.",
95 )
96 parser.add_argument(
97 "-pbc-z",
98 "--periodic-boundary-conditions-z",
99 action="store_true",
100 help="Use periodic boundary conditions in the z-axis.",
101 )
102
103 parser.add_argument(
104 "-m",
105 "--build-mode",
106 choices=peano4.output.CompileModes,
107 default=peano4.output.CompileModes[0], # Release
108 help="|".join(peano4.output.CompileModes),
109 )
110
111 parser.add_argument(
112 "-et",
113 "--end-time",
114 type=float,
115 default=5.0,
116 help="End time of the simulation.",
117 )
118 parser.add_argument(
119 "-ns",
120 "--number-of-snapshots",
121 type=int,
122 default=10,
123 help="Number of snapshots (plots).",
124 )
125
126 parser.add_argument(
127 "-ps",
128 "--patch-size",
129 type=int,
130 help="Number of finite volumes per axis (dimension) per patch.",
131 )
132 parser.add_argument(
133 "-rk-order",
134 "--rk-order",
135 type=int,
136 help="Order of time discretisation for Runge-Kutta scheme.",
137 )
138 parser.add_argument(
139 "-dg-order",
140 "--dg-order",
141 type=int,
142 help="Order of space discretisation for Discontinuous Galerkin.",
143 )
144
145 parser.add_argument(
146 "-md",
147 "--min-depth",
148 type=float,
149 default=1,
150 help="Determines maximum size of a single cell on each axis.",
151 )
152 parser.add_argument(
153 "-amr",
154 "--amr-levels",
155 type=int,
156 default=0,
157 help="Number of AMR grid levels on top of max. size of a cell.",
158 )
159
160 parser.add_argument(
161 "--storage",
162 type=str,
163 choices=[e.name for e in exahype2.solvers.Storage],
164 default="Heap",
165 help="The storage scheme to use."
166 )
167
168 available_load_balancing_strategies = [
169 "None",
170 "SpreadOut",
171 "SpreadOutHierarchically",
172 "SpreadOutOnceGridStagnates",
173 "RecursiveBipartition",
174 "SplitOversizedTree",
175 "cascade::SpreadOut_RecursiveBipartition",
176 "cascade::SpreadOut_SplitOversizedTree",
177 ]
178 parser.add_argument(
179 "-lbs",
180 "--load-balancing-strategy",
181 choices=available_load_balancing_strategies,
182 default="SpreadOutOnceGridStagnates",
183 help="|".join(available_load_balancing_strategies),
184 )
185 parser.add_argument(
186 "-lbq",
187 "--load-balancing-quality",
188 type=float,
189 default=0.99,
190 help="The quality of the load balancing.",
191 )
192 parser.add_argument(
193 "--trees",
194 type=int,
195 default=-1,
196 help="Number of trees (partitions) per rank after initial decomposition.",
197 )
198 parser.add_argument(
199 "--threads",
200 type=int,
201 default=0,
202 help="Number of threads per rank.",
203 )
204 parser.add_argument(
205 "-f",
206 "--fuse-tasks",
207 type=int,
208 default=131072,
209 help="Number of enclave tasks to fuse into one meta task.",
210 )
211 parser.add_argument(
212 "-timeout",
213 "--timeout",
214 type=int,
215 default=3600,
216 help="MPI timeout in seconds.",
217 )
218 parser.add_argument(
219 "-fpe",
220 "--fpe",
221 action="store_true",
222 help="Enable a floating-point exception handler.",
223 )
224 parser.add_argument(
225 "-no-make",
226 "--no-make",
227 action="store_true",
228 help="Do not compile the code after generation.",
229 )
230
231 parser.add_argument(
232 "--peano-dir",
233 default="../../../",
234 help="Peano directory",
235 )
236
237 return parser
238
239 def setup_solver(self, args):
240 solver_params = {
241 "name": "Euler",
242 "unknowns": {"rho": 1, "u": 1, "v": 1, "w": 1, "e": 1}
243 if args.dimensions == 3
244 else {"rho": 1, "u": 1, "v": 1, "e": 1},
245 "auxiliary_variables": 0,
246 }
247
248 if args.stateless:
249 solver_params.update(
250 {
251 "pde_terms_without_state": True,
252 }
253 )
254
255 if "Fixed" in args.solver:
256 solver_params.update(
257 {
258 "normalised_time_step_size": args.time_step_size,
259 }
260 )
261 elif "Adaptive" in args.solver:
262 solver_params.update(
263 {
264 "time_step_relaxation": args.time_step_relaxation,
265 }
266 )
267
268 max_h = (1.1 * min(args.width[0:args.dimensions]) / (3.0**args.min_depth))
269 min_h = max_h * 3.0 ** (-args.amr_levels)
270
271 if "FV" in args.solver:
272 solver_params.update(
273 {
274 "patch_size": args.patch_size,
275 "max_volume_h": max_h,
276 "min_volume_h": min_h,
277 }
278 )
279 implementation_params = {
280 "initial_conditions": exahype2.solvers.PDETerms.User_Defined_Implementation,
281 "boundary_conditions": exahype2.solvers.PDETerms.User_Defined_Implementation,
282 "refinement_criterion": exahype2.solvers.PDETerms.User_Defined_Implementation,
283 "flux": "applications::exahype2::euler::flux(Q, faceCentre, volumeH, t, dt, normal, F);",
284 "eigenvalues": "applications::exahype2::euler::maxEigenvalue(Q, faceCentre, volumeH, t, dt, normal, maxEigenvalue);",
285 }
286 elif "RKDG" in args.solver:
287 solver_params.update(
288 {
289 "rk_order": args.rk_order,
290 "polynomials": exahype2.solvers.GaussLegendreBasis(args.dg_order),
291 "max_cell_h": max_h,
292 "min_cell_h": min_h,
293 }
294 )
295 implementation_params = {
296 "initial_conditions": exahype2.solvers.PDETerms.User_Defined_Implementation,
297 "boundary_conditions": exahype2.solvers.PDETerms.User_Defined_Implementation,
298 "refinement_criterion": exahype2.solvers.PDETerms.User_Defined_Implementation,
299 "flux": "applications::exahype2::euler::flux(Q, x, h, t, dt, normal, F);",
300 "eigenvalues": "return applications::exahype2::euler::maxEigenvalue(Q, x, h, t, dt, normal);",
301 }
302 elif "ADERDG" in args.solver:
303 solver_params.update(
304 {
305 "order": args.dg_order,
306 "max_cell_h": max_h,
307 "min_cell_h": min_h,
308 }
309 )
310 implementation_params = {
311 "initial_conditions": exahype2.solvers.PDETerms.User_Defined_Implementation,
312 "boundary_conditions": exahype2.solvers.PDETerms.User_Defined_Implementation,
313 "refinement_criterion": exahype2.solvers.PDETerms.User_Defined_Implementation,
314 "flux": "applications::exahype2::euler::flux(Q, x, h, t, dt, normal, F);",
315 "eigenvalues": """
316 double lambda[NumberOfUnknowns] = {0.};
317 applications::exahype2::euler::maxEigenvalue(Q, x, h, t, dt, normal, lambda);
318 return *std::max_element(lambda, lambda+NumberOfUnknowns);
319 """,
320 }
321
322 solver = self._available_solvers[args.solver](**solver_params)
323 solver.plot_description = ", ".join(solver_params["unknowns"].keys()) + ", "
324 if solver_params["auxiliary_variables"] != 0:
325 solver.plot_description += ", ".join(solver_params["auxiliary_variables"].keys())
326 solver.set_implementation(**implementation_params)
327 solver.switch_storage_scheme(exahype2.solvers.Storage[args.storage], exahype2.solvers.Storage[args.storage])
328
329 if "ADERDG" in args.solver:
330 solver.add_kernel_optimisations(is_linear = False, polynomials=exahype2.solvers.aderdg.Polynomials.Gauss_Lobatto)
331
332 return solver
333
334 def setup_project(self, args, solver):
335 project = exahype2.Project(
336 namespace=["applications", "exahype2", "euler"],
337 project_name="Euler",
338 directory=".",
339 executable=f"Euler.{args.build_mode}",
340 )
341
342 project.add_solver(solver)
343
344 if args.number_of_snapshots <= 0:
345 time_in_between_plots = 0.0
346 else:
347 time_in_between_plots = args.end_time / args.number_of_snapshots
348 project.set_output_path(args.output)
349
350 project.set_global_simulation_parameters(
351 dimensions=args.dimensions,
352 size=args.width[0:args.dimensions],
353 offset=args.offset[0:args.dimensions],
354 min_end_time=args.end_time,
355 max_end_time=args.end_time,
356 first_plot_time_stamp=0.0,
357 time_in_between_plots=time_in_between_plots,
358 periodic_BC=[
359 args.periodic_boundary_conditions_x,
360 args.periodic_boundary_conditions_y,
361 args.periodic_boundary_conditions_z,
362 ],
363 )
364
365 if args.load_balancing_strategy != "None":
366 strategy = f"toolbox::loadbalancing::strategies::{args.load_balancing_strategy}"
367 assume_periodic_boundary_conditions = any([
368 args.periodic_boundary_conditions_x,
369 args.periodic_boundary_conditions_y,
370 args.periodic_boundary_conditions_z,
371 ])
372 configuration = (
373 f"new ::exahype2::LoadBalancingConfiguration("
374 f"{args.load_balancing_quality},"
375 f"0,"
376 f"{'true' if assume_periodic_boundary_conditions else 'false'},"
377 f"{args.trees},"
378 f"{args.trees})"
379 )
380 project.set_load_balancing(strategy, configuration)
381
382 project.set_number_of_threads(args.threads)
383
384 project.set_multicore_orchestration(
385 "tarch::multicore::orchestration::Hardcoded::createFuseAll(%s, 0)"
386 % str(args.fuse_tasks)
387 )
388 project.additional_includes.append("tarch/multicore/orchestration/Hardcoded.h")
389
390 project.set_timeout(args.timeout)
391
392 project.set_Peano4_installation(args.peano_dir, mode=peano4.output.string_to_mode(args.build_mode))
393 project = project.generate_Peano4_project(verbose=True)
394
395 if args.fpe:
396 project.set_fenv_handler("FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW")
397
398 return project
399
400 def build(self, args, project):
401 project.build(
402 make=not args.no_make,
403 make_clean_first=True,
404 throw_away_data_after_build=True,
405 )
setup_project(self, args, solver)
Definition euler.py:334
build(self, args, project)
Definition euler.py:400
setup_solver(self, args)
Definition euler.py:239
setup_parser(self)
Definition euler.py:23
dict _available_solvers
Definition euler.py:10
ExaHyPE 2 project.
Definition Project.py:14
The Gauss-Legendre Basis is by construction the only basis which yields diagonal mass matrices.