Peano
Loading...
Searching...
No Matches
Project.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
5
6import dastgen2
7
8import os
9import sys
10
11import exahype2.grid
13
14class Project(object):
15 """!
16
17 ExaHyPE 2 project
18
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.
26
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
29 solver types.
30
31 @see generate_Peano4_project()
32 """
33
34 def __init__(self, namespace, project_name, executable, directory=".", subdirectory="", abstract_overwrite=True):
35 self._project = peano4.Project(namespace, project_name, directory, subdirectory)
36 self._subdirectory = subdirectory
37 self._abstract_overwrite = abstract_overwrite
38
39 self._solvers = []
40 self._domain_offset = [0.0, 0.0, 0.0]
41 self._domain_size = [1.0, 1.0, 1.0]
42 self._dimensions = 3
51 self._log_filter_file = "exahype.log-filter"
52 self._number_of_threads = "tarch::multicore::Core::UseDefaultNumberOfThreads"
53 self._multicore_orchestration = "tarch::multicore::orchestration::createDefaultStrategy()"
54 self._timeout = 3600
55 self._gpus = []
56 self._additional_includes = [ "tarch/logging/LogFilterFileReader.h",
57 "tarch/accelerator/Device.h"
58 ]
60 self._build_mode = peano4.output.CompileMode.Asserts
61 self._executable_name = executable
62 self._periodic_BC = [False, False, False]
63 self._plot_filters = []
64 self._output_path = "./"
68
73
74
75 self.create_grid = peano4.solversteps.Step("CreateGrid", False)
76 self.init_grid = peano4.solversteps.Step("InitGrid", False)
77 self.create_grid_but_postpone_refinement = peano4.solversteps.Step("CreateGridButPostponeRefinement", False)
78 self.create_grid_and_converge_lb = peano4.solversteps.Step("CreateGridAndConvergeLoadBalancing", False)
79 self.plot_solution = peano4.solversteps.Step("PlotSolution", False)
80 self.checkpoint_solution = peano4.solversteps.Step("CheckpointSolution", False)
82
83
84 def set_load_balancing(self, load_balancer_name, load_balancer_arguments=""):
85 """! Set load balancing scheme
86
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.
90
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
95 sufficient:
96
97 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98 project.add_mainfile_include( "toolbox/loadbalancing/strategies/Hardcoded.h)
99 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100
101 If you use a bespoke load balancing, you also have to add the
102 implementation file or hosting library to the project.
103
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".
107
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.
114 """
115 self._load_balancer_name = load_balancer_name
116 self._load_balancer_arguments = load_balancer_arguments
117
118
119 def set_log_filter_file(self, file_name):
120 """! Set a log filter file name
121
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.
126
127 @param file_name String
128 Name of the log filter file that the application should load on
129 startup.
130
131 """
132 self._log_filter_file = file_name
133
134
135 def set_number_of_threads(self, value):
136 """! Set number of threads to use
137
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)
145 instead.
146
147 """
148 self._number_of_threads = value
149
150
152 """! Set orchestration
153
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,
157 on the heap.
158
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().
162
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:
166
167 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168 project.add_mainfile_include( "tarch/multicore/orchestration/Hardcoded.h")
169 project.set_multicore_orchestration(
170 "new benchmarks::exahype2::ccz4::MulticoreOrchestration()"
171 )
172 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173
174 @see exahype2.Project.add_mainfile_include()
175 @param value C++ expression delivering a new orchestration object on the heap
176
177 """
178 self._multicore_orchestration = value
179
180
181 def set_timeout(self, value):
182 """! Set timeout
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
187 indefinitely.
188 """
189 if value < 0:
190 raise Exception("Timeout has to be greater or equal to 0")
191 self._timeout = value
192
193
194 def set_gpus(self, value):
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.
198 """
199 self._gpus = value
200
201
202 """
203 The standard extensions that I use for both Peano and ExaHyPE.
204 """
205 LibraryDebug = "_debug"
206 LibraryRelease = ""
207 LibraryTrace = "_trace"
208 LibraryAsserts = "_asserts"
209 LibraryStats = "_stats"
210
211 def set_Peano4_installation(self, src_path, mode=peano4.output.CompileMode.Release):
212 """
213 src_path: string
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
216 libraries.
217
218 mode: peano4.output.CompileMode
219 """
220 self._Peano_src_directory = src_path
221 self._build_mode = mode
222
223 def add_solver(self, solver):
224 self._solvers.append(solver)
225
226 def add_plot_filter(self, offset, size, frequency=1):
227 """
228 Add a new filter to Peano/ExaHyPE
229
230 offset: (float,float,float)
231
232 size: (float,float,float)
233
234 frequency: int
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.
238 """
239 new_entry = "{{"
240 new_entry += str(offset[0])
241 for i in offset[1:]:
242 new_entry += ","
243 new_entry += str(i)
244 new_entry += "},{"
245 new_entry += str(size[0])
246 for i in size[1:]:
247 new_entry += ","
248 new_entry += str(i)
249 new_entry += "},"
250 new_entry += str(frequency)
251 new_entry += "}"
252
253 self._plot_filters.append(new_entry)
254
256 self._solvers = []
257 self._project.cleanup()
258
260 """
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.
265 """
266 self._project.constants.clear()
267 offset_string = "{" + str(self._domain_offset[0])
268 size_string = "{" + str(self._domain_size[0])
269 for i in range(1, self._dimensions):
270 offset_string += ","
271 size_string += ","
272 offset_string += str(self._domain_offset[i])
273 size_string += str(self._domain_size[i])
274 offset_string += "}"
275 size_string += "}"
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>"
281 )
282 self._project.constants.export_const_with_type(
283 "DomainSize", size_string, "tarch::la::Vector<Dimensions,double>"
284 )
285 self._project.constants.export("MinTerminalTime", str(self._min_terminal_time))
287 self._project.constants.export(
288 "MaxTerminalTime", str(self._max_terminal_time)
289 )
290 else:
291 self._project.constants.export(
292 "MaxTerminalTime", "std::numeric_limits<double>::max()"
293 )
294
296 self._project.constants.export(
297 "FirstPlotTimeStamp", f"{self._restart_timestamp:.{5}g}"
298 )
299 self._project.constants.export(
300 "FirstCheckpointTimeStamp", f"{self._restart_timestamp:.{5}g}"
301 )
302 else:
303 self._project.constants.export(
304 "FirstPlotTimeStamp", str(self._first_plot_time_stamp)
305 )
306 self._project.constants.export(
307 "FirstCheckpointTimeStamp", str(self._first_checkpoint_time_stamp)
308 )
309
310 self._project.constants.export(
311 "TimeInBetweenPlots", str(self._time_in_between_plots)
312 )
313
314 self._project.constants.export(
315 "TimeInBetweenCheckpoints", str(self._time_in_between_checkpoints)
316 )
317
319 if self._solvers_file_collection==[] or len(self._solvers_file_collection)<len(self._solvers):
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")
322 sys.exit(1)
323 else:
324 for i in range(len(self._solvers)):
325 file_string = "{" + self._solvers_file_collection[i][0]
326 for j in range(1, len(self._solvers_file_collection[i])):
327 file_string += ","
328 file_string += self._solvers_file_collection[i][j]
329 file_string += "}"
330 self._project.constants.export_const_with_type(
331 "CheckpointFilesOf"+self._solvers[i]._name, file_string, "std::vector<std::string>"
332 )
333 self._project.constants.export(
334 "CheckpointTimeStamp", str(self._restart_timestamp)
335 )
336
337 self._project.constants.export("PlotterPrecision", str(self._plotter_precision))
338 self._project.constants.export_boolean_sequence("PeriodicBC", self._periodic_BC)
339
340 build_string = "python3 "
341 for i in sys.argv:
342 build_string += " "
343 build_string += i
344 self._project.constants.export_string("BuildInformation", build_string)
345 self._project.constants.export_string(
346 "ConfigureInformation", self._project.output.makefile.configure_call
347 )
348
349 self._project.output.readme.add_package_description(
350 """
351
352### ExaHyPE 2
353
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
360
361 @article{Reinarz:2020:ExaHyPE,
362 title = {ExaHyPE: An engine for parallel dynamically adaptive simulations of wave problems},
363 journal = {Computer Physics Communications},
364 volume = {254},
365 pages = {107251},
366 year = {2020},
367 issn = {0010-4655},
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.
373 Program summary
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.
375 }
376 }
377"""
378 )
379
380 for i in self._solvers:
381 self._project.output.readme.add_entry(
382 i.create_readme_descriptor(self._domain_offset[0], self._domain_size[0])
383 )
384 # self._min_volume_h = min_volume_h
385 # self._max_volume_h = max_volume_h
386
388 self._project.output.makefile.set_dimension(self._dimensions)
389 self._project.output.makefile.set_executable_name(self._executable_name)
390
392 self,
393 dimensions,
394 offset,
395 size,
396 min_end_time,
397 first_plot_time_stamp,
398 time_in_between_plots,
399 periodic_BC=[False, False, False],
400 plotter_precision=5,
401 max_end_time=0.0,
402 first_checkpoint_time_stamp=0.0,
403 time_in_between_checkpoints=0.0
404 ):
405 """
406 ! Set the global simulation parameters
407
408 @param dimensions: 2 or 3
409
410 @param offset: [Float]
411 Has to have dimension number of entries.
412
413 @param size: [Float}
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.
419
420 @param first_plot_time_stamp: Float
421 Is irrelevant if time_in_between_plots equals zero
422
423 @param time_in_between_plots: Float
424 Set to zero if you don't want to have any plots
425
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.
431 """
432 self._domain_offset = offset
433 self._domain_size = size
434 self._dimensions = dimensions
435
436 assert (
437 len(self._domain_offset) == dimensions
438 ), "domain offset vector and dimensions don't match"
439 assert (
440 len(self._domain_size) == dimensions
441 ), "domain offset vector and dimensions don't match"
442
443 self._max_terminal_time = max_end_time
444 self._min_terminal_time = min_end_time
445 self._first_plot_time_stamp = first_plot_time_stamp
446 self._time_in_between_plots = time_in_between_plots
447 self._first_checkpoint_time_stamp = first_checkpoint_time_stamp
448 self._time_in_between_checkpoints = time_in_between_checkpoints
449 self._project.constants.export(
450 "TimeInBetweenPlots", str(self._time_in_between_plots)
451 )
452 self._project.constants.export(
453 "TimeInBetweenCheckpoints", str(self._time_in_between_checkpoints)
454 )
455
456 self._periodic_BC = []
457 self._plotter_precision = plotter_precision
458 for d in range(0, dimensions):
459 self._periodic_BC.append(periodic_BC[d])
460 if plotter_precision <= 0:
461 raise Exception("Plotter precision has to be bigger than 0")
462
463 def set_restart_from_checkpoint(self, expected_restart_timestamp=0, checkpoint_path="./"):
464 '''
465 set checkpointing. The function accept the corresponding peano
466 patch file and create corresponding arrays recording the checkpoint
467 file names.
468
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.
473
474 @param checkpoint_file string
475 the location of the checkpoint meta-file
476 '''
477
478 self._restart_from_checkpoint = True
479 self._restart_timestamp = expected_restart_timestamp
480 self._checkpoint_path = checkpoint_path
481
482 for solver in self._solvers:
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:
487 for line in file:
488 if line.strip().split()==[]: continue
489 if line.strip().split()[0] == "timestamp" and float(line.strip().split()[1])>=self._restart_timestamp:
490 self._restart_timestamp = float(line.strip().split()[1])
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:
495 break
496 if recording_current_snapshot:
497 self._solvers_file_collection.append(solver_file_collection)
498
499
500 def set_output_path(self, path):
501 self._output_path = path
502 if not os.path.exists(self._output_path):
503 try:
504 os.makedirs(self._output_path)
505 except:
506 print("Couldn't create the defined output path, please ensure that this path exists")
507 if not self._output_path.endswith("/"):
508 self._output_path += "/"
509
510 def add_mainfile_include(self,value):
511 """!
512 Add a new include file to the main file (but also to the solver repository)
513
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.
517
518 @param value String
519 The value is the actual content within the include, i.e. if you pass in
520 "abc.h", then the code will insert
521
522 ~~~~~~~~~~~~~~~~~~~~~~~~~~
523#include "abc.h"
524 ~~~~~~~~~~~~~~~~~~~~~~~~~~
525
526 into the repository file. There is no need to add the include
527 statement.
528
529 """
530 self._additional_includes.append( value )
531
534 "SOLVERS": [],
535 "LOAD_BALANCER": self._load_balancer_name,
536 "LOAD_BALANCER_ARGUMENTS": self._load_balancer_arguments,
537 "PLOT_FILTER": self._plot_filters,
538 "TRACERS": [x.name for x in self._tracer_particles],
539 "LOG_FILTER_FILE": self._log_filter_file,
540 "NUMBER_OF_THREADS": self._number_of_threads,
541 "MULTICORE_ORCHESTRATION": self._multicore_orchestration,
542 "TIMEOUT": self._timeout,
543 "GPUS": self._gpus,
544 "ADDITIONAL_INCLUDES": self._additional_includes,
545 }
546
548 """
549 I have to call finishedTraversal() for each tracer set. As tracers
550 are a subclass of DoF, they have a name property.
551 """
552
554
555 for solver in self._solvers:
556 self.solverRepositoryDictionary["SOLVERS"].append(
557 (solver._name, solver.get_name_of_global_instance())
558 )
559
560 templatefile_prefix = (
561 os.path.realpath(__file__).replace(".pyc", "").replace(".py", "")
562 )
563 generated_solver_files = (
565 templatefile_prefix + "SolverRepository.template.h",
566 templatefile_prefix + "SolverRepository.template.cpp",
567 "SolverRepository",
568 self._project.namespace + ["repositories"],
569 self._project.subdirectory + "repositories",
571 True,
572 )
573 )
574
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
578 )
579
581 self,
582 name,
583 attribute_count=0,
584 plot=True,
585 sort_descend_invocation_order_within_action_sets=-1,
586 plot_descend_invocation_order_within_action_sets=65536,
587 ):
588 """!
589
590 Add a tracer to the project
591
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().
596
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.
603
604 @see peano4.toolbox.particles.Particle
605
606
607 ## Projection of data onto particles and database dumping
608
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
612 on-the-fly.
613
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
617 behaviour.
618
619 See the class application.exahype2.ccz.CCZ4Solver and its derived
620 variants for examples.
621
622
623 ## Moving particles
624
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
634 this behaviour.
635
636
637 ## ExaHyPE-specific particle attributes
638
639 We add each
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
644 domains.
645
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.
650
651 @see peano4.toolbox.particles.PlotParticlesInVTKFormat.add_attribute_to_plot()
652
653
654 ## Action set order
655
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
658 automatically added:
659
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.
664
665 Both action sets are assigned the standard priority of sort_descend_invocation_order_within_action_sets.
666
667
668 ## Arguments
669
670 name: String
671 Has to be a unique name for this tracer
672
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.
676
677 h and noise:
678 See tracer.InsertParticles
679
680 plot: Boolean
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
684 anyway.
685
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.
692
693 Returns the particle set that you can use to modify further
694 """
695 particle = peano4.toolbox.particles.Particle(name)
696
697 if attribute_count > 0:
698 particle_attr = peano4.dastgen2.Peano4DoubleArray(
699 "data", str(attribute_count)
700 )
701 particle.data.add_attribute(particle_attr)
702
703 particle.data.add_attribute(
704 dastgen2.attributes.Enumeration("MoveState", ["NotMovedYet", "Moved"])
705 )
706
707 particle_number = peano4.dastgen2.Peano4IntegerArray("number", "2")
708 particle.data.add_attribute(particle_number)
709
710 particles = peano4.toolbox.particles.ParticleSet(particle)
711
712 self._project.datamodel.add_global_object(particle)
713 self._project.datamodel.add_vertex(particles)
714
715 self.plot_solution.use_vertex(particles)
716 self.checkpoint_solution.use_vertex(particles)
717 self.init_grid.use_vertex(particles)
718 self.perform_time_step.use_vertex(particles)
719 self.create_grid.use_vertex(particles)
720 self.create_grid_but_postpone_refinement.use_vertex(particles)
721 self.create_grid_and_converge_lb.use_vertex(particles)
722
723 #
724 # Initialisation
725 #
726 self.init_grid.add_action_set(
728 )
729
730 update_particle_association_action_set = (
732 )
733 update_particle_association_action_set.descend_invocation_order = sort_descend_invocation_order_within_action_sets
734 update_particle_association_action_set.parallel = True
735
736 update_particle_parallel_state_action_set = (
738 )
739 update_particle_parallel_state_action_set.descend_invocation_order = (
740 sort_descend_invocation_order_within_action_sets
741 )
742 update_particle_parallel_state_action_set.parallel = True
743
744 #
745 # Move particles
746 #
747 self.perform_time_step.add_action_set(update_particle_association_action_set)
748 self.perform_time_step.add_action_set(update_particle_parallel_state_action_set)
749
750 #
751 # Plotter: The timestamp here is slightly wrong, as I use the min time stamp. It
752 # really should be the time stamp of the underlying solver. However, tracers are
753 # not tied to one solver, so I have to find a quantity that makes sense. If the
754 # user requires the time stamp, they have to add this one as data field to the
755 # particle
756 #
757 if plot:
759 filename=name,
760 particle_set=particles,
761 time_stamp_evaluation="repositories::getMinTimeStamp()",
762 additional_includes="""
763#include "repositories/SolverRepository.h"
764""",
765 )
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())"
770 )
771 particle_plotter.descend_invocation_order = plot_descend_invocation_order_within_action_sets
772 self.plot_solution.add_action_set(particle_plotter)
773 self.checkpoint_solution.add_action_set(particle_plotter)
774
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)
777
778 self.checkpoint_solution.add_action_set(update_particle_association_action_set)
779 self.checkpoint_solution.add_action_set(update_particle_parallel_state_action_set)
780
781 self._tracer_particles.append(particle)
782 self._tracer_particle_sets.append(particles)
783
784 return particles
785
786 def add_action_set_to_timestepping(self, action_set):
787 """!
788
789 Add a new action set to the time stepping
790
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()
793 to find out which
794 priority you should assign to action_set.
795
796 """
797 self.perform_time_step.add_action_set(action_set)
798
799 def add_action_set_to_plot_solution(self, action_set):
800 """!
801
802 Add a new action set to the plotting
803
804 """
805 self.plot_solution.add_action_set(action_set)
806
808 """!
809
810 Add a new action set to the checkpointing
811
812 """
813 self.checkpoint_solution.add_action_set(action_set)
814
815 def add_action_set_to_initialisation(self, action_set):
816 self.init_grid.add_action_set(action_set)
817
818 def add_action_set_to_create_grid(self, action_set):
819 """!
820
821 Add an action set to create grid
822
823 This routine actually adds an action set to each and every grid
824 creation routine. After all, we distinguish three flavours of it
825
826 - with refinement;
827 - without refinement as we've just refined or split up domain;
828 - without refinement to let load balancing converge.
829
830 """
831 self.create_grid.add_action_set(action_set)
832 self.create_grid_but_postpone_refinement.add_action_set(action_set)
833 self.create_grid_and_converge_lb.add_action_set(action_set)
834
835 def generate_Peano4_project(self, verbose=False):
836 """!
837
838 Construct a Peano 4 project and return it
839
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.
843
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
849 Peano setup.
850 """
851 # self._project.cleanup()
852
853 self._project.solversteps.add_step(self.create_grid)
854 self._project.solversteps.add_step(self.init_grid)
855 self._project.solversteps.add_step(self.create_grid_but_postpone_refinement)
856 self._project.solversteps.add_step(self.create_grid_and_converge_lb)
857 self._project.solversteps.add_step(self.plot_solution)
858 self._project.solversteps.add_step(self.checkpoint_solution)
859 self._project.solversteps.add_step(self.perform_time_step)
860
861 for solver in self._solvers:
862 print("---------------------------------------")
863 print("Create data for solver " + solver._name)
864 print("---------------------------------------")
865 print(str(solver))
866
867 solver.add_to_Peano4_datamodel(self._project.datamodel, verbose)
868
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)
871 solver.add_use_data_statements_to_Peano4_solver_step(self.checkpoint_solution)
872 solver.add_use_data_statements_to_Peano4_solver_step(self.perform_time_step)
873 solver.add_use_data_statements_to_Peano4_solver_step(self.init_grid)
874 solver.add_use_data_statements_to_Peano4_solver_step(
876 )
877 solver.add_use_data_statements_to_Peano4_solver_step(
879 )
880
881 solver.add_actions_to_create_grid(
882 self.create_grid, evaluate_refinement_criterion=True
883 )
884
885 if self._restart_from_checkpoint: #avoid error when use solver without checkpoint feature
886 solver.add_actions_to_init_grid(self.init_grid, self._restart_from_checkpoint)
887 solver.add_actions_to_plot_solution(self.plot_solution, self._output_path, self._restart_from_checkpoint)
888 solver.add_actions_to_checkpoint_solution(self.checkpoint_solution, self._output_path, self._restart_from_checkpoint)
889 else:
890 solver.add_actions_to_init_grid(self.init_grid)
891 solver.add_actions_to_plot_solution(self.plot_solution, self._output_path)
892 if ( (self._time_in_between_checkpoints != 0) or (self._first_checkpoint_time_stamp != 0) ):
893 solver.add_actions_to_checkpoint_solution(self.checkpoint_solution, self._output_path)
894
895 solver.add_actions_to_create_grid(
897 evaluate_refinement_criterion=False,
898 )
899 solver.add_actions_to_create_grid(
900 self.create_grid_and_converge_lb, evaluate_refinement_criterion=False
901 )
902
903 solver.add_actions_to_perform_time_step(self.perform_time_step)
904
905 if self._abstract_overwrite==False:
906 solver.add_implementation_files_to_project(
907 self._project.namespace, self._project.output, self._dimensions, self._subdirectory, self._abstract_overwrite
908 )
909 else:
910 solver.add_implementation_files_to_project( self._project.namespace, self._project.output, self._dimensions, self._subdirectory )
911
913
914 self._project.main = exahype2.ExaHyPEMain(self._project)
915
917 self._project.output.makefile.parse_configure_script_outcome(
919 )
920 self.__export_constants()
921
922 self._project.output.makefile.set_mode(self._build_mode)
923
924 return self._project
925
926
928 step,
929 ):
930 """! Inform ExaHyPE 2 that there is an additional solver step not resulting from vanilla solver versions
931
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
937 point already.
938
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.
946
947 @param step: peano4.solversteps.Step
948
949 """
950 for solver in self._solvers:
951 solver.add_use_data_statements_to_Peano4_solver_step(step)
952
953 for tracer_set in self._tracer_particle_sets:
954 step.use_vertex(tracer_set)
955
956 @property
957 def subdirectory(self):
958 return self._subdirectory
959
960 @property
962 return self._additional_includes
Wrapper around C++ enumerations which is not a datatype supported natively by MPI.
Definition Enumeration.py:6
ExaHyPE 2 project.
Definition Project.py:14
set_restart_from_checkpoint(self, expected_restart_timestamp=0, checkpoint_path="./")
set checkpointing.
Definition Project.py:463
__generate_solver_repository(self)
I have to call finishedTraversal() for each tracer set.
Definition Project.py:547
init_new_user_defined_algorithmic_step(self, step)
Inform ExaHyPE 2 that there is an additional solver step not resulting from vanilla solver versions.
Definition Project.py:929
add_action_set_to_timestepping(self, action_set)
Add a new action set to the time stepping.
Definition Project.py:786
set_load_balancing(self, load_balancer_name, load_balancer_arguments="")
Set load balancing scheme.
Definition Project.py:84
set_number_of_threads(self, value)
Set number of threads to use.
Definition Project.py:135
set_Peano4_installation(self, src_path, mode=peano4.output.CompileMode.Release)
src_path: string Path (relative or absolute) to the src directory of Peano.
Definition Project.py:211
add_solver(self, solver)
Definition Project.py:223
set_output_path(self, path)
Definition Project.py:500
add_plot_filter(self, offset, size, frequency=1)
Add a new filter to Peano/ExaHyPE.
Definition Project.py:226
generate_Peano4_project(self, verbose=False)
Construct a Peano 4 project and return it.
Definition Project.py:835
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.
Definition Project.py:587
__init__(self, namespace, project_name, executable, directory=".", subdirectory="", abstract_overwrite=True)
Definition Project.py:34
set_timeout(self, value)
Set timeout value has to be a number greater or equal to zero, this then sets the timeout in seconds ...
Definition Project.py:181
add_action_set_to_plot_solution(self, action_set)
Add a new action set to the plotting.
Definition Project.py:799
__set_solver_repository_dict(self)
Definition Project.py:532
set_multicore_orchestration(self, value)
Set orchestration.
Definition Project.py:151
add_action_set_to_create_grid(self, action_set)
Add an action set to create grid.
Definition Project.py:818
add_mainfile_include(self, value)
Add a new include file to the main file (but also to the solver repository)
Definition Project.py:510
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
Definition Project.py:404
set_log_filter_file(self, file_name)
Set a log filter file name.
Definition Project.py:119
__export_constants(self)
We export ExaHyPE's constants.
Definition Project.py:259
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...
Definition Project.py:194
add_action_set_to_checkpoint_solution(self, action_set)
Add a new action set to the checkpointing.
Definition Project.py:807
add_action_set_to_initialisation(self, action_set)
Definition Project.py:815
Represents a Peano 4 project.
Definition Project.py:16
Specialisation of array using Peano's tarch.
Update the parallel state of particles and keep stats of them.