521 Add the data from __create_data_structures() to the Peano 4 project
522 and configure their generators
524 Only _patch_overlap_current_time_step is exchanged between ranks,
525 and only on the faces the solver's grid selector holds for. The
526 task graph compiler uses, loads and stores data only where the
527 solver's grid selector holds, too (@ref peano4.api.datamodel.DoF).
535Right-hand side estimates
536-------------------------
550 peano_project.datamodel.add_cell(self.
_solver_solver._stage_input)
551 peano_project.datamodel.add_cell(self.
_solver_solver._patch_with_halo)
552 peano_project.datamodel.add_cell(self.
_solver_solver._rhs_estimates)
553 peano_project.datamodel.add_face(self.
_solver_solver._patch_overlap_current_time_step)
554 peano_project.datamodel.add_face(self.
_solver_solver._patch_overlap_update)
558 peano_project.datamodel.add_cell(self.
_solver_solver._max_eigenvalue)
568 current_time_step = self.
_solver_solver._patch_overlap_current_time_step
569 current_time_step.generator.merge_method_definition = (
570 toolbox.blockstructured.api.get_face_merge_implementation(current_time_step)
572 current_time_step.generator.includes +=
"""
573#include "peano4/utils/Loop.h"
575 current_time_step.generator.send_condition = (
578 current_time_step.generator.receive_and_merge_condition = (
582 self.
_solver_solver._patch_overlap_update.generator.send_condition =
"false"
583 self.
_solver_solver._patch_overlap_update.generator.receive_and_merge_condition = (
859 Add the data to the Peano 4 project, generate the kernels and add
860 the tasks of one Runge-Kutta step to time_step
862 Per stage k, the time step holds the following tasks (see the class
863 documentation for the data flow):
865 - {SolverName}_Apply Dirichlet BCs stage k: sets the ghost grid
866 cells along the domain boundary for Dirichlet boundary conditions.
867 The task does not exist if all axes are periodic, or for Sommerfeld
868 boundary conditions, which advance the ghost grid cells within the
869 roll over of the projection onto the faces.
870 - {SolverName}_Reconstruct stage k: reconstructs the stage's input
872 - {SolverName}_Evaluate right hand side stage k.
873 - {SolverName}_Prepare stage k+1, or {SolverName}_Complete time step
874 after the last stage: computes the linear combination of the
875 estimates. Prepare stage k+1 is tagged with
876 exahype2.api.Solver.IntermediateSolutionUpdateTag, Complete time
877 step with exahype2.api.Solver.SolutionUpdateTaskTag, i.e.
878 postprocessing such as the enforcement of constraints can be
879 inserted directly after them (see @ref
880 page_exahype2_solver_manipulate_solver_steps).
881 - {SolverName}_Project stage k+1 onto faces, or {SolverName}_Project
882 solution onto faces after the last stage: projects the outcome of
883 the linear combination onto the faces. After the last stage, it
884 also computes the maximum eigenvalue of the new solution.
886 After the last stage, {SolverName}_Compute time step size determines
887 the time step size of the next time step and advances the solver's
888 time stamp. {SolverName}_Dynamic mesh refinement finally evaluates the
889 adaptivity criterion if the solver has one
890 (@ref exahype2.api.blockstructured.create_dynamic_mesh_refinement_action_set.create_dynamic_mesh_refinement_action_set()),
891 switches the load balancing on again and informs it that the time
896 "Create time stepping task graph for fourth-order Finite Differences "
897 f
"with Runge-Kutta of order {self.rk_order} over block-structured meshes"
901 exahype2_project.periodic_BC
904 f
"Solver {self._solver.name}: the advection velocity has "
905 f
"{len(self.advection_velocity)} entries, but the domain has "
906 f
"{len(exahype2_project.periodic_BC)} dimensions"
911 isinstance(term, MaxEigenvalue)
and not term.stateless
914 f
"Solver {self._solver.name} uses adaptive time step sizes, but has no "
915 "non-stateless MaxEigenvalue PDE term. Add one via "
916 "solver.add_pde_term(exahype2.api.MaxEigenvalue(...)), or pass a "
917 "time_step_size to CentralDifferencesWithRungeKutta."
920 relative_time_step_sizes = self.
butcher_tableau.relative_time_step_sizes()
923 SommerfeldBoundaryConditions,
926 for earlier, later
in zip(
927 relative_time_step_sizes, relative_time_step_sizes[1:]
931 f
"Solver {self._solver.name} uses Sommerfeld boundary conditions, but "
932 f
"the time stamps c={relative_time_step_sizes} of the stages of its "
933 f
"Runge-Kutta scheme of order {self.rk_order} decrease. The roll over "
934 "advances the ghost grid cells from one stage to the next, so it "
935 "requires non-decreasing time stamps "
936 "(@ref exahype2::blockstructured::applySommerfeldBoundaryConditions())."
959 Access = peano4.api.taskgraph.Task.DataAccess
960 Entity = peano4.api.taskgraph.Task.GridEntity
962 previous_stage_task =
None
970 name=f
"{name}_Reconstruct stage {stage}", entity=Entity.CELL
973 name=f
"{name}_Evaluate right hand side stage {stage}",
978 name=f
"{name}_Complete time step", entity=Entity.CELL
981 name=f
"{name}_Project solution onto faces", entity=Entity.CELL
985 name=f
"{name}_Prepare stage {stage + 1}", entity=Entity.CELL
988 name=f
"{name}_Project stage {stage + 1} onto faces",
991 time_step.add_task(reconstruction_task)
992 time_step.add_task(right_hand_side_task)
993 time_step.add_task(combination_task)
994 time_step.add_task(projection_task)
997 if previous_stage_task
is not None:
998 reconstruction_task.add_dependency(previous_stage_task)
1004 reconstruction_task.add_action_set(
1005 toolbox.loadbalancing.api.actionsets.ToggleLoadBalancing(
1006 enable_load_balancing=
False,
1007 plug_into_prepare_traversal=
True,
1014 reconstruction_task.use_cell(
1016 Access.READ_AND_WRITE
if stage == 0
else Access.READ_AND_DISCARD,
1018 reconstruction_task.use_cell(self.
_solver_solver._patch_with_halo, Access.WRITE)
1021 reconstruction_task.use_face(
1023 get_access_to_persistent_face_data(
1027 reconstruction_task.add_action_set(
1028 toolbox.blockstructured.api.ReconstructPatchWithHalo(
1030 patch_overlap=self.
_solver_solver._patch_overlap_current_time_step,
1033 add_assertions_to_halo_exchange=
False,
1034 additional_includes=includes,
1039 reconstruction_task.add_action_set(
1040 toolbox.blockstructured.api.InterpolateHangingFaces(
1043 additional_includes=includes,
1050 boundary_task = ApplyDirichletBoundaryConditions.add_task_to_time_step(
1054 reconstruction_task,
1055 name_suffix=f
" stage {stage}",
1056 relative_time_step_size=self.
butcher_tableau.relative_time_step_sizes()[
1060 if boundary_task
is not None and previous_stage_task
is not None:
1061 boundary_task.add_dependency(previous_stage_task)
1064 right_hand_side_task.add_dependency(reconstruction_task)
1065 right_hand_side_task.use_cell(
1068 right_hand_side_task.use_cell(
1072 right_hand_side_task.add_action_set(action_set)
1084 weights = weight_matrix[stage + 1]
1086 combination_task.add_dependency(right_hand_side_task)
1087 combination_task.use_cell(self.
_solver_solver._patch, Access.READ_AND_WRITE)
1088 combination_task.use_cell(
1091 if not is_last_stage:
1092 combination_task.use_cell(self.
_solver_solver._stage_input, Access.WRITE)
1093 combination_task.add_action_set(
1098 combination_task.tags.add(
1099 Solver.SolutionUpdateTaskTag
1101 else Solver.IntermediateSolutionUpdateTag
1106 projection_task.add_dependency(combination_task)
1107 projection_task.use_cell(output, Access.READ_AND_WRITE)
1108 projection_task.use_face(
1111 projection_task.use_face(
1113 get_access_to_persistent_face_data(
1118 projection_task.use_cell(self.
_solver_solver._max_eigenvalue, Access.WRITE)
1119 projection_task.add_action_set(
1122 projection_task.add_action_set(
1136 next_relative_time_step_size = (
1137 1.0
if is_last_stage
else relative_time_step_sizes[stage + 1]
1139 projection_task.add_action_set(
1140 RollOverUpdatedFaceWithSommerfeldBoundaryConditions.create_roll_over(
1146 f
"{next_relative_time_step_size - relative_time_step_sizes[stage]!r}"
1147 f
" * repositories::{self._solver.get_name_of_global_instance()}.getMinTimeStepSize()"
1151 previous_stage_task = projection_task
1155 name=f
"{name}_Compute time step size",
1157 may_spawn_background_tasks=
False,
1159 time_step_size_task.add_dependency(previous_stage_task)
1161 time_step_size_task.use_cell(
1164 time_step_size_task.add_action_set(
1173 time_step_size_task.add_action_set(
1181 time_step.add_task(time_step_size_task)
1189 name=f
"{name}_Dynamic mesh refinement",
1191 may_spawn_background_tasks=
False,
1193 dynamic_mesh_refinement_task.use_cell(
1196 dynamic_mesh_refinement = create_dynamic_mesh_refinement_action_set(
1203 if dynamic_mesh_refinement
is not None:
1204 dynamic_mesh_refinement_task.add_action_set(dynamic_mesh_refinement)
1205 dynamic_mesh_refinement_task.add_action_set(
1206 toolbox.loadbalancing.api.actionsets.LoadBalancing(
1207 enable_load_balancing=
True
1210 dynamic_mesh_refinement_task.add_dependency(time_step_size_task)
1211 dynamic_mesh_refinement_task.add_dependency(previous_stage_task)
1212 time_step.add_task(dynamic_mesh_refinement_task)
1215 time_step.visualise(title=
"Time stepping task graph for {}".format(name))
1217 time_step.log_as_text(title=
"Time stepping task graph for {}".format(name))