Peano
Loading...
Searching...
No Matches
PlotAsVTKFile.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
3import os
4
5import peano4.api
7
8from ..Quantities import resolve_quantities
9from ..Solver import Solver
10
11
13 toolbox.blockstructured.api.PlotPatchesInPeanoBlockFormat
14):
15 """!
16
17 PlotPatchesInPeanoBlockFormat which only does something if its plotter
18 is active
19
20 The toolbox action set opens a new snapshot file in beginTraversal()
21 and adds it to the index file. That has to be skipped altogether for a
22 plotter which is not active, so the guards of all operations are
23 combined with the plotter's is<Name>Active(). The predicate does not
24 change throughout the plot sweep, as finish<Name>() - which moves the
25 plotter on to its next output - is only called in unprepareTraversal()
26 (@ref exahype2.api.Solver.Solver.Plotter).
27
28 """
29
30 def __init__(self, is_active_predicate, finish_call, **kwargs):
31 super().__init__(**kwargs)
32 self._is_active_predicate = is_active_predicate
33 self._finish_call = finish_call
34
35 def get_guard_of_operation(self, operation_name):
36 return (
38 + " and ("
39 + super().get_guard_of_operation(operation_name)
40 + ")"
41 )
42
44 return " " + self._finish_call
45
46
48 """!
49
50 Plotting counterpart of the fourth-order Finite Differences with
51 Runge-Kutta time stepping (@ref exahype2.api.rkfd4): writes the patch
52 data solver._patch of a block-structured mesh out as a VTK file. As the
53 Finite Differences are cell-centred, each grid cell of a patch is
54 plotted as one cell of the plot mesh.
55
56 The plotter is active in regular time intervals
57 (@ref exahype2.api.Solver.Solver.Plotter): It is active as soon as the
58 solver's min time stamp has reached the time stamp of its next plot.
59 After each plot, this time stamp is incremented by
60 time_in_between_plots. A solver can have several plotters, e.g. two
61 PlotAsVTKFile plotters with different plot intervals and filters, as
62 long as they write into different files.
63
64 If the solver's variables carry names, the plotter writes them as
65 comma-separated list into the description of the output files (@ref
66 exahype2.api.Solver.Solver.variable_names_per_entry()). Paraview then shows them in the
67 name of the data array, and tarch.plotter.api.notebook.show_solution()
68 uses them to label the unknowns. Otherwise, the description is the
69 solver's unknown identifier.
70
71 The class is a copy of exahype2.api.fv.PlotAsVTKFile, as rkfd4 does not
72 depend on the Finite Volume package.
73
74 """
75
77 self,
78 solver: Solver,
79 first_plot_time_stamp=0.0,
80 time_in_between_plots=0.1,
81 plotter_precision=5,
82 output_path=".",
83 filename="solution",
84 name: str = None,
85 quantities=None,
86 binary=True,
87 ):
88 """!
89
90 @param solver: exahype2.api.Solver
91 The solver whose solution is plotted.
92
93 @param first_plot_time_stamp: float
94 Time stamp of the first plot.
95
96 @param time_in_between_plots: float
97 Has to be positive. If you don't want to have any plots for a
98 solver, don't give it a plotter.
99
100 @param plotter_precision: int
101 Number of significant digits written per value. Has to be
102 positive.
103
104 @param output_path: str
105 Directory the plot files are written into.
106
107 @param filename: str
108 The plot files are called filename-SolverName. Plotters of the
109 same solver have to use different file names or output paths.
110
111 @param name: str or None
112 Name of the plotter (@ref exahype2.api.Solver.Solver.Plotter).
113
114 @param quantities: List[str or int] or None
115 The entries of Q which are written per volume. A string is the
116 name of a variable as passed to the solver and selects all of its
117 entries, an int is the index of one entry of Q. Auxiliary
118 variables can be selected, too
119 (@ref exahype2.api.Quantities.resolve_quantities()). None writes
120 all entries.
121
122 @param binary: bool
123 Write the values as raw doubles instead of text
124 (@ref tarch::plotter::griddata::blockstructured::PeanoBinaryPatchFileWriter).
125 The files are smaller and the values bit-exact, and the plotter's
126 precision then only affects the patch offsets and sizes. The
127 Python scripts of tarch.plotter.api read both formats. Pass False
128 to get human-readable files.
129
130 """
131 super().__init__(solver, name)
132
133 if time_in_between_plots <= 0:
134 raise Exception("Time in between plots has to be bigger than 0")
135 if plotter_precision <= 0:
136 raise Exception("Plotter precision has to be bigger than 0")
137 self._first_plot_time_stamp = first_plot_time_stamp
138 self._time_in_between_plots = time_in_between_plots
139 self._plotter_precision = plotter_precision
141 self._output_path = output_path
142 self._filename = filename
143 self._quantities = quantities
144 self._binary = binary
145
147 return os.path.join(self._output_path, self._filename + "-" + self._solver_solver.name)
148
149 def add_plot_filter(self, offset, size, frequency=1):
150 """!
151
152 Add a new filter to Peano/ExaHyPE
153
154 Restrict plotting to patches overlapping a given box. Filters are
155 baked directly into the guard of the generated plot action set (see
156 construct_output()), i.e. the generated C++ code evaluates the exact
157 offset/size this filter was constructed with - it never consults any
158 project-wide, separately configured filter object.
159
160 @param offset: (float,float,float)
161
162 @param size: (float,float,float)
163
164 @param frequency: int
165 A positive value. Peano makes snapshots every dt simulation
166 units. This is something you specify once per simulation. But
167 you might decide only to splot every k of these snapshots.
168
169 @todo Not evaluated yet: every filter currently plots on every
170 snapshot it spatially overlaps with, regardless of frequency.
171 """
172 if frequency != 1:
173 raise Exception(
174 "Frequency-based plot filtering is not wired up yet in the "
175 "new exahype2.api - exahype2.api.rkfd4.PlotAsVTKFile only supports spatial "
176 "(offset/size) plot filters for now. Call add_plot_filter() "
177 "with frequency=1 (the default)."
178 )
179 self._plot_filters.append((offset, size))
180
181 def construct_output(self, exahype2_project, peano_project, plot):
182 """!
183
184 Add one task to the plot graph which writes the solver's patches
185
186 """
187 peano4.api.Logger().log(
188 "Create plot task graph for fourth-order Finite Differences with Runge-Kutta over block-structured meshes"
189 )
190
191 assert hasattr(self._solver_solver, "_patch"), (
192 f"Solver {self._solver.name} has no attribute _patch. "
193 "PlotAsVTKFile assumes the numerical scheme has added this field "
194 "to the solver immediately upon construction."
195 )
196
199 )
200
201 write_vtk_file_task = peano4.api.taskgraph.Task(
202 name=f"{self._solver.name}_{self.name}_Write VTK file",
203 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
204 may_spawn_background_tasks=False,
205 )
206 plot.add_task(write_vtk_file_task)
207
208 write_vtk_file_task.add_action_set(
210 is_active_predicate=self.create_is_active_predicate(),
211 finish_call=self.create_finish_call(),
213 patch=self._solver_solver._patch,
214 dataset_name=self._solver_solver._unknown_identifier(),
215 description=self._create_description(),
216 guard=self._create_guard(),
217 select_dofs=self._create_selected_entries(),
218 additional_includes="""
219#include "../repositories/SolverRepository.h"
220""",
221 precision=self._plotter_precision,
222 binary=self._binary,
223 time_stamp_evaluation="0.5*(repositories::getMinTimeStamp()+repositories::getMaxTimeStamp())",
224 )
225 )
226 write_vtk_file_task.use_cell(
227 self._solver_solver._patch, peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE
228 )
229
230 self._log_plot_graph(plot)
231
232 def _log_plot_graph(self, plot):
233 if peano4.api.Logger().is_visualisation:
234 plot.visualise(title="Plot task graph for {}".format(self._solver_solver.name))
235 if peano4.api.Logger().is_text:
236 plot.log_as_text(title="Plot task graph for {}".format(self._solver_solver.name))
237
239 """!
240
241 Indices of the entries of Q which are written, or None for all of
242 them
243
244 """
245 if self._quantities is None:
246 return None
247 return resolve_quantities(
248 self._solver_solver, self._quantities, include_auxiliary_variables=True
249 )
250
252 """!
253
254 Comma-separated names of the entries which are written, or the
255 solver's unknown identifier if its variables carry no names
256
257 """
258 names = self._solver_solver.variable_names_per_entry()
259 if not names:
260 return self._solver_solver._unknown_identifier()
261 selected_entries = self._create_selected_entries()
262 if selected_entries is not None:
263 names = [names[index] for index in selected_entries]
264 return ", ".join(names)
265
266 def _create_guard(self):
267 """!
268
269 Guard of the cells which are plotted
270
271 The guard is built directly from self._plot_filters (known here, in
272 Python) rather than delegating to some project-wide C++ filter
273 object: the generated code carries the exact offset/size values this
274 plotter was configured with, and nothing else. Only the cells
275 selected by the solver's grid selector are plotted, as only those
276 are updated. Other cells would hold outdated data overlapping the
277 actual solution.
278
279 @return str
280 C++ predicate over marker.
281
282 """
283 guard = "(" + self._solver_solver.grid_selector.createCellGuard() + ")"
284 if self._plot_filters:
285 guard += (
286 " and ("
287 + " or ".join(
288 "marker.overlaps({"
289 + ",".join(str(x) for x in offset)
290 + "},{"
291 + ",".join(str(x) for x in size)
292 + "})"
293 for offset, size in self._plot_filters
294 )
295 + ")"
296 )
297 return guard
How a Solver writes out its solution.
Definition Solver.py:147
str output_file_prefix(self)
Prefix of the files the plotter writes, including the path.
Definition Solver.py:222
_add_time_interval_bookkeeping_to_solver(self, float first_time_stamp, float time_in_between)
Make the plotter active in regular time intervals.
Definition Solver.py:268
str create_is_active_predicate(self)
C++ predicate which holds if the plotter is active.
Definition Solver.py:233
str create_finish_call(self)
C++ statement which moves the plotter on to its next output.
Definition Solver.py:249
Plotting counterpart of the fourth-order Finite Differences with Runge-Kutta time stepping (exahype2....
output_file_prefix(self)
Prefix of the files the plotter writes, including the path.
__init__(self, Solver solver, first_plot_time_stamp=0.0, time_in_between_plots=0.1, plotter_precision=5, output_path=".", filename="solution", str name=None, quantities=None, binary=True)
add_plot_filter(self, offset, size, frequency=1)
Add a new filter to Peano/ExaHyPE.
construct_output(self, exahype2_project, peano_project, plot)
Add one task to the plot graph which writes the solver's patches.
_create_selected_entries(self)
Indices of the entries of Q which are written, or None for all of them.
_create_description(self)
Comma-separated names of the entries which are written, or the solver's unknown identifier if its var...
_create_guard(self)
Guard of the cells which are plotted.
PlotPatchesInPeanoBlockFormat which only does something if its plotter is active.
__init__(self, is_active_predicate, finish_call, **kwargs)
Singleton logger for the Peano 4 Python API.
Definition Logger.py:37
One task within a peano4.api.taskgraph.Graph.
Definition Task.py:8