3from abc
import abstractmethod
9 Action set (reactions to events)
11 Peano runs through the mesh tied to an observer. The observer
12 "sees" events and issues actions tied to these events. That is
13 the observer listens to the tree traversal for events alike "this
14 is the first time I see (touch) a vertex". A list of events
15 that we can listen to is specified by this class through class
16 attributes starting with OPERATION_. Peano's documentation holds
17 a @ref peano_action_sets "discussion of events and their temporal and spatial ordering".
19 For each grid traversal, Peano expects one C++ observer. The
20 observer is represented within Python through
21 peano4.solversteps.Step, i.e. this class creates eventually one
22 peano4.output.Observer which in return writes out the C++ code.
23 Each observer can have an arbitrary number of action set classes.
24 Each step consequently can hold an action set. The observer's job
25 is it to take information like "I've just entered a spacetree
26 cell" and to break it down into actions like
28 - this vertex is read for the first time
29 - this hanging vertex has to be created
30 - this face is read for the first time
31 - this cell now is entered and these are the associated faces
34 For each of these "actions", the generated C++ code will call the
35 corresponding functions of all associated action sets one by one.
37 @image html ActionSet.png
39 The cartoon above illustrates these three layers: Users or Peano
40 extensions build up logical program steps (left top). They are
41 basically containers with a unique name. Each step holds an arbitrary
42 number of ActionSets. They are, first of all, mappings where each
43 logical action is potentially tied to a C++ code snippet. When
44 the Peano project is generated, each action set is translated into
45 its counterpart in the output namespace which is now a complete
46 description of this class, i.e. holds all functions required, all
47 parameters, ... It copies over the C++ code snippet from its
48 specifiation. This Python representation can then be dumped into
52 ## Lifecycle and parallelisation
54 Action sets are non-persistent, i.e. if you generate C++ code,
55 remind yourself that the class implementing a particular action
56 set will be generated once per grid sweep per tree. As a logical
57 consequence, different action sets are in principle totally
58 independent. If they exchange data, you have to realise this.
59 However, there's a creational routine and a merge command, i.e.
60 you can implement forks and joins (reductions) "natively". There
61 are also functions to inject static data into an action set.
63 There will be one class per action set per context (observer)
64 in which it is used. One object will be created per grid sweep, and
65 it will have the tree identifier -1 by default. The actual
66 objects that then are used are constructed from this prototype
67 object via the augmented copy constructor. The other important
68 role of the prototype object, i.e. the one tied to spacetree id
69 -1, is to manage the grid traversal events. It is this object
70 that is asked to hand out grid traversals. Consult the documentation
71 of get_constructor_body() for details on the tree id.
73 If you want to realise BSP-like programming, then you typically
74 realise the data sharing via the copy constructor. The
75 attributes of the action set then are all thread-local, i.e.
76 there's no need to be afraid of memory races. The join in turn
77 should be done within OPERATION_END_TRAVERSAL. Here, you'll need a
78 semaphore, as the fusion of objects is not per se thread-safe.
81 ## The injected C++ snippets
83 To inject C++ code, i.e. what has to be done, you make get_body_of_operation()
84 return this code if the corresponding argument is passed in. This result
85 should be plain C++ code which the generator really can take and copy
86 n paste into the generated implementation files. If you want these
87 injected snippets to do something solver-specific, a lot of action
88 sets read out there environment and apply jinja2 templates to tailor
89 the snippet to their needs. For example: If you want to do something
90 with the adjacent vertices of a cell, you have to know what these will
91 be called eventually. In this case, it makes sense to study the naming
92 conventions that peano4.output.ActionSet will put in place.
94 The easiest way to find these out is to generate some code, to look into
95 the generated output, and then to reconstruct the naming conventions.
96 To be able to do so, it makes sense to let get_action_set_name() return
97 a unique name, so it is easier for you to find what C++ file corresponds
100 A discussion some event functions and their semantics as well as further
101 info on the arguments can be found in the documentation of
102 @ref peano_action_sets.
105 ## Order of invocation and concurrency level
107 A discussion of the order of events can be found in the documentation of
108 @ref peano_action_sets.
113 @param parallel: Boolean
114 See section on "Order of invocation and concurrency level" in class
117 @param descend_invocation_order: Integer
118 See section on "Order of invocation and concurrency level" in class
123 def __init__(self, descend_invocation_order=0, parallel=False):
130 """! Define a tailored constructor body
132 By default, the constructor of an action set is empty. If you you assign
133 attributes to your action set, you however might want to initialise them
134 here. We do not support initialisation lists, to all has to be done via
135 setters unless you create attributes on the heap.
137 The constructor's signature will look similar to
140 EnumerateAndInitSolution2petsc_actionsets_InitVertexDoFs0(int treeNumber);
143 where the treeNumber is -1 if this is the global instance of the
144 action set owned by a rank, or a number greater or equal 0 if this action
145 set is a clone of the glocal action set that's used by one tree traversal.
147 @see get_attributes() to add attributes to your action set
150 return "// @todo Should be overwritten\n"
157 return "// @todo Should be overwritten\n"
160 return "return std::vector< peano4::grid::GridControlEvent >();\n"
170 OPERATION_BEGIN_TRAVERSAL =
"beginTraversal"
171 OPERATION_END_TRAVERSAL =
"endTraversal"
173 OPERATION_CREATE_PERSISTENT_VERTEX =
"createPersistentVertex"
174 OPERATION_DESTROY_PERSISTENT_VERTEX =
"destroyPersistentVertex"
175 OPERATION_CREATE_HANGING_VERTEX =
"createHangingVertex"
176 OPERATION_DESTROY_HANGING_VERTEX =
"destroyHangingVertex"
177 OPERATION_CREATE_PERSISTENT_FACE =
"createPersistentFace"
178 OPERATION_DESTROY_PERSISTENT_FACE =
"destroyPersistentFace"
179 OPERATION_CREATE_HANGING_FACE =
"createHangingFace"
180 OPERATION_DESTROY_HANGING_FACE =
"destroyHangingFace"
181 OPERATION_CREATE_CELL =
"createCell"
182 OPERATION_DESTROY_CELL =
"destroyCell"
184 OPERATION_TOUCH_VERTEX_FIRST_TIME =
"touchVertexFirstTime"
185 OPERATION_TOUCH_VERTEX_LAST_TIME =
"touchVertexLastTime"
186 OPERATION_TOUCH_FACE_FIRST_TIME =
"touchFaceFirstTime"
187 OPERATION_TOUCH_FACE_LAST_TIME =
"touchFaceLastTime"
188 OPERATION_TOUCH_CELL_FIRST_TIME =
"touchCellFirstTime"
189 OPERATION_TOUCH_CELL_LAST_TIME =
"touchCellLastTime"
195 Return actual C++ code snippets to be inserted into C++ code
197 See class' string constants starting with OPERATION_ for possible values
201 return "// @todo Should be overwritten by mapping\n"
207 Return unique action set name
209 Returns a description (word) for the mapping which is also used as class name
210 for the generated type. As a consequence, the result should be one word (if
211 possible) and uppercase. Also, every subclass should overwrite this routine.
213 The generator will take the result and construct eventually classes similar to
214 MyStep2Dummy.h and MyStep2Dummy.cpp or similar for the example below, where we
224 Is the user allowed to modify the output
226 Return whether you expect the user to modify the generated code. If this
227 is the case, then the API places the generated output in the directory
228 actions. Otherwise, it goes into the observer directory and will be
229 overwritten in each and every Python run.
238 Return attributes as copied and pasted into the generated class.
240 Please note that action sets are not persistent, i.e. there is one
241 object creation per grid sweep per tree.
250 Return include statements that you need.
252 All of these includes will eventually end up in the header of the generated
Action set (reactions to events)
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, descend_invocation_order=0, parallel=False)
get_constructor_body(self)
Define a tailored constructor body.
get_action_set_name(self)
Return unique action set name.
get_body_of_unprepareTraversal(self)
get_body_of_getGridControlEvents(self)
get_attributes(self)
Return attributes as copied and pasted into the generated class.
get_static_initialisations(self, full_qualified_classname)
get_destructor_body(self)
user_should_modify_template(self)
Is the user allowed to modify the output.
get_body_of_prepareTraversal(self)
get_includes(self)
Return include statements that you need.