1"""Boundary condition terms of exahype2.api and how the numerical schemes
2realise them (@ref exahype2.api.blockstructured.BoundaryConditions)."""
14TOUCH_FACE_LAST_TIME = peano4.api.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME
18 return types.SimpleNamespace(periodic_BC=list(periodic_BC))
21def _solver(*boundary_terms, max_eigenvalue=True):
23 solver.add_pde_term(
exahype2.api.Flux(implementation=
"F[0] = Q[0]; F[1] = Q[1];"))
26 implementation=
"Q[0] = 1.0; Q[1] = 0.0; Q[2] = 0.0;"
33 for term
in boundary_terms:
34 solver.add_pde_term(term)
39 return exahype2.api.SommerfeldBoundaryConditions(
40 implementation=
"Q[0] = 1.0; Q[1] = 0.0;", **kwargs
45 return exahype2.api.DirichletBoundaryConditions(implementation=
"Q[0] = 1.0;")
49 has_domain_boundary = exahype2.api.blockstructured.BoundaryConditions.has_domain_boundary
50 assert not has_domain_boundary(
_project([
True,
True,
True]))
51 assert has_domain_boundary(
_project([
True,
False,
True]))
52 assert has_domain_boundary(
_project([
False,
False,
False]))
56 get_boundary_conditions = exahype2.api.blockstructured.BoundaryConditions.get_boundary_conditions
59 get_boundary_conditions(
_solver(dirichlet),
_project([
False] * 3))
is dirichlet
69@pytest.mark.parametrize(
70 "solver, periodic_BC, message",
74 (
lambda:
_solver(), [
False] * 3,
"no boundary condition PDE term"),
78 "more than one boundary condition term",
83 "no non-stateless MaxEigenvalue",
88 "has 2 entries, but the domain has 3 dimensions",
93 solver, periodic_BC, message
95 with pytest.raises(ValueError, match=message):
103 assert term.name ==
"sommerfeldFarFieldSolution"
104 assert term.get_origin(2) == [1.0, 2.0]
105 assert _sommerfeld().get_origin(3) == [0.0, 0.0, 0.0]
106 declaration = term.generator.generate_declaration()
107 assert "virtual void sommerfeldFarFieldSolution(" in declaration
108 assert "const tarch::la::Vector<Dimensions, double>& x" in declaration
112 scheme_factory, grid_construction_factory, solver, periodic_BC, tmp_path
114 """! Setup and time step task graphs of solver over the unit cube"""
115 solver.numerical_scheme = scheme_factory(solver)
116 solver.grid_construction = grid_construction_factory(solver)
118 [
"probe"],
"probe",
"probe", directory=str(tmp_path)
120 exahype2_project.set_global_simulation_parameters(
122 offset=[0.0, 0.0, 0.0],
123 size=[1.0, 1.0, 1.0],
125 periodic_BC=periodic_BC,
129 solver.generate_solver_realisation(exahype2_project, peano_project, *graphs)
130 return [{task.name: task
for task
in graph.tasks}
for graph
in graphs[:2]]
137 solver, volume_size=0.1
144 solver, volume_size=0.1
150 solver, patch_size=4, rk_order=2
153 solver, volume_size=0.1
162 action_set.get_body_of_operation(TOUCH_FACE_LAST_TIME)
163 for task
in tasks.values()
164 for action_set
in task.action_sets
165 if isinstance(action_set, actionsets.RollOverUpdatedFace)
169@pytest.mark.parametrize("scheme", SCHEMES)
171 scheme_factory, grid_construction_factory, actionsets = SCHEMES[scheme]
174 grid_construction_factory,
176 [
False,
False,
False],
179 assert not any(
"Dirichlet" in name
for name
in time_step)
183 assert "applyDirichletBoundaryConditions(" in setup_roll_over
184 assert "initPointWisely(x, Q)" in setup_roll_over
185 assert "applySommerfeldBoundaryConditions(" not in setup_roll_over
190 for body
in roll_overs:
191 assert "applySommerfeldBoundaryConditions(" in body
192 assert "sommerfeldFarFieldSolution(x, Q)" in body
193 assert "maxEigenvalue(Q, x, normal, &lambdaMax)" in body
194 assert "tarch::la::Vector<Dimensions, double>({0.5, 0.5, 0.5})" in body
195 assert body.index(
"applySommerfeldBoundaryConditions") < body.index(
202 task.face_data_access[solver._patch_overlap_current_time_step]
203 for task
in tasks.values()
204 if solver._patch_overlap_current_time_step
in task.face_data
208@pytest.mark.parametrize("scheme", SCHEMES)
210 """! The roll over reads the old face data, so no task may discard it,
211 and the projection has to load it"""
212 scheme_factory, grid_construction_factory, actionsets = SCHEMES[scheme]
215 scheme_factory, grid_construction_factory, solver, [
False] * 3, tmp_path
218 peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE
222@pytest.mark.parametrize("scheme", SCHEMES)
224 scheme_factory, grid_construction_factory, actionsets = SCHEMES[scheme]
227 scheme_factory, grid_construction_factory, solver, [
False] * 3, tmp_path
230 peano4.api.taskgraph.Task.DataAccess.READ_AND_DISCARD
235@pytest.mark.parametrize("scheme", SCHEMES)
237 scheme_factory, grid_construction_factory, actionsets = SCHEMES[scheme]
240 grid_construction_factory,
242 [
False,
False,
False],
245 assert any(
"Apply Dirichlet BCs" in name
for name
in time_step)
247 time_step, actionsets
249 assert "BoundaryConditions(" not in body
252@pytest.mark.parametrize("scheme", SCHEMES)
254 scheme_factory, grid_construction_factory, actionsets = SCHEMES[scheme]
257 grid_construction_factory,
262 assert not any(
"Dirichlet" in name
for name
in time_step)
264 time_step, actionsets
266 assert "BoundaryConditions(" not in body
269@pytest.mark.parametrize("scheme", SCHEMES)
271 scheme_factory, grid_construction_factory, actionsets = SCHEMES[scheme]
272 with pytest.raises(ValueError, match=
"all axes are periodic"):
275 grid_construction_factory,
The conservative flux F(Q) of a hyperbolic PDE.
Point-wise initial condition: given the physical position of a single degree of freedom,...
The maximum absolute eigenvalue of the flux Jacobian in a given direction, i.e.
Abstract base class for all ExaHyPE 2 solvers.
Finite Volumes with a Rusanov Riemann solver and explicit Euler time stepping, realised over a block-...
Finite Volumes with a Rusanov Riemann solver and optimistic explicit Euler time stepping,...
Setup phase counterpart to RusanovWithExplicitEuler: sets the initial condition for a Finite Volume s...
Fourth-order central Finite Differences with explicit Runge-Kutta time stepping, realised over a bloc...
Setup phase of the fourth-order Finite Differences with Runge-Kutta time stepping (exahype2....
Represents a Peano 4 project.
Holds a sequence of Task instances.
get_boundary_conditions(solver, exahype2_project)
The solver's boundary condition term, or None if the domain has no boundary.
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_sommerfeld_keeps_old_face_data_alive(scheme, tmp_path)
The roll over reads the old face data, so no task may discard it, and the projection has to load it.
test_sommerfeld_term_generates_far_field_solution()
test_sommerfeld_replaces_roll_over_of_setup_and_time_step(scheme, tmp_path)
test_has_domain_boundary()
test_dirichlet_keeps_boundary_task_and_plain_roll_over(scheme, tmp_path)
_realisation(scheme_factory, grid_construction_factory, solver, periodic_BC, tmp_path)
Setup and time step task graphs of solver over the unit cube.
test_periodic_domain_rejects_boundary_condition_term(scheme, tmp_path)
_accesses_to_persistent_face_data(solver, tasks)
test_dirichlet_discards_face_data_after_reconstruction(scheme, tmp_path)
test_periodic_domain_has_no_boundary_treatment(scheme, tmp_path)
test_get_boundary_conditions_rejects_inconsistent_terms(solver, periodic_BC, message)
_roll_over_bodies(tasks, actionsets)
_solver(*boundary_terms, max_eigenvalue=True)
test_get_boundary_conditions_returns_the_one_term()