Peano
Loading...
Searching...
No Matches
SpawnCellTaskActionSet.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 Producer-side wrapper around an action set, which spawns touchCellFirstTime() as a task
10
11 The wrapper delegates all events to the wrapped action set with the
12 following exceptions:
13
14 - touchCellFirstTime() evaluates the wrapped action set's guard. If the
15 guard holds, the wrapper takes a new task number from the task
16 enumerator, stores it in the cell's task label and spawns the wrapped
17 action set's body as a task with this number. If the guard does not
18 hold, the task label is set to
19 tarch::multicore::TaskEnumerator::NoNumber.
20 - createCell() furthermore initialises the task label with NoNumber.
21
22 The task enumerator is a static attribute of the task labels, i.e. it is
23 shared by all producers and consumers which use these labels.
24
25 The spawned task captures its environment by value ([=]). Cell data
26 managed via smart pointers (e.g.
27 @ref peano4.api.datamodel.PatchToDoubleArrayWithSmartPointer) is copied
28 shallowly, i.e. the task writes into the cell's data. Plain arrays are
29 copied deeply, i.e. writes are lost.
30
31 Enumerators over vertices and faces hold pointers into Peano's stacks,
32 which are invalid once touchCellFirstTime() has terminated. The task
33 therefore captures each enumerator which its body might use as
34 peano4::datamanagement::FaceHeapDataEnumerator or
35 peano4::datamanagement::VertexHeapDataEnumerator under the same name.
36 These enumerators hold copies of the faces or vertices. The copies are
37 shallow if the data is managed via smart pointers.
38
39 @ref peano4.api.taskgraph.compiler.CellTaskProducerConsumer warns about
40 data which is not managed via smart pointers.
41
42 All other events, including unprepareTraversal(), endTraversal() and the
43 touch...LastTime() events, remain within the producer. They are hence
44 invoked before the spawned tasks have necessarily terminated.
45 @ref peano4.api.taskgraph.compiler.CellTaskProducerConsumer therefore
46 only splits tasks whose action sets do not realise these events, unless
47 the task explicitly allows it
48 (@ref peano4.api.taskgraph.Task.Task.may_spawn_background_tasks).
49
50 """
51
53 self,
54 action_set: ActionSet,
55 task_labels_name: str,
56 task_number_attribute_name: str,
57 previous_task_number_attribute_name: str,
58 face_enumerators: list = [],
59 vertex_enumerators: list = [],
60 ):
61 """!
62
63 @param action_set: peano4.api.solversteps.ActionSet
64 The wrapped action set.
65
66 @param task_labels_name: str
67 Name of the DaStGen2 cell data type holding the task labels. The
68 generated observer passes it into the event as fineGridCell<name>.
69
70 @param task_number_attribute_name: str
71 Name of the attribute within the task labels which holds the task
72 number.
73
74 @param previous_task_number_attribute_name: str or None
75 Name of the attribute holding the task number of the task spawned
76 by the previous action set of the same producer. The spawned task
77 depends on this task, so the action sets' bodies are executed in
78 their original order. If None, the task has no incoming
79 dependencies.
80
81 @param face_enumerators: [str]
82 Names of the face enumerators, e.g. fineGridFacesQ, which the task
83 captures as peano4::datamanagement::FaceHeapDataEnumerator.
84
85 @param vertex_enumerators: [str]
86 Names of the vertex enumerators, e.g. fineGridVerticesQ, which the
87 task captures as peano4::datamanagement::VertexHeapDataEnumerator.
88
89 """
90 super().__init__(descend_invocation_order=action_set.descend_invocation_order, parallel=action_set.parallel)
91 self.action_set = action_set
92 self._task_labels_name = task_labels_name
93 self._task_number_attribute_name = task_number_attribute_name
94 self._previous_task_number_attribute_name = previous_task_number_attribute_name
95 self._face_enumerators = list(face_enumerators)
96 self._vertex_enumerators = list(vertex_enumerators)
97
98 def _lambda_captures(self) -> str:
99 """!
100
101 Capture list of the spawned task's lambda: Everything by value, and
102 the vertex and face enumerators as copies of their data under the
103 same name.
104
105 """
106 captures = ["="]
107 captures += [
108 f"{name} = peano4::datamanagement::FaceHeapDataEnumerator({name})" for name in self._face_enumerators
109 ]
110 captures += [
111 f"{name} = peano4::datamanagement::VertexHeapDataEnumerator({name})" for name in self._vertex_enumerators
112 ]
113 return ", ".join(captures)
114
115 def _accessor(self, attribute_name: str) -> str:
116 return attribute_name[0].capitalize() + attribute_name[1:]
117
119 return self.action_set.get_constructor_body()
120
122 return self.action_set.get_destructor_body()
123
124 def get_static_initialisations(self, full_qualified_classname):
125 return self.action_set.get_static_initialisations(full_qualified_classname)
126
136 def get_body_of_operation(self, operation_name):
137 # Not used, as get_implementation_of_operation() is overwritten
138 return ""
139
140 def get_implementation_of_operation(self, operation_name):
141 """!
142
143 Delegate to the wrapped action set besides the events listed in the
144 class description
145
146 """
147 task_label = f"fineGridCell{self._task_labels_name}"
148 if operation_name == ActionSet.OPERATION_CREATE_CELL:
149 return (
151 + f"\n {task_label}.set{self._accessor(self._task_number_attribute_name)}( tarch::multicore::TaskEnumerator::NoNumber );\n"
152 )
153 elif operation_name == ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
155 in_dependencies = "tarch::multicore::NoInDependencies"
156 else:
157 previous_task_number = f"{task_label}.get{self._accessor(self._previous_task_number_attribute_name)}()"
158 in_dependencies = f"{previous_task_number}>=0 ? std::set<tarch::multicore::TaskNumber>{{ {previous_task_number} }} : tarch::multicore::NoInDependencies"
159 return f"""
160 if ({self.action_set.get_guard_of_operation(operation_name)}) {{
161 const int taskNumber = {task_label}.getTaskEnumerator().getNumber();
162 {task_label}.set{self._accessor(self._task_number_attribute_name)}( taskNumber );
163 tarch::multicore::spawnTask(
164 new tarch::multicore::TaskWithCopyOfFunctor(
165 tarch::multicore::Task::DontFuse,
166 tarch::multicore::Task::DefaultPriority,
167 [{self._lambda_captures()}]() mutable {{
168{self.action_set.get_body_of_operation(operation_name)}
169 }}
170 ),
171 {in_dependencies},
172 taskNumber
173 );
174 }}
175 else {{
176 {task_label}.set{self._accessor(self._task_number_attribute_name)}( tarch::multicore::TaskEnumerator::NoNumber );
177 }}
178"""
179 else:
180 return self.action_set.get_implementation_of_operation(operation_name)
181
183 return self.action_set.get_action_set_name()
184
186 return False
187
188 def get_attributes(self):
189 return self.action_set.get_attributes()
190
191 def get_includes(self):
192 return (
194 + """
195#include <set>
196#include "tarch/multicore/multicore.h"
197#include "tarch/multicore/Task.h"
198#include "tarch/multicore/TaskEnumerator.h"
199#include "peano4/datamanagement/FaceHeapDataEnumerator.h"
200#include "peano4/datamanagement/VertexHeapDataEnumerator.h"
201"""
202 )
Action set (reactions to events)
Definition ActionSet.py:6
get_implementation_of_createGridControlEventsForNextTraversal(self)
Return the C++ implementation of createGridControlEventsForNextTraversal()
Definition ActionSet.py:218
get_implementation_of_prepareTraversal(self)
Return the C++ implementation of prepareTraversal()
Definition ActionSet.py:234
get_implementation_of_unprepareTraversal(self)
Return the C++ implementation of unprepareTraversal()
Definition ActionSet.py:250
Producer-side wrapper around an action set, which spawns touchCellFirstTime() as a task.
get_implementation_of_operation(self, operation_name)
Delegate to the wrapped action set besides the events listed in the class description.
str _lambda_captures(self)
Capture list of the spawned task's lambda: Everything by value, and the vertex and face enumerators a...
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, ActionSet action_set, str task_labels_name, str task_number_attribute_name, str previous_task_number_attribute_name, list face_enumerators=[], list vertex_enumerators=[])
get_body_of_createGridControlEventsForNextTraversal(self)
Return the grid control events that this action set wants to trigger.
get_attributes(self)
Return attributes as copied and pasted into the generated class.