Peano
Loading...
Searching...
No Matches
PlotPatchesInPeanoBlockFormat.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 jinja2
6
7
9 """!
10
11 Simple patch plotter
12
13 Very simple plotter that should be used in combination with Patches.
14 Patches with varying datatypes are supported via the "dataType" parameter,
15 but this defaults to doubles. This parameter should contain the C-style-
16 name of the type of the variable in the patch, e.g. float, double, etc.
17 This plotter works only for cell patches, i.e. patches associated with
18 faces or vertices are not supported.
19
20 At the moment, I can only plot one dataset (patch type) per plotter.
21 In theory, the underlying Peano plotter however could dump multiple
22 patches at once.
23
24 Also, this dump expects incoming data to be AoS.
25 """
26
27 def __init__(self,
28 filename,
29 patch,
30 dataset_name,
31 description, time_stamp_evaluation,
32 plot_cell_data=True,
33 metadata = "",
34 mapping = [],
35 guard="true",
36 additional_includes="",
37 precision=3,
38 select_dofs = None,
39 dataType="double",
40 restart_preprocess=False,
41 patch_scaling=1.0,
42 metadata_evaluation=None,
43 binary=False):
44 """!
45
46 Construct the block plotter
47
48 plot_cell_data: Boolean
49 Shall I plot cell data or vertex data. If you map the patches onto
50 vertex data, then I have to decrease the dofs pre axis, as we basically
51 plot the dual grid.
52
53 description: String
54
55 mapping: Series of d-tuples which describe how to distort quadrature/sampling
56 points within a reference cube/square. Can be empty alternatively.
57
58 precision: int
59 Number of significant digits of the plotted values. The writer
60 does not round or set small values to zero, so 17 writes the doubles
61 without loss, e.g. for a checkpoint. Patch offsets and sizes use at
62 least six digits
63 (@ref tarch::plotter::griddata::blockstructured::PeanoTextPatchFileWriter).
64
65 select_dofs: [Int] or None
66 You can make the plotter only plot some of the dofs of interest
67
68 patch_scaling: float
69 Factor by which the plotted patch's box is scaled relative to the
70 cell, around the cell's centre. 1.0 plots the patch over the cell.
71 A patch with N dofs per axis plus a halo of M dofs on each side
72 uses (N+2M)/N, so every halo value sits at its true coordinate.
73
74 metadata_evaluation: str or None
75 C++ expression which yields a std::string at runtime. If set, its
76 value replaces metadata in the meta-data block of the file header.
77 Use it for data which is only known when the file is written, such
78 as time stamps.
79
80 binary: Boolean
81 Write the plotted values as raw doubles
82 (@ref tarch::plotter::griddata::blockstructured::PeanoBinaryPatchFileWriter)
83 instead of text
84 (@ref tarch::plotter::griddata::blockstructured::PeanoTextPatchFileWriter).
85 The file header and the metadata remain text in either case, and the
86 file header says which of the two formats the file has. A binary
87 file is smaller and bit-exact, i.e. precision then only affects the
88 patch offsets and sizes.
89
90 """
91 super(PlotPatchesInPeanoBlockFormat,self).__init__(descend_invocation_order=1,parallel=False)
92
93 valid_datatypes = {"float", "double", "long double", "_Float16", "std::float16_t", "__bf16", "std::bfloat16_t"}
94
95 self._plot_cell_data = plot_cell_data
96
97 self.d = {}
98 self.d[ "FILENAME" ] = filename
99 self.d[ "GUARD_PREDICATE" ] = guard
100
101 self.additional_includes = additional_includes
102
103 dofs_per_axis = patch.dim[0]
104
105 self.d[ "DOFS_PER_AXIS" ] = str(dofs_per_axis)
106
107 if select_dofs==None:
108 self.d[ "PLOTTED_UNKNOWNS" ] = str(patch.no_of_unknowns)
109 else:
110 self.d[ "PLOTTED_UNKNOWNS" ] = str(len(select_dofs))
111 self.d[ "UNKNOWNS" ] = str(patch.no_of_unknowns)
112 self.d[ "SELECT_DOFS" ] = select_dofs
113
114 self.d[ "NAME" ] = dataset_name
115 self.d[ "DESCRIPTION" ] = description
116 self.d[ "METADATA" ] = metadata
117 if len(mapping)==0:
118 self.d[ "MAPPING_2D"] = "double* mapping = nullptr;"
119 self.d[ "MAPPING_3D"] = "double* mapping = nullptr;"
120 else:
121 counter = 0
122 self.d[ "MAPPING_2D"] = "double mapping[" + str(2*dofs_per_axis*dofs_per_axis) + "] = {"
123 self.d[ "MAPPING_3D"] = "double mapping[" + str(3*dofs_per_axis*dofs_per_axis*dofs_per_axis) + "] = {"
124 for i in mapping:
125 if counter>0:
126 separator = ", "
127 else:
128 separator = " "
129 if counter<dofs_per_axis*dofs_per_axis:
130 self.d[ "MAPPING_2D"] += separator + str(i[0])
131 self.d[ "MAPPING_2D"] += ", " + str(i[1])
132 self.d[ "MAPPING_2D"] += "\n"
133 self.d[ "MAPPING_3D"] += separator + str(i[0])
134 self.d[ "MAPPING_3D"] += ", " + str(i[1])
135 if len(i)>2:
136 self.d[ "MAPPING_3D"] += ", " + str(i[2])
137 else:
138 self.d[ "MAPPING_3D"] += ", 0.0"
139 self.d[ "MAPPING_3D"] += "\n"
140 counter += 1
141
142 self.d[ "MAPPING_2D"] += "};"
143 self.d[ "MAPPING_3D"] += "};"
144
145 for i in patch.dim:
146 if i!=patch.dim[0]:
147 print( "Error: patch plotter requires patch to have same dimension along all coordinate axes")
148
149 if dataType not in valid_datatypes:
150 raise Exception("Chosen datatype " + dataType + " for plotting of patches is not a recognized choice.")
151
152 self.d[ "PRECISION" ] = precision
153 self.d[ "WRITER_CLASS" ] = "PeanoBinaryPatchFileWriter" if binary else "PeanoTextPatchFileWriter"
154 self.d[ "DATATYPE" ] = dataType
155 self.d[ "TIMESTAMP" ] = time_stamp_evaluation
156 self.d[ "PATCH_SCALING" ] = patch_scaling
157 self.d[ "METADATA_EVALUATION" ] = metadata_evaluation
158 # Patch offsets and sizes need at least six significant digits on
159 # adaptive meshes, even if the data is written with fewer.
160 self.d[ "WRITER_PRECISION" ] = max(precision, 6)
161
162 self._restart_preprocess = restart_preprocess
163
164
165 __Template_Constructor = """
166 _writer = nullptr;
167 _dataWriter = nullptr;
168 _treeNumber = treeNumber;
169
170 logDebug( "PlotGrid2PlotGridInPeanoBlockFormat1()", "created tree instance for " << treeNumber );
171"""
172
173
175 return self.__Template_Constructor.format(**self.d)
176
177
178 __Template_EndTraversal = """
179 assertion1( _dataWriter!=nullptr, _treeNumber );
180 assertion1( _writer!=nullptr, _treeNumber );
181
182 _dataWriter->close();
183 _writer->writeToFile();
184
185 delete _dataWriter;
186 delete _writer;
187
188 _dataWriter = nullptr;
189 _writer = nullptr;
190"""
191
192
194 return ""
195
196
198 return " return std::vector< peano4::grid::GridControlEvent >();\n"
199
200
202 return __name__.replace(".py", "").replace(".", "_")
203
204
206 return False
207
208
209 __Template_TouchCellFirstTime_CellPlot = """
210 int vertexIndices[TwoPowerD];
211
212 const double PatchScaling = {{PATCH_SCALING}};
213
214 assertion( _writer!=nullptr );
215 assertion( _dataWriter!=nullptr );
216
217 const int patchIndex = _writer->plotPatch(
218 marker.x() - marker.h() * PatchScaling * 0.5,
219 marker.h() * PatchScaling
220 );
221
222 int cellIndex = _dataWriter->getFirstCellWithinPatch(patchIndex);
223 int currentDoF = 0;
224
225 dfor(k,{{DOFS_PER_AXIS}}) {
226 {% if SELECT_DOFS==None %}
227 {{DATATYPE}}* data = fineGridCell{{NAME}}.value + currentDoF;
228 {% else %}
229 {{DATATYPE}} data[] = {
230 fineGridCell{{NAME}}.value[ currentDoF + {{SELECT_DOFS[0]}} ]
231 {% for i in SELECT_DOFS[1:] %}
232 , fineGridCell{{NAME}}.value[ currentDoF + {{i}} ]
233 {% endfor %}
234 };
235 {% endif %}
236 _dataWriter->plotCell( cellIndex, data );
237 cellIndex++;
238 currentDoF += {{UNKNOWNS}};
239 }
240"""
241
242# self.d[ "SELECT_DOFS" ] = select_dofs
243
244
245 __Template_TouchCellFirstTime_VertexPlot = """
246 int vertexIndices[TwoPowerD];
247
248 const double PatchScaling = {{PATCH_SCALING}};
249
250 assertion( _writer!=nullptr );
251 assertion( _dataWriter!=nullptr );
252
253 const int patchIndex = _writer->plotPatch(
254 marker.x() - marker.h() * PatchScaling * 0.5,
255 marker.h() * PatchScaling
256 );
257
258 int vertexIndex = _dataWriter->getFirstVertexWithinPatch(patchIndex);
259 int currentDoF = 0;
260
261 dfor(k,{{DOFS_PER_AXIS}}) {
262 {% if SELECT_DOFS==None %}
263 {{DATATYPE}}* data = fineGridCell{{NAME}}.value + currentDoF;
264 {% else %}
265 {{DATATYPE}} data[] = {
266 fineGridCell{{NAME}}.value[ currentDoF + {{SELECT_DOFS[0]}} ]
267 {% for i in SELECT_DOFS[1:] %}
268 , fineGridCell{{NAME}}.value[ currentDoF + {{i}} ]
269 {% endfor %}
270 };
271 {% endif %}
272 _dataWriter->plotVertex( vertexIndex, data );
273 vertexIndex++;
274 currentDoF += {{UNKNOWNS}};
275 }
276"""
277
278 __Template_BeginTraversal_Generic = """
279 std::ostringstream snapshotFileName;
280 snapshotFileName << "{{FILENAME}}-" << counter;
281
282 if (tarch::mpi::Rank::getInstance().getNumberOfRanks()>1 ) {
283 snapshotFileName << "-rank-" << tarch::mpi::Rank::getInstance().getRank();
284 }
285
286 _writer = new tarch::plotter::griddata::blockstructured::{{WRITER_CLASS}}(
287 Dimensions, snapshotFileName.str(), "{{FILENAME}}",
288 tarch::plotter::griddata::blockstructured::{{WRITER_CLASS}}::IndexFileMode::AppendNewData,
289 {{TIMESTAMP}},
290 {{WRITER_PRECISION}}
291 );
292
293 #if Dimensions==2
294 {{MAPPING_2D}}
295 #else
296 {{MAPPING_3D}}
297 #endif
298"""
299
300 __Template_BeginTraversal_Generic_Restart = """
301 tarch::mpi::Lock lock( _semaphore );
302
303 static int counter = -1;
304 counter++;
305
306 static bool preprocessFinished=false;
307 if (not preprocessFinished){
308 if ( tarch::mpi::Rank::getInstance().isGlobalMaster()){
309 counter=tarch::plotter::griddata::blockstructured::restartPreprocess("{{FILENAME}}", CheckpointTimeStamp);
310 }
311 MPI_Bcast(&counter, 1, MPI_INT, 0, MPI_COMM_WORLD);
312 preprocessFinished=true;
313 }
314
315"""+__Template_BeginTraversal_Generic
316
317 __Template_BeginTraversal_Generic = """
318 tarch::mpi::Lock lock( _semaphore );
319
320 static int counter = -1;
321 counter++;
322
323"""+__Template_BeginTraversal_Generic
324
325
326 __Template_BeginTraversal_CellPlot = __Template_BeginTraversal_Generic + """
327 _dataWriter = _writer->createCellDataWriter( "{{NAME}}", {{DOFS_PER_AXIS}}, {{PLOTTED_UNKNOWNS}}, "{{DESCRIPTION}}", {% if METADATA_EVALUATION %}{{METADATA_EVALUATION}}{% else %}"{{METADATA}}"{% endif %}, mapping );
328 _dataWriter->setPrecision( {{PRECISION}} );
329"""
330 __Template_BeginTraversal_CellPlot_Restart = __Template_BeginTraversal_Generic_Restart + """
331 _dataWriter = _writer->createCellDataWriter( "{{NAME}}", {{DOFS_PER_AXIS}}, {{PLOTTED_UNKNOWNS}}, "{{DESCRIPTION}}", {% if METADATA_EVALUATION %}{{METADATA_EVALUATION}}{% else %}"{{METADATA}}"{% endif %}, mapping );
332 _dataWriter->setPrecision( {{PRECISION}} );
333"""
334
335 __Template_BeginTraversal_VertexPlot = __Template_BeginTraversal_Generic + """
336 _dataWriter = _writer->createVertexDataWriter( "{{NAME}}", {{DOFS_PER_AXIS}}, {{PLOTTED_UNKNOWNS}}, "{{DESCRIPTION}}", {% if METADATA_EVALUATION %}{{METADATA_EVALUATION}}{% else %}"{{METADATA}}"{% endif %}, mapping );
337 _dataWriter->setPrecision( {{PRECISION}} );
338"""
339 __Template_BeginTraversal_VertexPlot_Restart = __Template_BeginTraversal_Generic_Restart + """
340 _dataWriter = _writer->createVertexDataWriter( "{{NAME}}", {{DOFS_PER_AXIS}}, {{PLOTTED_UNKNOWNS}}, "{{DESCRIPTION}}", {% if METADATA_EVALUATION %}{{METADATA_EVALUATION}}{% else %}"{{METADATA}}"{% endif %}, mapping );
341 _dataWriter->setPrecision( {{PRECISION}} );
342"""
343
344 def get_body_of_operation(self,operation_name):
345 result = "\n"
346 if operation_name==ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME and self._plot_cell_data:
347 result = jinja2.Template( self.__Template_TouchCellFirstTime_CellPlot ).render(**self.d)
348 if operation_name==ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME and not self._plot_cell_data:
349 result = jinja2.Template( self.__Template_TouchCellFirstTime_VertexPlot ).render(**self.d)
350
351 if operation_name==ActionSet.OPERATION_BEGIN_TRAVERSAL and self._plot_cell_data:
352 if self._restart_preprocess:
353 result = jinja2.Template( self.__Template_BeginTraversal_CellPlot_Restart ).render(**self.d)
354 else:
355 result = jinja2.Template( self.__Template_BeginTraversal_CellPlot ).render(**self.d)
356
357 if operation_name==ActionSet.OPERATION_BEGIN_TRAVERSAL and not self._plot_cell_data:
358 if self._restart_preprocess:
359 result = jinja2.Template( self.__Template_BeginTraversal_VertexPlot_Restart ).render(**self.d)
360 else:
361 result = jinja2.Template( self.__Template_BeginTraversal_VertexPlot ).render(**self.d)
362
363 if operation_name==ActionSet.OPERATION_END_TRAVERSAL:
364 result = jinja2.Template( self.__Template_EndTraversal ).render(**self.d)
365 return result
366
367
368 def get_guard_of_operation(self,operation_name):
369 if operation_name==ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
370 return self.d[ "GUARD_PREDICATE" ]
371 return "true"
372
373
374 def get_attributes(self):
375 writer = "tarch::plotter::griddata::blockstructured::" + self.d["WRITER_CLASS"]
376 data_writer = "CellDataWriter" if self._plot_cell_data else "VertexDataWriter"
377 return """
378 static tarch::mpi::BooleanSemaphore _semaphore;
379
380 int _treeNumber;
381
382 """ + writer + """* _writer;
383 """ + writer + "::" + data_writer + """* _dataWriter;
384"""
385
386
387 def get_includes(self):
388 return """
389#include "tarch/plotter/griddata/blockstructured/PeanoTextPatchFileWriter.h"
390#include "tarch/plotter/griddata/blockstructured/PeanoBinaryPatchFileWriter.h"
391#include "tarch/multicore/Lock.h"
392#include "tarch/multicore/BooleanSemaphore.h"
393#include "tarch/mpi/Lock.h"
394#include "tarch/mpi/BooleanSemaphore.h"
395#include "peano4/utils/Loop.h"
396#include "peano4/parallel/SpacetreeSet.h"
397""" + self.additional_includes
398
399
400 def get_static_initialisations(self,full_qualified_classname):
401 return """
402tarch::mpi::BooleanSemaphore """ + full_qualified_classname + """::_semaphore;
403"""
404
user_should_modify_template(self)
Is the user allowed to modify the output.
get_body_of_createGridControlEventsForNextTraversal(self)
Return the grid control events that this action set wants to trigger.
get_guard_of_operation(self, operation_name)
Return the guard of an operation.
get_attributes(self)
Return attributes as copied and pasted into the generated class.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, filename, patch, dataset_name, description, time_stamp_evaluation, plot_cell_data=True, metadata="", mapping=[], guard="true", additional_includes="", precision=3, select_dofs=None, dataType="double", restart_preprocess=False, patch_scaling=1.0, metadata_evaluation=None, binary=False)
Construct the block plotter.
Action set (reactions to events)
Definition ActionSet.py:6