Peano
Loading...
Searching...
No Matches
SetupSimulationOverRegularGrid.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.api
5import toolbox.loadbalancing.api.actionsets
6
7from ..InitPointWisely import InitPointWisely
8from ..Solver import Solver
9from .actionsets import InitialCondition
10from .actionsets import ProjectPatchOntoFaces
11from .actionsets import RollOverUpdatedFaceWithSommerfeldBoundaryConditions
12
13
15 """!
16
17 Setup phase of the fourth-order Finite Differences with Runge-Kutta time
18 stepping (@ref exahype2.api.rkfd4): sets the initial condition over a
19 regular block-structured mesh and prepares the data required for the
20 first time step.
21
22 The mesh is not refined adaptively: setup constructs the regular grid
23 the simulation is going to stay on, fills in the initial condition and
24 projects it onto the faces, where the first Runge-Kutta stage picks it
25 up to reconstruct the halo of each patch.
26
27 The solver this is attached to has to have an exahype2.api.InitPointWisely
28 PDE term registered (via solver.add_pde_term(...)), as that is what fills
29 in the initial condition this class' setup task graph relies on;
30 construct_output() asserts this before it builds anything.
31
32 The class is a copy of exahype2.api.fv.SetupSimulationOverRegularGrid,
33 as rkfd4 does not depend on the Finite Volume package. It works against
34 the data the numerical scheme assigns to the solver: solver._patch,
35 solver._patch_overlap_update and solver._patch_overlap_current_time_step,
36 plus the numerical scheme's patch_size.
37
38 """
39
40 def __init__(self, solver: Solver, volume_size: float):
41 """!
42
43 @param volume_size: float
44 Maximum edge length of one Finite Differences grid cell, i.e. the
45 maximum mesh width h of the scheme. Every mesh cell hosts one
46 patch of patch_size grid cells per axis. The setup refines every
47 mesh cell whose edge length is greater than or equal to
48 volume_size times the patch size (@ref
49 peano4.api.actionsets.ConstructRegularGrid), i.e. the resulting
50 grid cells are strictly smaller than volume_size. If you want grid
51 cells of exactly 1/27 with patches of size 9, pass in a value
52 slightly bigger than 1/27: 1/27 itself yields mesh cells of size
53 1/9 and hence grid cells of size 1/81.
54
55 """
56 super().__init__(solver)
57 self.volume_size = volume_size
58
59 def construct_output(self, exahype2_project, peano_project, setup_simulation):
60 """!
61
62 Create the actual sequence of tasks following the description
63 from @ref page_exahype_numerical_scheme "Adding a numerical scheme", as grid construction,
64 numerical scheme, but also plotting all follow the same pattern
65 of tasks and dependencies.
66
67 """
69 "Create setup task graph for fourth-order Finite Differences with Runge-Kutta over a regular, block-structured mesh"
70 )
71
72 assert any(
73 isinstance(term, InitPointWisely) for term in self._solver_solver.pde_terms
74 ), (
75 f"Solver {self._solver.name} has no InitPointWisely PDE term registered. "
76 "SetupSimulationOverRegularGrid needs one to fill in the initial condition - "
77 "add one via solver.add_pde_term(exahype2.api.InitPointWisely(...))."
78 )
79
80 # Repeat while the mesh still changes, while the load balancing still
81 # wants to split, or while a split is still being carried out. Splits
82 # within these sweeps are safe, as the sweeps do not hold any data
83 # that lives from one sweep to the next.
84 refine_task = peano4.api.taskgraph.Task(
85 name=f"{self._solver.name}_Refine mesh",
86 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
87 task_has_to_repeat=(
88 "not peano4::grid::isGridStationary( peano4::parallel::SpacetreeSet::getInstance().getGridStatistics() )"
89 " or ( ::toolbox::loadbalancing::LoadBalancingService::getInstance().hasLoadBalancing()"
90 " and ( not ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasStagnated()"
91 " or ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasSplitRecently() ) )"
92 ),
93 )
94 consolidate_load_balancing_task = peano4.api.taskgraph.Task(
95 name=f"{self._solver.name}_Consolidate mesh",
96 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
97 task_has_to_repeat=(
98 "not peano4::grid::isGridStationary( peano4::parallel::SpacetreeSet::getInstance().getGridStatistics() )"
99 " or ( ::toolbox::loadbalancing::LoadBalancingService::getInstance().hasLoadBalancing()"
100 " and ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasSplitRecently() )"
101 ),
102 )
103
104 assert hasattr(self._solver_solver.numerical_scheme, "patch_size"), (
105 f"Solver {self._solver.name}'s numerical scheme has no attribute "
106 "patch_size. SetupSimulationOverRegularGrid assumes the numerical "
107 "scheme has added this field to itself immediately upon construction."
108 )
109 # Load balancing is expensive. Once the load balancing has split,
110 # we therefore do not add any further mesh elements for a while, so
111 # the mesh and the new trees can catch up: if we kept on refining,
112 # the freshly split trees would immediately become unbalanced again,
113 # and the load balancing would have to split once more. The
114 # refinement hence only continues if no load balancing is installed
115 # or if the installed load balancing has not split recently.
116 refine_task.add_action_set(
118 self.volume_size * self._solver_solver.numerical_scheme.patch_size,
119 guard=(
120 "not ::toolbox::loadbalancing::LoadBalancingService::getInstance().hasLoadBalancing()"
121 " or not ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasSplitRecently()"
122 ),
123 includes="""
124#include "toolbox/loadbalancing/AbstractLoadBalancing.h"
125#include "toolbox/loadbalancing/LoadBalancingService.h"
126""",
127 )
128 )
129 # Inform the load balancing after every mesh refinement sweep
130 refine_task.add_action_set(toolbox.loadbalancing.api.actionsets.LoadBalancing())
131 # Once the mesh is constructed, switch the load balancing off and let
132 # the mesh consolidate: we keep on running mesh sweeps until the
133 # mesh is stationary and the most recent splits have been carried out.
134 consolidate_load_balancing_task.add_action_set(
135 toolbox.loadbalancing.api.actionsets.ToggleLoadBalancing(
136 enable_load_balancing=False, plug_into_prepare_traversal=True
137 )
138 )
139 consolidate_load_balancing_task.add_action_set(
140 toolbox.loadbalancing.api.actionsets.LoadBalancing()
141 )
142
143 initial_condition_task = peano4.api.taskgraph.Task(
144 name=f"{self._solver.name} Initial condition",
145 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
146 )
147 project_on_faces_task = peano4.api.taskgraph.Task(
148 name=f"{self._solver.name} Project on faces",
149 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
150 )
151
152 consolidate_load_balancing_task.add_dependency(refine_task)
153 initial_condition_task.add_dependency(consolidate_load_balancing_task)
154 project_on_faces_task.add_dependency(initial_condition_task)
155
156 initial_condition_task.add_action_set(
158 self._solver_solver, guard=self._solver_solver.grid_selector.createCellGuard()
159 )
160 )
161 project_on_faces_task.add_action_set(
163 self._solver_solver._patch,
164 self._solver_solver._patch_overlap_update,
165 guard=self._solver_solver.grid_selector.createCellGuard(),
166 includes=self._solver_solver._get_default_includes()
167 + self._solver_solver.user_solver_includes,
168 )
169 )
170 # Sommerfeld boundary conditions initialise the ghost grid cells with
171 # the initial condition (@ref exahype2.api.blockstructured.BoundaryConditions)
172 project_on_faces_task.add_action_set(
173 RollOverUpdatedFaceWithSommerfeldBoundaryConditions.create_roll_over(
174 self._solver_solver,
175 exahype2_project,
176 guard=self._solver_solver.grid_selector.createFaceGuard(),
177 includes=self._solver_solver._get_default_includes()
178 + self._solver_solver.user_solver_includes,
179 )
180 )
181
182 setup_simulation.add_task(refine_task)
183 setup_simulation.add_task(consolidate_load_balancing_task)
184 setup_simulation.add_task(initial_condition_task)
185 setup_simulation.add_task(project_on_faces_task)
186
187 initial_condition_task.use_cell(
188 self._solver_solver._patch, peano4.api.taskgraph.Task.DataAccess.WRITE
189 )
190 project_on_faces_task.use_cell(
191 self._solver_solver._patch, peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE
192 )
193 project_on_faces_task.use_face(
194 self._solver_solver._patch_overlap_update,
195 peano4.api.taskgraph.Task.DataAccess.TEMPORARY,
196 )
197 project_on_faces_task.use_face(
198 self._solver_solver._patch_overlap_current_time_step,
199 peano4.api.taskgraph.Task.DataAccess.WRITE,
200 )
201
202 if peano4.api.Logger().is_visualisation:
203 setup_simulation.visualise(
204 title="Setup task graph for {}".format(self._solver_solver.name)
205 )
206 if peano4.api.Logger().is_text:
207 setup_simulation.log_as_text(
208 title="Setup task graph for {}".format(self._solver_solver.name)
209 )
How a Solver drives the construction of the mesh it runs on.
Definition Solver.py:102
Setup phase of the fourth-order Finite Differences with Runge-Kutta time stepping (exahype2....
construct_output(self, exahype2_project, peano_project, setup_simulation)
Create the actual sequence of tasks following the description from Adding a numerical scheme,...
Fill a patch's initial condition, one grid cell at a time, by calling the solver's exahype2....
Project a patch's data onto the overlap held on its surrounding faces, so the halo layers can be reco...
Singleton logger for the Peano 4 Python API.
Definition Logger.py:37
Refine the mesh - solver-agnostic - down to a regular grid of a given resolution.
One task within a peano4.api.taskgraph.Graph.
Definition Task.py:8
This is a set of generic action sets that multiple Peano users or extensions built on top of Peano mi...
Definition __init__.py:1