Peano
Loading...
Searching...
No Matches
ApplyDirichletBoundaryConditions.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
3from peano4.api.solversteps.ActionSet import ActionSet
4
5import peano4.api
7import jinja2
8
9from ...blockstructured.DirichletBoundaryConditions import DirichletBoundaryConditions
10from ...blockstructured.BoundaryConditions import get_boundary_conditions
11
12
14 """!
15
16 Set the ghost grid cells along the domain boundary through the solver's
17 exahype2.api.DirichletBoundaryConditions term
18
19 The action set plugs into touchFaceFirstTime() and delegates to
20 exahype2::blockstructured::applyDirichletBoundaryConditions(), which
21 holds the logic described below. Each face carries an
22 overlap of 2*overlap grid cells along its normal
23 (solver._patch_overlap_current_time_step), i.e. 2*HALO_SIZE for the
24 fourth-order Finite Differences of @ref exahype2.api.rkfd4 :
25 the left half belongs to the cell left of the face, the right half to
26 the cell right of it. On the domain boundary, one of these two cells
27 lies outside of the domain. Nobody ever writes its half of the face
28 data. This action set fills exactly this half: For each of the
29 outside's grid cells, it invokes
30
31 @code
32 repositories::<solver>.dirichletBoundaryConditions( x, t, Q );
33 @endcode
34
35 with x being the centre of the (ghost) grid cell and t the time stamp
36 of the Runge-Kutta stage, i.e. the solver's current time stamp
37 getMinTimeStamp() plus relative_time_step_size times its time step size
38 getMinTimeStepSize(). Faces along periodic axes are
39 skipped (PeriodicBC from the project's Constants.h). Whether a face is
40 on the domain boundary is derived from its position, i.e. compared
41 against DomainOffset and DomainOffset+DomainSize.
42
43 The subsequent reconstruction
44 (toolbox.blockstructured.api.ReconstructPatchWithHalo) reads the face
45 data in touchCellFirstTime(). As Peano touches all faces of a cell for
46 the first time before it enters the cell, the boundary task and the
47 reconstruction can share one mesh traversal (@ref
48 peano4.api.taskgraph.compiler.FuseSteps.translate()).
49
50 Use add_task_to_time_step() to add the corresponding task to a time
51 step's task graph.
52
53 ## Why Dirichlet conditions are not part of the roll over
54
55 exahype2.api.SommerfeldBoundaryConditions do without a boundary task:
56 They advance the ghost cells within the roll over of the face data
57 after the projection. Dirichlet conditions could be realised the same
58 way, as the roll over could evaluate the boundary values at the time
59 stamp of the next update. We deliberately keep them as a separate task
60 which runs directly before the reconstruction, as this will not work
61 anymore once we support local time stepping: With local time stepping,
62 each cell advances with its own time step size, and the time stamp at
63 which the ghost cells have to hold the boundary values is only known
64 once the adjacent cell starts its next update, but not when the face
65 data are rolled over after its previous update.
66
67 The class mirrors
68 exahype2.api.fv.actionsets.ApplyDirichletBoundaryConditions, as rkfd4
69 does not depend on the Finite Volume package. Both share the C++
70 routine. Different to the Finite Volume version, it evaluates the
71 boundary values at the time stamp of the Runge-Kutta stage. With the time stamp of the time step instead, all stages would
72 see the same boundary values, and the scheme would drop to first order
73 along the boundary.
74
75 """
76
77 TemplateTouchFaceFirstTime = jinja2.Template(
78 """
79 ::exahype2::blockstructured::applyDirichletBoundaryConditions(
80 [](const tarch::la::Vector<Dimensions,double>& x, double t, double* Q) -> void {
81 repositories::{{SOLVER_INSTANCE}}.dirichletBoundaryConditions(x, t, Q);
82 },
83 marker,
84 DomainOffset,
85 DomainSize,
86 PeriodicBC,
87 {{NUMBER_OF_GRID_CELLS_PER_AXIS}},
88 {{OVERLAP}},
89 {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}},
90 repositories::{{SOLVER_INSTANCE}}.getMinTimeStamp() + {{RELATIVE_TIME_STEP_SIZE}} * repositories::{{SOLVER_INSTANCE}}.getMinTimeStepSize(),
91 {{FACE_ACCESSOR}}.value
92 );
93"""
94 )
95
96 def __init__(self, solver, patch_overlap, guard, relative_time_step_size=0.0):
97 """!
98
99 @param solver: exahype2.api.Solver
100 The solver whose dirichletBoundaryConditions() is invoked.
101
102 @param patch_overlap: peano4.api.datamodel.Patch
103 The face data to set, i.e. solver._patch_overlap_current_time_step.
104 Its dim[0] is twice the overlap, its dim[1] the number of grid
105 cells per axis of the cell patch.
106
107 @param guard: str
108 C++ boolean expression over a FaceMarker called marker. Typically
109 solver.grid_selector.createFaceGuard().
110
111 @param relative_time_step_size: float
112 The @f$ c_k @f$ of the Runge-Kutta stage, i.e. the stage's time
113 stamp relative to the time step size, @ref
114 exahype2.api.rungekutta.ButcherTableau.ButcherTableau.relative_time_step_sizes().
115
116 """
117 super().__init__(descend_invocation_order=1, parallel=False)
118 self._solver = solver
119 self.guard = guard
120 self.d = {
121 "RELATIVE_TIME_STEP_SIZE": repr(float(relative_time_step_size)),
122 "SOLVER_INSTANCE": solver.get_name_of_global_instance(),
123 "NUMBER_OF_GRID_CELLS_PER_AXIS": str(patch_overlap.dim[1]),
124 "OVERLAP": str(int(patch_overlap.dim[0] / 2)),
125 "NUMBER_OF_UNKNOWNS": str(solver.unknowns),
126 "NUMBER_OF_AUXILIARY_VARIABLES": str(solver.auxiliary_variables),
127 "FACE_ACCESSOR": "fineGridFace" + patch_overlap.name,
128 }
129
130 def get_body_of_operation(self, operation_name):
131 if (
132 operation_name
133 == peano4.api.solversteps.ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME
134 ):
135 return self.TemplateTouchFaceFirstTime.render(**self.d)
136 return ""
137
138 def get_guard_of_operation(self, operation_name):
139 if (
140 operation_name
141 == peano4.api.solversteps.ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME
142 ):
143 return self.guard
144 return "true"
145
147 return __name__.replace(".py", "").replace(".", "_")
148
150 return False
151
152 def get_includes(self):
153 return (
154 """
155#include "exahype2/blockstructured/DirichletBoundaryConditions.h"
156"""
157 + self._solver._get_default_includes()
158 + self._solver.user_solver_includes
159 )
160
161 @staticmethod
163 solver,
164 exahype2_project,
165 time_step,
166 reconstruction_task,
167 name_suffix="",
168 relative_time_step_size=0.0,
169 additional_guard="true",
170 ):
171 """!
172
173 Add the boundary task in front of the reconstruction of the halo
174
175 If all axes of the domain are periodic, or if the solver uses
176 exahype2.api.SommerfeldBoundaryConditions (which replace the roll
177 over instead), the routine does nothing. Otherwise, it adds a FACE
178 task which sets the ghost grid
179 cells of solver._patch_overlap_current_time_step, and makes
180 reconstruction_task depend on it.
181
182 @param solver: exahype2.api.Solver
183 The solver. Its boundary condition terms have to be consistent
184 with the domain, @ref
185 exahype2.api.blockstructured.BoundaryConditions.get_boundary_conditions().
186
187 @param exahype2_project: exahype2.api.Project
188 Provides the periodic boundary conditions.
189
190 @param time_step: peano4.api.taskgraph.Graph
191 The time step's task graph.
192
193 @param reconstruction_task: peano4.api.taskgraph.Task
194 The task reading solver._patch_overlap_current_time_step to
195 reconstruct the patches' halos.
196
197 @param name_suffix: str
198 Appended to the task's name. A time step with several Runge-Kutta
199 stages adds one boundary task per stage, and the names of the
200 tasks have to differ.
201
202 @param relative_time_step_size: float
203 The @f$ c_k @f$ of the Runge-Kutta stage, see the constructor.
204
205 @param additional_guard: str
206 C++ predicate which is combined with the guard of the boundary
207 action set, e.g. the is<Name>Active() of a plotter which
208 reconstructs the halo (@ref exahype2.api.rkfd4.WriteCheckpoint).
209
210 @return peano4.api.taskgraph.Task or None
211 The boundary task, or None if no Dirichlet task is required.
212
213 """
214 if not isinstance(
215 get_boundary_conditions(solver, exahype2_project),
216 DirichletBoundaryConditions,
217 ):
218 return None
219
220 boundary_task = peano4.api.taskgraph.Task(
221 name=f"{solver.name}_Apply Dirichlet BCs{name_suffix}",
222 entity=peano4.api.taskgraph.Task.GridEntity.FACE,
223 )
224 boundary_task.use_face(
225 solver._patch_overlap_current_time_step,
226 peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE,
227 )
228 boundary_task.add_action_set(
230 solver,
231 solver._patch_overlap_current_time_step,
232 guard="("
233 + additional_guard
234 + ") and ("
235 + solver.grid_selector.createFaceGuard()
236 + ")",
237 relative_time_step_size=relative_time_step_size,
238 )
239 )
240 time_step.add_task(boundary_task)
241 reconstruction_task.add_dependency(boundary_task)
242 return boundary_task
Dirichlet boundary conditions: given a position x outside of the domain and a time stamp t,...
Set the ghost grid cells along the domain boundary through the solver's exahype2.api....
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
add_task_to_time_step(solver, exahype2_project, time_step, reconstruction_task, name_suffix="", relative_time_step_size=0.0, additional_guard="true")
Add the boundary task in front of the reconstruction of the halo.
Action set (reactions to events)
Definition ActionSet.py:6
One task within a peano4.api.taskgraph.Graph.
Definition Task.py:8
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
Definition __init__.py:1