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