Peano
Loading...
Searching...
No Matches
ProjectPatchOntoFaces.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
3import peano4
4import jinja2
5
6from .AbstractRKFDActionSet import AbstractRKFDActionSet
7
8from peano4.solversteps.ActionSet import ActionSet
9
10from exahype2.solvers.ButcherTableau import ButcherTableau
11
12
14 """!
15
16 Project patch data onto faces, so the faces hold valid data which can feed into the subsequent Runge-Kutta step
17
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.
28
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.
32
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.
38
39 ## Auxiliary parameters
40
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.
45
46 ## Last Runge-Kutta step
47
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.
53
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.
57
58 ## Invocation order
59
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()
65 inverts this order.
66
67 ## Write data
68
69 The data is written onto the faces' QUpdate data field. Faces in the
70 Runge-Kutta scheme hold three different Q representations:
71
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.
75
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
78 reconstruction.
79
80 ## Realisation
81
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.
85
86 ## Boundary flags
87
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
91 RollOverUpdatedFace.
92
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
95
96 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97 not marker.hasBeenRefined()
98 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99
100 if we want to support dynamic coarsening.
101
102 ## Use action set in additional helper sweeps
103
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.
110
111 If the action set is used by an additional grid sweep outside of the actual
112 time stepping, the checks become simpler:
113
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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118
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
121 reflected by the +1.
122
123 Besides this, you also have to roll over the data:
124
125
126 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127 roll_over_projected_faces = exahype2.solvers.rkfd.actionsets.RollOverUpdatedFace(my_solver,
128 my_solver._store_face_data_default_guard(),
129 )
130 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131
132 All solvers at the moment send out their face data in the suspended mode,
133 so you should be fine here.
134
135
136 """
137
138
139
140 __Template_TouchCellLastTime = """
141 logTraceIn( "touchCellLastTime(...)---ProjectPatchOntoFaces" );
142 {% for PREDICATE_NO in range(0,PREDICATES|length-RECONSTRUCTION_STAGES) %}
143 if ({{PREDICATES[PREDICATE_NO]}}) {
144
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 );
147
148 {% if RECONSTRUCTION_STAGES != 0 %}
149 {{PRIMARY_VARS_INDICES}}
150 {{AUXILIARY_VARS_INDICES}}
151 {% endif %}
152
153 // Set the variable
154 // double timeStepSize
155 {{COMPUTE_TIME_STEP_SIZE}}
156
157 for(int d=0; d<Dimensions; d++) {
158 /**
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.
162 */
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;
167 patchCell(d) = i;
168 overlapCell(d) = i+{{OVERLAP}};
169
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);
173 logDebug(
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) ]
178 );
179
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) ];
184
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) ];
191 {% endif %}
192 {% endfor %}
193 {% endif %}
194 }
195 {% else %}
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) ];
199
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) ];
206 {% endif %}
207 {% endfor %}
208 {% endif %}
209 }
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.
213 }
214 {% endif %}
215
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) ];
219 }
220
221 patchCell(d) = i+{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}-{{OVERLAP}};
222 overlapCell(d) = i;
223
224 overlapCellSerialised = toolbox::blockstructured::serialiseVoxelIndexInOverlap(overlapCell,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},{{OVERLAP}},d);
225 logDebug(
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) ]
230 );
231
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) ];
236
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) ];
243 {% endif %}
244 {% endfor %}
245 {% endif %}
246 }
247 {% else %}
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) ];
251
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) ];
258 {% endif %}
259 {% endfor %}
260 {% endif %}
261 }
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.
265 }
266 {% endif %}
267
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) ];
271 }
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
277
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]}}) {
281
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 );
284
285 {% if RECONSTRUCTION_STAGES != 0 %}
286 {{PRIMARY_VARS_INDICES}}
287 {{AUXILIARY_VARS_INDICES}}
288 {% endif %}
289
290 // Set the variable
291 // double timeStepSize
292 {{COMPUTE_TIME_STEP_SIZE}}
293
294 for(int d=0; d<Dimensions; d++) {
295 /**
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.
299 */
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;
304 patchCell(d) = i;
305 overlapCell(d) = i+{{OVERLAP}};
306
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);
310 logDebug(
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) ]
315 );
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) ];
319
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) ];
326 {% endif %}
327 {% endfor %}
328 {% endif %}
329 }
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.
334
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) ];
338 }
339
340 patchCell(d) = i+{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}-{{OVERLAP}};
341 overlapCell(d) = i;
342
343 overlapCellSerialised = toolbox::blockstructured::serialiseVoxelIndexInOverlap(overlapCell,{{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},{{OVERLAP}},d);
344 logDebug(
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) ]
349 );
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) ];
353
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) ];
360 {% endif %}
361 {% endfor %}
362 {% endif %}
363 }
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.
368
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) ];
372 }
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
378
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());
384 }
385 logTraceOut( "touchCellLastTime(...)---ProjectPatchOntoFaces" );
386"""
387
388 def __init__(self, solver):
389 AbstractRKFDActionSet.__init__(self, solver)
390 self._guards = []
392
393 @property
394 def guards(self):
395 if self._guards == []:
396 raise Exception("Guards are not initialised")
397 return self._guards
398
399 @guards.setter
400 def guards(self, new_guards):
401 if (
402 new_guards != []
403 and len(new_guards) != self._solver.number_of_Runge_Kutta_steps() + 1
404 ):
405 raise Exception(
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
408 )
409 )
410 self._guards = new_guards
411
413 return __name__.replace(".py", "").replace(".", "_")
414
415 def get_body_of_operation(self, operation_name):
416 result = "\n"
417 if operation_name == ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
418 d = {}
419 if self._solver._patch_overlap_update.dim[0] % 2 != 0:
420 print(
421 "Error: Patch associated to face has to have even number of cells. Otherwise, it is not a symmetric overlap."
422 )
423 assert patch_overlap.dim[0] % 2 == 0
424 if self._solver._patch.dim[0] != self._solver._patch.dim[1]:
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")
429 assert (
430 self._solver._patch_overlap_update.dim[1]
431 == self._solver._patch.dim[0]
432 )
433
434 d["PREDICATES"] = self.guardsguards
435 d["FACE_METADATA_ACCESSOR"] = (
436 "fineGridFaces" + self._solver._face_label.name
437 )
438 d["CELL_METADATA_ACCESSOR"] = (
439 "fineGridCell" "" + self._solver._cell_label.name
440 )
441 d["FACES_ACCESSOR"] = (
442 "fineGridFaces" + self._solver._patch_overlap_update.name
443 )
444 d["CELL_ACCESSOR"] = "fineGridCell" + self._solver._patch.name
445 d["BUTCHER_TABLEAU_WEIGHTS"] = self._butcher_tableau.weight_matrix()
446 d[
447 "BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES"
448 ] = self._butcher_tableau.time_step_sizes()
449
450 self._solver._init_dictionary_with_default_parameters(d)
451 self._solver.add_entries_to_text_replacement_dictionary(d)
452
453 result = jinja2.Template(self.__Template_TouchCellLastTime).render(**d)
454 pass
455 return result
456
457 def get_includes(self):
458 return """
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(
464 self
465 )
Project patch data onto faces, so the faces hold valid data which can feed into the subsequent Runge-...
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
Action set (reactions to events)
Definition ActionSet.py:6