19 Represents an ExaHyPE 2 project. An ExaHyPE2 project is a Peano 4
20 project with a particular set of actions (algorithmic phases)
21 that you can choose from and with particular solver types. It
22 realises a builder mechanism, i.e. you build up your ExaHyPE 2
23 project and then you finally tell the project "give me the Peano 4
24 project". From hereon, you can use this Peano 4 project to actually
25 set up the Peano 4 application.
27 The project will have a marker per cell that encodes stuff alike
28 a boundary marker. But it is also used to coordinate different
31 @see generate_Peano4_project()
34 def __init__(self, namespace, project_name, executable, directory=".", subdirectory="", abstract_overwrite=True):
57 "tarch/accelerator/Device.h"
85 """! Set load balancing scheme
87 The load balancing scheme controls how subtress are distributed both
88 among ranks and threads, i.e. the instance is important for MPI but
89 also whenever you use any multithreading strategy.
91 Similar to set_multicore_orchestration(), you have to let the project
92 know about where the load balancing is held. If you rely on the
93 load balancing toolbox and if you have configured Peano with the
94 load balancing toolbox, then simply adding the right eader is
97 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98 project.add_mainfile_include( "toolbox/loadbalancing/strategies/Hardcoded.h)
99 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101 If you use a bespoke load balancing, you also have to add the
102 implementation file or hosting library to the project.
104 @param load_balancer_name: string
105 Should be full-qualified name of the load balancer.
106 By default, I recommend to pass "toolbox::loadbalancing::strategies::RecursiveSubdivision".
108 @param load_balancer_arguments: string
109 If your load balancing requires parameters, add them
110 here. It is a string that will be copied into the C++ class instantiation.
111 Please add the brackets yourself, i.e. "(3,4,5)" is fine, but "3,4,5" is not.
112 The only exception is the empty parameter list. Here, you can/should simply
113 add the empty string.
120 """! Set a log filter file name
122 Pass in the empty string, if you don't want the code to use the
123 hard-coded defaults. That is, by default an ExaHyPE2 application
124 searches for a file exahype.log-filter. Through this call, you can
125 instruct the project to use another filter file.
127 @param file_name String
128 Name of the log filter file that the application should load on
136 """! Set number of threads to use
138 Pass in number of threads (positive integer) or a string such as
139 "tarch::multicore::Core::UseDefaultNumberOfThreads". Please note that
140 this value is handed through to Peano which in turn passes it on the
141 tarch::multicore::Core::configure(int). It then depends on the
142 multithreading backend if this backend allows you to set the thread
143 count manually. Many backends (such as OpenMP) do not allow this,
144 but require users to use environment variables (or scheduler options)
152 """! Set orchestration
154 The orchestration accepts one value which is a C++ statement. This
155 value has to be a string which creates an orchestration object,
156 i.e. an object of the type tarch::multicore::orchestration::Orchestration,
159 You can either create it directly (in this case you need to add a new),
160 or you can use a factory method such as
161 tarch::multicore::orchestration::StrategyFactory::createDefaultStrategy().
163 Depending on where you come from, you might have to add the strategy's
164 header file to the project explicitly. By default, the ExaHyPE 2
165 project only is aware of very few strategies. Here's an example:
167 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168 project.add_mainfile_include( "tarch/multicore/orchestration/Hardcoded.h")
169 project.set_multicore_orchestration(
170 "new benchmarks::exahype2::ccz4::MulticoreOrchestration()"
172 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174 @see exahype2.Project.add_mainfile_include()
175 @param value C++ expression delivering a new orchestration object on the heap
183 value has to be a number greater or equal to zero, this then sets the
184 timeout in seconds after which a node waiting for an MPI message shall
185 quit an shutdown the whole application with an error report.
186 If zero is passed, this feature is switched off and nodes will wait
190 raise Exception(
"Timeout has to be greater or equal to 0")
195 """! Set GPUs to be used
196 value is a list of integers or the empty list if you want the code to
197 use all GPUs that are visible to a rank.
203 The standard extensions that I use for both Peano and ExaHyPE.
205 LibraryDebug =
"_debug"
207 LibraryTrace =
"_trace"
208 LibraryAsserts =
"_asserts"
209 LibraryStats =
"_stats"
214 Path (relative or absolute) to the src directory of Peano. This path
215 should hold both the headers (in subdirectories) and all the static
218 mode: peano4.output.CompileMode
228 Add a new filter to Peano/ExaHyPE
230 offset: (float,float,float)
232 size: (float,float,float)
235 A positive value. Peano makes snapshots every dt simulation
236 units. This is something you specify once per simulation. But
237 you might decide only to splot every k of these snapshots.
240 new_entry += str(offset[0])
245 new_entry += str(size[0])
250 new_entry += str(frequency)
261 We export ExaHyPE's constants. Besides the constants from ExaHyPE,
262 we also export some parameters from Peano onto the ExaHyPE constants
263 file. Therefore, it is important that you parse the configure output
264 before we export the constants.
276 self.
_project.constants.add_include(
"""#include <bitset>""")
277 self.
_project.constants.add_include(
"""#include "tarch/la/Vector.h" """)
278 self.
_project.constants.add_include(
"""#include "peano4/utils/Globals.h" """)
279 self.
_project.constants.export_const_with_type(
280 "DomainOffset", offset_string,
"tarch::la::Vector<Dimensions,double>"
282 self.
_project.constants.export_const_with_type(
283 "DomainSize", size_string,
"tarch::la::Vector<Dimensions,double>"
292 "MaxTerminalTime",
"std::numeric_limits<double>::max()"
297 "FirstPlotTimeStamp", f
"{self._restart_timestamp:.{5}g}"
300 "FirstCheckpointTimeStamp", f
"{self._restart_timestamp:.{5}g}"
320 error_message =
"No checkpoint found for all/part of solvers, please check your path and checkpoint files."
321 sys.stderr.write(error_message +
"\n")
330 self.
_project.constants.export_const_with_type(
331 "CheckpointFilesOf"+self.
_solvers[i]._name, file_string,
"std::vector<std::string>"
340 build_string =
"python3 "
344 self.
_project.constants.export_string(
"BuildInformation", build_string)
345 self.
_project.constants.export_string(
346 "ConfigureInformation", self.
_project.output.makefile.configure_call
349 self.
_project.output.readme.add_package_description(
354This code uses ExaHyPE in its second generation. The first generation of the
355code was developed through an EU FET HPC project called ExaHyPE. This first
356generation was built on top of Peano in its third generation. The present
357code uses ExaHyPE 2 which is a complete rewrite built on top of Peano 4. We
358do not yet have a release paper for this second generation of ExaHyPE, and
359thus appreciate any citation of the original release paper
361 @article{Reinarz:2020:ExaHyPE,
362 title = {ExaHyPE: An engine for parallel dynamically adaptive simulations of wave problems},
363 journal = {Computer Physics Communications},
368 doi = {https://doi.org/10.1016/j.cpc.2020.107251},
369 url = {https://www.sciencedirect.com/science/article/pii/S001046552030076X},
370 author = {Anne Reinarz and Dominic E. Charrier and Michael Bader and Luke Bovard and Michael Dumbser and Kenneth Duru and Francesco Fambri and Alice-Agnes Gabriel and Jean-Matthieu Gallard and Sven K\"oppel and Lukas Krenz and Leonhard Rannabauer and Luciano Rezzolla and Philipp Samfass and Maurizio Tavelli and Tobias Weinzierl},
371 keywords = {Hyperbolic, PDE, ADER-DG, Finite volumes, AMR, MPI, TBB, MPI+X},
372 abstract = {ExaHyPE (An Exascale Hyperbolic PDE Engine) is a software engine for solving systems of first-order hyperbolic partial differential equations (PDEs). Hyperbolic PDEs are typically derived from the conservation laws of physics and are useful in a wide range of application areas. Applications powered by ExaHyPE can be run on a student's laptop, but are also able to exploit thousands of processor cores on state-of-the-art supercomputers. The engine is able to dynamically increase the accuracy of the simulation using adaptive mesh refinement where required. Due to the robustness and shock capturing abilities of ExaHyPE's numerical methods, users of the engine can simulate linear and non-linear hyperbolic PDEs with very high accuracy. Users can tailor the engine to their particular PDE by specifying evolved quantities, fluxes, and source terms. A complete simulation code for a new hyperbolic PDE can often be realised within a few hours - a task that, traditionally, can take weeks, months, often years for researchers starting from scratch. In this paper, we showcase ExaHyPE's workflow and capabilities through real-world scenarios from our two main application areas: seismology and astrophysics.
374 Program title: ExaHyPE-Engine Program Files doi: http://dx.doi.org/10.17632/6sz8h6hnpz.1 Licensing provisions: BSD 3-clause Programming languages: C++, Python, Fortran Nature of Problem: The ExaHyPE PDE engine offers robust algorithms to solve linear and non-linear hyperbolic systems of PDEs written in first order form. The systems may contain both conservative and non-conservative terms. Solution method: ExaHyPE employs the discontinuous Galerkin (DG) method combined with explicit one-step ADER (arbitrary high-order derivative) time-stepping. An a-posteriori limiting approach is applied to the ADER-DG solution, whereby spurious solutions are discarded and recomputed with a robust, patch-based finite volume scheme. ExaHyPE uses dynamical adaptive mesh refinement to enhance the accuracy of the solution around shock waves, complex geometries, and interesting features.
381 self.
_project.output.readme.add_entry(
397 first_plot_time_stamp,
398 time_in_between_plots,
399 periodic_BC=[False, False, False],
402 first_checkpoint_time_stamp=0.0,
403 time_in_between_checkpoints=0.0
406 ! Set the global simulation parameters
408 @param dimensions: 2 or 3
410 @param offset: [Float]
411 Has to have dimension number of entries.
414 Has to have dimension number of entries and all of them have to be
415 positive. At this point, we strongly suggest that all size entries
416 are exactly the same. While Peano and ExaHyPE do support anisotropic
417 meshes, most compute kernels do not, so working with something else
418 than a square or cube will likely break all numerics.
420 @param first_plot_time_stamp: Float
421 Is irrelevant if time_in_between_plots equals zero
423 @param time_in_between_plots: Float
424 Set to zero if you don't want to have any plots
426 @param max_end_time: Float
427 If you set it zero (or actually any value smaller than min_end_time), then
428 the code will run until the cell that lags behind the most hits the min time.
429 If you specify a valid max time however, you can stop the sim as soon as the
430 most advanced cell exceeds this threshold.
438 ),
"domain offset vector and dimensions don't match"
441 ),
"domain offset vector and dimensions don't match"
458 for d
in range(0, dimensions):
460 if plotter_precision <= 0:
461 raise Exception(
"Plotter precision has to be bigger than 0")
465 set checkpointing. The function accept the corresponding peano
466 patch file and create corresponding arrays recording the checkpoint
469 @param restart_timestamp float
470 targeting restart timestamp, the function will find the first
471 checkpointed timestamp right after this input time. Thus the final
472 restarting timestamp may not be equal to this specified time.
474 @param checkpoint_file string
475 the location of the checkpoint meta-file
483 checkpoint_meta_file=checkpoint_path+
"checkpoint-"+solver._name+
".peano-patch-file"
484 recording_current_snapshot=
False
485 solver_file_collection=[]
486 with open(checkpoint_meta_file,
'r')
as file:
488 if line.strip().split()==[]:
continue
489 if line.strip().split()[0] ==
"timestamp" and float(line.strip().split()[1])>=self.
_restart_timestamp:
491 recording_current_snapshot=
True
492 if line.strip().split()[0] ==
"include" and recording_current_snapshot==
True:
493 solver_file_collection.append( line.strip().split()[1] )
494 if line.strip().split()[0] ==
"end" and recording_current_snapshot==
True:
496 if recording_current_snapshot:
506 print(
"Couldn't create the defined output path, please ensure that this path exists")
512 Add a new include file to the main file (but also to the solver repository)
514 The name is slightly misleading. As ExaHyPE's code generation never
515 overwrites a mainfile by a user, the includes actually go into the
516 solver repository rather than the main file.
519 The value is the actual content within the include, i.e. if you pass in
520 "abc.h", then the code will insert
522 ~~~~~~~~~~~~~~~~~~~~~~~~~~
524 ~~~~~~~~~~~~~~~~~~~~~~~~~~
526 into the repository file. There is no need to add the include
549 I have to call finishedTraversal() for each tracer set. As tracers
550 are a subclass of DoF, they have a name property.
557 (solver._name, solver.get_name_of_global_instance())
560 templatefile_prefix = (
561 os.path.realpath(__file__).replace(
".pyc",
"").replace(
".py",
"")
563 generated_solver_files = (
565 templatefile_prefix +
"SolverRepository.template.h",
566 templatefile_prefix +
"SolverRepository.template.cpp",
568 self.
_project.namespace + [
"repositories"],
569 self.
_project.subdirectory +
"repositories",
575 self.
_project.output.add(generated_solver_files)
576 self.
_project.output.makefile.add_cpp_file(
577 self.
_project.subdirectory +
"repositories/SolverRepository.cpp", generated=
True
585 sort_descend_invocation_order_within_action_sets=-1,
586 plot_descend_invocation_order_within_action_sets=65536,
590 Add a tracer to the project
592 Tracers have to be the very last thing you add to your project.
593 At this point, all solvers have to be added to the project.
594 However, you have to add the tracers prior to any user-defined
595 routines. See docu of init_new_user_defined_algorithmic_step().
597 We rely on the particle toolbox. Therefore, our particles have
598 already a position x, a search radius (which we don't usually
599 use here), and a (parallel) state. The search radius determines
600 how Peano sorts particles within the tree, and we can set it to
601 zero here. This ensures that the particle has no real volume and
602 thus is always sieved through to the finest grid level.
604 @see peano4.toolbox.particles.Particle
607 ## Projection of data onto particles and database dumping
609 The projection onto the particle has to be realised separately, as
610 it depends on the solver variant chosen. The same holds for the
611 dump of particle data into a database if this shall happen
614 Most bigger applications add their solvers an add_tracer() operation,
615 which takes all of this domain knowledge into account. This
616 add_tracer() then forwards to this routine, adding further
619 See the class application.exahype2.ccz.CCZ4Solver and its derived
620 variants for examples.
625 Tracers in ExaHyPE can move, though they do not have to move. Even if
626 they move, they never have a native velocity, i.e. their velocity will
627 always be a projection of an ExaHyPE solution. We are talking about
628 tracers after all and not about a proper PIC approach. Due to this
629 constraint, we do not need a velocity vector. However, we need an
630 additional enumeration which clarifies if a
631 particle has moved already or not. This enumeration is needed by the
632 particle update routines. Obviously, nothing stops you from adding
633 a separate velocity field to the tracer object and thus to redefine
637 ## ExaHyPE-specific particle attributes
640 particle a number which is a tuple consisting of the tree number
641 (on which tree has a particle been generated plus what was the
642 tree-local number of this particle at the time). Through this
643 tuple, we can track tracers later on even if they move across
646 We can plot the data - if there is data to be tracked - directly,
647 as it is a large double array. For the index, we have to type cast
648 the data, as this is a tuple of integers, and Peano's VTK plotter
649 supports only double vectors.
651 @see peano4.toolbox.particles.PlotParticlesInVTKFormat.add_attribute_to_plot()
656 We add the particle ordering with descend order -1. This should do the job
657 for most setups, but we might be wrong. The following action sets are
660 - UpdateParallelState is added to each and every time step and plotting
661 sweep. As we also add
662 - peano4.toolbox.particles.api.UpdateParticleGridAssociation_LiftDrop to each and every time step,
663 particles can move at any point. We always resort them immediately.
665 Both action sets are assigned the standard priority of sort_descend_invocation_order_within_action_sets.
671 Has to be a unique name for this tracer
673 attribute_count: integer
674 Number of attributes that we track per particle (scalar values added
675 pre particle). Can be 0 if you don't want any attributes.
678 See tracer.InsertParticles
681 If this flag is set, ExaHyPE dumps the particles as vtu files whenever
682 it writes patch files. You can switch this behaviour off. A lot of codes
683 do so if they dump the tracer data independently into another database
686 sort_descend_invocation_order_within_action_sets: Integer
687 You have to clarify what the priority of the tracer is within the
688 action sets. By default, all ExaHyPE solvers start with priority
689 0 and then up to n. So you are fine with using the default of -1
690 which means that the tracer precedes any solver. However, there
691 might be cases where you wanna move the priorities manually.
693 Returns the particle set that you can use to modify further
697 if attribute_count > 0:
699 "data", str(attribute_count)
701 particle.data.add_attribute(particle_attr)
703 particle.data.add_attribute(
708 particle.data.add_attribute(particle_number)
712 self.
_project.datamodel.add_global_object(particle)
713 self.
_project.datamodel.add_vertex(particles)
730 update_particle_association_action_set = (
733 update_particle_association_action_set.descend_invocation_order = sort_descend_invocation_order_within_action_sets
734 update_particle_association_action_set.parallel =
True
736 update_particle_parallel_state_action_set = (
739 update_particle_parallel_state_action_set.descend_invocation_order = (
740 sort_descend_invocation_order_within_action_sets
742 update_particle_parallel_state_action_set.parallel =
True
760 particle_set=particles,
761 time_stamp_evaluation=
"repositories::getMinTimeStamp()",
762 additional_includes=
"""
763#include "repositories/SolverRepository.h"
766 if attribute_count > 0:
767 particle_plotter.add_attribute_to_plot(particle_attr, attribute_count)
768 particle_plotter.add_attribute_to_plot(
769 particle_number, 2,
"tarch::la::convertScalar<double>(p->getNumber())"
771 particle_plotter.descend_invocation_order = plot_descend_invocation_order_within_action_sets
775 self.
plot_solution.add_action_set(update_particle_association_action_set)
776 self.
plot_solution.add_action_set(update_particle_parallel_state_action_set)
789 Add a new action set to the time stepping
791 You have to be careful with the priorities, i.e. you might want to
792 use myproject.perform_time_step.max_priority() or myproject.perform_time_step.min_priority()
794 priority you should assign to action_set.
802 Add a new action set to the plotting
810 Add a new action set to the checkpointing
816 self.
init_grid.add_action_set(action_set)
821 Add an action set to create grid
823 This routine actually adds an action set to each and every grid
824 creation routine. After all, we distinguish three flavours of it
827 - without refinement as we've just refined or split up domain;
828 - without refinement to let load balancing converge.
838 Construct a Peano 4 project and return it
840 Build the Peano 4 project, i.e., all the action sets et al that you require
841 to run this ExaHyPE 2 application. The project is built within self._project
842 and eventually returned.
844 This routine generates a Peano project, i.e. the domain-specific ExaHyPE
845 view is translated into a Peano model. Once you have called this routine,
846 any changes to the ExaHyPE 2 configuration do not propagate into the Peano
847 setup anymore. If you alter the ExaHyPE setup, you have to call
848 generate_Peano4_project() again to get a new snapshot/version of the
862 print(
"---------------------------------------")
863 print(
"Create data for solver " + solver._name)
864 print(
"---------------------------------------")
867 solver.add_to_Peano4_datamodel(self.
_project.datamodel, verbose)
869 solver.add_use_data_statements_to_Peano4_solver_step(self.
create_grid)
870 solver.add_use_data_statements_to_Peano4_solver_step(self.
plot_solution)
873 solver.add_use_data_statements_to_Peano4_solver_step(self.
init_grid)
874 solver.add_use_data_statements_to_Peano4_solver_step(
877 solver.add_use_data_statements_to_Peano4_solver_step(
881 solver.add_actions_to_create_grid(
882 self.
create_grid, evaluate_refinement_criterion=
True
890 solver.add_actions_to_init_grid(self.
init_grid)
895 solver.add_actions_to_create_grid(
897 evaluate_refinement_criterion=
False,
899 solver.add_actions_to_create_grid(
906 solver.add_implementation_files_to_project(
917 self.
_project.output.makefile.parse_configure_script_outcome(
930 """! Inform ExaHyPE 2 that there is an additional solver step not resulting from vanilla solver versions
932 Use this routine whenever you have created your own
933 @ref page_architecture "algorithmic step". Please note that the routine
934 should be called after you have created all of your solvers. Otherwise,
935 we'll miss out a few of your solvers and the data access patterns
936 will/might be corrupted. Also all tracers have to be added at this
939 The routine has no side-effects, i.e. does not alter the underlying
940 project. It only manipulates the step. Therefore, you can even call it
941 after you have distilled the Peano project from the ExaHyPE project,
942 i.e. after you have called exahype2.Project.generate_Peano4_project().
943 In return, you however still have to add the new step manually to the
944 Peano project. That is, this routine merely initialises the new step,
945 but it does not yet add it to the sweeps known by Peano.
947 @param step: peano4.solversteps.Step
951 solver.add_use_data_statements_to_Peano4_solver_step(step)
954 step.use_vertex(tracer_set)
Wrapper around C++ enumerations which is not a datatype supported natively by MPI.
_time_in_between_checkpoints
set_restart_from_checkpoint(self, expected_restart_timestamp=0, checkpoint_path="./")
set checkpointing.
__generate_solver_repository(self)
I have to call finishedTraversal() for each tracer set.
init_new_user_defined_algorithmic_step(self, step)
Inform ExaHyPE 2 that there is an additional solver step not resulting from vanilla solver versions.
_first_checkpoint_time_stamp
add_action_set_to_timestepping(self, action_set)
Add a new action set to the time stepping.
set_load_balancing(self, load_balancer_name, load_balancer_arguments="")
Set load balancing scheme.
set_number_of_threads(self, value)
Set number of threads to use.
set_Peano4_installation(self, src_path, mode=peano4.output.CompileMode.Release)
src_path: string Path (relative or absolute) to the src directory of Peano.
solverRepositoryDictionary
set_output_path(self, path)
add_plot_filter(self, offset, size, frequency=1)
Add a new filter to Peano/ExaHyPE.
__configure_makefile(self)
generate_Peano4_project(self, verbose=False)
Construct a Peano 4 project and return it.
add_tracer(self, name, attribute_count=0, plot=True, sort_descend_invocation_order_within_action_sets=-1, plot_descend_invocation_order_within_action_sets=65536)
Add a tracer to the project.
__init__(self, namespace, project_name, executable, directory=".", subdirectory="", abstract_overwrite=True)
set_timeout(self, value)
Set timeout value has to be a number greater or equal to zero, this then sets the timeout in seconds ...
add_action_set_to_plot_solution(self, action_set)
Add a new action set to the plotting.
additional_includes(self)
__set_solver_repository_dict(self)
set_multicore_orchestration(self, value)
Set orchestration.
add_action_set_to_create_grid(self, action_set)
Add an action set to create grid.
add_mainfile_include(self, value)
Add a new include file to the main file (but also to the solver repository)
set_global_simulation_parameters(self, dimensions, offset, size, min_end_time, first_plot_time_stamp, time_in_between_plots, periodic_BC=[False, False, False], plotter_precision=5, max_end_time=0.0, first_checkpoint_time_stamp=0.0, time_in_between_checkpoints=0.0)
! Set the global simulation parameters
set_log_filter_file(self, file_name)
Set a log filter file name.
create_grid_and_converge_lb
__export_constants(self)
We export ExaHyPE's constants.
set_gpus(self, value)
Set GPUs to be used value is a list of integers or the empty list if you want the code to use all GPU...
add_action_set_to_checkpoint_solution(self, action_set)
Add a new action set to the checkpointing.
create_grid_but_postpone_refinement
add_action_set_to_initialisation(self, action_set)
Represents a Peano 4 project.
Specialisation of array using Peano's tarch.
Represents a particle set.
For constructor's time_stamp_evaluation argument.
Update the parallel state of particles and keep stats of them.
Associate particles to spacetree vertices.