6from .AbstractRKFDActionSet
import AbstractRKFDActionSet
16 Project patch data onto faces, so the faces hold valid data which can feed into the subsequent Runge-Kutta step
18 This class is based upon peano4.toolbox.blockstructured.ProjectPatchOntoFaces.
19 Yet, it differs fundamentally in the way the inner-most loop is realised:
20 The standard projection from the toolbox takes a solution from a patch
21 and copies parts of this solution onto the faces. This is not what we want
22 to have here: we have the solution plus a number of estimates, and we want
23 to write exactly the type of Runge-Kutta linear combination onto the face
24 that we need to set the proper halo data on the adjacent cells in the next
25 grid sweep. Therefore, this class expects the Butcher tableau and first
26 computes the Runge-Kutta linear combination. The outcome of this is then
27 projected onto the faces.
29 The routine is always called as one of the last things, i.e. we have a
30 valid estimate in. To some degree, we anticipate what will happening next
31 in the Runge-Kutta scheme.
33 Once more: Each cell hosts the p predictions created by Runge-Kutta of the
34 pth order. These are stored in the field rhs estimates. The projection
35 combines these predictions using the Butcher tableau and projects the
36 linear combination onto the face. The action set never ever uses what's
37 stored in the value array. It always computes this linear combination.
39 ## Auxiliary parameters
41 Auxiliary parameters are not subject to the PDE in ExaHyPE's jargon. They
42 typically carry material parameters or similar. We project them onto the
43 faces, but here we don't do linear combinations due to the Butcher
44 tableau, as the rhs estimates do not hold any auxiliary parameters at all.
46 ## Last Runge-Kutta step
48 The last Runge-Kutta step is slightly different. After the last
49 Runge-Kutta estimate, the solver combines all the estimates into a new
50 solution. Consult the action set ComputeFinalLinearCombination for details.
51 After this has happened, we could take the plain solution stored within the
52 cell and write this guy onto the faces.
54 Instead, we ignore the face that the action set ComputeFinalLinearCombination
55 would do all of this. Instead, we compute the final linear combination
56 from the rhs guesses (redundantly) and project the outcome onto the faces.
60 To be able to recompute the linear combination of rhs guesses from the
61 Runge-Kutta scheme, this projection has to be invoked before we determine
62 the final linear combination per cell and overwrite the solution in the
63 patch. This means its descend_invocation_order has to be higher than
64 the one from the linear combination computation, as touchCellLastTime()
69 The data is written onto the faces' QUpdate data field. Faces in the
70 Runge-Kutta scheme hold three different Q representations:
72 1. The old solution from the previous time step.
73 2. The current solution.
74 3. The update solution, i.e. the one we have just projected.
76 It is the your job to ensure that the updated solution is later on copied
77 over into the new solution, so it is taken into account by the halo/patch
82 I did not find a convenient, simple way how to tweak the projection from
83 the toolbox according to this scheme. So I ended up with copying the whole
84 thing over and change the critical things myself.
88 Another difference compared to the toolbox projection is that the projection also sets the isUpdated() flag and the
89 UpdatedTimeStamp(). As the projection writes to these two updated records, it is
90 important that you roll it over afterwards. This is done via the mapping
93 It is important to study this action set in combination with DynamicAMR. In the
94 documentation of the latter I explain why we need the guard
96 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97 not marker.hasBeenRefined()
98 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100 if we want to support dynamic coarsening.
102 ## Use action set in additional helper sweeps
104 The action set expects users to specify one predicate per Runge-Kutta step.
105 This means there is one if that checks which Runge-Kutta step is active.
106 This one is typically combined with two other checks: Is the solver
107 currently handling an unrefined cell (we only solve on the finest level)
108 and are we in the right phase of an enclave solve. The latter is relevant
109 if and only if we work with enclave tasking.
111 If the action set is used by an additional grid sweep outside of the actual
112 time stepping, the checks become simpler:
114 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115 project_patch_onto_faces = exahype2.solvers.rkfd.actionsets.ProjectPatchOntoFaces(my_solver)
116 project_patch_onto_faces.guards = [ my_solver._store_cell_data_default_guard() for x in range(0,my_solver.number_of_Runge_Kutta_steps()+1) ]
117 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
119 Here, we basically say "for each unrefined cell always for each Runge-Kutta
120 step as well as for the final linear combination". The latter one is
123 Besides this, you also have to roll over the data:
126 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127 roll_over_projected_faces = exahype2.solvers.rkfd.actionsets.RollOverUpdatedFace(my_solver,
128 my_solver._store_face_data_default_guard(),
130 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132 All solvers at the moment send out their face data in the suspended mode,
133 so you should be fine here.
140 __Template_TouchCellLastTime =
"""
141 logTraceIn( "touchCellLastTime(...)---ProjectPatchOntoFaces" );
142 {% for PREDICATE_NO in range(0,PREDICATES|length-RECONSTRUCTION_STAGES) %}
143 if ({{PREDICATES[PREDICATE_NO]}}) {
145 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithAuxiliaryVariables( 1, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, 0, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}});
146 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithoutAuxiliaryVariables( {{RK_STEPS}}, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, 0, {{NUMBER_OF_UNKNOWNS}}, 0 );
148 {% if RECONSTRUCTION_STAGES != 0 %}
149 {{PRIMARY_VARS_INDICES}}
150 {{AUXILIARY_VARS_INDICES}}
154 // double timeStepSize
155 {{COMPUTE_TIME_STEP_SIZE}}
157 for(int d=0; d<Dimensions; d++) {
159 * d-loop over all dimensions except d. The vector k's entry d is set
160 * to 0. We start with the left/bottom face, i.e. the one closer to the
161 * coordinate system's origin.
163 dfore(k,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},d,0) {
164 for (int i=0; i<{{OVERLAP}}; i++) {
165 tarch::la::Vector<Dimensions,int> patchCell = k;
166 tarch::la::Vector<Dimensions,int> overlapCell = k;
168 overlapCell(d) = i+{{OVERLAP}};
170 // I could use the enumerator as well. Doesn't really matter here. One
171 // thing is tied to ExaHyPE, the other one to the blockstructured toolbox.
172 int overlapCellSerialised = toolbox::blockstructured::serialiseVoxelIndexInOverlap(overlapCell,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},{{OVERLAP}},d);
174 "touchCellLastTime(....)",
175 "project " << patchCell << "->" << overlapCell <<
176 "(" << enumeratorWithAuxiliaryVariables(0,patchCell,0) << "->" << overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}) << "): " <<
177 fineGridCellEulerRKFDQ.value[ enumeratorWithAuxiliaryVariables(0,patchCell,0) ]
180 {% if RECONSTRUCTION_STAGES==0 or PREDICATE_NO==PREDICATES|length-RECONSTRUCTION_STAGES-1 %}
181 for (int j=0; j<{{NUMBER_OF_UNKNOWNS}}; j++) {
182 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
183 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
185 {% if PREDICATE_NO<PREDICATES|length-RECONSTRUCTION_STAGES %}
186 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1]|length) %}
187 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]!=0 %}
188 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] +=
189 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]}} *
190 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},patchCell,j) ];
196 for (int j : primaryVarsIndices) {
197 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
198 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
200 {% if PREDICATE_NO<PREDICATES|length-RECONSTRUCTION_STAGES %}
201 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1]|length) %}
202 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]!=0 %}
203 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] +=
204 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]}} *
205 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},patchCell,j) ];
210 for (int j : auxiliaryVarsIndices) {
211 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] = 0;
212 // actually no need for this initialization as we do overwritten in reconstruction, but we keep it for safety.
216 for (int j={{NUMBER_OF_UNKNOWNS}}; j<{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}; j++) {
217 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
218 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
221 patchCell(d) = i+{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}-{{OVERLAP}};
224 overlapCellSerialised = toolbox::blockstructured::serialiseVoxelIndexInOverlap(overlapCell,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},{{OVERLAP}},d);
226 "touchCellLastTime(....)",
227 "project " << patchCell << "->" << overlapCell <<
228 "(" << enumeratorWithAuxiliaryVariables(0,patchCell,0) << "->" << overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}) << "): " <<
229 fineGridCellEulerRKFDQ.value[ enumeratorWithAuxiliaryVariables(0,patchCell,0) ]
232 {% if RECONSTRUCTION_STAGES==0 or PREDICATE_NO==PREDICATES|length-RECONSTRUCTION_STAGES-1 %}
233 for (int j=0; j<{{NUMBER_OF_UNKNOWNS}}; j++) {
234 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
235 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
237 {% if PREDICATE_NO<PREDICATES|length-RECONSTRUCTION_STAGES %}
238 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1]|length) %}
239 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]!=0 %}
240 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] +=
241 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]}} *
242 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},patchCell,j) ];
248 for (int j : primaryVarsIndices) {
249 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
250 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
252 {% if PREDICATE_NO<PREDICATES|length-RECONSTRUCTION_STAGES %}
253 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1]|length) %}
254 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]!=0 %}
255 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] +=
256 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO+1][WEIGHT_NO]}} *
257 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},patchCell,j) ];
262 for (int j : auxiliaryVarsIndices) {
263 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] = 0;
264 // actually no need for this initialization as we do overwritten in reconstruction, but we keep it for safety.
268 for (int j={{NUMBER_OF_UNKNOWNS}}; j<{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}; j++) {
269 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
270 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
272 } // overlap depth loop
273 } // dfore, i..e loop over submanifold
274 } // loop over dimensions
275 } // if predicate holds, i.e. right RK step
276 {% endfor %} // all the predicates are done now
278 {% for PREDICATE_NO in range(0, RECONSTRUCTION_STAGES) %}
279 //start to project for reconstructed derivatives
280 if ({{PREDICATES[PREDICATE_NO+PREDICATES|length-RECONSTRUCTION_STAGES]}}) {
282 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithAuxiliaryVariables( 1, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, 0, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}});
283 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithoutAuxiliaryVariables( {{RK_STEPS}}, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, 0, {{NUMBER_OF_UNKNOWNS}}, 0 );
285 {% if RECONSTRUCTION_STAGES != 0 %}
286 {{PRIMARY_VARS_INDICES}}
287 {{AUXILIARY_VARS_INDICES}}
291 // double timeStepSize
292 {{COMPUTE_TIME_STEP_SIZE}}
294 for(int d=0; d<Dimensions; d++) {
296 * d-loop over all dimensions except d. The vector k's entry d is set
297 * to 0. We start with the left/bottom face, i.e. the one closer to the
298 * coordinate system's origin.
300 dfore(k,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},d,0) {
301 for (int i=0; i<{{OVERLAP}}; i++) {
302 tarch::la::Vector<Dimensions,int> patchCell = k;
303 tarch::la::Vector<Dimensions,int> overlapCell = k;
305 overlapCell(d) = i+{{OVERLAP}};
307 // I could use the enumerator as well. Doesn't really matter here. One
308 // thing is tied to ExaHyPE, the other one to the blockstructured toolbox.
309 int overlapCellSerialised = toolbox::blockstructured::serialiseVoxelIndexInOverlap(overlapCell,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},{{OVERLAP}},d);
311 "touchCellLastTime(....)",
312 "project " << patchCell << "->" << overlapCell <<
313 "(" << enumeratorWithAuxiliaryVariables(0,patchCell,0) << "->" << overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}) << "): " <<
314 fineGridCellEulerRKFDQ.value[ enumeratorWithAuxiliaryVariables(0,patchCell,0) ]
316 for (int j : primaryVarsIndices) {
317 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
318 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
320 {% if PREDICATE_NO<PREDICATES|length %}
321 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO]|length) %}
322 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]!=0 %}
323 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] +=
324 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]}} *
325 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},patchCell,j) ];
330 for (int j : auxiliaryVarsIndices) {
331 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
332 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{PREDICATE_NO}},patchCell,j) ];
333 } //abuse of RHS, auxiliary variables are stored there.
335 for (int j={{NUMBER_OF_UNKNOWNS}}; j<{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}; j++) {
336 {{FACES_ACCESSOR}}(d).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
337 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
340 patchCell(d) = i+{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}-{{OVERLAP}};
343 overlapCellSerialised = toolbox::blockstructured::serialiseVoxelIndexInOverlap(overlapCell,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},{{OVERLAP}},d);
345 "touchCellLastTime(....)",
346 "project " << patchCell << "->" << overlapCell <<
347 "(" << enumeratorWithAuxiliaryVariables(0,patchCell,0) << "->" << overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}) << "): " <<
348 fineGridCellEulerRKFDQ.value[ enumeratorWithAuxiliaryVariables(0,patchCell,0) ]
350 for (int j : primaryVarsIndices) {
351 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
352 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
354 {% if PREDICATE_NO<PREDICATES|length %}
355 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO]|length) %}
356 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]!=0 %}
357 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] +=
358 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]}} *
359 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},patchCell,j) ];
364 for (int j : auxiliaryVarsIndices) {
365 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
366 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{PREDICATE_NO}},patchCell,j) ];
367 } //abuse of RHS, auxiliary variables are stored there.
369 for (int j={{NUMBER_OF_UNKNOWNS}}; j<{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}; j++) {
370 {{FACES_ACCESSOR}}(d+Dimensions).value[overlapCellSerialised*({{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}})+j] =
371 {{CELL_ACCESSOR}}.value[ enumeratorWithAuxiliaryVariables(0,patchCell,j) ];
373 } // overlap depth loop
374 } // dfore, i..e loop over submanifold
375 } // loop over dimensions
376 } // if predicate holds, i.e. right RK step
377 {% endfor %} // all the predicates are done now
379 for (int d=0; d<Dimensions; d++) {
380 {{FACE_METADATA_ACCESSOR}}(d).setUpdated(1,true);
381 {{FACE_METADATA_ACCESSOR}}(d).setUpdatedTimeStamp(1,{{CELL_METADATA_ACCESSOR}}.getTimeStamp());
382 {{FACE_METADATA_ACCESSOR}}(d+Dimensions).setUpdated(0,true);
383 {{FACE_METADATA_ACCESSOR}}(d+Dimensions).setUpdatedTimeStamp(0,{{CELL_METADATA_ACCESSOR}}.getTimeStamp());
385 logTraceOut( "touchCellLastTime(...)---ProjectPatchOntoFaces" );
389 AbstractRKFDActionSet.__init__(self, solver)
396 raise Exception(
"Guards are not initialised")
403 and len(new_guards) != self.
_solver.number_of_Runge_Kutta_steps() + 1
406 "Expect one guard per Runge Kutta step and a projection throughout the initialisation. Have {} steps but got guards {}".format(
407 self.
_solver.number_of_Runge_Kutta_steps(), new_guards
413 return __name__.replace(
".py",
"").replace(
".",
"_")
417 if operation_name == ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
419 if self.
_solver._patch_overlap_update.dim[0] % 2 != 0:
421 "Error: Patch associated to face has to have even number of cells. Otherwise, it is not a symmetric overlap."
423 assert patch_overlap.dim[0] % 2 == 0
425 print(
"Error: Can only handle square patches.")
426 assert patch.dim[0] == patch.dim[1]
427 if self.
_solver._patch_overlap_update.dim[1] != self.
_solver._patch.dim[0]:
428 print(
"Error: Patch of overlap and patch of cell have to match")
430 self.
_solver._patch_overlap_update.dim[1]
435 d[
"FACE_METADATA_ACCESSOR"] = (
436 "fineGridFaces" + self.
_solver._face_label.name
438 d[
"CELL_METADATA_ACCESSOR"] = (
439 "fineGridCell" "" + self.
_solver._cell_label.name
441 d[
"FACES_ACCESSOR"] = (
442 "fineGridFaces" + self.
_solver._patch_overlap_update.name
444 d[
"CELL_ACCESSOR"] =
"fineGridCell" + self.
_solver._patch.name
447 "BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES"
450 self.
_solver._init_dictionary_with_default_parameters(d)
451 self.
_solver.add_entries_to_text_replacement_dictionary(d)
459#include "peano4/utils/Loop.h"
460#include "toolbox/blockstructured/Enumeration.h"
461#include "exahype2/fd/BoundaryConditions.h"
462#include "exahype2/enumerator/enumerator.h"
463""" + AbstractRKFDActionSet.get_includes(
Project patch data onto faces, so the faces hold valid data which can feed into the subsequent Runge-...
get_includes(self)
Return include statements that you need.
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
str __Template_TouchCellLastTime
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, solver)
solver: ADERDG Reference to creating class
Action set (reactions to events)