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 counterpart to RusanovWithExplicitEuler: sets the initial
18 condition for a Finite Volume scheme with a Rusanov Riemann solver,
19 realised over a block-structured mesh, and prepares the data required
20 for the first time step.
21
22 Unlike SetupSimulationWithUserCodedRefinementCriterion, this variant
23 does not refine the mesh at all: it assumes the mesh is already the
24 regular grid it is going to stay, so setup only has to fill in the
25 initial condition and project it onto the faces.
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 """
33
34
46 FinishedInitialRegularMeshSetup = "exahype2.api.fv.SetupSimulationOverRegularGrid.FinishedInitialRegularMeshSetup"
47
48 def __init__(self, solver: Solver, volume_size: float):
49 """!
50
51 @param volume_size: float
52 Maximum edge length of one Finite Volume. Every mesh cell hosts one
53 patch of patch_size volumes per axis. The setup refines every cell
54 whose edge length is greater than or equal to volume_size times the
55 patch size (@ref peano4.api.actionsets.ConstructRegularGrid), i.e.
56 the resulting volumes are strictly smaller than volume_size. If you
57 want volumes of exactly 1/27 with patches of size 9, pass in a value
58 slightly bigger than 1/27: 1/27 itself yields cells of size 1/9 and
59 hence volumes of size 1/81.
60
61 """
62 super().__init__(solver)
63 self.volume_size = volume_size
64
65
66
68 exahype2_project,
69 peano_project,
70 setup_simulation):
71 """!
72
73 Create the actual sequence of tasks following the description
74 from @ref page_exahype_numerical_scheme "Adding a numerical scheme", as grid construction,
75 numerical scheme, but also plotting all follow the same pattern
76 of tasks and dependencies.
77
78 The routine first builds the task graph through
79 _construct_task_graph() and then reports it through
80 _report_task_graph().
81
82 """
83 self._construct_task_graph(exahype2_project, peano_project, setup_simulation)
84 self._report_task_graph(setup_simulation)
85
87 exahype2_project,
88 peano_project,
89 setup_simulation):
90 """!
91
92 Add the tasks of the setup over a regular mesh to setup_simulation
93
94 The initial condition task carries the tag
95 FinishedInitialRegularMeshSetup.
96
97 """
98 peano4.api.Logger().log("Create setup task graph for Finite Volume scheme over a regular, block-structured mesh with Rusanov flux")
99
100 assert any(isinstance(term, InitPointWisely) for term in self._solver_solver.pde_terms), (
101 f"Solver {self._solver.name} has no InitPointWisely PDE term registered. "
102 "SetupSimulationOverRegularGrid needs one to fill in the initial condition - "
103 "add one via solver.add_pde_term(exahype2.api.InitPointWisely(...))."
104 )
105
106 # Repeat while the mesh still changes, while the load balancing still
107 # wants to split, or while a split is still being carried out. Splits
108 # within these sweeps are safe, as the sweeps do not hold any data
109 # that lives from one sweep to the next.
110 refine_task = peano4.api.taskgraph.Task(name=f"{self._solver.name}_Refine mesh",
111 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
112 task_has_to_repeat=(
113 "not peano4::grid::isGridStationary( peano4::parallel::SpacetreeSet::getInstance().getGridStatistics() )"
114 " or ( ::toolbox::loadbalancing::LoadBalancingService::getInstance().hasLoadBalancing()"
115 " and ( not ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasStagnated()"
116 " or ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasSplitRecently() ) )"
117 )
118 )
119 consolidate_load_balancing_task = peano4.api.taskgraph.Task(name=f"{self._solver.name}_Consolidate mesh",
120 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
121 task_has_to_repeat=(
122 "not peano4::grid::isGridStationary( peano4::parallel::SpacetreeSet::getInstance().getGridStatistics() )"
123 " or ( ::toolbox::loadbalancing::LoadBalancingService::getInstance().hasLoadBalancing()"
124 " and ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasSplitRecently() )"
125 )
126 )
127
128 assert hasattr(self._solver_solver.numerical_scheme, "patch_size"), (
129 f"Solver {self._solver.name}'s numerical scheme has no attribute "
130 "patch_size. SetupSimulationOverRegularGrid assumes the numerical "
131 "scheme has added this field to itself immediately upon construction."
132 )
133 # Load balancing is expensive. Once the load balancing has split,
134 # we therefore do not add any further mesh elements for a while, so
135 # the mesh and the new trees can catch up: if we kept on refining,
136 # the freshly split trees would immediately become unbalanced again,
137 # and the load balancing would have to split once more. The
138 # refinement hence only continues if no load balancing is installed
139 # or if the installed load balancing has not split recently.
140 refine_task.add_action_set(
142 self.volume_size * self._solver_solver.numerical_scheme.patch_size,
143 guard=(
144 "not ::toolbox::loadbalancing::LoadBalancingService::getInstance().hasLoadBalancing()"
145 " or not ::toolbox::loadbalancing::LoadBalancingService::getInstance().getLoadBalancing()->hasSplitRecently()"
146 ),
147 includes="""
148#include "toolbox/loadbalancing/AbstractLoadBalancing.h"
149#include "toolbox/loadbalancing/LoadBalancingService.h"
150""",
151 )
152 )
153 # Inform the load balancing after every mesh refinement sweep
154 refine_task.add_action_set(toolbox.loadbalancing.api.actionsets.LoadBalancing())
155 # Once the mesh is constructed, switch the load balancing off and let
156 # the mesh consolidate: we keep on running mesh sweeps until the
157 # mesh is stationary and the most recent splits have been carried out.
158 consolidate_load_balancing_task.add_action_set(
159 toolbox.loadbalancing.api.actionsets.ToggleLoadBalancing(
160 enable_load_balancing=False, plug_into_prepare_traversal=True
161 )
162 )
163 consolidate_load_balancing_task.add_action_set(toolbox.loadbalancing.api.actionsets.LoadBalancing())
164
165 initial_condition_task = peano4.api.taskgraph.Task(name=f"{self._solver.name} Initial condition", entity=peano4.api.taskgraph.Task.GridEntity.CELL)
167 project_on_faces_task = peano4.api.taskgraph.Task(name=f"{self._solver.name} Project on faces", entity=peano4.api.taskgraph.Task.GridEntity.CELL)
168
169 consolidate_load_balancing_task.add_dependency(refine_task)
170 initial_condition_task.add_dependency(consolidate_load_balancing_task)
171 project_on_faces_task.add_dependency(initial_condition_task)
172
173 initial_condition_task.add_action_set(
174 InitialCondition(self._solver_solver, guard=self._solver_solver.grid_selector.createCellGuard())
175 )
176 project_on_faces_task.add_action_set(
178 self._solver_solver._patch,
179 self._solver_solver._patch_overlap_update,
180 guard=self._solver_solver.grid_selector.createCellGuard(),
181 includes=self._solver_solver._get_default_includes() + self._solver_solver.user_solver_includes,
182 )
183 )
184
187 if hasattr(self._solver_solver.numerical_scheme, "create_restriction_of_hanging_faces"):
188 project_on_faces_task.add_action_set(
189 self._solver_solver.numerical_scheme.create_restriction_of_hanging_faces()
190 )
191
193 project_on_faces_task.add_action_set(
194 RollOverUpdatedFaceWithSommerfeldBoundaryConditions.create_roll_over(
195 self._solver_solver,
196 exahype2_project,
197 guard=self._solver_solver.grid_selector.createFaceGuard(),
198 includes=self._solver_solver._get_default_includes() + self._solver_solver.user_solver_includes,
199 )
200 )
201
202 setup_simulation.add_task(refine_task)
203 setup_simulation.add_task(consolidate_load_balancing_task)
204 setup_simulation.add_task(initial_condition_task)
205 setup_simulation.add_task(project_on_faces_task)
206
207 initial_condition_task.use_cell(self._solver_solver._patch, peano4.api.taskgraph.Task.DataAccess.WRITE)
208 project_on_faces_task.use_cell(self._solver_solver._patch, peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE)
209 project_on_faces_task.use_face(self._solver_solver._patch_overlap_update, peano4.api.taskgraph.Task.DataAccess.TEMPORARY)
210 project_on_faces_task.use_face(self._solver_solver._patch_overlap_current_time_step, peano4.api.taskgraph.Task.DataAccess.WRITE)
211
212 def _report_task_graph(self, setup_simulation):
213 """!
214
215 Visualise or log the setup task graph, depending on the logger's verbosity
216
217 """
218 if peano4.api.Logger().is_visualisation:
219 setup_simulation.visualise(title="Setup task graph for {}".format(self._solver_solver.name))
220 if peano4.api.Logger().is_text:
221 setup_simulation.log_as_text(title="Setup task graph for {}".format(self._solver_solver.name))
How a Solver drives the construction of the mesh it runs on.
Definition Solver.py:102
Setup phase counterpart to RusanovWithExplicitEuler: sets the initial condition for a Finite Volume s...
_construct_task_graph(self, exahype2_project, peano_project, setup_simulation)
Add the tasks of the setup over a regular mesh to setup_simulation.
_solver
On adaptive meshes, restrict the fine data from the hanging faces onto the coarse faces.
str FinishedInitialRegularMeshSetup
Tag of the task which completes the setup over the initial regular mesh.
construct_output(self, exahype2_project, peano_project, setup_simulation)
Create the actual sequence of tasks following the description from Adding a numerical scheme,...
_report_task_graph(self, setup_simulation)
Visualise or log the setup task graph, depending on the logger's verbosity.
Fill a Finite Volume patch's initial condition, one volume at a time, by calling the solver's exahype...
Project a Finite Volume patch's data onto the overlap held on its surrounding faces,...
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