3from .AbstractADERDGActionSet
import AbstractADERDGActionSet
7import peano4.solversteps
12 The extrapolated solution from the space-time predictor has to be projected onto
13 the faces, so we can then solve the Riemann problems. So the projection
14 happens in one grid sweep, the corresponding Riemann solve in the next one.
17 _Template_TouchCellFirstTime_Preamble =
"""
18 bool isHangingCell = false;
19 for (int d = 0; d < 2 * Dimensions; d++) {
20 if (fineGridFaces{{SOLVER_NAME}}FaceLabel(d).getIsHanging()) {
27 const double timeStamp = fineGridCell{{SOLVER_NAME}}CellLabel.getTimeStamp();
28 // Needs to declare and define timeStepSize
29 {{COMPUTE_TIME_STEP_SIZE}}
32 constexpr int SpaceFaceSize = {{ORDER}} + 1;
33 constexpr int SpaceBasisSize = ({{ORDER}} + 1) * ({{ORDER}} + 1);
35 constexpr int SpaceFaceSize = ({{ORDER}} + 1) * ({{ORDER}} + 1);
36 constexpr int SpaceBasisSize = ({{ORDER}} + 1) * ({{ORDER}} + 1) * ({{ORDER}} + 1);
39 constexpr int SpaceTimeBasisSize = SpaceBasisSize * ({{ORDER}} + 1);
40 constexpr int BasisElementsPerFace = kernels::{{SOLVER_NAME}}::getBndFaceSize();
41 constexpr int FluxElementsPerFace = kernels::{{SOLVER_NAME}}::getBndFluxSize();
43 auto* Q = fineGridCell{{UNKNOWN_IDENTIFIER}}.value;
44 auto* oldQ = fineGridCell{{UNKNOWN_IDENTIFIER}}_old.value;
46 {{PREPROCESS_RECONSTRUCTED_PATCH}}
48 {{CREATE_PREDICTOR_ALLOCATIONS}}
50 std::copy_n(Q, SpaceBasisSize * ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}}), oldQ);
53 _Template_TouchCellFirstTime_Core =
"""
54 {{FUSED_PREDICTOR_VOLUME_INTEGRAL}}
55 {{PROJECT_SOLUTION_TO_FACES}}
58 _Template_TouchCellFirstTime_Epilogue =
"""
59 fineGridCell{{SOLVER_NAME}}CellLabel.setTimeStepSize(timeStepSize);
61 repositories::{{SOLVER_INSTANCE}}.update(timeStepSize, timeStamp, marker.h()(0));
65 _Template_PredictorAllocations =
"""
66 {{CORRECTOR_COMPUTATION_PRECISION}}* lQhbnd[2*Dimensions] = {
67 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(0).value + BasisElementsPerFace,
68 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(1).value + BasisElementsPerFace,
70 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(2).value + BasisElementsPerFace,
72 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(0+Dimensions).value,
73 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(1+Dimensions).value,
75 fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(2+Dimensions).value
79 {{CORRECTOR_COMPUTATION_PRECISION}}* lFhbnd[2*Dimensions] = {
80 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(0).value + FluxElementsPerFace,
81 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(1).value + FluxElementsPerFace,
83 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(2).value + FluxElementsPerFace,
85 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(0+Dimensions).value,
86 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(1+Dimensions).value,
88 fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(2+Dimensions).value
92 ::exahype2::CellData<{{SOLUTION_STORAGE_PRECISION}}, {{CORRECTOR_COMPUTATION_PRECISION}}> cellData(
93 fineGridCell{{UNKNOWN_IDENTIFIER}}.value,
102 _Template_FSTPVI_Linear_Without_PS =
"""
103 // Linear, without point sources
104 int numberOfIterations = kernels::{{SOLVER_NAME}}::fusedSpaceTimePredictorVolumeIntegral<{{SOLUTION_STORAGE_PRECISION}}, {{PREDICTOR_COMPUTATION_PRECISIONS[PRECISION_NUM]}}, {{CORRECTOR_COMPUTATION_PRECISION}}>(
105 repositories::{{SOLVER_INSTANCE}},
106 lQhbnd, lFhbnd, cellData.QIn[0],
107 marker.x(), marker.h(), timeStamp, timeStepSize,
108 std::vector<int>() // Empty vector
112 _Template_FSTPVI_Linear_With_PS =
"""
113 const auto pointSources = kernels::{{SOLVER_NAME}}::pointSources(
114 repositories::{{SOLVER_INSTANCE}},
119 if (!pointSources.empty()) {
120 // Linear, with point sources
121 int numberOfIterations = kernels::{{SOLVER_NAME}}::fusedSpaceTimePredictorVolumeIntegral<{{SOLUTION_STORAGE_PRECISION}}, {{PREDICTOR_COMPUTATION_PRECISIONS[PRECISION_NUM]}}, {{CORRECTOR_COMPUTATION_PRECISION}}>(
122 repositories::{{SOLVER_INSTANCE}},
123 lQhbnd, lFhbnd, cellData.QIn[0],
124 marker.x(), marker.h(), timeStamp, timeStepSize,
128 // Linear, without point sources
129 int numberOfIterations = kernels::{{SOLVER_NAME}}::fusedSpaceTimePredictorVolumeIntegralWithoutPointSources<{{SOLUTION_STORAGE_PRECISION}}, {{PREDICTOR_COMPUTATION_PRECISIONS[PRECISION_NUM]}}, {{CORRECTOR_COMPUTATION_PRECISION}}>(
130 repositories::{{SOLVER_INSTANCE}},
131 lQhbnd, lFhbnd, cellData.QIn[0],
132 marker.x(), marker.h(), timeStamp, timeStepSize,
138 _Template_FSTPVI_Nonlinear =
"""
139 // Nonlinear, without point sources
140 int numberOfIterations = kernels::{{SOLVER_NAME}}::fusedSpaceTimePredictorVolumeIntegral<{{SOLUTION_STORAGE_PRECISION}}, {{PREDICTOR_COMPUTATION_PRECISIONS[PRECISION_NUM]}}, {{CORRECTOR_COMPUTATION_PRECISION}}>(
141 repositories::{{SOLVER_INSTANCE}},
142 lQhbnd, lFhbnd, cellData.QIn[0],
143 marker.x(), marker.h(), timeStamp, timeStepSize
147 _Template_SetFaceTimeStamps =
"""
149 * Copy the estimates into the face data containers. Note that Peano uses a different ordering of
150 * the faces that the kernels, so these are reordered somewhat.
151 * The kernels order by dimension, then side of the face whereas Peano orders by
152 * side, then dimension.
153 * E.g., in 2d the kernels have the order left, right, lower face, upper face
154 * whereas Peano orders: left, lower, right, upper.
156 * 2d: 0,1,2,3 -> 0,2,1,3
157 * 3d: 0,1,2,3,4,5 -> 0,3,1,4,2,5
160 for (int d = 0; d < Dimensions; d++) {
161 // Timestamp information for boundary handling
162 fineGridFaces{{SOLVER_NAME}}FaceLabel(d).setNewTimeStamp(1, timeStamp);
163 fineGridFaces{{SOLVER_NAME}}FaceLabel(d + Dimensions).setNewTimeStamp(0, timeStamp);
167 _Template_NumberOfPrecisionsIterator =
"""
168 ::exahype2::PrecisionCommand myPrecision = repositories::{{SOLVER_INSTANCE}}.precisionCriterion(
173 repositories::{{SOLVER_INSTANCE}}.getSolverState()
176 switch (myPrecision) {
177 {% for PRECISION_NUM in range(0,PREDICTOR_COMPUTATION_PRECISIONS|length) %}
178 case ::exahype2::PrecisionCommand::{{PRECISIONS_CAPITALIZED[PRECISION_NUM]}}:
179 {{ITERATION_CONTENT}}
183 assertion1WithExplanation(
184 false, myPrecision, "chosen precision was not in the previously specified options, as such there are no compiled kernels for this option."
189 _Template_PerformRiemannSolutionOnHangingFacesAndSetFaceTimeStamps =
"""
191 * Copy the estimates into the face data containers. Note that Peano uses a different ordering of
192 * the faces that the kernels, so these are reordered somewhat.
193 * The kernels order by dimension, then side of the face whereas Peano orders by
194 * side, then dimension.
195 * E.g., in 2d the kernels have the order left, right, lower face, upper face
196 * whereas Peano orders: left, lower, right, upper.
198 * 2d: 0,1,2,3 -> 0,2,1,3
199 * 3d: 0,1,2,3,4,5 -> 0,3,1,4,2,5
201 * On hanging faces, this instead computes the Riemann solution and face integral, then
202 * stores the solution of this into the face. The reason for this is that performing the
203 * Riemann solution on the hanging cell and restricting these is much more accurate than
204 * performing them on the coarse faces and projecting those to the fine faces, to the
205 * degree that the later breaks many simulations.
208 for (int d = 0; d < Dimensions; d++) {
212 if (fineGridFaces{{SOLVER_NAME}}FaceLabel(d).getIsHanging()) {
213 {{CORRECTOR_COMPUTATION_PRECISION}}* FL = fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d).value;
214 {{CORRECTOR_COMPUTATION_PRECISION}}* FR = fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d).value + FluxElementsPerFace;
215 {{CORRECTOR_COMPUTATION_PRECISION}}* QL = fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d).value;
216 {{CORRECTOR_COMPUTATION_PRECISION}}* QR = fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d).value + BasisElementsPerFace;
219 bool isBoundary = false;
220 tarch::la::Vector<Dimensions, double> faceCentre = marker.x();
221 faceCentre[d] -= 0.5 * marker.h()[d];
223 {{CORRECTOR_COMPUTATION_PRECISION}}* FIn = FR;
228 if (fineGridFaces{{SOLVER_NAME}}FaceLabel(d+Dimensions).getIsHanging()) {
229 {{CORRECTOR_COMPUTATION_PRECISION}}* FL = fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d + Dimensions).value;
230 {{CORRECTOR_COMPUTATION_PRECISION}}* FR = fineGridFaces{{UNKNOWN_IDENTIFIER}}FluxEstimates(d + Dimensions).value + FluxElementsPerFace;
231 {{CORRECTOR_COMPUTATION_PRECISION}}* QL = fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d + Dimensions).value;
232 {{CORRECTOR_COMPUTATION_PRECISION}}* QR = fineGridFaces{{UNKNOWN_IDENTIFIER}}Estimates(d + Dimensions).value + BasisElementsPerFace;
234 int faceNumber = d + Dimensions;
235 bool isBoundary = false;
236 tarch::la::Vector<Dimensions, double> faceCentre = marker.x();
237 faceCentre[d] += 0.5 * marker.h()[d];
239 {{CORRECTOR_COMPUTATION_PRECISION}}* FIn = FL;
245 _Template_RiemannSolver =
"""
246 kernels::{{SOLVER_NAME}}::riemannSolver<{{CORRECTOR_COMPUTATION_PRECISION}}>(
247 repositories::{{SOLVER_INSTANCE}},
260 _Template_CustomRiemannSolver =
"""
261 repositories::{{SOLVER_INSTANCE}}.riemannSolver(
276 _Template_FaceIntegral =
"""
277 const double inverseDxDirection = 1.0 / marker.h()[d];
278 kernels::{{SOLVER_NAME}}::faceIntegral(
288 def __init__(self, solver, guard, on_hanging_cells=False):
290 guard: String (C++ code)
291 Predicate which controls whether this action set should run
292 on_hanging_cells: bool
293 Determines whether this is running on hanging cells or not,
294 the actions on both differ
296 super(Prediction, self).
__init__(solver)
301 solver._riemann_solver_implementation != PDETerms.None_Implementation
304 solver._point_sources_implementation != PDETerms.None_Implementation
312 == peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
315 self.
_solver._init_dictionary_with_default_parameters(d)
316 self.
_solver.add_entries_to_text_replacement_dictionary(d)
320 d[
"PRECISIONS_CAPITALIZED"] = [
321 x.replace(
" ",
"_").replace(
"std::",
"").capitalize()
322 for x
in d[
"PREDICTOR_COMPUTATION_PRECISIONS"]
328 "FUSED_PREDICTOR_VOLUME_INTEGRAL"
332 "FUSED_PREDICTOR_VOLUME_INTEGRAL"
338 d[
"RIEMANN_SOLVER"] = jinja2.Template(
342 d[
"RIEMANN_SOLVER"] = jinja2.Template(
345 d[
"FACE_INTEGRAL"] = jinja2.Template(
349 "PROJECT_SOLUTION_TO_FACES"
358 d[
"ITERATION_CONTENT"] = jinja2.Template(
361 result += jinja2.Template(
365 d[
"PRECISION_NUM"] = 0
366 result += jinja2.Template(
369 result += jinja2.Template(
373 result = jinja2.Template(result).render(**d)
387#include "exahype2/CellData.h"
393 +
"""/FaceIntegral.h"
396 +
"""/RiemannSolver.h"
399 +
"""/FusedSpaceTimePredictorVolumeIntegral.h"
407 +
"""/PointSources.h"
410 +
"""/FusedSpaceTimePredictorVolumeIntegralWithoutPointSources.h"
The extrapolated solution from the space-time predictor has to be projected onto the faces,...
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
str _Template_SetFaceTimeStamps
str _Template_FSTPVI_Linear_With_PS
str _Template_PerformRiemannSolutionOnHangingFacesAndSetFaceTimeStamps
get_includes(self)
Return include statements that you need.
_use_custom_riemann_solver
str _Template_TouchCellFirstTime_Core
str _Template_NumberOfPrecisionsIterator
__init__(self, solver, guard, on_hanging_cells=False)
guard: String (C++ code) Predicate which controls whether this action set should run on_hanging_cells...
str _Template_PredictorAllocations
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
str _Template_FSTPVI_Nonlinear
str _Template_TouchCellFirstTime_Epilogue
str _Template_CustomRiemannSolver
str _Template_FaceIntegral
str _Template_FSTPVI_Linear_Without_PS
str _Template_RiemannSolver
str _Template_TouchCellFirstTime_Preamble