Peano
Loading...
Searching...
No Matches
PreprocessSolution.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3
4from .AbstractRKFDActionSet import AbstractRKFDActionSet
5
6import peano4
7import jinja2
8
9
10from peano4.toolbox.blockstructured.ReconstructPatchAndApplyFunctor import ReconstructPatchAndApplyFunctor
11
12
14 """!
15
16 PreprocessSolution differs from other action sets, as I only create it once. See
17 FV.create_action_sets(). Once the instance does exist, you can tailor it. But you
18 can also completely overwrite it.
19
20 """
21 def __init__(self,solver):
22 AbstractRKFDActionSet.__init__(self,solver)
23 # Is there for compatibility reasons
24 self.guard = "true"
26
27
28 def get_body_of_operation(self,operation_name):
29 result = ""
30 return result
31
32
34 return __name__.replace(".py", "").replace(".", "_")
35
36
37
39 """!
40
41 Preprocess the solution and reconstruct halo for this
42
43 This action set preprocesses the solution. By default, it only plugs into the
44 very first grid sweep of a time step. That is, if you have a Runge-Kutta solver
45 and/or enclave solver, these guys usually need multiple sweeps. We only plug
46 into the very first one.
47
48 If it becomes active, it first of all creates an array called oldQWithHalo. It
49 is held on the heap and will be destroyed automatically later on. This array
50 is properly befilled. You can postprocess it, but if you alter entries
51 therein, these alterations will be lost after the preprocessing step.
52
53 ## Enclave solver variant
54
55 The action set can work in an enclave solver style or as plain invocation.
56 Plain invocation means we just reconstruct the patch plus halo, invoke a
57 compute kernel on it, and then free this reconstruction data structure
58 again.
59
60 Enclave-style means that we do the reconstruction, but then embed the actual
61 operation and the freeing into a task. We use the actual enclave task number
62 as task number. Peano does not allow multiple tasks in the system with the
63 same number, so if an enclave task is spawned afterwards, we have a read-write-read
64 dependency.
65
66 @todo Das ist falsch
67
68
69 """
70 def __init__(self,
71 solver,
72 compute_kernel_implementation,
73 enclave_task_cell_label = None
74 ):
75 """!
76
77 Construct the preprocessing
78
79 If we work with an enclave task, the modelling is pretty straightforward.
80 However, we have to explicitly delete the reconstructed data structure
81 oldQWithHalo, as we tell the parent class not to delete stuff. If they
82 deleted the oldQWithHalo, it would be at the end of the function. At this
83 point our task might not have finished yet. We need the delete within the
84 task.
85
86 @param enclave_task_cell_label: String or None
87 If this field is none, we do not use any tasking. If it is a string, we assume
88 it denotes a cell label (usually it is something similar to
89 fineGridCellMySolver_FD4CellLabel). In this case, we spawn a separate task as
90 enclave task.
91
92 """
93 if enclave_task_cell_label==None:
94 functor_implementation = compute_kernel_implementation
95 reconstructed_array_memory_location = peano4.toolbox.blockstructured.ReconstructedArrayMemoryLocation.HeapThroughTarch
96 else:
97 functor_implementation = """
98 auto taskBody = [=,this]() -> bool { """ + compute_kernel_implementation + """
99 ::tarch::freeMemory(oldQWithHalo, tarch::MemoryLocation::Heap );
100 return false;
101 };
102
103 if (
104 marker.willBeEnclaveCell()
105 or
106 marker.hasBeenEnclaveCell()
107 ) {
108 taskBody();
109 }
110 else {
111 assertion( """ + enclave_task_cell_label + """.getSemaphoreNumber()<0 );
112
113 tarch::multicore::Task* newTask = new tarch::multicore::TaskWithCopyOfFunctor (
114 tarch::multicore::Task::DontFuse,
115 tarch::multicore::Task::DefaultPriority,
116 taskBody
117 );
118
119 int newTaskNumber = ::exahype2::EnclaveTask::reserveTaskNumber();
120
121 tarch::multicore::spawnTask(
122 newTask,
123 tarch::multicore::NoInDependencies,
124 newTaskNumber
125 );
126
127 """ + enclave_task_cell_label + """.setSemaphoreNumber( newTaskNumber );
128 }
129 """
130 reconstructed_array_memory_location = peano4.toolbox.blockstructured.ReconstructedArrayMemoryLocation.HeapThroughTarchWithoutDelete
131
132 super(PreprocessReconstructedSolutionWithHalo,self).__init__(patch = solver._patch,
133 patch_overlap = solver._patch_overlap_new,
134 functor_implementation = functor_implementation,
135 reconstructed_array_memory_location = reconstructed_array_memory_location,
136 guard = "repositories::instanceOf" + solver._name + ".isFirstGridSweepOfTimeStep()",
137 add_assertions_to_halo_exchange = False
138 )
139 self._solver = solver
140
142 return __name__.replace(".py", "").replace(".", "_")
143
144
145 def get_includes(self):
146 return super(PreprocessReconstructedSolutionWithHalo,self).get_includes() + """
147#include <functional>
148#include "exahype2/fd/PatchUtils.h"
149#include "exahype2/EnclaveTask.h"
150#include "tarch/multicore/Task.h"
151""" + self._solver._get_default_includes() + self._solver.user_action_set_includes
152
153
155 """!
156
157 Preprocess solution mesh cell by mesh cell without mesh cell interactions
158
159 PreprocessSolution differs from other action sets, as I only create it once. See
160 FV.create_action_sets(). Once the instance does exist, you can tailor it. But you
161 can also completely overwrite it.
162
163 The postprocessing plugs into touch cell last time. It is the last action set added
164 by the default implementation. Therefore, it is the first action set of which
165 touchCellLastTime() is called. The reason why I plug into the leaving of the cell
166 is that some solvers may add further action sets to the solve. Enclave tasking for
167 example adds the merger as additional action set. These action sets plug into
168 touchCellFirstTime() - and consequently their first time is called after the
169 postprocessing's first time. By making the postprocessing use touchCellLastTime(),
170 I ensure that any additional action set added by a subclass can still precede the
171 postprocessing.
172
173
174 """
175 def __init__(self,solver):
176 AbstractRKFDActionSet.__init__(self,solver)
177 self.guard = "true"
180
181
182 def add_postprocessing_kernel(self, operation_per_point):
183 """
184
185 Add a code snippet which is applied to each and every point. You have the following
186 variables which are well-defined:
187
188 - value: Is a pointer to the current finite volume's data
189 - volumeX: A tarch::la::Vector over doubles
190 - volumeH: A tarch::la::Vector over doubles
191
192
193 operation_per_point: String
194 C/C++ code snippet
195
196 """
197 self._compute_kernel += """
198 if (
199 not marker.hasBeenRefined()
200 and
201 {{PREDICATE}}
202 ) {
203 logTraceIn( "touchCellFirstTime(...)" );
204 int index = 0;
205 dfor( volume, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} ) {
206 double* value = fineGridCell{{UNKNOWN_IDENTIFIER}}.value + index;
207 auto volumeX = ::exahype2::fv::getVolumeCentre( marker.x(), marker.h(), {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, volume);
208 auto volumeH = ::exahype2::fv::getVolumeSize( marker.h(), {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}});
209
210 """ + operation_per_point + """
211
212 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
213 }
214 logTraceOut( "touchCellFirstTime(...)" );
215 }
216"""
217
218
219 def get_body_of_operation(self,operation_name):
220 result = ""
221 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
222 d = {}
223 self._solver._init_dictionary_with_default_parameters(d)
224 self._solver.add_entries_to_text_replacement_dictionary(d)
225 d[ "PREDICATE" ] = jinja2.Template(self.guard, undefined=jinja2.DebugUndefined).render(**d)
226 result = jinja2.Template(self._compute_kernel, undefined=jinja2.DebugUndefined).render(**d)
227 pass
228 return result
229
230
232 return __name__.replace(".py", "").replace(".", "_")
Preprocess solution mesh cell by mesh cell without mesh cell interactions.
__init__(self, solver)
solver: ADERDG Reference to creating class
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
add_postprocessing_kernel(self, operation_per_point)
Add a code snippet which is applied to each and every point.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
PreprocessSolution differs from other action sets, as I only create it once.
__init__(self, solver)
solver: ADERDG Reference to creating class
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
__init__(self, solver, compute_kernel_implementation, enclave_task_cell_label=None)
Construct the preprocessing.