3from enum
import IntEnum
9 All arrays are held on the call stack. Might not work with PGI compilers or
10 Clang, but it does work with GCC and Intel. This mode is the preferred one,
11 as all memory frees are implicitly done.
15 Create data on the heap. Done via a plain new. You have to delete the
16 reconstructed data yourself.
19 HeapWithoutDelete = 2,
21 Use tarch::allocateMemory()
24 HeapThroughTarchWithoutDelete = 4,
26 Use tarch::allocateMemory()
28 ManagedSharedAcceleratorDeviceMemoryThroughTarch = 5,
29 ManagedSharedAcceleratorDeviceMemoryThroughTarchWithoutDelete = 6
35 This class assumes that you have NxNxN patch within your block. It also assumes that
36 you have an 2MxNxN patch on your faces. M<N. The code interprets these face-associated
37 data as overlap with the patch, hooks into touchCellLastTime, and projects the cell's
38 patch data onto the overlap (simple copy). See ProjectPatchOntoFaces for details.
40 If the face patches are auxiliary patches holding copies from the cell patches, then
41 we can reconstruct N+2M x N+2M x N+2M patches per cell whenever we hit a cell: We
42 create a new temporary array, and copy data from both the cell patch and the faces
43 into this array (gather operation). After that, we can launch the passed functor
44 giving it access to the temporary, large array plus the original patch data.
46 If you want to swap the functor, please replace self.functor_implementation,
47 and ensure that all external references (text replacements) are already
48 resolved. Consult _add_action_set_entries_to_dictionary() for details.
55 functor_implementation,
56 reconstructed_array_memory_location=ReconstructedArrayMemoryLocation.Heap,
58 add_assertions_to_halo_exchange = True
62 patch: peano4.datamodel.Patch
63 Patch which is to be used
65 patch_overlap: peano4.datamodel.Patch
66 Consult remark above about how the dimensions of this overlap
69 ## Functor_implementation
71 The functor implementation is a plain C/C++
73 - If you want to use brackets in your implementation, please use double brackets {{ }} as
74 the template system otherwise gets confused.
75 - The following C++ variables are defined:
80 Both are plain double pointers.
84 I use quite a lot of validitiy checks for the copied data via comparison to its self. This
85 way, I can at least spot nans. I use the dictionary entries ASSERTION_WITH_X_ARGUMENTS to
86 realise this, and they are, by default, set to Peano's assertion macros. You can redefine
90 super(ReconstructPatchAndApplyFunctor,self).
__init__(descend_invocation_order=1,parallel=
False)
92 assert isinstance(reconstructed_array_memory_location,ReconstructedArrayMemoryLocation),
"type of argument is {}".format( type(reconstructed_array_memory_location) )
94 if patch_overlap.dim[0] % 2 != 0:
95 print(
"Error: Patch associated to face has to have even number of cells. Otherwise, it is not a symmetric overlap." )
96 assert( patch_overlap.dim[0] % 2 == 0 )
97 if patch.dim[0] != patch.dim[1]:
98 print(
"Error: Can only handle square patches." )
99 assert( patch.dim[0] == patch.dim[1] )
100 if patch_overlap.dim[1] != patch.dim[0]:
101 print(
"Error: Patch of overlap and patch of cell have to match" )
102 assert( patch_overlap.dim[1] == patch.dim[0] )
121 If you inherit from this class and specialise this routine, you can add
122 more entries to the dictionary. This is important if you change the
123 actual compute kernels (templates) and use futher unknowns in there. If
124 you specialise the function, i.e. overwrite it in a subclass, please
125 ensure that you use the superclass still.
127 Please note that we do not replace entries in the functor implementation:
128 The overall code created by this action set consists of different parts
129 realised as different templates. The templates are subject to a text
130 replacement system and then are concatenated. One of the things that is
131 replaced within the templates is the actual functor implementation
132 (CELL_FUNCTOR_IMPLEMENTATION). If this one contains again free parameters,
133 it is your responsibility to first resolve those parameters, and then to
134 reset the functor in this routine.
136 If you want to replace the functor, you can hence either first call this
137 routine and then change d["CELL_FUNCTOR_IMPLEMENTATION"] or you set
138 self.functor_implementation and then you call this routine, i.e. the
142 d[
"GUARD" ] = self.
guard
155 d[
"FACES_ACCESSOR" ] =
"fineGridFaces" + self.
overlap_name
156 d[
"CELL_ACCESSOR" ] =
"fineGridCell" + self.
patch_name
158 d[
"ASSERTION_WITH_1_ARGUMENTS" ] =
"assertion1"
159 d[
"ASSERTION_WITH_2_ARGUMENTS" ] =
"assertion2"
160 d[
"ASSERTION_WITH_3_ARGUMENTS" ] =
"assertion3"
161 d[
"ASSERTION_WITH_4_ARGUMENTS" ] =
"assertion4"
162 d[
"ASSERTION_WITH_5_ARGUMENTS" ] =
"assertion5"
163 d[
"ASSERTION_WITH_6_ARGUMENTS" ] =
"assertion6"
164 d[
"ASSERTION_WITH_7_ARGUMENTS" ] =
"assertion7"
169 d[
"ASSERTION_PREFIX_FOR_HALO" ] =
"false"
171 d[
"ASSERTION_PREFIX_FOR_HALO" ] =
"true"
174 d[
"CREATE_RECONSTRUCTED_PATCH" ] =
"""
176 double* oldQWithHalo = new double[""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_2D" ] +
"""];
178 double* oldQWithHalo = new double[""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_3D" ] +
"""];
182 d[
"CREATE_RECONSTRUCTED_PATCH" ] =
"""
184 double oldQWithHalo[""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_2D" ] +
"""];
186 double oldQWithHalo[""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_3D" ] +
"""];
190 d[
"CREATE_RECONSTRUCTED_PATCH" ] =
"""
192 double* oldQWithHalo = ::tarch::allocateMemory<double>(""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_2D" ] +
""", ::tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory);
194 double* oldQWithHalo = ::tarch::allocateMemory<double>(""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_3D" ] +
""", ::tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory);
198 d[
"CREATE_RECONSTRUCTED_PATCH" ] =
"""
200 double* oldQWithHalo = ::tarch::allocateMemory<double>(""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_2D" ] +
""", ::tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory);
202 double* oldQWithHalo = ::tarch::allocateMemory<double>(""" + d[
"NUMBER_OF_DOUBLE_VALUES_IN_RECONSTRUCTED_PATCH_3D" ] +
""", ::tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory);
209 d[
"DESTROY_RECONSTRUCTED_PATCH" ] =
"""
210 delete[] oldQWithHalo;
213 d[
"DESTROY_RECONSTRUCTED_PATCH" ] =
"""
214 ::tarch::freeMemory(oldQWithHalo, tarch::MemoryLocation::Heap );
217 d[
"DESTROY_RECONSTRUCTED_PATCH" ] =
"""
218 ::tarch::freeMemory(oldQWithHalo, tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory );
221 d[
"DESTROY_RECONSTRUCTED_PATCH" ] =
""
224 return """ _treeNumber = treeNumber;
229 return __name__.replace(
".py",
"").replace(
".",
"_")
236 _Template_TouchCellFirstTime_Preamble =
"""
237 auto serialisePatchIndex = [](tarch::la::Vector<Dimensions,int> overlapCell, int normal) {{
240 for (int d=0; d<Dimensions; d++) {{
241 result += overlapCell(d) * base;
246 base *= {DOFS_PER_AXIS};
253 logTraceInWith1Argument( "touchCellFirstTime(...)", marker.toString() );
255 {CREATE_RECONSTRUCTED_PATCH}
259 _Template_TouchCellFirstTime_Fill_Patch =
"""
261 // Loop over original patch (k) and copy stuff over.
263 dfor(sourceCell,{DOFS_PER_AXIS}) {{
264 tarch::la::Vector<Dimensions,int> destinationCell = sourceCell + tarch::la::Vector<Dimensions,int>({OVERLAP});
265 int sourceCellSerialised = peano4::utils::dLinearised(sourceCell,{DOFS_PER_AXIS});
266 int destinationCellSerialised = peano4::utils::dLinearised(destinationCell,{DOFS_PER_AXIS} + 2*{OVERLAP});
267 for (int j=0; j<{UNKNOWNS}; j++) {{
268 oldQWithHalo[destinationCellSerialised*{UNKNOWNS}+j] = {CELL_ACCESSOR}.value[ sourceCellSerialised*{UNKNOWNS}+j ];
269 {ASSERTION_WITH_4_ARGUMENTS}( oldQWithHalo[destinationCellSerialised*{UNKNOWNS}+j]==oldQWithHalo[destinationCellSerialised*{UNKNOWNS}+j], sourceCell, j, _treeNumber, marker.toString() );
275 _Template_TouchCellFirstTime_Fill_Halos =
"""
277 // Bring in the auxiliary patches, i.e. befill halo
279 for(int d=0; d<Dimensions; d++) {{
280 logTraceInWith1Argument( "touchCellFirstTime(...)::loopOverFace", d );
282 // d-loop over all dimensions except d. The vector k's entry d is set
283 // to 0. We start with the left/bottom face, i.e. the one closer to the
284 // coordinate system's origin.
286 dfore(k,{DOFS_PER_AXIS},d,0) {{
287 for (int i=0; i<{OVERLAP}; i++) {{
288 tarch::la::Vector<Dimensions,int> destinationCell = k + tarch::la::Vector<Dimensions,int>({OVERLAP});
289 tarch::la::Vector<Dimensions,int> sourceCell = k;
290 destinationCell(d) = i;
293 int destinationCellSerialised = peano4::utils::dLinearised(destinationCell,{DOFS_PER_AXIS} + 2*{OVERLAP});
294 int sourceCellSerialised = serialisePatchIndex(sourceCell,d);
296 for (int j=0; j<{UNKNOWNS}; j++) {{
297 oldQWithHalo[ destinationCellSerialised*{UNKNOWNS}+j ] = {FACES_ACCESSOR}(d).value[ sourceCellSerialised*{UNKNOWNS}+j ];
298 {ASSERTION_WITH_7_ARGUMENTS}(
299 {ASSERTION_PREFIX_FOR_HALO} or
300 oldQWithHalo[ destinationCellSerialised*{UNKNOWNS}+j ]==oldQWithHalo[ destinationCellSerialised*{UNKNOWNS}+j ],
301 sourceCell, destinationCell, j, d, marker.toString(), _treeNumber, marker.toString()
305 destinationCell(d) = i+{DOFS_PER_AXIS}+{OVERLAP};
306 sourceCell(d) = i+{OVERLAP};
308 destinationCellSerialised = peano4::utils::dLinearised(destinationCell,{DOFS_PER_AXIS} + 2*{OVERLAP});
309 sourceCellSerialised = serialisePatchIndex(sourceCell,d);
310 for (int j=0; j<{UNKNOWNS}; j++) {{
311 oldQWithHalo[ destinationCellSerialised*{UNKNOWNS}+j ] = {FACES_ACCESSOR}(d+Dimensions).value[ sourceCellSerialised*{UNKNOWNS}+j ];
312 {ASSERTION_WITH_7_ARGUMENTS}(
313 {ASSERTION_PREFIX_FOR_HALO} or
314 oldQWithHalo[ destinationCellSerialised*{UNKNOWNS}+j ]==oldQWithHalo[ destinationCellSerialised*{UNKNOWNS}+j ],
315 sourceCell, destinationCell, j, d, marker.toString(), _treeNumber, marker.toString()
320 logTraceOut( "touchCellFirstTime(...)::loopOverFace" );
325 _Template_TouchCellFirstTime_Core =
"""
326 double* newQ = {CELL_ACCESSOR}.value;
327 {CELL_FUNCTOR_IMPLEMENTATION}
329 {DESTROY_RECONSTRUCTED_PATCH}
333 _Template_TouchCellFirstTime_Epilogue =
"""
334 logTraceOut( "touchCellFirstTime(...)" );
341 if operation_name==ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
354 return """int _treeNumber;
361#include "peano4/utils/Loop.h"
362#include "tarch/multicore/Core.h"
Action set (reactions to events)