Peano
Loading...
Searching...
No Matches
ADERDG.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 os
4from enum import IntEnum
5from abc import abstractmethod
6
7import jinja2
8
9import peano4.output
10import peano4.datamodel
12
13import exahype2.grid
16
17from exahype2.solvers.PDETerms import PDETerms
18from exahype2.solvers.aderdg.Architectures import Architectures
19from exahype2.solvers.aderdg.LagrangeBasis import GaussLegendreBasis, GaussLobattoBasis
20
21from exahype2.solvers.Storage import Storage
22
23"""
24Used to have a central way for all of this class' descendants to differentiate between Gauss-Legendre
25and Gauss-Lobatto nodes, helps to avoid having to constantly pass a string and ensure that this string is
26the same everywhere.
27"""
28class Polynomials(IntEnum):
29 Gauss_Legendre = 0,
30 Gauss_Lobatto = 1
31
32"""
33Denotes valid precisions for kernels and storage but also is supposed to allow a little more flexibility
34in the naming. If a user wants to name it float because they're more used to C-based languages that's
35fine but if they'd rather use single we allow it as well.
36"""
37PrecisionType = {
38 "SP": "float",
39 "float": "float",
40 "single": "float",
41 "fp32": "float",
42 "DP": "double",
43 "double": "double",
44 "fp64": "double",
45 "quadruple": "long double",
46 "long double": "long double",
47 "fp128": "long double",
48 "float16_t": "std::float16_t",
49 "std::float16_t": "std::float16_t",
50 "_Float16": "_Float16",
51 "fp16": "_Float16",
52 "bfloat16_t": "std::bfloat16_t",
53 "std::bfloat16_t": "std::bfloat16_t",
54 "__bf16": "__bf16",
55 "bfloat": "__bf16",
56 "bf16": "__bf16"
57}
58
59class ADERDG(object):
61 self,
62 name,
63 order,
64 unknowns,
65 auxiliary_variables,
66 min_cell_h,
67 max_cell_h,
68 plot_grid_properties=False,
69 ):
70 self._name = name
71
72 """
73 Polynomial order of the representation of the underlying function in each spatial dimension.
74 The number of support points used to represent this polynomial is always the order + 1
75 """
76 self._order = order
77
78 """
79 self._unknowns and self._auxiliary_variables respectively hold the number of unknowns and
80 auxiliary variables in the equation to be computed. Unknowns are variables that change over
81 time whereas auxiliary variables can be space-dependent but don't vary over time.
82 These can be specified either as simple ints or by a dictionary
83 (e.g.) unknowns = {'a': 1, 'b': 1, 'c': 3}
84 in which the user specifies the multiplicity of the variable (the velocity has one component
85 per dimension for example.)
86 If they are specified by a dictionary then the code generates a "VariableShortcuts" file which
87 allows the user to specify a variable by name and automatically maps this to the right position
88 in an array for better legibility. Otherwise they must manually remember the position of each
89 variable manually.
90
91 use_var_shortcut is used to know whether or not the user passed their variables via a dict
92 variable_names and variable_pos are used internally to remember the names and respective
93 positions of variables if set by a dictionary.
94 """
95 self._use_var_shortcut = False
97 self._variable_pos = [0]
98
99 if type(unknowns) is dict:
100 self._unknowns = sum(unknowns.values())
101 self._variable_names += list(unknowns.keys())
102 for var in list(unknowns.values()):
103 self._variable_pos.append(var + self._variable_pos[-1])
104 self._use_var_shortcut = True
105 elif type(unknowns) is int:
106 self._unknowns = unknowns
107 else:
108 raise Exception(
109 "not a valid type for parameter unknowns, needs to be int or dictionary."
110 )
111
112 if type(auxiliary_variables) is dict:
113 self._auxiliary_variables = sum(auxiliary_variables.values())
114 self._variable_names += list(auxiliary_variables.keys())
115 for var in list(auxiliary_variables.values()):
116 self._variable_pos.append(var + self._variable_pos[-1])
117 self._use_var_shortcut = True
118 elif type(auxiliary_variables) is int:
119 self._auxiliary_variables = auxiliary_variables
120 else:
121 raise Exception(
122 "not a valid type for parameter auxiliary_variables, needs to be int or dictionary."
123 )
124
125 """
126 Minimal and maximal accepted sizes for the cell, domain will be subdivided until the cell size is smaller
127 than the minimal size but will never be subdivided to be smaller than the minimal size.
128 """
129 self._min_cell_h = min_cell_h
130 self._max_cell_h = max_cell_h
131 if min_cell_h > max_cell_h:
132 raise Exception(
133 "min_cell_h ("
134 + str(min_cell_h)
135 + ") is bigger than max_cell_h ("
136 + str(max_cell_h)
137 + ")"
138 )
139
140 self._is_linear = False
141 self._polynomials = Polynomials.Gauss_Legendre
142 self._basis = GaussLegendreBasis(order + 1)
143 self._architecture = "noarch"
144 self._use_libxsmm = False
145
147
148 self._predictor_computation_precisions = [PrecisionType["double"]]
149 self._corrector_computation_precision = PrecisionType["double"]
150 self._solution_persistent_storage_precision = PrecisionType["double"]
153
154 # Whether or not to plot information about the grid as well as information about the content of the patches
155 self._plot_grid_properties = plot_grid_properties
157
160
161 # Used by children classes or setters in order to add constants or includes to the corresponding part
165
166 """
167 These specify the time step, they must be set by child classes in order to advance the timestepping.
168 These are the main difference between child classes as they all use the same underlying routines.
169 """
170 self._compute_time_step_size = "#error Not yet defined"
171 self._compute_new_time_step_size = "#error Not yet defined"
172
173 """
174 These are all the optional and mandatory plugins that can be specified by the user.
175 eigenvalues, boundary conditions, refinement criteria and initial conditions must
176 all be specified, all others are optional but can be added via the set_implementation() function.
177 There are four choices for these, three of which are specified in PDETerms:
178 User_Defined_Implementation creates empty stubs that the user must then manually fill.
179 None_implementation leaves out this optional stub and ensures the kernels don't use this function.
180 Empty_implementation does... the same thing as user_defined I think?
181 The final option is to fill these with a string, in which case this string is directly taken as
182 C++ code and used as the implementation of this function. The user is trusted to provide code that
183 compiles and runs properly, it is never checked.
184 """
185 self._flux_implementation = PDETerms.None_Implementation
186 self._ncp_implementation = PDETerms.None_Implementation
187 self._source_term_implementation = PDETerms.None_Implementation
188 self._point_sources_implementation = PDETerms.None_Implementation
189 self._eigenvalues_implementation = PDETerms.None_Implementation
190 self._material_param_implementation = PDETerms.None_Implementation
191
192 self._refinement_criterion_implementation = PDETerms.None_Implementation
193 self._initial_conditions_implementation = PDETerms.None_Implementation
194 self._boundary_conditions_implementation = PDETerms.None_Implementation
195
196 self._precision_criterion_implementation = PDETerms.None_Implementation
197 self._riemann_solver_implementation = PDETerms.None_Implementation
199
200 """
201 These will be used by children of this class to fill them with the declaration and definition of the
202 above mandatory and optional functions.
203 """
208
209 """
210 Used by child classes; will contain code to be executed at the start and end respectively of the
211 time step. Typically specifies some timestep variable and advances the overall timestamp of the
212 entire solver.
213 """
216
219
220 """
221 These are ADER-DG CFL factors, they help determine the maximal stable timestep size.
222 Up to order 4, computed via von Neumann analysis [1].
223 [1] M. Dumbser, D. S. Balsara, E. F. Toro, and C.-D. Munz,
224 ‘A unified framework for the construction of one-step finite volume and discontinuous Galerkin schemes on unstructured meshes’, Journal of Computational Physics, vol. 227, no. 18, pp. 8209–8253, Sep. 2008.
225 They are necessary to compute stable timestep sizes as dt <= c*dx / (lambda_max*(2N+1)
226 with c the CFL for given order, lambda_max the maximal eigenvalue, N the order and dx the minimal mesh distance.
227 """
228 self._cflAder = [
229 1.0,
230 0.33,
231 0.17,
232 0.1,
233 0.069,
234 0.045,
235 0.038,
236 0.03,
237 0.02,
238 0.015,
239 0.008821428571428572,
240 0.005235326086956522,
241 0.0031307249999999996,
242 0.0018842326388888888,
243 0.001140285614224138,
244 0.0006933672202620968,
245 ]
246
247 # Safety factor for CFL (Courant-Friedrichs-Lewy) condition
249
250 """
251 Used if the user wants to add some function to postprocessing, meaning
252 it should be added after every other computation in ADER-DG is done.
253 """
255
258
259 self.switch_storage_scheme(Storage.Heap, Storage.Heap)
260
261 # Create initial structures and action_sets, these are re-generated essentially anytime something about the solver is modified.
263 self.create_action_sets()
264
265 def __str__(self):
266 result = (
267 """
268Name: """
269 + self._name
270 + """
271Type: """
272 + self.__class__.__module__
273 + """
274Storage schemes: """
275 + str(self._cell_data_storage) + ", " + str(self._face_data_storage)
276 + """
277DG order: """
278 + str(self._order)
279 + """
280Polynomials: """
281 + str(self._polynomials.name)
282 + """
283Basis: """
284 + str(self._basis)
285 + """
286Basis size: """
287 + str(self._order + 1)
288 + """
289Linear: """
290 + str(self._is_linear)
291 + """
292Unknowns: """
293 + str(self._unknowns)
294 + """
295Auxiliary variables: """
296 + str(self._auxiliary_variables)
297 + """
298h_cell_min: """
299 + str(self._min_cell_h)
300 + """
301h_cell_max: """
302 + str(self._max_cell_h)
303 + """
304Initial conditions: """
306 + """
307Boundary conditions: """
309 + """
310Refinement criterion: """
312 + """
313Eigenvalues: """
315 + """
316Flux: """
317 + str(self._flux_implementation)
318 + """
319NCP: """
320 + str(self._ncp_implementation)
321 + """
322Source term: """
324 + """
325Point sources: """
327 + """
328Number of point sources:"""
329 + str(self._number_of_point_sources)
330 + """
331Riemann solver: """
333 + """
334Material parameters: """
336 + """
337"""
338 )
339 return result
340
341 __repr__ = __str__
342
343 """
344 Creates all the structures that are attached on the Peano grid either in a cell or on the faces.
345 These are defined as Peano patches which have given sizes to contain persistent data as well as
346 conditions for when they should be merged, sent, received, stored, loaded, etc.
347 """
348 @abstractmethod
351
352 # Current time step contains the solution, projections are respectively the projection
353 # of the solution and of the fluxes on the faces as predicted by the space-time predictor.
355 (self._order + 1, self._order + 1, self._order + 1),
357 self._unknown_identifier(),
359 )
361 (self._order + 1, self._order + 1, self._order + 1),
363 self._unknown_identifier() + "_old",
365 )
367 (2, self._order+1, self._order+1),
369 self._unknown_identifier() + "Estimates",
371 )
373 (2, self._order+1, self._order+1),
374 self._unknowns,
375 self._unknown_identifier() + "FluxEstimates",
377 )
378
379 if self._cell_data_storage == Storage.CallStack:
383 )
387 )
388 elif self._cell_data_storage == Storage.Heap:
392 )
396 )
397 elif self._cell_data_storage == Storage.SmartPointers:
401 )
405 )
406 else:
407 assert False, "Storage variant {} not supported".format(
409 )
410
411 if self._face_data_storage == Storage.CallStack:
415 )
419 )
420 elif self._face_data_storage == Storage.Heap:
424 )
428 )
429 elif self._face_data_storage == Storage.SmartPointers:
433 )
437 )
438 else:
439 assert False, "Storage variant {} not supported".format(
441 )
442
443 # Custom merge implementation takes into account that the faces project such that
444 # the left cell projects to the left half of the face and the right cell projects to the right half.
445 self._rhs_estimates_projection.generator.merge_method_definition = (
446 get_face_overlap_merge_implementation(self._rhs_estimates_projection)
447 )
448 self._rhs_estimates_projection.generator.includes += """
449#include "peano4/utils/Loop.h"
450#include "repositories/SolverRepository.h"
451"""
452
453 self._flux_estimates_projection.generator.merge_method_definition = (
454 get_face_overlap_merge_implementation(self._flux_estimates_projection)
455 )
456 self._flux_estimates_projection.generator.includes += """
457#include "peano4/utils/Loop.h"
458#include "repositories/SolverRepository.h"
459"""
460
461 self._current_time_step.generator.load_store_compute_flag = "::peano4::grid::constructLoadStoreComputeFlag({},{},{})".format(
465 )
466
467 self._previous_time_step.generator.load_store_compute_flag = "::peano4::grid::constructLoadStoreComputeFlag({},{},{})".format(
471 )
472
473 self._rhs_estimates_projection.generator.load_store_compute_flag = "::peano4::grid::constructLoadStoreComputeFlag({},{},{})".format(
477 )
478
479 # Gets overwritten in subclasses to take into account when to send or receive faces
480 self._rhs_estimates_projection.generator.send_condition = "false"
481 self._rhs_estimates_projection.generator.receive_and_merge_condition = "false"
482
483 self._flux_estimates_projection.generator.load_store_compute_flag = "::peano4::grid::constructLoadStoreComputeFlag({},{},{})".format(
487 )
488
489 self._flux_estimates_projection.generator.send_condition = "false"
490 self._flux_estimates_projection.generator.receive_and_merge_condition = "false"
491
492 self._current_time_step.generator.includes += """
493#include "../repositories/SolverRepository.h"
494"""
495
496 self._previous_time_step.generator.includes += """
497#include "../repositories/SolverRepository.h"
498"""
499
500 self._rhs_estimates_projection.generator.includes += """
501#include "../repositories/SolverRepository.h"
502"""
503
504 self._flux_estimates_projection.generator.includes += """
505#include "../repositories/SolverRepository.h"
506"""
507
508 self._cell_label = exahype2.grid.create_cell_label(self._name)
509 self._face_label = exahype2.grid.create_face_label(self._name)
510
511 """
512 Creates the action sets, these are actions tied to the grid that are executed at given points of
513 grid generation, construction or steps of the ADER-DG solver. Peano handles grid structures that
514 contain data as well as operations that are executed on that data. These are the latter.
515 The guard here are the conditions for the execution of the operation, as in they are only executed
516 if the guard evaluates to true.
517 """
518 @abstractmethod
520 # Updates faces and cells (whether at boundary, refined etc.)
523 self._action_set_update_face_label.descend_invocation_order = 0
524 self._action_set_update_cell_label.descend_invocation_order = 0
525
526 # Sets initial conditions for the solution
528 self, self._store_cell_data_default_guard(), "true"
529 )
530 self._action_set_initial_conditions.descend_invocation_order = 1
531
533 self, self._store_cell_data_default_guard(), "false"
534 )
535 self._action_set_initial_conditions_for_grid_construction.descend_invocation_order = 1
536
539 )
540 self._action_set_handle_boundary.descend_invocation_order = 1
541
543 solver=self,
544 delete_guard=self._delete_face_data_default_guard(),
545 interpolate_guard=self._interpolate_face_data_default_guard(),
546 restrict_guard=self._restrict_face_data_default_guard(),
547 )
549
550 # All the actual computation of the solution happens in the prediction and correction action sets.
551 # Predictor extrapolates the solution from time t onto time-nodes, then projects this
552 # extrapolated solution to the faces.
553 # Correction uses the extrapolated face solutions from the predictor and the neighboring
554 # cells to compute a solution at the next timestep.
557 self._action_set_correction.descend_invocation_order = 2 # Needs to happen after handle_boundary
558
560 self, self._store_cell_data_default_guard(), on_hanging_cells=False)
561 self._action_set_prediction.descend_invocation_order = 3
562
564 self, self._store_cell_data_default_guard(), on_hanging_cells=True)
565 self._action_set_prediction_on_hanging_cells.descend_invocation_order = 3
566
567 # Handles adaptive mesh refinement
569 solver=self,
571 + " and (repositories::"
573 + ".isFirstGridSweepOfTimeStep() or repositories::"
575 + ".getSolverState()=="
576 + self._name
577 + "::SolverState::GridInitialisation)",
578 build_up_new_refinement_instructions=True,
579 called_by_grid_construction=False,
580 implement_previous_refinement_instructions=True
581 )
582 self._action_set_AMR.descend_invocation_order = 4
583
585 solver=self,
587 build_up_new_refinement_instructions=False,
588 implement_previous_refinement_instructions=True,
589 called_by_grid_construction=False,
590 )
591 self._action_set_AMR_commit_without_further_analysis.descend_invocation_order = 4
592
594 solver=self,
596 build_up_new_refinement_instructions=True,
597 implement_previous_refinement_instructions=True,
598 called_by_grid_construction=True,
599 )
600 self._action_set_AMR_throughout_grid_construction.descend_invocation_order = 4
601
602 if self._action_set_postprocess_solution == None:
604 self._action_set_postprocess_solution.descend_invocation_order = 4
605
606 def create_readme_descriptor(self, domain_offset, domain_size):
607 return (
608 """ ExaHyPE 2 ADER-DG solver of order: """
609 + str(self._order)
610 + """ with a domain size of: """
611 + str(domain_size)
612 + """ and a domain offset of: """
613 + str(domain_offset)
614 )
615
620 return self.user_solver_includes
621
623 """
624 Add further includes to this property, if your action sets require some additional
625 routines from other header files.
626 """
627 self.user_action_set_includes += value
628
629 def add_user_solver_includes(self, value):
630 """
631 Add further includes to this property, if your solver requires some additional
632 routines from other header files.
633 """
634 self.user_solver_includes += value
635
637 return (
638 "not marker.willBeRefined() "
639 + "and repositories::"
641 + ".getSolverState()!="
642 + self._name
643 + "::SolverState::GridConstruction"
644 )
645
647 return (
648 "not marker.willBeRefined() "
649 + "and repositories::"
651 + ".getSolverState()!="
652 + self._name
653 + "::SolverState::GridConstruction"
654 )
655
657 return (
658 "not marker.willBeRefined() "
659 + "and repositories::"
661 + ".getSolverState()!="
662 + self._name
663 + "::SolverState::GridConstruction"
664 )
665
667 return (
668 "not marker.hasBeenRefined() "
669 + "and repositories::"
671 + ".getSolverState()!="
672 + self._name
673 + "::SolverState::GridConstruction "
674 + "and repositories::"
676 + ".getSolverState()!="
677 + self._name
678 + "::SolverState::GridInitialisation"
679 )
680
682 return (
683 "not marker.willBeRefined() "
684 + "and repositories::"
686 + ".getSolverState()!="
687 + self._name
688 + "::SolverState::GridConstruction"
689 )
690
692 return (
693 "not marker.hasBeenRefined() "
694 + "and repositories::"
696 + ".getSolverState()!="
697 + self._name
698 + "::SolverState::GridConstruction "
699 + "and repositories::"
701 + ".getSolverState()!="
702 + self._name
703 + "::SolverState::GridInitialisation"
704 )
705
707 return (
709 + " and not repositories::"
711 + ".PeriodicBC[marker.getSelectedFaceNumber()%Dimensions]"
712 + " and not marker.hasBeenRefined() and fineGridFace"
713 + self._name
714 + "FaceLabel.getBoundary()"
715 )
716
718 return "true"
719
721 return (
722 "repositories::"
724 + ".getSolverState()!="
725 + self._name
726 + "::SolverState::GridInitialisation"
727 )
728
730 return "true"
731
733 return self._name + "Q"
734
736 return "instanceOf" + self._name
737
739 return """
740#include "tarch/la/Vector.h"
741
742#include "peano4/utils/Globals.h"
743#include "peano4/utils/Loop.h"
744
745#include "repositories/SolverRepository.h"
746""" + "#include <stdfloat>" if self._use_half_precision else ""
747
748 """
749 The following functions will be called by the Peano 4 project,
750 they tell Peano which of our generated data it should attach
751 to each grid element and use.
752 """
753 def add_to_Peano4_datamodel(self, datamodel, verbose):
754 if verbose:
755 print("Patch data")
756 print("----------")
757 print(str(self._current_time_step))
758 print("Patch overlap data")
759 print("----------")
760 print(str(self._rhs_estimates_projection))
761 print(str(self._flux_estimates_projection))
762 datamodel.add_cell(self._cell_label)
763 datamodel.add_cell(self._current_time_step)
764 datamodel.add_cell(self._previous_time_step)
765 datamodel.add_face(self._face_label)
766 datamodel.add_face(self._rhs_estimates_projection)
767 datamodel.add_face(self._flux_estimates_projection)
768
770 step.use_cell(self._cell_label)
771 step.use_cell(self._current_time_step)
772 step.use_cell(self._previous_time_step)
773 step.use_face(self._face_label)
774 step.use_face(self._rhs_estimates_projection)
775 step.use_face(self._flux_estimates_projection)
776
778 step.add_action_set(self._action_set_initial_conditions)
779 step.add_action_set(self._action_set_update_face_label)
780 step.add_action_set(self._action_set_update_cell_label)
781 step.add_action_set(self._action_set_AMR)
782 step.add_action_set(self._action_set_postprocess_solution)
783
784 def add_actions_to_create_grid(self, step, evaluate_refinement_criterion):
786 step.add_action_set(self._action_set_update_face_label)
787 step.add_action_set(self._action_set_update_cell_label)
788 if evaluate_refinement_criterion:
789 step.add_action_set(self._action_set_AMR_throughout_grid_construction)
790 else:
792
793 def add_actions_to_plot_solution(self, step, output_path):
794 d = {}
797
798 step.add_action_set(self._action_set_update_face_label)
799 step.add_action_set(self._action_set_update_cell_label)
800
801 mapping = []
802 for z in self._basis.quadrature_points():
803 for y in self._basis.quadrature_points():
804 for x in self._basis.quadrature_points():
805 mapping.append((x, y, z))
806
807 # Calls a generator which generates a standard plotter that uses the tarch library.
808 step.add_action_set(
810 filename=output_path + "solution-" + self._name,
811 patch=self._previous_time_step,
812 dataset_name=self._unknown_identifier()+"_old",
813 description=self.plot_description,
814 mapping=mapping,
815 select_dofs=self.select_dofs_to_print,
816 guard="repositories::plotFilter.plotPatch(marker) and "
818 additional_includes="""
819#include "exahype2/PlotFilter.h"
820#include "../repositories/SolverRepository.h"
821""",
822 precision="PlotterPrecision",
823 time_stamp_evaluation="0.5*(repositories::getMinTimeStamp()+repositories::getMaxTimeStamp())",
824 plot_cell_data=False,
826 )
827 )
828
830
831 if self._plot_grid_properties:
832 step.add_action_set(
834 filename=output_path + "grid-" + self._name,
835 cell_unknown=None,
836 guard_guard="repositories::plotFilter.plotPatch(marker) and "
838 additional_includes="""
839#include "exahype2/PlotFilter.h"
840#include "../repositories/SolverRepository.h"
841""",
842 plot_cell_data=False,
843 )
844 )
845 pass
846
847 # These actions are executed during each time step
849 step.add_action_set(self._action_set_update_face_label)
850 step.add_action_set(self._action_set_update_cell_label)
852
853 step.add_action_set(self._action_set_handle_boundary)
854 step.add_action_set(self._action_set_correction)
855 step.add_action_set(self._action_set_prediction)
856 step.add_action_set(self._action_set_prediction_on_hanging_cells)
857
858 step.add_action_set(self._action_set_AMR)
859 step.add_action_set(self._action_set_postprocess_solution)
860
861 def set_plot_description(self, description):
862 self.plot_description = description
863
864 def _generate_kernels(self, namespace, output, subdirectory, dimensions):
865 if (not self._is_linear) and (
866 self._material_param_implementation != PDETerms.None_Implementation
867 or self._point_sources_implementation != PDETerms.None_Implementation
868 ):
869 raise Exception(
870 "Material parameters and point sources are currently only available for linear generated kernels."
871 )
872
873 d = {}
876 d["DIMENSIONS"] = dimensions
877 d["NUMBER_OF_DOF_3D"] = 1 if dimensions == 2 else d["NUMBER_OF_DOF"]
878 d["FULL_QUALIFIED_SOLVER_NAME"] = "::".join(namespace) + "::" + self._name
879
880 kernels_namespace = namespace + ["kernels", self._name]
881 kernels_output_path = subdirectory + "kernels/" + self._name
882 kernels_templates_prefix = os.path.dirname(os.path.realpath(__file__)) + "/kernels/"
883
884 if not os.path.exists(kernels_output_path):
885 os.makedirs(kernels_output_path)
886
887 generated_kernels = (
889 headfile_template=kernels_templates_prefix + "CellErrorIntegral.template.h",
890 cppfile_template=kernels_templates_prefix + "CellErrorIntegral.template.cpp",
891 classname=kernels_output_path + "/CellErrorIntegral",
892 namespace=kernels_namespace,
893 subdirectory=subdirectory + ".",
894 dictionary=d,
895 default_overwrite=True,
896 apply_iteratively=True,
897 )
898 )
899 output.add(generated_kernels)
900 output.makefile.add_h_file(kernels_output_path + "/CellErrorIntegral.h", generated=True)
901 output.makefile.add_cpp_file(kernels_output_path + "/CellErrorIntegral.cpp", generated=True)
902
903 generated_kernels = (
905 headfile_template=kernels_templates_prefix + "MaxScaledEigenvalue.template.h",
906 cppfile_template=kernels_templates_prefix + "MaxScaledEigenvalue.template.cpp",
907 classname=kernels_output_path + "/MaxScaledEigenvalue",
908 namespace=kernels_namespace,
909 subdirectory=subdirectory + ".",
910 dictionary=d,
911 default_overwrite=True,
912 apply_iteratively=True,
913 )
914 )
915 output.add(generated_kernels)
916 output.makefile.add_h_file(kernels_output_path + "/MaxScaledEigenvalue.h", generated=True)
917 output.makefile.add_cpp_file(kernels_output_path + "/MaxScaledEigenvalue.cpp", generated=True)
918
919 generated_kernels = (
921 headfile_template=kernels_templates_prefix + "FaceIntegral.template.h",
922 cppfile_template=kernels_templates_prefix + "FaceIntegral.template.cpp",
923 classname=kernels_output_path + "/FaceIntegral",
924 namespace=kernels_namespace,
925 subdirectory=subdirectory + ".",
926 dictionary=d,
927 default_overwrite=True,
928 apply_iteratively=True,
929 )
930 )
931 output.add(generated_kernels)
932 output.makefile.add_h_file(kernels_output_path + "/FaceIntegral.h", generated=True)
933 output.makefile.add_cpp_file(kernels_output_path + "/FaceIntegral.cpp", generated=True)
934
935 generated_kernels = (
937 headfile_template=kernels_templates_prefix + "RiemannSolver.template.h",
938 cppfile_template=kernels_templates_prefix + "RiemannSolverLinear.template.cpp" if self._is_linear
939 else kernels_templates_prefix + "RiemannSolverNonlinear.template.cpp",
940 classname=kernels_output_path + "/RiemannSolver",
941 namespace=kernels_namespace,
942 subdirectory=subdirectory + ".",
943 dictionary=d,
944 default_overwrite=True,
945 apply_iteratively=True,
946 )
947 )
948 output.add(generated_kernels)
949 output.makefile.add_h_file(kernels_output_path + "/RiemannSolver.h", generated=True)
950 output.makefile.add_cpp_file(kernels_output_path + "/RiemannSolver.cpp", generated=True)
951
953 kernels_namespace, output, subdirectory, kernels_templates_prefix, kernels_output_path
954 )
956 kernels_namespace, output, subdirectory, kernels_templates_prefix, kernels_output_path
957 )
959 kernels_namespace, output, subdirectory, kernels_templates_prefix, kernels_output_path
960 )
962 kernels_namespace, output, subdirectory, kernels_templates_prefix, kernels_output_path
963 )
965 kernels_namespace, output, subdirectory, kernels_templates_prefix, kernels_output_path
966 )
967
968 if self._point_sources_implementation != PDETerms.None_Implementation:
969 generated_kernels = (
971 headfile_template=kernels_templates_prefix + "PointSources.template.h",
972 cppfile_template=kernels_templates_prefix + "PointSources.template.cpp",
973 classname=kernels_output_path + "/PointSources",
974 namespace=kernels_namespace,
975 subdirectory=subdirectory + ".",
976 dictionary=d,
977 default_overwrite=True,
978 apply_iteratively=True,
979 )
980 )
981 output.add(generated_kernels)
982 output.makefile.add_h_file(kernels_output_path + "/PointSources.h", generated=True)
983 output.makefile.add_cpp_file(kernels_output_path + "/PointSources.cpp", generated=True)
984
985 if self._use_libxsmm:
986 generated_kernels = (
988 headfile_template=kernels_templates_prefix + "Gemms.template.h",
989 cppfile_template=kernels_templates_prefix + "Gemms.template.cpp",
990 classname=kernels_output_path + "/Gemms",
991 namespace=kernels_namespace,
992 subdirectory=subdirectory + ".",
993 dictionary=d,
994 default_overwrite=True,
995 apply_iteratively=True,
996 )
997 )
998 output.add(generated_kernels)
999 output.makefile.add_h_file(kernels_output_path + "/Gemms.h", generated=True)
1000 output.makefile.add_cpp_file(kernels_output_path + "/Gemms.cpp", generated=True)
1001
1002 """"
1003 This is a very ugly fix that should be replaced asap.
1004 Essentially, the libxsmm kernel generator generates faulty code if
1005 'noarch' is specified. This code works fine except that it contains a
1006 #ifdef which is missing its corresponding #endif.
1007 This code just inserts that missing #endif.
1008 """
1009 if self._use_libxsmm and self._architecture == "noarch":
1010 file = open("kernels/" + self._name + "/FusedSpaceTimePredictorVolumeIntegral_libxsmm.c", "r")
1011 content = file.read()
1012 file.close()
1013 file = open("kernels/" + self._name + "/FusedSpaceTimePredictorVolumeIntegral_libxsmm.c", "w")
1014 content = content.replace("__FILE__)\n", "__FILE__)\n#endif\n")
1015 file.write(content)
1016 file.close()
1017
1018 file = open("kernels/" + self._name + "/AMRRoutines_libxsmm.c", "r")
1019 content = file.read()
1020 file.close()
1021 file = open("kernels/" + self._name + "/AMRRoutines_libxsmm.c", "w")
1022 content = content.replace("__FILE__)\n", "__FILE__)\n#endif\n")
1023 file.write(content)
1024 file.close()
1025
1026 """
1027 This tells Peano to add the solver files to the project. It generates any files that are not
1028 specifically cell or face data or grid actions such as the actionsets.
1029 Currently it generates solver implementation and header files as well as abstract solver
1030 implementation and header files.
1031 In addition to this if the user has specified that they would like to use shortcuts to refer
1032 to their variable (e.g., specified their unknowns or aux. variables through a dict) it generates
1033 a VariableShortcuts file which is then connected to the solver so that users can specify their
1034 variables through name.
1035 """
1036 def add_implementation_files_to_project(self, namespace, output, dimensions, subdirectory=""):
1037 """
1038 The ExaHyPE2 project will call this operation when it sets
1039 up the overall environment.
1040
1041 This routine is typically not invoked by a user.
1042
1043 output: peano4.output.Output
1044 """
1045 templatefile_prefix = os.path.dirname(os.path.realpath(__file__)) + "/"
1046
1047 if self._solver_template_file_class_name is None:
1048 templatefile_prefix += self.__class__.__name__
1049 else:
1050 templatefile_prefix += self._solver_template_file_class_name
1051
1052 if subdirectory:
1053 subdirectory += "/"
1054
1055 abstractHeaderDictionary = {}
1056 implementationDictionary = {}
1057 self._init_dictionary_with_default_parameters(abstractHeaderDictionary)
1058 self._init_dictionary_with_default_parameters(implementationDictionary)
1059 self.add_entries_to_text_replacement_dictionary(abstractHeaderDictionary)
1060 self.add_entries_to_text_replacement_dictionary(implementationDictionary)
1061
1062 generated_abstract_header_file = (
1064 templatefile_prefix + "Abstract.template.h",
1065 templatefile_prefix + "Abstract.template.cpp",
1066 "Abstract" + self._name,
1067 namespace,
1068 subdirectory + ".",
1069 abstractHeaderDictionary,
1070 True,
1071 True,
1072 )
1073 )
1074 generated_solver_files = (
1076 templatefile_prefix + ".template.h",
1077 templatefile_prefix + ".template.cpp",
1078 self._name,
1079 namespace,
1080 subdirectory + ".",
1081 implementationDictionary,
1082 False,
1083 True,
1084 )
1085 )
1086
1087 output.add(generated_abstract_header_file)
1088 output.add(generated_solver_files)
1089 output.makefile.add_h_file(subdirectory + "Abstract" + self._name + ".h", generated=True)
1090 output.makefile.add_h_file(subdirectory + self._name + ".h", generated=True)
1091 output.makefile.add_cpp_file(subdirectory + "Abstract" + self._name + ".cpp", generated=True)
1092 output.makefile.add_cpp_file(subdirectory + self._name + ".cpp", generated=True)
1093
1094 if self._use_var_shortcut:
1095 generated_shortcut_file = peano4.output.Jinja2TemplatedHeaderFile(
1096 os.path.dirname(os.path.realpath(__file__))
1097 + "/"
1098 + "../VariableShortcuts.template.h",
1099 "VariableShortcuts",
1100 namespace,
1101 subdirectory + ".",
1102 implementationDictionary,
1103 True,
1104 True,
1105 )
1106 output.add(generated_shortcut_file)
1107 output.makefile.add_h_file(subdirectory + "VariableShortcuts.h", generated=True)
1108
1109 self._generate_kernels(namespace, output, subdirectory, dimensions)
1110
1111 def set_solver_constants(self, datastring):
1112 self._solver_constants = datastring
1113
1114 def add_solver_constants(self, datastring):
1115 self._solver_constants += datastring
1116
1117 @property
1118 def order(self):
1119 return self._order
1120
1121 @property
1122 def unknowns(self):
1123 return self._unknowns
1124
1125 @property
1127 return self._auxiliary_variables
1128
1129 @property
1133 @preprocess_reconstructed_patch.setter
1137 self.create_action_sets()
1138
1139 @property
1143 @postprocess_updated_patch.setter
1144 def postprocess_updated_patch(self, kernel):
1145 self._postprocess_updated_patch = kernel
1147 self.create_action_sets()
1148
1149 @abstractmethod
1153 """
1154 Generates a dictionary of "words" that will later be used in various templates to fill these out by adding
1155 information from the solver or which was specified by the user.
1156 """
1158 d["SOLVER_INSTANCE"] = self.get_name_of_global_instance()
1159 d["SOLVER_NAME"] = self._name
1160 d["UNKNOWN_IDENTIFIER"] = self._unknown_identifier()
1161
1162 d["ALIGNMENT"] = Architectures.get_alignment(self._architecture)
1163 d["SIMD_WIDTH"] = Architectures.get_simd_width(self._architecture)
1164 d["ORDER"] = self._order
1165 d["NUMBER_OF_DOF"] = self._order + 1
1166 d["NUMBER_OF_DOF_PADDED"] = Architectures.get_size_with_padding(self._architecture, self._order + 1)
1167 d["NUMBER_OF_UNKNOWNS"] = self._unknowns
1168 d["NUMBER_OF_UNKNOWNS_PADDED"] = Architectures.get_size_with_padding(self._architecture, self._unknowns)
1169 d["NUMBER_OF_AUXILIARY_VARIABLES"] = self._auxiliary_variables
1170 d["NUMBER_OF_AUXILIARY_VARIABLES_PADDED"] = Architectures.get_size_with_padding(self._architecture, self._auxiliary_variables)
1171 d["NUMBER_OF_DATA"] = self._unknowns + self._auxiliary_variables
1172 d["NUMBER_OF_DATA_PADDED"] = Architectures.get_size_with_padding(self._architecture, self._unknowns + self._auxiliary_variables)
1173
1174 d["CFL_SAFETY_FACTOR"] = self._cflSafetyFactor
1175 d["CFL_ADER"] = self._cflAder[self._order] # /(2*(self._order+1)+1)
1176
1177 d["USE_HALF_PRECISION"] = self._use_half_precision
1178 d["IS_LINEAR"] = self._is_linear
1179 d["LINEARITY"] = "linear" if self._is_linear else "nonlinear"
1180
1181 d["USE_GAUSS_LOBATTO"] = ( "true" if self._polynomials is Polynomials.Gauss_Lobatto else "false" )
1182 d["POLYNOMIAL_TYPE"] = ( "lobatto" if self._polynomials is Polynomials.Gauss_Lobatto else "legendre" )
1183
1184 d["SOLUTION_STORAGE_PRECISION"] = self._solution_persistent_storage_precision
1185
1186 d["PREDICTOR_COMPUTATION_PRECISIONS"] = self._predictor_computation_precisions
1187 d["CORRECTOR_COMPUTATION_PRECISION"] = self._corrector_computation_precision
1188
1189 d["COMPUTATION_PRECISIONS"] = self._predictor_computation_precisions[:]
1190 if self._corrector_computation_precision not in d["COMPUTATION_PRECISIONS"]:
1191 d["COMPUTATION_PRECISIONS"].append(self._corrector_computation_precision)
1192 if self._precompute_picard_precision!=False and self._precompute_picard_precision not in d["COMPUTATION_PRECISIONS"]:
1193 d["COMPUTATION_PRECISIONS"].append(self._precompute_picard_precision)
1194 d["NUMBER_OF_PREDICTOR_PRECISIONS"] = len(d["PREDICTOR_COMPUTATION_PRECISIONS"])
1195 d["NUMBER_OF_PRECISIONS"] = len(d["COMPUTATION_PRECISIONS"])
1196
1197 if self._min_cell_h > self._max_cell_h:
1198 raise Exception("min/max h are inconsistent")
1199 d["MAX_CELL_H"] = self._max_cell_h
1200 d["MIN_CELL_H"] = self._min_cell_h
1201
1202 d["SOLVER_CONSTANTS"] = self._solver_constants
1203 d["SOLVER_INCLUDES"] = self.get_user_solver_includes()
1204
1205 d["BOUNDARY_CONDITIONS_IMPLEMENTATION"] = self._boundary_conditions_implementation
1206 d["REFINEMENT_CRITERION_IMPLEMENTATION"] = self._refinement_criterion_implementation
1207 d["INITIAL_CONDITIONS_IMPLEMENTATION"] = self._initial_conditions_implementation
1208 d["ADAPTIVE_PRECISION_IMPLEMENTATION"] = self._precision_criterion_implementation
1209 d["RIEMANN_SOLVER_IMPLEMENTATION"] = self._riemann_solver_implementation
1210
1211 d["ABSTRACT_SOLVER_USER_DECLARATIONS"] = jinja2.Template(
1212 self._abstract_solver_user_declarations, undefined=jinja2.DebugUndefined
1213 ).render(**d)
1214 d["ABSTRACT_SOLVER_USER_DEFINITIONS"] = jinja2.Template(
1215 self._abstract_solver_user_definitions, undefined=jinja2.DebugUndefined
1216 ).render(**d)
1217 d["SOLVER_USER_DECLARATIONS"] = jinja2.Template(
1218 self._solver_user_declarations, undefined=jinja2.DebugUndefined
1219 ).render(**d)
1220 d["SOLVER_USER_DEFINITIONS"] = jinja2.Template(
1221 self._solver_user_definitions, undefined=jinja2.DebugUndefined
1222 ).render(**d)
1223
1224 d["START_TIME_STEP_IMPLEMENTATION"] = jinja2.Template(
1225 self._start_time_step_implementation, undefined=jinja2.DebugUndefined
1226 ).render(**d)
1227 d["FINISH_TIME_STEP_IMPLEMENTATION"] = jinja2.Template(
1228 self._finish_time_step_implementation, undefined=jinja2.DebugUndefined
1229 ).render(**d)
1230
1231 d["CONSTRUCTOR_IMPLEMENTATION"] = jinja2.Template(
1232 self._constructor_implementation, undefined=jinja2.DebugUndefined
1233 ).render(**d)
1234 d["DESTRUCTOR_IMPLEMENTATION"] = jinja2.Template(
1235 self._destructor_implementation, undefined=jinja2.DebugUndefined
1236 ).render(**d)
1237 d["COMPUTE_TIME_STEP_SIZE"] = jinja2.Template(
1238 self._compute_time_step_size, undefined=jinja2.DebugUndefined
1239 ).render(**d)
1240 d["COMPUTE_NEW_TIME_STEP_SIZE"] = jinja2.Template(
1241 self._compute_new_time_step_size, undefined=jinja2.DebugUndefined
1242 ).render(**d)
1243
1244 d["PREPROCESS_RECONSTRUCTED_PATCH"] = jinja2.Template(
1245 self._preprocess_reconstructed_patch, undefined=jinja2.DebugUndefined
1246 ).render(**d)
1247 d["POSTPROCESS_UPDATED_PATCH"] = jinja2.Template(
1248 self._postprocess_updated_patch, undefined=jinja2.DebugUndefined
1249 ).render(**d)
1250
1251 d["USE_FLUX"] = self._flux_implementation != PDETerms.None_Implementation
1252 d["USE_NCP"] = self._ncp_implementation != PDETerms.None_Implementation
1253 d["USE_SOURCE"] = self._source_term_implementation != PDETerms.None_Implementation
1254 d["USE_MATERIAL_PARAMETERS"] = self._material_param_implementation != PDETerms.None_Implementation
1255 d["USE_POINT_SOURCE"] = self._point_sources_implementation != PDETerms.None_Implementation
1256 d["NUMBER_OF_POINT_SOURCES"] = self._number_of_point_sources
1257
1258 d["USE_VARIABLE_SHORTCUT"] = self._use_var_shortcut
1259 d["VARIABLE_NAMES"] = self._variable_names
1260 d["VARIABLE_POSITIONS"] = self._variable_pos
1261
1262 d["QUADRATURE_POINTS"] = ", ".join(self._basis.quadrature_points())
1263
1264 d["USE_LIBXSMM"] = self._use_libxsmm
1265 d["ARCHITECTURE"] = self._architecture
1266
1267 # self._basis.init_dictionary_with_default_parameters(d)
1268
1270 self,
1271 flux,
1272 ncp,
1273 eigenvalues,
1274 boundary_conditions,
1275 refinement_criterion,
1276 initial_conditions,
1277 source_term,
1278 material_parameters,
1279 point_source,
1280 additional_action_set_includes,
1281 additional_user_includes,
1282 ):
1283 """
1284 If you pass in User_Defined, then the generator will create C++ stubs
1285 that you have to befill manually. If you pass in None_Implementation, it
1286 will create nop, i.e., no implementation or defaults. Any other string
1287 is copied 1:1 into the implementation. If you pass in None, then the
1288 set value so far won't be overwritten.
1289 """
1290 if boundary_conditions is not None:
1291 self._boundary_conditions_implementation = boundary_conditions
1292 if refinement_criterion is not None:
1293 self._refinement_criterion_implementation = refinement_criterion
1294 if initial_conditions is not None:
1295 self._initial_conditions_implementation = initial_conditions
1296
1297 if flux is not None:
1298 self._flux_implementation = flux
1299 if ncp is not None:
1300 self._ncp_implementation = ncp
1301 if eigenvalues is not None:
1302 self._eigenvalues_implementation = eigenvalues
1303 if source_term is not None:
1304 self._source_term_implementation = source_term
1305 if material_parameters is not None:
1306 self._material_param_implementation = material_parameters
1307
1308 if type(point_source) != int:
1309 raise Exception(
1310 "point_source needs to be an integer, this determines the number of point sources that will be used."
1311 )
1312
1313 if point_source > 0:
1314 self._point_sources_implementation = PDETerms.User_Defined_Implementation
1315 self._number_of_point_sources = point_source
1316
1317 self.user_action_set_includes += additional_action_set_includes
1318 self.user_solver_includes += additional_user_includes
1319
1321 self.create_action_sets()
1322
1324 self,
1325 is_linear = False,
1326 polynomials = Polynomials.Gauss_Legendre,
1327 use_libxsmm = False,
1328 precision = False,
1329 predictor_computation_precisions = False,
1330 corrector_computation_precision = False,
1331 solution_persistent_storage_precision = False,
1332 precompute_picard_precision = False,
1333 precision_criterion_implementation = PDETerms.User_Defined_Implementation,
1334 riemann_solver_implementation = PDETerms.None_Implementation,
1335 architecture = "noarch",
1336 initialise_patches = False
1337 ):
1338 if polynomials is Polynomials.Gauss_Legendre:
1339 self._basis = GaussLegendreBasis(self._order + 1)
1340 elif polynomials is Polynomials.Gauss_Lobatto:
1341 self._basis = GaussLobattoBasis(self._order + 1)
1342 else:
1343 raise Exception(
1344 "No proper basis chosen: {}, valid options are Gauss_Legendre and Gauss_Lobatto nodes".format(
1345 polynomials
1346 )
1347 )
1348
1349 self._is_linear = is_linear
1350 self._polynomials = polynomials
1351
1352 self._use_libxsmm = use_libxsmm
1353
1354 if precision!=False:
1355 if precision not in PrecisionType.keys():
1356 raise AssertionError(
1357 "The chosen precision was not a valid choice. valid choices are: "
1358 + ", ".join(PrecisionType.keys())
1359 )
1360 else:
1361 self._predictor_computation_precisions = [PrecisionType[precision]]
1362 self._precompute_picard_precision = PrecisionType[precision]
1363 self._solution_persistent_storage_precision = PrecisionType[precision]
1364 self._corrector_computation_precision = PrecisionType[precision]
1365
1366 if solution_persistent_storage_precision != False:
1367 if solution_persistent_storage_precision not in PrecisionType.keys():
1368 raise AssertionError(
1369 "The chosen precision was not a valid choice. valid choices are: "
1370 + ", ".join(PrecisionType.keys())
1371 )
1372 self._solution_persistent_storage_precision = PrecisionType[solution_persistent_storage_precision]
1373
1374 if corrector_computation_precision != False:
1375 if corrector_computation_precision not in PrecisionType.keys():
1376 raise AssertionError(
1377 "The chosen precision was not a valid choice. valid choices are: "
1378 + ", ".join(PrecisionType.keys())
1379 )
1380 self._corrector_computation_precision = PrecisionType[corrector_computation_precision]
1381
1382 if precompute_picard_precision != False:
1383 if precompute_picard_precision not in PrecisionType.keys():
1384 raise AssertionError(
1385 "The chosen precision was not a valid choice. valid choices are: "
1386 + ", ".join(PrecisionType.keys())
1387 )
1388 self._precompute_picard_precision = PrecisionType[precompute_picard_precision]
1389
1390 if predictor_computation_precisions != False:
1392 for prec in predictor_computation_precisions:
1393 if prec not in PrecisionType.keys():
1394 raise AssertionError(
1395 "The chosen precision was not a valid choice. valid choices are: "
1396 + ", ".join(PrecisionType.keys())
1397 )
1398 self._predictor_computation_precisions.append(PrecisionType[prec])
1399
1400 if len(self._predictor_computation_precisions) > 1:
1401 self._precision_criterion_implementation = precision_criterion_implementation
1402
1403 if riemann_solver_implementation is not PDETerms.None_Implementation:
1404 self._riemann_solver_implementation = riemann_solver_implementation
1405
1406 self._architecture = architecture
1407
1408 self._initialise_patches = initialise_patches
1409
1411 self.create_action_sets()
1412
1414 self,
1415 cell_data_storage: Storage,
1416 face_data_storage: Storage,
1417 ):
1418 """
1419 By default, we hold all data on the heap using raw pointers. You can explicitly switch
1420 to storage on the call stack or heap using smart pointers.
1421
1422 @see create_data_structures()
1423 """
1424 assert isinstance(cell_data_storage, Storage)
1425 assert isinstance(face_data_storage, Storage)
1426
1427 self._cell_data_storage = cell_data_storage
1428 self._face_data_storage = face_data_storage
1429
1431 self.create_action_sets()
1432
1434 d = {
1435 "OVERLAP": patch_overlap.dim[0]
1436 / 2, # Assumed to always be two, but present here anyway.
1437 "DOFS_PER_AXIS": patch_overlap.dim[1],
1438 "UNKNOWNS": patch_overlap.no_of_unknowns,
1439 }
1440 Template = """
1441 #if Dimensions == 2
1442 constexpr int SpaceFaceSize = {DOFS_PER_AXIS} * {UNKNOWNS}; // Order + 1
1443 #else
1444 constexpr int SpaceFaceSize = {DOFS_PER_AXIS} * {DOFS_PER_AXIS} * {UNKNOWNS}; // (Order + 1)^2
1445 #endif
1446
1447 const int faceDimension = marker.getSelectedFaceNumber() % Dimensions;
1448 // If the outer normal is positive, the normal points to the right so the face is on the right.
1449 const int faceLR = (marker.outerNormal()[faceDimension] > 0.0 ? 0 : 1);
1450
1451 // std::copy_n(from, how_many, to);
1452 std::copy_n(
1453 &neighbour.value[(1 - faceLR) * SpaceFaceSize],
1454 SpaceFaceSize,
1455 &value[(1 - faceLR) * SpaceFaceSize]
1456 );
1457"""
1458 return Template.format(**d)
Update the cell label within a sweep.
Definition CellLabel.py:9
add_actions_to_plot_solution(self, step, output_path)
Definition ADERDG.py:793
set_implementation(self, flux, ncp, eigenvalues, boundary_conditions, refinement_criterion, initial_conditions, source_term, material_parameters, point_source, additional_action_set_includes, additional_user_includes)
If you pass in User_Defined, then the generator will create C++ stubs that you have to befill manuall...
Definition ADERDG.py:1282
create_readme_descriptor(self, domain_offset, domain_size)
Definition ADERDG.py:606
add_user_solver_includes(self, value)
Add further includes to this property, if your solver requires some additional routines from other he...
Definition ADERDG.py:629
add_implementation_files_to_project(self, namespace, output, dimensions, subdirectory="")
The ExaHyPE2 project will call this operation when it sets up the overall environment.
Definition ADERDG.py:1036
add_use_data_statements_to_Peano4_solver_step(self, step)
Definition ADERDG.py:769
__init__(self, name, order, unknowns, auxiliary_variables, min_cell_h, max_cell_h, plot_grid_properties=False)
Definition ADERDG.py:69
add_actions_to_create_grid(self, step, evaluate_refinement_criterion)
Definition ADERDG.py:784
add_solver_constants(self, datastring)
Definition ADERDG.py:1114
set_solver_constants(self, datastring)
Definition ADERDG.py:1111
add_user_action_set_includes(self, value)
Add further includes to this property, if your action sets require some additional routines from othe...
Definition ADERDG.py:622
_generate_kernels(self, namespace, output, subdirectory, dimensions)
Definition ADERDG.py:864
switch_storage_scheme(self, Storage cell_data_storage, Storage face_data_storage)
By default, we hold all data on the heap using raw pointers.
Definition ADERDG.py:1417
_provide_cell_data_to_compute_kernels_default_guard(self)
Definition ADERDG.py:646
add_kernel_optimisations(self, is_linear=False, polynomials=Polynomials.Gauss_Legendre, use_libxsmm=False, precision=False, predictor_computation_precisions=False, corrector_computation_precision=False, solution_persistent_storage_precision=False, precompute_picard_precision=False, precision_criterion_implementation=PDETerms.User_Defined_Implementation, riemann_solver_implementation=PDETerms.None_Implementation, architecture="noarch", initialise_patches=False)
Definition ADERDG.py:1337
_action_set_couple_resolution_transitions_and_handle_dynamic_mesh_refinement
Definition ADERDG.py:542
set_plot_description(self, description)
Definition ADERDG.py:861
_provide_face_data_to_compute_kernels_default_guard(self)
Definition ADERDG.py:656
add_to_Peano4_datamodel(self, datamodel, verbose)
Definition ADERDG.py:753
The linear combination of the Runge-Kutta trials has to be projected onto the faces,...
Definition Correction.py:10
ExaHyPE 2 ADER-DG handling of adaptive meshes.
Definition DynamicAMR.py:9
The linear combination of the Runge-Kutta trials has to be projected onto the faces,...
PostprocessSolution differs from other action sets, as we only create it once.
The extrapolated solution from the space-time predictor has to be projected onto the faces,...
Definition Prediction.py:10
Very simple converter which maps the patch 1:1 onto a double array.
get_face_overlap_merge_implementation(patch_overlap)
Definition ADERDG.py:1433