Peano
Loading...
Searching...
No Matches
BoundaryConditions.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
3"""!
4
5Decide which boundary treatment a solver's numerical scheme has to generate
6
7All numerical schemes evaluate the same two helpers: has_domain_boundary()
8tells whether the domain has a boundary at all, i.e. whether at least one
9axis is not periodic. get_boundary_conditions() returns the solver's
10boundary condition term and checks that the solver's PDE terms are
11consistent with the domain:
12
13- If all axes are periodic, the domain has no boundary. The schemes then
14 generate no boundary treatment at all, and the solver must not hold a
15 boundary condition term.
16- Otherwise, the solver has to hold exactly one boundary condition term,
17 i.e. either an exahype2.api.DirichletBoundaryConditions or an
18 exahype2.api.SommerfeldBoundaryConditions term.
19
20"""
21from .DirichletBoundaryConditions import DirichletBoundaryConditions
22from ..MaxEigenvalue import MaxEigenvalue
23from .SommerfeldBoundaryConditions import SommerfeldBoundaryConditions
24
25
26BOUNDARY_CONDITION_TERMS = (DirichletBoundaryConditions, SommerfeldBoundaryConditions)
27
28
29def has_domain_boundary(exahype2_project) -> bool:
30 """!
31
32 Does the domain have a boundary, i.e. is at least one axis not periodic?
33
34 @param exahype2_project: exahype2.api.Project
35 Provides the periodic boundary conditions (periodic_BC).
36
37 @return bool
38 False if and only if all axes are periodic.
39
40 """
41 return not all(exahype2_project.periodic_BC)
42
43
44def get_access_to_persistent_face_data(solver, exahype2_project, default):
45 """!
46
47 Access qualifier of the persistent face data for a task of the time step
48
49 Sommerfeld boundary conditions advance the ghost cells within the roll
50 over of the projection onto the faces, and they read the old face data
51 there (@ref exahype2::blockstructured::applySommerfeldBoundaryConditions()).
52 The face data hence has to survive the reconstruction of the halo, and
53 the projection has to load it:
54 peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag only stores
55 data after tasks which write it, and only loads it before tasks which
56 read it. With Sommerfeld boundary conditions, all tasks of the time step
57 which use the persistent face data therefore have to declare
58 READ_AND_WRITE.
59
60 @param solver: exahype2.api.Solver
61
62 @param exahype2_project: exahype2.api.Project
63
64 @param default: peano4.api.taskgraph.Task.DataAccess
65 The qualifier the task uses without Sommerfeld boundary conditions,
66 typically READ_AND_DISCARD for the reconstruction and WRITE for the
67 projection.
68
69 @return peano4.api.taskgraph.Task.DataAccess
70
71 """
73
74 if isinstance(
75 get_boundary_conditions(solver, exahype2_project), SommerfeldBoundaryConditions
76 ):
77 return peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE
78 return default
79
80
81def get_boundary_conditions(solver, exahype2_project):
82 """!
83
84 The solver's boundary condition term, or None if the domain has no boundary
85
86 @param solver: exahype2.api.Solver
87 The solver whose PDE terms are checked.
88
89 @param exahype2_project: exahype2.api.Project
90 Provides the periodic boundary conditions (periodic_BC).
91
92 @return exahype2.api.DirichletBoundaryConditions,
93 exahype2.api.SommerfeldBoundaryConditions or None
94 None if and only if all axes are periodic.
95
96 @exception ValueError
97 If all axes are periodic and the solver holds a boundary condition
98 term, if at least one axis is not periodic and the solver holds no or
99 more than one boundary condition term, if the term is stateless, or if
100 the solver holds a SommerfeldBoundaryConditions term but no
101 non-stateless MaxEigenvalue term.
102
103 """
104 terms = [
105 term for term in solver.pde_terms if isinstance(term, BOUNDARY_CONDITION_TERMS)
106 ]
107 periodic_BC = exahype2_project.periodic_BC
108
109 if not has_domain_boundary(exahype2_project):
110 if terms:
111 raise ValueError(
112 f"Solver {solver.name} holds the boundary condition term(s) "
113 f"{', '.join(type(term).__name__ for term in terms)}, but all axes "
114 f"are periodic (periodic_BC={periodic_BC}), i.e. the domain has "
115 "no boundary. Remove the term(s) via solver.remove_pde_term(...), "
116 "or make at least one axis non-periodic."
117 )
118 return None
119
120 if not terms:
121 raise ValueError(
122 f"Solver {solver.name} has non-periodic boundaries "
123 f"(periodic_BC={periodic_BC}), but no boundary condition PDE term. "
124 "Add one via solver.add_pde_term(exahype2.api.DirichletBoundaryConditions(...)) "
125 "or solver.add_pde_term(exahype2.api.SommerfeldBoundaryConditions(...)), "
126 "or make all axes periodic."
127 )
128 if len(terms) > 1:
129 raise ValueError(
130 f"Solver {solver.name} holds more than one boundary condition term "
131 f"({', '.join(type(term).__name__ for term in terms)}). Keep exactly one."
132 )
133
134 [term] = terms
135 if term.stateless:
136 raise ValueError(
137 f"Solver {solver.name} holds a stateless {type(term).__name__} term, "
138 "but only the non-stateless variant is supported. Add it with stateless=False."
139 )
140 if isinstance(term, SommerfeldBoundaryConditions) and not any(
141 isinstance(other, MaxEigenvalue) and not other.stateless
142 for other in solver.pde_terms
143 ):
144 raise ValueError(
145 f"Solver {solver.name} uses Sommerfeld boundary conditions, which take "
146 "their wave speed from the maximum eigenvalue, but has no non-stateless "
147 "MaxEigenvalue PDE term. Add one via "
148 "solver.add_pde_term(exahype2.api.MaxEigenvalue(...))."
149 )
150 if isinstance(term, SommerfeldBoundaryConditions):
151 # Validates the number of entries of the origin
152 term.get_origin(len(periodic_BC))
153 return term
bool has_domain_boundary(exahype2_project)
Does the domain have a boundary, i.e.
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
Definition __init__.py:1