12def _solver(time_step_size=None, rk_order=3, boundary="dirichlet"):
16 "dirichlet", "sommerfeld", or None for a solver without boundary
17 condition term, i.e. for a domain that is periodic along all axes.
21 solver.add_pde_term(
exahype2.api.Flux(implementation=
"F[0] = Q[0]; F[1] = Q[1];"))
23 if boundary ==
"dirichlet":
25 exahype2.api.DirichletBoundaryConditions(implementation=
"Q[0] = 0.0;")
27 elif boundary ==
"sommerfeld":
29 exahype2.api.SommerfeldBoundaryConditions(implementation=
"Q[0] = 0.0;")
32 solver, patch_size=4, rk_order=rk_order, time_step_size=time_step_size
38 exahype2_project = types.SimpleNamespace(periodic_BC=list(periodic_BC))
41 solver.numerical_scheme.construct_output(exahype2_project, peano_project, time_step)
42 return {task.name: task
for task
in time_step.tasks}
47 assert set(tasks) == {
48 "Probe_Apply Dirichlet BCs stage 0",
49 "Probe_Apply Dirichlet BCs stage 1",
50 "Probe_Apply Dirichlet BCs stage 2",
51 "Probe_Reconstruct stage 0",
52 "Probe_Reconstruct stage 1",
53 "Probe_Reconstruct stage 2",
54 "Probe_Evaluate right hand side stage 0",
55 "Probe_Evaluate right hand side stage 1",
56 "Probe_Evaluate right hand side stage 2",
57 "Probe_Prepare stage 1",
58 "Probe_Prepare stage 2",
59 "Probe_Complete time step",
60 "Probe_Project stage 1 onto faces",
61 "Probe_Project stage 2 onto faces",
62 "Probe_Project solution onto faces",
63 "Probe_Compute time step size",
64 "Probe_Dynamic mesh refinement",
68 tasks[f
"Probe_Prepare stage {stage}"]
69 in tasks[f
"Probe_Project stage {stage} onto faces"].dependencies
72 tasks[f
"Probe_Project stage {stage} onto faces"]
73 in tasks[f
"Probe_Reconstruct stage {stage}"].dependencies
77 tasks[
"Probe_Project stage 1 onto faces"]
78 in tasks[
"Probe_Apply Dirichlet BCs stage 1"].dependencies
81 tasks[
"Probe_Apply Dirichlet BCs stage 1"]
82 in tasks[
"Probe_Reconstruct stage 1"].dependencies
85 tasks[
"Probe_Project solution onto faces"]
86 in tasks[
"Probe_Compute time step size"].dependencies
91 return {name
for name, task
in tasks.items()
if tag
in task.tags}
97 final =
_tagged(tasks, exahype2.api.Solver.SolutionUpdateTaskTag)
98 intermediate =
_tagged(tasks, exahype2.api.Solver.IntermediateSolutionUpdateTag)
99 assert set(final) == {
"Probe_Complete time step"}
100 assert set(intermediate) == {
"Probe_Prepare stage 1",
"Probe_Prepare stage 2"}
101 tagged = final | intermediate
107 for action_set
in tasks[name].action_sets
113 [action_set] = tasks[
"Probe_Apply Dirichlet BCs stage 2"].action_sets
114 body = action_set.get_body_of_operation(
115 peano4.api.solversteps.ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME
119 "repositories::instanceOfProbe.getMinTimeStamp() + 1.0 * "
120 "repositories::instanceOfProbe.getMinTimeStepSize()," in body
126 _solver(rk_order=2, boundary=
None), tmp_path, periodic_BC=(
True,
True,
True)
128 assert not any(
"Dirichlet" in name
for name
in tasks)
134 for task
in tasks.values()
135 for action_set
in task.action_sets
140 with pytest.raises(ValueError, match=
"all axes are periodic"):
147 for name, task
in tasks.items()
148 for action_set
in task.action_sets
155 assert not any(
"Dirichlet" in name
for name
in tasks)
157 assert set(roll_overs) == {
158 "Probe_Project stage 1 onto faces",
159 "Probe_Project stage 2 onto faces",
160 "Probe_Project solution onto faces",
164 for name, increment
in [
165 (
"Probe_Project stage 1 onto faces",
"0.5"),
166 (
"Probe_Project stage 2 onto faces",
"0.5"),
167 (
"Probe_Project solution onto faces",
"0.0"),
169 action_set = roll_overs[name]
174 body = action_set.get_body_of_operation(
175 peano4.api.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME
177 assert "::exahype2::blockstructured::applySommerfeldBoundaryConditions(" in body
179 f
"{increment} * repositories::instanceOfProbe.getMinTimeStepSize()," in body
181 assert "tarch::la::Vector<Dimensions, double>({0.0, 0.0, 0.0})" in body
183 assert body.index(
"applySommerfeldBoundaryConditions") < body.index(
189 solver =
_solver(rk_order=3, boundary=
"sommerfeld")
192 solver.numerical_scheme.butcher_tableau,
193 "relative_time_step_sizes",
194 lambda: [0.0, 1.0, 0.5],
196 with pytest.raises(ValueError, match=
"decrease"):
203 solver.numerical_scheme.butcher_tableau,
204 "relative_time_step_sizes",
205 lambda: [0.0, 1.0, 0.5],
208 assert "Probe_Apply Dirichlet BCs stage 2" in tasks
212 solver =
_solver(rk_order=4, boundary=
None)
214 tableau = solver.numerical_scheme.butcher_tableau
216 def combination(task_name):
219 for action_set
in tasks[task_name].action_sets
226 for stage
in range(1, 4):
227 action_set = combination(f
"Probe_Prepare stage {stage}")
228 assert action_set.weights == tableau.weight_matrix()[stage]
229 assert action_set.output
is solver._stage_input
230 final = combination(
"Probe_Complete time step")
231 assert final.weights == tableau.final_estimate_weights()
232 assert final.output
is solver._patch
237 kernels = tmp_path /
"kernels"
241 "Probe_fd4_eigenvalue_2d",
242 "Probe_fd4_eigenvalue_3d",
243 "rungekutta_linear_combination",
245 assert (kernels / (name +
".h")).exists(), name
246 assert (kernels / (name +
".cpph")).exists(), name
247 wrapper = (kernels /
"Probe_fd4.h").read_text()
248 assert '#include "Probe_fd4_2d.h"' in wrapper
249 assert '#include "Probe_fd4_eigenvalue_3d.h"' in wrapper
250 assert "Probe_rightHandSideWithFD4" in (kernels /
"Probe_fd4_2d.cpph").read_text()
254 solver =
_solver(time_step_size=0.01, boundary=
None)
256 assert not (tmp_path /
"kernels" /
"Probe_fd4_eigenvalue_2d.h").exists()
259 for task
in tasks.values()
260 for action_set
in task.action_sets
262 [time_step_size] = tasks[
"Probe_Compute time step size"].action_sets
264 "const double admissibleTimeStepSize = 0.01;"
265 in time_step_size.get_body_of_unprepareTraversal()
270 solver =
_solver(rk_order=4, boundary=
None)
272 [action_set] = tasks[
"Probe_Evaluate right hand side stage 2"].action_sets
273 body = action_set.get_body_of_operation(
274 peano4.api.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
277 assert "getMinTimeStamp() + 0.6666666666666666 * timeStepSize" in body
278 assert "fineGridCellProbeQRhsEstimates.value + 64;" in body
279 assert "fineGridCellProbeQRhsEstimates.value + 256;" in body
281 "Probe_rightHandSideWithFD4<\n 4,\n 2,\n 2,\n 1\n>(\n patchData,\n [&]("
290 solver, patch_size=4, rk_order=2
292 with pytest.raises(AssertionError):
298 Peano's stacks require that each stored datum is loaded by the next
299 sweep which uses it. The reconstruction of a later stage is the last
300 reader of the stage input, as the next combination writes it from
301 scratch, so it must not store it.
303 solver =
_solver(rk_order=4, boundary=
None)
305 Access = peano4.api.taskgraph.Task.DataAccess
307 tasks[
"Probe_Reconstruct stage 0"].cell_data_access[solver._patch]
308 == Access.READ_AND_WRITE
310 for stage
in range(1, 4):
311 reconstruction = tasks[f
"Probe_Reconstruct stage {stage}"]
313 reconstruction.cell_data_access[solver._stage_input]
314 == Access.READ_AND_DISCARD
317 tasks[f
"Probe_Prepare stage {stage}"].cell_data_access[solver._stage_input]
The conservative flux F(Q) of a hyperbolic PDE.
The maximum absolute eigenvalue of the flux Jacobian in a given direction, i.e.
Abstract base class for all ExaHyPE 2 solvers.
Fourth-order central Finite Differences with explicit Runge-Kutta time stepping, realised over a bloc...
Combine the solution with the right-hand side estimates of the Runge-Kutta stages.
Store the maximum eigenvalue over all grid cells of a patch.
Project a patch's data onto the overlap held on its surrounding faces, so the halo layers can be reco...
Roll over the face data, and set the ghost grid cells along the domain boundary through exahype2....
Copy patch_overlap_update - the face overlap exahype2.api.rkfd4.actionsets.ProjectPatchOntoFaces has ...
Represents a Peano 4 project.
Holds a sequence of Task instances.
The Python-side model of "what happens during one mesh sweep".
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
test_dirichlet_accepts_decreasing_stage_time_stamps(tmp_path, monkeypatch)
test_stage_combinations_use_rows_of_butcher_tableau(tmp_path)
test_one_reconstruction_per_stage_and_chain_of_stages(tmp_path)
test_periodic_domain_needs_no_boundary_tasks(tmp_path)
test_fixed_time_step_size_skips_eigenvalue(tmp_path)
test_boundary_values_use_stage_time_stamp(tmp_path)
test_right_hand_side_uses_stage_time_stamp_and_estimate_slot(tmp_path)
test_stage_input_is_loaded_once_after_each_store(tmp_path)
Peano's stacks require that each stored datum is loaded by the next sweep which uses it.
test_sommerfeld_replaces_roll_over_and_omits_boundary_tasks(tmp_path)
test_stage_combinations_are_tagged_as_solution_updates(tmp_path)
test_adaptive_time_stepping_requires_max_eigenvalue(tmp_path)
test_periodic_domain_rejects_boundary_condition_term(tmp_path)
_solver(time_step_size=None, rk_order=3, boundary="dirichlet")
test_kernels_are_generated_for_both_dimensions(tmp_path)
test_sommerfeld_rejects_decreasing_stage_time_stamps(tmp_path, monkeypatch)
_construct_time_step(solver, directory, periodic_BC=(False, False, False))