Peano
Loading...
Searching...
No Matches
ProjectPatchWithHaloOntoFaces.py
Go to the documentation of this file.
1# This file is part of the Peano project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3from peano4.api.solversteps.ActionSet import ActionSet
4
5
7 """!
8
9 Write a patch with halo onto the overlaps of all of its faces
10
11 Counterpart of ReconstructPatchWithHalo: That action set gathers a cell's
12 NxNxN patch and the 2MxNxN overlaps of its faces into one patch with halo
13 of (N+2M)x(N+2M)x(N+2M) entries. This action set takes such a patch with
14 halo and writes it back onto the face overlaps. Different to
15 ProjectPatchOntoFaces, it writes both halves of each overlap: the half
16 inside the cell from the patch, and the half outside of the cell from the
17 halo. Afterwards, the overlaps hold exactly the data the patch with halo
18 has been reconstructed from. The corners of the halo are not used.
19
20 The action set is used to restore the face data from a checkpoint
21 (@ref exahype2.api.blockstructured.LoadCheckpoint.LoadCheckpoint): Along the
22 domain boundary, the outer half of each overlap holds the ghost data. A
23 projection from the patch alone cannot restore it.
24
25 Faces between two cells receive their data from both cells. If the patches
26 with halo are consistent, as they are in a checkpoint, both cells write the
27 same values.
28
29 """
30
31 def __init__(self,
32 patch_with_halo,
33 patch_overlap,
34 guard="true",
35 additional_includes=""):
36 """!
37
38 @param patch_with_halo: peano4.api.datamodel.Patch
39 Cell data of (N+2M)^d entries which is projected.
40
41 @param patch_overlap: peano4.api.datamodel.Patch
42 Face data of 2M x N^(d-1) entries which is written.
43
44 @param guard: str
45 C++ predicate. The action set only projects cells for which it holds.
46
47 @param additional_includes: str
48 Further includes the generated code needs, e.g. for the guard.
49
50 """
51 super(ProjectPatchWithHaloOntoFaces, self).__init__(descend_invocation_order=1, parallel=False)
52
53 if patch_overlap.dim[0] % 2 != 0:
54 raise Exception("Patch associated to face has to have even number of cells. Otherwise, it is not a symmetric overlap.")
55 if patch_with_halo.dim[0] != patch_overlap.dim[1] + patch_overlap.dim[0]:
56 raise Exception("patch_with_halo has to hold the face overlap's tangential extent plus its full width per axis.")
57
58 self.guard = guard
59 self.unknowns = int(patch_with_halo.no_of_unknowns)
60 self.dofs_per_axis = int(patch_overlap.dim[1])
61 self.overlap = int(patch_overlap.dim[0] // 2)
62 self.patch_with_halo = patch_with_halo.name
63 self.patch_overlap = patch_overlap.name
64 self.additional_includes = additional_includes
65
67 return ""
68
70 return __name__.replace(".py", "").replace(".", "_")
71
73 return False
74
75 def get_body_of_operation(self, operation_name):
76 if operation_name != ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
77 return "\n"
78 return f"""
79 logTraceInWith1Argument( "touchCellFirstTime(...)", marker.toString() );
80
81 constexpr int Unknowns = {self.unknowns};
82 constexpr int DoFsPerAxis = {self.dofs_per_axis};
83 constexpr int Overlap = {self.overlap};
84 constexpr int EntriesPerAxisHalo = DoFsPerAxis + 2 * Overlap;
85
86 // Index of an entry within a face overlap with 2*Overlap entries along the
87 // normal and DoFsPerAxis entries along all other axes
88 auto serialiseOverlapIndex = [](const tarch::la::Vector<Dimensions,int>& overlapCell, int normal) {{
89 int base = 1;
90 int result = 0;
91 for (int d=0; d<Dimensions; d++) {{
92 result += overlapCell(d) * base;
93 base *= (d==normal) ? 2*Overlap : DoFsPerAxis;
94 }}
95 return result;
96 }};
97
98 const double* patchWithHalo = fineGridCell{self.patch_with_halo}.value;
99
100 for (int d=0; d<Dimensions; d++) {{
101 dfore(k,DoFsPerAxis,d,0) {{
102 for (int j=0; j<2*Overlap; j++) {{
103 tarch::la::Vector<Dimensions,int> overlapCell = k;
104 overlapCell(d) = j;
105 const int overlapCellSerialised = serialiseOverlapIndex(overlapCell,d);
106
107 // Left/bottom face: entries 0 to 2*Overlap-1 along d of the patch with halo
108 tarch::la::Vector<Dimensions,int> patchCell = k + tarch::la::Vector<Dimensions,int>(Overlap);
109 patchCell(d) = j;
110 int patchCellSerialised = peano4::utils::dLinearised(patchCell,EntriesPerAxisHalo);
111 for (int unknown=0; unknown<Unknowns; unknown++) {{
112 fineGridFaces{self.patch_overlap}(d).value[overlapCellSerialised*Unknowns+unknown] = patchWithHalo[patchCellSerialised*Unknowns+unknown];
113 }}
114
115 // Right/top face: entries DoFsPerAxis to DoFsPerAxis+2*Overlap-1 along d
116 patchCell(d) = DoFsPerAxis + j;
117 patchCellSerialised = peano4::utils::dLinearised(patchCell,EntriesPerAxisHalo);
118 for (int unknown=0; unknown<Unknowns; unknown++) {{
119 fineGridFaces{self.patch_overlap}(d+Dimensions).value[overlapCellSerialised*Unknowns+unknown] = patchWithHalo[patchCellSerialised*Unknowns+unknown];
120 }}
121 }}
122 }}
123 }}
124
125 logTraceOut( "touchCellFirstTime(...)" );
126"""
127
128 def get_guard_of_operation(self, operation_name):
129 if operation_name == ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
130 return self.guard
131 return "true"
132
133 def get_attributes(self):
134 return ""
135
136 def get_includes(self):
137 return """
138#include "peano4/utils/Loop.h"
139""" + self.additional_includes
Write a patch with halo onto the overlaps of all of its faces.
__init__(self, patch_with_halo, patch_overlap, guard="true", additional_includes="")
user_should_modify_template(self)
Is the user allowed to modify the output.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
get_guard_of_operation(self, operation_name)
Return the guard of an operation.
get_attributes(self)
Return attributes as copied and pasted into the generated class.
Action set (reactions to events)
Definition ActionSet.py:6