3from .SeparateSweeps
import SeparateSweeps
15 ReconstructPatchAndApplyFunctor,
25 Update one cell that is compute Runge-Kutta step on it
27 This routine is significantly simpler than its counterpart in SeparateSweeps,
28 as we basically check if a cell is an enclave cell or not. If it is one, we
29 spawn a task. If not, we call the static routine from the task class which
30 updates the patch. All the computations thus are removed.
34 SolveRiemannProblemsOverPatch = jinja2.Template(
36 double timeStamp = fineGridCell{{SOLVER_NAME}}CellLabel.getTimeStamp();
39 // double timeStepSize
40 {{COMPUTE_TIME_STEP_SIZE}}
42 {% for PREDICATE_NO in range(0,PREDICATES|length) %}
43 if ({{PREDICATES[PREDICATE_NO]}}) {
44 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithAuxiliaryVariablesOnReconstructedPatch( 1, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, {{HALO_SIZE}}, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}});
45 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithoutAuxiliaryVariables( {{RK_STEPS}}, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, 0, {{NUMBER_OF_UNKNOWNS}}, 0 );
47 dfor( dof, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} ) {
48 for (int unknown=0; unknown<{{NUMBER_OF_UNKNOWNS}}; unknown++) {
49 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO]|length) %}
50 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]!=0 %}
51 oldQWithHalo[ enumeratorWithAuxiliaryVariablesOnReconstructedPatch(0,dof,unknown) ] +=
52 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]}} *
53 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},dof,unknown) ];
59 newQ = fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value + enumeratorWithoutAuxiliaryVariables({{PREDICATE_NO}},0,0);
63 {{PREPROCESS_RECONSTRUCTED_PATCH}}
65 assertion2( tarch::la::greaterEquals( timeStamp, 0.0 ), timeStamp, timeStepSize );
66 assertion2( tarch::la::greaterEquals( timeStepSize, 0.0 ), timeStamp, timeStepSize );
68 ::exahype2::fd::validatePatch(
70 {{NUMBER_OF_UNKNOWNS}},
71 {{NUMBER_OF_AUXILIARY_VARIABLES}},
72 {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},
73 {{HALO_SIZE}}, // halo
74 std::string(__FILE__) + "(" + std::to_string(__LINE__) + "): " + marker.toString()
75 ); // previous time step has to be valid
77 double subTimeStamp=timeStamp;
78 {% for PREDICATE_NO in range(0,PREDICATES|length-1) %}
79 if ({{PREDICATES[PREDICATE_NO]}}) {
80 subTimeStamp += {{BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES[PREDICATE_NO]}}*timeStepSize;
84 if ( marker.willBeSkeletonCell() ) {
85 tasks::{{SOLVER_NAME}}EnclaveTask::applyKernelToCell(
93 fineGridCell{{SEMAPHORE_LABEL}}.setSemaphoreNumber( ::exahype2::EnclaveBookkeeping::SkeletonTask );
96 assertion( marker.willBeEnclaveCell() );
97 assertion( not marker.willBeRefined() );
98 auto newEnclaveTask = new tasks::{{SOLVER_NAME}}EnclaveTask(
103 {% if MAKE_COPY_OF_ENCLAVE_TASK_DATA %}
110 int predecessorEnclaveTaskNumber = fineGridCell{{SEMAPHORE_LABEL}}.getSemaphoreNumber();
112 tarch::multicore::spawnTask(
114 predecessorEnclaveTaskNumber>=0 ? std::set<int>{predecessorEnclaveTaskNumber} : tarch::multicore::NoInDependencies,
115 newEnclaveTask->getTaskId()
118 if (predecessorEnclaveTaskNumber>=0) {
119 ::exahype2::EnclaveTask::releaseTaskNumber(predecessorEnclaveTaskNumber);
122 fineGridCell{{SEMAPHORE_LABEL}}.setSemaphoreNumber( newEnclaveTask->getTaskId() );
124 // Time stamp is not updated, as this will be done by final linear combination
125 // fineGridCell{{SOLVER_NAME}}CellLabel.setTimeStamp(timeStamp + timeStepSize);
133 one_huge_boolean_guard_expression =
"false"
134 for expr
in solver._primary_sweeps_of_Runge_Kutta_step_on_cell:
135 one_huge_boolean_guard_expression +=
" or (" + expr +
")"
139 patch_overlap=solver._patch_overlap_new,
140 functor_implementation=
"""
141#error please switch to your Riemann solver of choice
143 reconstructed_array_memory_location=peano4.toolbox.blockstructured.ReconstructedArrayMemoryLocation.ManagedSharedAcceleratorDeviceMemoryThroughTarchWithoutDelete,
144 guard=one_huge_boolean_guard_expression,
145 add_assertions_to_halo_exchange=
False,
153 +
"""CellLabel.setHasUpdated(false);
163 This is our plug-in point to alter the underlying dictionary
168 self.
_solver._init_dictionary_with_default_parameters(d)
169 self.
_solver.add_entries_to_text_replacement_dictionary(d)
171 d[
"PREDICATES"] = self.
_solver._primary_sweeps_of_Runge_Kutta_step_on_cell
174 "BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES"
186#include "tarch/NonCriticalAssertions.h"
187#include "exahype2/enumerator/enumerator.h"
188#include "exahype2/fd/PatchUtils.h"
189#include "exahype2/EnclaveBookkeeping.h"
190#include "tarch/multicore/Task.h"
192 + self.
_solver._get_default_includes()
193 + self.
_solver.user_action_set_includes
197 self.
_solver._enclave_task_name()
202 return __name__.replace(
".py",
"").replace(
".",
"_") +
"_UpdateCell"
207 {% for PREDICATE_NO in range(0,PREDICATES|length) %}
209 not marker.hasBeenRefined()
211 marker.hasBeenEnclaveCell()
213 {{PREDICATES[PREDICATE_NO]}}
216 constexpr int NumberOfDoFsPerCell = {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} * {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}};
217 double* QOut = fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value + {{PREDICATE_NO}} * NumberOfDoFsPerCell * {{NUMBER_OF_UNKNOWNS}};
219 constexpr int NumberOfDoFsPerCell = {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} * {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} * {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}};
220 double* QOut = fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value + {{PREDICATE_NO}} * NumberOfDoFsPerCell * {{NUMBER_OF_UNKNOWNS}};
223 const int taskNumber = fineGridCell{{LABEL_NAME}}.getSemaphoreNumber();
224 if ( taskNumber>=0 ) {
225 double maxEigenvalue; // not used here
226 ::exahype2::EnclaveBookkeeping::getInstance().waitForTaskToTerminateAndCopyResultOver( taskNumber, QOut, maxEigenvalue );
227 fineGridCell{{LABEL_NAME}}.setSemaphoreNumber( ::exahype2::EnclaveBookkeeping::NoEnclaveTaskNumber );
234 super(MergeEnclaveTaskOutcome, self).
__init__(solver)
236 self.
label_name = exahype2.grid.UpdateCellLabel.get_attribute_name(solver._name)
242 == peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
245 self.
_solver._init_dictionary_with_default_parameters(d)
246 self.
_solver.add_entries_to_text_replacement_dictionary(d)
248 d[
"PREDICATES"] = self.
_solver._secondary_sweeps_of_Runge_Kutta_step_on_cell
249 result = jinja2.Template(self.
Template).render(**d)
255 __name__.replace(
".py",
"").replace(
".",
"_") +
"_MergeEnclaveTaskOutcome"
262#include "exahype2/EnclaveBookkeeping.h"
270 Enclave variant of the solver where we still run through mesh once per Runge-Kutta sweep
272 The concept of (enclave) tasking within ExaHyPE solvers is described in
273 detail in the @ref page_exahype_solvers_enclave_solvers "generic enclave discussion of ExaHyPE".
274 This class is a prototype realisation of this concept which other solvers
275 then specialise for particular numerical schemes.
277 The class basically replaces the standard "update a cell" action set with an
278 action set that might or might not spawn a task. In return, it adds a further
279 action set which merges the arising task outcomes into the actual mesh
280 structure. By default, we use peano4::datamanagement::CellMarker::willBeEnclaveCell()
281 and peano4::datamanagement::CellMarker::hasBeenEnclaveCell() to guide the
282 decision whether to spawn a task or not. You can overwrite this decision
283 by redefining the corresponding entry in the dictionary befilled by
284 add_entries_to_text_replacement_dictionary().
288 Use the attributes self.enclave_task_priority to change the priority of the
289 task. This value can either be a string that C++ can evaluate into a
290 priority or a plain numerical value. I set it to
292 self.enclave_task_priority = "tarch::multicore::Task::DefaultPriority-1"
309 plot_grid_properties,
311 pde_terms_without_state,
318 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaPrimarySubStep{}".format(
326 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaPrimarySubStep0AfterGridInitialisation".format(
333 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSecondarySubStep{}".format(
348 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaPrimarySubStep{}".format(
356 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaPrimarySubStep0AfterGridInitialisation".format(
363 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSecondarySubStep{}".format(
376 +
".getSolverState()=="
378 +
"::SolverState::RungeKuttaPrimarySubStep0AfterGridInitialisation "
381 self.
_primary_sweep_guard +=
" or repositories::{}.getSolverState()=={}::SolverState::RungeKuttaPrimarySubStep{}".format(
387 repositories::{}.getSolverState()=={}::SolverState::RungeKuttaPrimarySubStep0AfterGridInitialisation
388 or repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation
389 or repositories::{}.getSolverState()=={}::SolverState::Plotting
390 or repositories::{}.getSolverState()=={}::SolverState::Suspended
407 self.
_secondary_sweep_guard +=
" or repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSecondarySubStep{}".format(
413 repositories::{}.getSolverState()=={}::SolverState::GridInitialisation""".format(
422 super(SeparateSweepsWithEnclaveTasking, self).
__init__(
431 plot_grid_properties,
438 "#error Not yet defined. Set in your Python solver class."
441 "#error Not yet defined. Set in your Python solver class."
456 Call the superclass' create_data_structures() to ensure that all the data
457 structures are in place, i.e. each cell can host a patch, that each face hosts
458 patch overlaps, and so forth. These quantities are all set to defaults. See
459 FV.create_data_structures().
461 After that, take the patch overlap (that's the data stored within the faces)
462 and ensure that these are sent and received via MPI whenever they are also
463 stored persistently. The default in FV is that no domain boundary data exchange
464 is active. Finally, ensure that the old data is only exchanged between the
465 initialisation sweep and the first first grid run-through.
470 initialisation_sweep_guard = (
474 +
".getSolverState()=="
476 +
"::SolverState::GridInitialisation"
479 first_iteration_after_initialisation_guard = (
483 +
".getSolverState()=="
485 +
"::SolverState::RungeKuttaPrimarySubStep0AfterGridInitialisation or "
488 +
".getSolverState()=="
490 +
"::SolverState::PlottingAfterGridInitialisation"
496 first_iteration_after_initialisation_guard
499 secondary_sweep_or_initialisation_or_plotting_guard =
"""(
500 repositories::{}.getSolverState()=={}::SolverState::GridInitialisation or
501 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation or
502 repositories::{}.getSolverState()=={}::SolverState::Plotting or
503 repositories::{}.getSolverState()=={}::SolverState::Suspended or
504 repositories::{}.isLastGridSweepOfTimeStep()
513 primary_sweep_or_plotting =
"""(
514 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation or
515 repositories::{}.getSolverState()=={}::SolverState::Plotting or
516 repositories::{}.getSolverState()=={}::SolverState::Suspended or
517 repositories::{}.isFirstGridSweepOfTimeStep()
526 secondary_sweep_or_initialisation_or_plotting_guard
529 primary_sweep_or_plotting
532 first_sweep_of_time_step_or_plotting_guard =
"""(
533 repositories::{}.isFirstGridSweepOfTimeStep() or
534 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation or
535 repositories::{}.getSolverState()=={}::SolverState::Plotting or
536 repositories::{}.getSolverState()=={}::SolverState::Suspended
544 last_sweep_of_time_step_or_plotting_or_initialisation =
"""(
545 repositories::{}.getSolverState()=={}::SolverState::GridInitialisation or
546 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation or
547 repositories::{}.getSolverState()=={}::SolverState::Plotting or
548 repositories::{}.getSolverState()=={}::SolverState::Suspended or
549 repositories::{}.isLastGridSweepOfTimeStep()
558 self.
_patch_estimates.generator.load_store_compute_flag =
"::peano4::grid::constructLoadStoreComputeFlag({},{},{})".format(
563 + first_sweep_of_time_step_or_plotting_guard
568 + last_sweep_of_time_step_or_plotting_or_initialisation
575 Call superclass routine and then reconfigure the update cell call.
576 Only the UpdateCell action set is specific to a single sweep.
578 This operation is implicity called via the superconstructor.
580 ## Guard construction
582 We note that the guard sets all contain the storage predicate already,
583 i.e. they combine the logic state analysis with an evaluation of
584 _load_cell_data_default_guard() and _store_cell_data_default_guard().
585 The singular strings like _primary_sweep_guard do not have this check
586 built in. We have to add it here.
624 "{} and repositories::{}.getSolverState()=={}::SolverState::GridInitialisation".format(
644 Add the enclave task for the GPU
646 See superclass for further information.
650 SeparateSweepsWithEnclaveTasking, self
652 templatefile_prefix = os.path.join(
653 os.path.dirname(os.path.realpath(__file__)),
654 "SeparateSweeps.EnclaveTask.template",
660 implementationDictionary = {}
670 generated_solver_files = (
672 "{}.h".format(templatefile_prefix),
673 "{}.cpp".format(templatefile_prefix),
675 namespace + [
"tasks"],
676 subdirectory +
"tasks",
677 implementationDictionary,
682 output.add(generated_solver_files)
683 output.makefile.add_cpp_file(subdirectory +
"tasks/" + task_name +
".cpp", generated=
True)
691 Add enclave aspect to time stepping. If you study the superclass'
692 routine add_actions_to_perform_time_step() and consider that this action
693 set is invoked in the secondary grid sweep, then it becomes clear that
694 this merger has to come first, i.e. we first add the action set and then
695 we call the superclass' add_action_set().
697 We need the result of the volumetric operation before we sum up this
698 volumetric solution and the Riemann solution.
708 SeparateSweepsWithEnclaveTasking, self
711 d[
"FUSED_COMPUTE_KERNEL_CALL_CPU"] = jinja2.Template(
714 d[
"FUSED_COMPUTE_KERNEL_CALL_GPU"] = jinja2.Template(
718 d[
"SEMAPHORE_LABEL"] = exahype2.grid.UpdateCellLabel.get_attribute_name(
730#include "exahype2/CellData.h"
732 + super(SeparateSweeps, self).user_action_set_includes
740 cell_data_storage: Storage,
741 face_data_storage: Storage,
743 if cell_data_storage == Storage.SmartPointers:
_load_face_data_default_guard(self)
Extend the guard via ands only.
_provide_cell_data_to_compute_kernels_default_guard(self)
_action_set_project_patch_onto_faces
_store_cell_data_default_guard(self)
Extend the guard via ands only.
_action_set_roll_over_update_of_faces
user_action_set_includes(self)
Add further includes to this property, if your action sets require some additional routines from othe...
_load_cell_data_default_guard(self)
Extend the guard via ands only.
_action_set_couple_resolution_transitions_and_handle_dynamic_mesh_refinement
get_name_of_global_instance(self)
number_of_Runge_Kutta_steps(self)
Return number of steps required to realise the Runge-Kutta scheme.
_solver_template_file_class_name
_baseline_action_set_descend_invocation_order
user_solver_includes(self)
Add further includes to this property, if your solver requires some additional routines from other he...
_init_dictionary_with_default_parameters(self, d)
This one is called by all algorithmic steps before I invoke add_entries_to_text_replacement_dictionar...
create_data_structures(self)
Recall in subclasses if you wanna change the number of unknowns or auxiliary variables.
create_action_sets(self)
Create required action sets.
_store_face_data_default_guard(self)
Extend the guard via ands only.
_action_set_handle_boundary
add_entries_to_text_replacement_dictionary(self, d)
_action_set_compute_final_linear_combination
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, solver)
solver: ADERDG Reference to creating class
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
get_includes(self)
Return include statements that you need.
Enclave variant of the solver where we still run through mesh once per Runge-Kutta sweep.
_fused_volumetric_kernel_call_cpu
switch_storage_scheme(self, Storage cell_data_storage, Storage face_data_storage)
By default, we hold all data on the call stacks.
__init__(self, name, patch_size, overlap, rk_order, unknowns, auxiliary_variables, min_meshcell_h, max_meshcell_h, plot_grid_properties, kernel_namespace, pde_terms_without_state)
Instantiate a generic FV scheme with an overlap of 1.
_secondary_sweeps_of_Runge_Kutta_step_on_face
_fused_compute_kernel_call_gpu
_fused_volumetric_kernel_call_gpu
create_data_structures(self)
Call the superclass' create_data_structures() to ensure that all the data structures are in place,...
_action_set_merge_enclave_task_outcome
_solver_template_file_class_name
_primary_sweep_or_plot_guard
_primary_sweeps_of_Runge_Kutta_step_on_cell
make_copy_of_enclave_task_data
_secondary_sweeps_of_Runge_Kutta_step_on_cell
add_actions_to_perform_time_step(self, step)
Add enclave aspect.
add_implementation_files_to_project(self, namespace, output, dimensions, subdirectory="")
Add the enclave task for the GPU.
_fused_compute_kernel_call_cpu
_last_secondary_sweep_of_Runge_Kutta_step_on_cell
add_entries_to_text_replacement_dictionary(self, d)
d: Dictionary of string to string in/out argument
_secondary_sweep_or_initialisation_guard
_primary_sweeps_of_Runge_Kutta_step_on_face
create_action_sets(self)
Call superclass routine and then reconfigure the update cell call.
user_action_set_includes(self)
Add further includes to this property, if your action sets require some additional routines from othe...
Update one cell that is compute Runge-Kutta step on it.
_Template_TouchCellFirstTime_Preamble
__init__(self, solver)
patch: peano4.datamodel.Patch Patch which is to be used
_add_action_set_entries_to_dictionary(self, d)
This is our plug-in point to alter the underlying dictionary.
get_action_set_name(self)
Return unique action set name.
get_includes(self)
Return include statements that you need.
SolveRiemannProblemsOverPatch
Probably the simplest solver you could think off.
add_entries_to_text_replacement_dictionary(self, d)
d: Dictionary of string to string in/out argument
user_action_set_includes(self)
Add further includes to this property, if your action sets require some additional routines from othe...
create_data_structures(self)
Call the superclass' create_data_structures() to ensure that all the data structures are in place,...
create_action_sets(self)
Call superclass routine and then reconfigure the update cell call.
_solver_template_file_class_name