Peano
Loading...
Searching...
No Matches
EnumerateDoFs.py
Go to the documentation of this file.
1# This file is part of the Peano's PETSc extension. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3from peano4.solversteps.ActionSet import ActionSet
4
5import peano4
6import jinja2
7
8
10 """!
11
12 Enumerate the vertices, cells and face entries
13
14 This is the first step in a typical PETSc algorithm, as discussed on @ref documentation_multigrid_petsc.
15 It has to ensure that each mesh entity hosts the appropriate number of
16 degrees of freedom. It hence strongly depends on the solver chosen, as
17 different solvers place different amounts of data and auxiliary quantities on
18 the mesh entities. The information on data cardinality is queried from the
19 solver objects. The added logic contributed by this action set is if a mesh
20 entity really holds unknowns or not. That is, this action set injects the
21 domain layout and boundary data knowledge into the mesh. This guiding
22 principles of this injection are discussed on
23 @ref documentation_multigrid_boundary_conditions "Peano's generic boundary condition pages".
24
25 """
26
27
28 TemplateEnumerateVertex = """
29 auto isOnBoundary = [&]( const tarch::la::Vector< Dimensions, double > & x ) -> bool{
30 bool isOnBoundary = false;
31 for (int d=0; d<Dimensions; d++) {
32 isOnBoundary |= tarch::la::smallerEquals( x(d), DomainOffset(d) );
33 isOnBoundary |= tarch::la::greaterEquals( x(d), DomainOffset(d)+DomainSize(d) );
34 }
35 return isOnBoundary;
36 };
37
38 fineGridVertex{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( ::petsc::LocalToGlobalMap::NoDegreeOfFreedom );
39 fineGridVertex{{SOLVER_NAME}}PETScData.setType( vertexdata::{{SOLVER_NAME}}PETScData::Type::Undefined );
40
41 vertexdata::{{SOLVER_NAME}}PETScData::Type dofType = repositories::{{SOLVER_INSTANCE}}.getVertexDoFType(marker.x(),marker.h());
42
43 switch (dofType) {
44 case vertexdata::{{SOLVER_NAME}}PETScData::Type::Boundary:
45 {
46 fineGridVertex{{SOLVER_NAME}}PETScData.setType( vertexdata::{{SOLVER_NAME}}PETScData::Type::Boundary );
47 {% if BOUNDARY_VERTICES_HOLD_DATA %}
48 if ( marker.willBeRefined() ) {
49 fineGridVertex{{SOLVER_NAME}}PETScData.setType( vertexdata::{{SOLVER_NAME}}PETScData::Type::Coarse );
50 }
51 else {
52 fineGridVertex{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( _localVertexMap.reserveIndex( {{VERTEX_CARDINALITY}} ) );
53 }
54 {% endif %}
55 }
56 break;
57 case vertexdata::{{SOLVER_NAME}}PETScData::Type::Interior:
58 {
59 if (isOnBoundary(marker.x())) {
60 logWarning( "touchVertexFirstTime(...)", "vertex at " << marker.toString() << " labelled as interior even though it is located at global domain boundary" );
61 }
62 if ( marker.willBeRefined() ) {
63 fineGridVertex{{SOLVER_NAME}}PETScData.setType( vertexdata::{{SOLVER_NAME}}PETScData::Type::Coarse );
64 }
65 else {
66 fineGridVertex{{SOLVER_NAME}}PETScData.setType( vertexdata::{{SOLVER_NAME}}PETScData::Type::Interior );
67 fineGridVertex{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( _localVertexMap.reserveIndex( {{VERTEX_CARDINALITY}} ) );
68 }
69 }
70 break;
71 case vertexdata::{{SOLVER_NAME}}PETScData::Type::Coarse:
72 assertionMsg(false, "should not be returned by user" );
73 break;
74 case vertexdata::{{SOLVER_NAME}}PETScData::Type::Outside:
75 {
76 fineGridVertex{{SOLVER_NAME}}PETScData.setType( vertexdata::{{SOLVER_NAME}}PETScData::Type::Outside );
77 }
78 break;
79 case vertexdata::{{SOLVER_NAME}}PETScData::Type::Undefined:
80 assertionEquals( {{VERTEX_CARDINALITY}}, 0 );
81 break;
82 }
83"""
84
85
86 TemplateEnumerateFace = """
87 auto isOnBoundary = [&]( const tarch::la::Vector< Dimensions, double >& x) -> bool {
88 bool isOnBoundary = false;
89 for (int d=0; d<Dimensions; d++) {
90 isOnBoundary |= tarch::la::smallerEquals( x(d), DomainOffset(d) );
91 isOnBoundary |= tarch::la::greaterEquals( x(d), DomainOffset(d)+DomainSize(d) );
92 }
93 return isOnBoundary;
94 };
95
96 fineGridFace{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( ::petsc::LocalToGlobalMap::NoDegreeOfFreedom );
97 fineGridFace{{SOLVER_NAME}}PETScData.setType( facedata::{{SOLVER_NAME}}PETScData::Type::Undefined );
98
99 facedata::{{SOLVER_NAME}}PETScData::Type dofType = repositories::{{SOLVER_INSTANCE}}.getFaceDoFType(marker.x(),marker.h());
100
101 switch (dofType) {
102 case facedata::{{SOLVER_NAME}}PETScData::Type::Boundary:
103 {
104 fineGridFace{{SOLVER_NAME}}PETScData.setType( facedata::{{SOLVER_NAME}}PETScData::Type::Boundary );
105 {% if BOUNDARY_FACES_HOLD_DATA %}
106 if ( marker.willBeRefined() ) {
107 fineGridFace{{SOLVER_NAME}}PETScData.setType( facedata::{{SOLVER_NAME}}PETScData::Type::Coarse );
108 }
109 else {
110 fineGridFace{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( _localFaceMap.reserveIndex( {{FACE_CARDINALITY}} ) );
111 }
112 {% endif %}
113 }
114 break;
115 case facedata::{{SOLVER_NAME}}PETScData::Type::Interior:
116 {
117 if (isOnBoundary(marker.x())) {
118 logWarning( "touchFaceFirstTime(...)", "face at " << marker.toString() << " labelled as interior even though it is located at global domain boundary" );
119 }
120 if ( marker.willBeRefined() ) {
121 fineGridFace{{SOLVER_NAME}}PETScData.setType( facedata::{{SOLVER_NAME}}PETScData::Type::Coarse );
122 }
123 else {
124 fineGridFace{{SOLVER_NAME}}PETScData.setType( facedata::{{SOLVER_NAME}}PETScData::Type::Interior );
125 fineGridFace{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( _localFaceMap.reserveIndex( {{FACE_CARDINALITY}} ) );
126 }
127 }
128 break;
129 case facedata::{{SOLVER_NAME}}PETScData::Type::Coarse:
130 assertionMsg(false, "should not be returned by user" );
131 break;
132 case facedata::{{SOLVER_NAME}}PETScData::Type::Outside:
133 {
134 fineGridFace{{SOLVER_NAME}}PETScData.setType( facedata::{{SOLVER_NAME}}PETScData::Type::Outside );
135 }
136 break;
137 case facedata::{{SOLVER_NAME}}PETScData::Type::Undefined:
138 assertionEquals( {{FACE_CARDINALITY}}, 0 );
139 break;
140 }
141"""
142
143
144 TemplateEnumerateCell = """
145 fineGridCell{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( ::petsc::LocalToGlobalMap::NoDegreeOfFreedom );
146 fineGridCell{{SOLVER_NAME}}PETScData.setType( celldata::{{SOLVER_NAME}}PETScData::Type::Undefined );
147
148 celldata::{{SOLVER_NAME}}PETScData::Type dofType = repositories::{{SOLVER_INSTANCE}}.getCellDoFType(marker.x(),marker.h());
149
150 switch (dofType) {
151 case celldata::{{SOLVER_NAME}}PETScData::Type::Interior:
152 {
153 if ( marker.willBeRefined() ) {
154 fineGridCell{{SOLVER_NAME}}PETScData.setType( celldata::{{SOLVER_NAME}}PETScData::Type::Coarse );
155 }
156 else {
157 fineGridCell{{SOLVER_NAME}}PETScData.setType( celldata::{{SOLVER_NAME}}PETScData::Type::Interior );
158 fineGridCell{{SOLVER_NAME}}PETScData.setUnknownBaseNumber( _localCellMap.reserveIndex( {{CELL_CARDINALITY}} ) );
159 }
160 }
161 break;
162 case celldata::{{SOLVER_NAME}}PETScData::Type::Coarse:
163 assertionMsg(false, "should not be returned by user" );
164 break;
165 case celldata::{{SOLVER_NAME}}PETScData::Type::Outside:
166 {
167 fineGridCell{{SOLVER_NAME}}PETScData.setType( celldata::{{SOLVER_NAME}}PETScData::Type::Outside );
168 }
169 break;
170 case celldata::{{SOLVER_NAME}}PETScData::Type::Undefined:
171 assertionEquals( {{CELL_CARDINALITY}}, 0 );
172 break;
173 }
174"""
175
176
177 TemplateEndTraversal = """
178 logInfo(
179 "endTraversal()",
180 "vertex dofs=" << _localVertexMap.getTotalNumberOfIndices() <<
181 ", face dofs=" << _localFaceMap.getTotalNumberOfIndices() <<
182 ", cell dofs=" << _localCellMap.getTotalNumberOfIndices()
183 );
184
185 repositories::{{SOLVER_INSTANCE}}.getLocalToGlobalMap().merge( _localVertexMap, ::petsc::LocalToGlobalMap::Type::Vertex );
186 repositories::{{SOLVER_INSTANCE}}.getLocalToGlobalMap().merge( _localFaceMap, ::petsc::LocalToGlobalMap::Type::Face );
187 repositories::{{SOLVER_INSTANCE}}.getLocalToGlobalMap().merge( _localCellMap, ::petsc::LocalToGlobalMap::Type::Cell );
188"""
189
190
191 def __init__(self,
192 solver,
193 boundary_vertices_hold_data,
194 boundary_faces_hold_data,
195 ):
196 """!A
197
198Enumerate vertex-associated degrees of freedom
199
200The initialisation requires a solver object, as we have to know what C++
201object this solver will produce, and we need to know how many unknowns
202we have per vertex.
203
204solver: petsc.solvers.CollocatedLowOrderDiscretisation or similar solver where
205 degrees of freedom are assigned exclusively to the vertices.
206
207 """
208 super( EnumerateDoFs, self ).__init__()
209 self.d = {}
210 self.d["SOLVER_INSTANCE"] = solver.instance_name()
211 self.d["SOLVER_NAME"] = solver.typename()
212 self.d["VERTEX_CARDINALITY"] = solver.number_of_matrix_entries_per_vertex
213 self.d["FACE_CARDINALITY"] = solver.number_of_matrix_entries_per_face
214 self.d["CELL_CARDINALITY"] = solver.number_of_matrix_entries_per_cell
215 self.d["BOUNDARY_VERTICES_HOLD_DATA"] = boundary_vertices_hold_data
216 self.d["BOUNDARY_FACES_HOLD_DATA"] = boundary_faces_hold_data
217
218
219 def get_body_of_operation(self,operation_name):
220 """!
221
222Provide C++ code snippet for peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME
223
224Only touchVertexFirstTime is an event where this action set actually
225does something: It inserts the template TemplateInitVertex and
226replaces it with entries from the dictionary. The latter is befilled
227in init().
228
229 """
230 result = ""
231 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
232 result = jinja2.Template(self.TemplateEnumerateVertex).render(**self.d)
233 pass
234 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
235 result = jinja2.Template(self.TemplateEnumerateCell).render(**self.d)
236 pass
237 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME:
238 result = jinja2.Template(self.TemplateEnumerateFace).render(**self.d)
239 pass
240 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
241 result = jinja2.Template(self.TemplateEndTraversal).render(**self.d)
242 pass
243 return result
244
245
247 """!
248
249Configure name of generated C++ action set
250
251This action set will end up in the directory observers with a name that
252reflects how the observer (initialisation) is mapped onto this action
253set. The name pattern is ObserverName2ActionSetIdentifier where this
254routine co-determines the ActionSetIdentifier. We make is reflect the
255Python class name.
256
257 """
258 return __name__.replace(".py", "").replace(".", "_")
259
260
262 """!
263
264 The action set that Peano will generate that corresponds to this class
265 should not be modified by users and can safely be overwritten every time
266 we run the Python toolkit.
267
268 """
269 return False
270
271
272 def get_attributes(self):
273 """!
274
275Define the local map
276
277Every action set has excactly one attribute and that's an instance of
278petsc::LocalToGlobalMap. Before we run through a local mesh partition,
279the corresponding observer object will create a copy of the action set
280for this traversal. In the corresponding constructor, we initialise
281our thread-local copy of the map with the correct tree number.
282
283 """
284 return """
285 ::petsc::LocalToGlobalMap _localCellMap;
286 ::petsc::LocalToGlobalMap _localFaceMap;
287 ::petsc::LocalToGlobalMap _localVertexMap;
288"""
289
291 """!
292
293Define body of constructor
294
295Consult the superclass' description of the function for results. I
296basically initialise the _localMap with the correct tree number.
297
298@see get_attributes()
299
300 """
301 return """
302 _localCellMap.setTreeNumber( treeNumber );
303 _localFaceMap.setTreeNumber( treeNumber );
304 _localVertexMap.setTreeNumber( treeNumber );
305"""
306
307
308 def get_includes(self):
309 """!
310
311Consult multigrid.petsc.Project for details
312
313"""
314 return """
315#include "../repositories/SolverRepository.h"
316"""
317
Enumerate the vertices, cells and face entries.
get_constructor_body(self)
Define body of constructor.
get_body_of_operation(self, operation_name)
Provide C++ code snippet for peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME
get_includes(self)
Consult multigrid.petsc.Project for details.
get_action_set_name(self)
Configure name of generated C++ action set.
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
get_attributes(self)
Define the local map.
__init__(self, solver, boundary_vertices_hold_data, boundary_faces_hold_data)
A.
Action set (reactions to events)
Definition ActionSet.py:6