Peano
Loading...
Searching...
No Matches
FaceLabel.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
5import dastgen2
7import jinja2
8
9
11 def get_attribute_name(solver_name):
12 return solver_name + "FaceLabel"
13
14
15 """
16
17 SetLabels is an action set which is automatically merged into all ExaHyPE2
18 steps by the project. There's nothing for the user solvers to be done here.
19
20 There are four fields which have a value per side of the face:
21
22 - Updated: Boolean[2]
23 Shows if the corresponding adjacent cell (left vs right) has performed a
24 time step.
25 - UpdatedTimeStamp: Double[2]
26 Used only by the Finite Volumes solver so far to store a new time stamp
27 temporarily which is later on rolled over into the real time stamp.
28 - NewTimeStamp: Double[2]
29 New (and also current time stamp). This time stamp determines for example
30 if you want to do a local time step or not.
31 - OldTimeStamp: Double[2]
32 Time stamp of previous time step. The old time stamp is required for the
33 in-time interpolation, e.g.
34
35 In addition there are three fields that are in common to both faces:
36
37 - Boundary: Boolean
38 Shows whether the cell is at a domain boundary. This is set upon creation
39 by checking one's position in relation to the domain boundaries.
40 - IsHanging: Boolean
41 This states whether the face is a hanging face, i.e. whether the face
42 is adjacent to a cell with a coarser refinement level and therefore there
43 is no face directly "across" from this one for it to merge with.
44 - AboveHanging: Boolean
45 This states whether the face is above a hanging face, i.e. whether the
46 face is adjacent to a cell with a finer refinement level and therefore
47 the face directly "across" from this one will likely contain no useful
48 information, meaning said information must be obtained from the finer
49 level underneath this one.
50
51 ## Initialisation
52
53 The initialisation sets the boundary flag if the face is on the boundary.
54 It also sets the time stamps all to zero. This is actually a tricky thing
55 to do, so I'm not sure if it is a good idea: the DG solvers for example
56 require the face time stamps to be set properly. The Finite Volumes solver
57 in return benefits if it is not (properly) initialised, as it then is
58 simpler to spot inconsistencies and missing data updates.
59
60 ## IsHanging and AboveHanging
61
62 IsHanging is a redundant information. If a face is hanging, it is not held
63 persistently. Consequently, we get a createHangingFace() in each and every
64 mesh traversal and hence know implicitly that the face is hanging. The flag
65 therefore replicates information which is implicitly available anyway.
66
67 AboveHanging is stored persistently. At the moment, it is only used by
68 ADER-DG solvers. Most solvers should be able to work without this additional
69 information. For ADER-DG, it is used to ensure that Riemann-solves
70 are performed on fine faces and not on coarse faces, as the later would
71 cause unphysical transfer of information which lead to uncontrolled
72 oscillations.
73
74 AboveHanging is historical information. If the mesh is just about to refine,
75 then the flag might not be set even though we literally just add new
76 "subfaces". If a mesh coarsens, the flag might be set, even though we
77 literally just remove the adjacen fine grid cells. If you need to know what
78 happened in this very iteration, you can read out the flag NewAboveHanging,
79 but this one is only valid in touchFaceLastTime(), i.e. while we ascend in
80 the tree.
81
82 Please consult peano4::datamanagement::FaceMarger::hasBeenRefined() in this
83 context, too.
84
85 """
86 def __init__(self, solver_name):
87 super(UpdateFaceLabel,self).__init__(descend_invocation_order=1,parallel=False)
88 self._solver_name = solver_name
89 pass
90
91
93 return ""
94
95
97 return ""
98
99
100 _Template_TouchFaceFirstTime = """
101 fineGridFace{{FACE_LABEL_NAME}}.setUpdated( false );
102 fineGridFace{{FACE_LABEL_NAME}}.setNewAboveHanging( false );
103"""
104
105
106 _Template_CreateFace = """
107 logTraceInWith1Argument( "createPersistentFace(...)", marker.toString() );
108
109 tarch::la::Vector<Dimensions, double> offset(DomainOffset);
110 tarch::la::Vector<Dimensions, double> size(DomainSize);
111 bool isBoundary = false;
112 for (int d=0; d<Dimensions; d++) {
113 isBoundary |= tarch::la::equals( marker.x()(d), offset(d) );
114 isBoundary |= tarch::la::equals( marker.x()(d), offset(d) + size(d) );
115 }
116 fineGridFace{{FACE_LABEL_NAME}}.setBoundary( isBoundary );
117 fineGridFace{{FACE_LABEL_NAME}}.setIsHanging( false );
118 fineGridFace{{FACE_LABEL_NAME}}.setAboveHanging( false );
119 fineGridFace{{FACE_LABEL_NAME}}.setNewAboveHanging( false );
120 fineGridFace{{FACE_LABEL_NAME}}.setUpdatedTimeStamp( 0.0 );
121 fineGridFace{{FACE_LABEL_NAME}}.setNewTimeStamp( 0.0 );
122 fineGridFace{{FACE_LABEL_NAME}}.setOldTimeStamp( 0.0 );
123
124 logTraceOutWith1Argument( "createPersistentFace(...)", fineGridFace{{FACE_LABEL_NAME}}.toString() );
125"""
126
127
128 _Template_CreateHangingFace = """
129 logTraceInWith1Argument( "createHangingFace(...)", marker.toString() );
130 fineGridFace{{FACE_LABEL_NAME}}.setIsHanging( true );
131 coarseGridFaces{{FACE_LABEL_NAME}}(marker.getSelectedFaceNumber()).setNewAboveHanging( true );
132 logTraceOutWith1Argument( "createHangingFace(...)", fineGridFace{{FACE_LABEL_NAME}}.toString() );
133"""
134
135
136 _Template_DestroyHangingFace = """
137"""
138
139
140 _Template_TouchFaceLastTime = """
141 logTraceInWith1Argument( "touchFaceLastTime(...)", marker.toString() );
142 fineGridFace{{FACE_LABEL_NAME}}.setAboveHanging( fineGridFace{{FACE_LABEL_NAME}}.getNewAboveHanging() );
143 logTraceOutWith1Argument( "touchFaceLastTime(...)", fineGridFace{{FACE_LABEL_NAME}}.toString() );
144"""
145
146
148 return __name__.replace(".py", "").replace(".", "_")
149
150
152 return False
153
154
155 def get_body_of_operation(self,operation_name):
156 result = "\n"
157
158 d = {}
159 d[ "FACE_LABEL_NAME" ] = UpdateFaceLabel.get_attribute_name(self._solver_name)
160
161 if operation_name==ActionSet.OPERATION_CREATE_PERSISTENT_FACE or operation_name==ActionSet.OPERATION_CREATE_HANGING_FACE:
162 result = jinja2.Template( self._Template_CreateFace ).render( **d )
163 if operation_name==ActionSet.OPERATION_CREATE_HANGING_FACE:
164 result = jinja2.Template( self._Template_CreateHangingFace ).render( **d )
165 if operation_name==ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME:
166 result = jinja2.Template( self._Template_TouchFaceFirstTime ).render( **d )
167 if operation_name==ActionSet.OPERATION_TOUCH_FACE_LAST_TIME:
168 result = jinja2.Template( self._Template_TouchFaceLastTime ).render( **d )
169 if operation_name==ActionSet.OPERATION_DESTROY_HANGING_FACE:
170 result = jinja2.Template( self._Template_DestroyHangingFace ).render( **d )
171
172 return result
173
174
175 def get_attributes(self):
176 return ""
177
178
179 def get_includes(self):
180 return """
181#include "Constants.h"
182"""
183
184
185def create_face_label(solver_name):
186 """
187
188 Build up the DaStGen2 data structure that we need per face to maintain
189 per-face data per solver.
190
191 solver_name: string
192 Name of the solver
193
194 """
195 result = peano4.api.datamodel.DaStGen2( UpdateFaceLabel.get_attribute_name( solver_name ) )
196
197 result.data.add_attribute( dastgen2.attributes.Boolean("Boundary") )
198 result.data.add_attribute( dastgen2.attributes.Boolean("IsHanging") )
199 result.data.add_attribute( dastgen2.attributes.Boolean("AboveHanging") )
200 result.data.add_attribute( dastgen2.attributes.Boolean("NewAboveHanging") )
201 result.data.add_attribute( dastgen2.attributes.BooleanArray("Updated","2",compress=True) )
202 result.data.add_attribute( peano4.api.dastgen2.Peano4DoubleArray("UpdatedTimeStamp","2") )
203 result.data.add_attribute( peano4.api.dastgen2.Peano4DoubleArray("NewTimeStamp","2") )
204 result.data.add_attribute( peano4.api.dastgen2.Peano4DoubleArray("OldTimeStamp","2") )
205
206 result.peano4_mpi_and_storage_aspect.merge_implementation = """
207 switch (context) {
208 case ::peano4::grid::TraversalObserver::SendReceiveContext::BoundaryExchange:
209 case ::peano4::grid::TraversalObserver::SendReceiveContext::PeriodicBoundaryDataSwap:
210 {
211
212 _Boundary = _Boundary or neighbour._Boundary;
213 _AboveHanging = _AboveHanging or neighbour._AboveHanging;
214
215 const int normal = marker.getSelectedFaceNumber() % Dimensions;
216 const int neighbourEntry = marker.outerNormal()(normal)<0.0 ? 0 : 1;
217
218 _Updated[ neighbourEntry ] = neighbour._Updated[ neighbourEntry ];
219 _UpdatedTimeStamp( neighbourEntry ) = neighbour._UpdatedTimeStamp( neighbourEntry );
220 _NewTimeStamp( neighbourEntry ) = neighbour._NewTimeStamp( neighbourEntry );
221 _OldTimeStamp( neighbourEntry ) = neighbour._OldTimeStamp( neighbourEntry );
222 }
223 break;
224 default:
225 assertionMsg( false, "not implemented yet" );
226 }
227"""
228
229 return result
230
Represent an array of boolean flags.
get_action_set_name(self)
Return unique action set name.
Definition FaceLabel.py:147
user_should_modify_template(self)
Is the user allowed to modify the output.
Definition FaceLabel.py:151
__init__(self, solver_name)
Definition FaceLabel.py:86
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
Definition FaceLabel.py:155
get_attributes(self)
Return attributes as copied and pasted into the generated class.
Definition FaceLabel.py:175
get_includes(self)
Return include statements that you need.
Definition FaceLabel.py:179
get_constructor_body(self)
Define a tailored constructor body.
Definition FaceLabel.py:92
Specialisation of array using Peano's tarch.
Default superclass for any data model in Peano which is stored within the grid.
Definition DaStGen2.py:188
Action set (reactions to events)
Definition ActionSet.py:6