svMultiPhysics
Loading...
Searching...
No Matches
VtkData.h
1// SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the University of California, and others.
2// SPDX-License-Identifier: BSD-3-Clause
3
4#ifndef VTK_DATA_H
5#define VTK_DATA_H
6
7#include "Array.h"
8#include "Vector.h"
9
10#include <string>
11#include <utility>
12#include <vector>
13
14#include <vtkIdList.h>
15#include <vtkPointSet.h>
16#include <vtkPolyData.h>
17#include <vtkSmartPointer.h>
18#include <vtkUnstructuredGrid.h>
19
20/**
21 * @brief A mesh stored in one of the VTK XML file formats.
22 *
23 * The mesh is held as a vtkPointSet, and consists of the point coordinates,
24 * the element connectivity, and any number of named data arrays associated
25 * with the points, with the elements, or with the mesh as a whole (field
26 * data). The class provides the operations needed to read those from a file,
27 * to build them up before writing a file, and to copy them to and from the
28 * Array and Vector types used by the solver.
29 *
30 * The file format determines how the mesh is represented, which is what the
31 * derived classes provide: VtkVtpData holds a surface mesh as a vtkPolyData,
32 * VtkVtuData a volume mesh as a vtkUnstructuredGrid. Use create_reader() and
33 * create_writer() to obtain an object of the type matching a given file name.
34 */
35class VtkData {
36 public:
37 /**
38 * @brief Default constructor.
39 */
40 VtkData() = default;
41
42 /**
43 * @brief Virtual destructor.
44 */
45 virtual ~VtkData() = default;
46
47 /**
48 * @brief Read the mesh data from a VTK file.
49 *
50 * @throws svmp::FileFormatException if the file cannot be read, or if it
51 * contains no points or no elements
52 */
53 virtual void read_file(const std::string &file_name);
54
55 /**
56 * @brief Create an empty grid.
57 *
58 * Derived classes need to override this function by implementing the
59 * appropriate logic to create an empty grid. This will include initializing
60 * the correct vtkPointSet object.
61 */
62 virtual void create_grid() = 0;
63
64 /**
65 * @brief Write the mesh data to a VTK file.
66 *
67 * @throws svmp::CoreException if the file cannot be written
68 */
69 virtual void write() const = 0;
70
71 /**
72 * @brief Get the connectivity of the mesh elements.
73 *
74 * @return An array of size (num_points_per_elem, num_elems) containing the
75 * connectivity of the mesh elements. Each column corresponds to an
76 * element, and each row corresponds to a point index in that element.
77 */
78 Array<int> get_connectivity() const;
79
80 /**
81 * @brief Get the points of the mesh.
82 *
83 * @return An array of size (3, num_points) containing the coordinates of
84 * the mesh points. Each column corresponds to a point, and each row
85 * corresponds to a coordinate (x, y, z).
86 */
87 Array<double> get_points() const;
88
89 /**
90 * @brief Get the number of elements in the mesh.
91 */
92 int num_elems() const;
93
94 /**
95 * @brief Get the element type.
96 */
97 int elem_type() const;
98
99 /**
100 * @brief Get the number of points per element.
101 */
102 int num_points_per_elem() const;
103
104 /**
105 * @brief Get the number of points in the mesh.
106 */
107 int num_points() const;
108
109 /**
110 * @brief Set a double-valued element data array.
111 *
112 * @param[in] data_name The name of the data array to set.
113 * @param[in] data The data array to set, holding one value per element.
114 *
115 * @throws svmp::FE::InvalidArgumentException if the number of values
116 * differs from the number of elements of the mesh
117 */
118 void set_element_data(const std::string &data_name,
119 const Array<double> &data);
120
121 /**
122 * @brief Set an int-valued element data array.
123 *
124 * @param[in] data_name The name of the data array to set.
125 * @param[in] data The data array to set, holding one value per element.
126 *
127 * @throws svmp::FE::InvalidArgumentException if the number of values
128 * differs from the number of elements of the mesh
129 */
130 void set_element_data(const std::string &data_name, const Array<int> &data);
131
132 /**
133 * @brief Set an int-valued element data vector.
134 *
135 * @param[in] data_name The name of the data array to set.
136 * @param[in] data The data vector to set, holding one value per element.
137 *
138 * @throws svmp::FE::InvalidArgumentException if the number of values
139 * differs from the number of elements of the mesh
140 */
141 void set_element_data(const std::string &data_name,
142 const Vector<int> &data);
143
144 /**
145 * @brief Set a double-valued point data array.
146 *
147 * @param[in] data_name The name of the data array to set.
148 * @param[in] data The data array to set, holding one value per point.
149 *
150 * @throws svmp::FE::InvalidArgumentException if the number of values
151 * differs from the number of points of the mesh
152 */
153 void set_point_data(const std::string &data_name,
154 const Array<double> &data);
155
156 /**
157 * @brief Set an int-valued point data array.
158 *
159 * @param[in] data_name The name of the data array to set.
160 * @param[in] data The data array to set, holding one value per point.
161 *
162 * @throws svmp::FE::InvalidArgumentException if the number of values
163 * differs from the number of points of the mesh
164 */
165 void set_point_data(const std::string &data_name, const Array<int> &data);
166
167 /**
168 * @brief Set an int-valued point data array.
169 *
170 * @param[in] data_name The name of the data array to set.
171 * @param[in] data The data array to set, holding one value per point.
172 *
173 * @throws svmp::FE::InvalidArgumentException if the number of values
174 * differs from the number of points of the mesh
175 */
176 void set_point_data(const std::string &data_name, const Vector<int> &data);
177
178 /**
179 * @brief Set the point coordinates of the mesh.
180 *
181 * @param[in] points The coordinates, of size (3, num_points).
182 *
183 * @throws svmp::FE::InvalidArgumentException if there are no points or
184 * fewer than three coordinates are given for each point
185 */
186 void set_points(const Array<double> &points);
187
188 /**
189 * @brief Set the mesh connectivity to define the elements.
190 *
191 * The elements are appended to those already defined, so a mesh made of
192 * several parts is built up by calling this once per part.
193 *
194 * @param[in] nsd The number of spatial dimensions, which together with the
195 * number of points per element determines the element type.
196 * @param[in] conn The connectivity, of size (num_points_per_elem,
197 * num_elems). Each column holds the point indices of one element.
198 *
199 * @throws svmp::FE::InvalidArgumentException if a point index does not
200 * refer to one of the points of the mesh
201 */
202 void set_connectivity(const int nsd, const Array<int> &conn);
203
204 /**
205 * @brief Store a time value as field data.
206 *
207 * The value is written as a single-tuple Float64 field data array named
208 * 'TimeValue'. VTK XML readers such as ParaView turn this array into the
209 * pipeline time of the data object.
210 *
211 * @param[in] time The time value to associate with the data.
212 */
213 void set_time_value(const double time);
214
215 /**
216 * @brief Check if a given cell data array exists.
217 */
218 bool has_cell_data(const std::string &data_name) const;
219
220 /**
221 * @brief Check if a given point data array exists.
222 */
223 bool has_point_data(const std::string &data_name) const;
224
225 /**
226 * @brief Copy the mesh points to an Array.
227 *
228 * @param[out] points The array to copy the mesh points into. It must be
229 * of size (3, num_points).
230 *
231 * @throws svmp::FE::InvalidArgumentException if the points do not fit in
232 * the array
233 */
234 void copy_points(Array<double> &points) const;
235
236 /**
237 * @brief Copy an array of point data from the mesh into the given Array.
238 *
239 * @param[in] data_name The name of the point data array to copy.
240 * @param[out] mesh_data The array to copy the point data into. It must be
241 * of size (num_components, num_points).
242 *
243 * @throws svmp::FE::InvalidArgumentException if the mesh has no
244 * double-valued point data array with the given name, or if its values do
245 * not fit in mesh_data
246 */
247 void copy_point_data(const std::string &data_name,
248 Array<double> &mesh_data) const;
249
250 /**
251 * @brief Copy an array of point data from the mesh into the given Vector.
252 *
253 * @param[in] data_name The name of the point data array to copy.
254 * @param[out] mesh_data The vector to copy the point data into. It must be
255 * of size (num_points).
256 *
257 * @throws svmp::FE::InvalidArgumentException if the mesh has no
258 * double-valued point data array with the given name, or if its values do
259 * not fit in mesh_data
260 */
261 void copy_point_data(const std::string &data_name,
262 Vector<double> &mesh_data) const;
263
264 /**
265 * @brief Copy an array of int-valued point data from the mesh into the
266 * given Vector.
267 *
268 * @param[in] data_name The name of the point data array to copy.
269 * @param[out] mesh_data The vector to copy the point data into. It must be
270 * of size (num_points).
271 *
272 * @throws svmp::FE::InvalidArgumentException if the mesh has no int-valued
273 * point data array with the given name, or if its values do not fit in
274 * mesh_data
275 */
276 void copy_point_data(const std::string &data_name,
277 Vector<int> &mesh_data) const;
278
279 /**
280 * @brief Copy an array of cell data from the mesh into the given Array.
281 *
282 * @param[in] data_name The name of the cell data array to copy.
283 * @param[out] mesh_data The array to copy the cell data into. It must be
284 * of size (num_components, num_cells).
285 *
286 * @throws svmp::FE::InvalidArgumentException if the mesh has no
287 * double-valued cell data array with the given name, or if its values do
288 * not fit in mesh_data
289 */
290 void copy_cell_data(const std::string &data_name,
291 Array<double> &mesh_data) const;
292
293 /**
294 * @brief Copy an array of cell data from the mesh into the given Vector.
295 *
296 * @param[in] data_name The name of the cell data array to copy.
297 * @param[out] mesh_data The vector to copy the cell data into. It must be
298 * of size (num_points).
299 *
300 * @throws svmp::FE::InvalidArgumentException if the mesh has no
301 * double-valued cell data array with the given name, or if its values do
302 * not fit in mesh_data
303 */
304 void copy_cell_data(const std::string &data_name,
305 Vector<double> &mesh_data) const;
306
307 /**
308 * @brief Copy an array of int-valued cell data from the mesh into the given
309 * Vector.
310 *
311 * @param[in] data_name The name of the cell data array to copy.
312 * @param[out] mesh_data The vector to copy the cell data into. It must be
313 * of size (num_points).
314 *
315 * @throws svmp::FE::InvalidArgumentException if the mesh has no int-valued
316 * cell data array with the given name, or if its values do not fit in
317 * mesh_data
318 */
319 void copy_cell_data(const std::string &data_name,
320 Vector<int> &mesh_data) const;
321
322 /**
323 * @brief Get an array of point data from the mesh.
324 *
325 * @throws svmp::FE::InvalidArgumentException if the mesh has no
326 * double-valued point data array with the given name
327 *
328 * @todo[michelebucelli] This should fall back onto copy_point_data.
329 */
330 Array<double> get_point_data(const std::string &data_name) const;
331
332 /**
333 * @brief Get a list of point data names.
334 *
335 * @return A vector of strings containing the names of the point data
336 * arrays.
337 */
338 std::vector<std::string> get_point_data_names() const;
339
340 /**
341 * @brief Get the dimensions of a cell data array.
342 *
343 * @param[in] data_name The name of the cell data array to get the
344 * dimensions of.
345 *
346 * @return A pair of integers representing the number of components and the
347 * number of tuples in the array.
348 */
349 std::pair<int, int>
350 get_cell_data_dimensions(const std::string &data_name) const;
351
352 /**
353 * @brief Create an object to read a mesh from a VTK file.
354 *
355 * The concrete type is selected from the file extension, and the mesh is
356 * read as part of the construction. The file extension must be 'vtp' or
357 * 'vtu'.
358 *
359 * @param[in] file_name The name of the VTK file to read.
360 *
361 * @return A pointer to a newly allocated object holding the mesh read from
362 * the file. The caller owns the object and must delete it.
363 *
364 * @throws svmp::FE::InvalidArgumentException if the file extension is not
365 * 'vtp' or 'vtu'
366 */
367 static VtkData *create_reader(const std::string &file_name);
368
369 /**
370 * @brief Create an object to write a mesh to a VTK file.
371 *
372 * The concrete type is selected from the file extension, and the object is
373 * created holding an empty mesh. The file extension must be 'vtp' or 'vtu'.
374 * The file itself is written by write(), once the mesh has been defined.
375 *
376 * @param[in] file_name The name of the VTK file to write.
377 *
378 * @return A pointer to a newly allocated object holding an empty mesh. The
379 * caller owns the object and must delete it.
380 *
381 * @throws svmp::FE::InvalidArgumentException if the file extension is not
382 * 'vtp' or 'vtu'
383 */
384 static VtkData *create_writer(const std::string &file_name);
385
386 protected:
387 /**
388 * @brief Read the mesh data from a file.
389 *
390 * Derived classes need to override this function by implementing the
391 * appropriate reading logic. This will include selecting the correct VTK
392 * reader, and initializing vtk_data.
393 */
394 virtual void read_file_internal(const std::string &file_name) = 0;
395
396 /**
397 * @brief Get the VTK cell type for a given number of spatial dimensions and
398 * number of points per element.
399 *
400 * Derived classes must override this to implement the appropriate mapping
401 * from the number of spatial dimensions and number of points per element to
402 * the VTK cell type.
403 *
404 * @throws svmp::FE::InvalidArgumentException if there is no cell type that
405 * the file format can hold for the given element
406 */
407 virtual int cell_type(int nsd, int np_elem) const = 0;
408
409 /**
410 * @brief Insert a new cell into the VTK data object.
411 *
412 * Derived classes must override this to implement the appropriate insertion
413 * call.
414 *
415 * @param[in] vtk_cell_type The VTK cell type of the element.
416 * @param[in] elem_nodes The list of point IDs that define the element.
417 */
418 virtual void insert_cell(int vtk_cell_type,
419 vtkSmartPointer<vtkIdList> elem_nodes) = 0;
420 /**
421 * Pointer to the underlying VTK data object. The concrete type will be
422 * either vtkPolyData, for VTP files, or vtkUnstructuredGrid, for VTU files.
423 */
424 vtkSmartPointer<vtkPointSet> vtk_data;
425
426 /// Filename that the mesh is read from, or written to.
427 std::string file_name_;
428
429 /// Type of elements in the mesh.
430 int elem_type_ = -1;
431
432 /// Number of elements.
433 int num_elems_ = 0;
434
435 /// Number of points per element.
437
438 /// Number of points.
439 int num_points_ = 0;
440};
441
442/**
443 * @brief A mesh stored in the VTK XML polygonal data format ('.vtp' files).
444 *
445 * The mesh is held as a vtkPolyData, and its elements are polygons: the
446 * surface meshes that define the faces of a volume mesh, and the line meshes
447 * used for one-dimensional domains.
448 */
449class VtkVtpData : public VtkData {
450public:
451 /**
452 * @brief Default constructor.
453 *
454 * Creates an empty VtkVtpData object with an empty vtkPolyData grid.
455 */
456 VtkVtpData();
457
458 /**
459 * @brief Constructor.
460 *
461 * @param[in] file_name The name of the VTP file to read from or write to.
462 * @param[in] reader If true, the constructor reads the mesh data from the
463 * given file. If false, it creates an empty grid.
464 */
465 VtkVtpData(const std::string &file_name, bool reader = true);
466
467 /**
468 * @brief Create an empty grid.
469 */
470 virtual void create_grid() override;
471
472 /**
473 * @brief Write the mesh data to a file.
474 */
475 virtual void write() const override;
476
477protected:
478 /**
479 * @brief Read the mesh data from a file.
480 */
481 virtual void read_file_internal(const std::string &file_name) override;
482
483 /**
484 * @brief Get the VTK cell type of a surface element.
485 */
486 virtual int cell_type(int nsd, int np_elem) const override;
487
488 /**
489 * @brief Insert a new cell into the vtkPolyData object.
490 */
491 virtual void insert_cell(int vtk_cell_type,
492 vtkSmartPointer<vtkIdList> elem_nodes) override;
493
494 /**
495 * The mesh, represented as a vtkPolyData object.
496 */
497 vtkSmartPointer<vtkPolyData> vtk_polydata;
498};
499
500/**
501 * @brief A mesh stored in the VTK XML unstructured grid format ('.vtu' files).
502 *
503 * The mesh is held as a vtkUnstructuredGrid, whose elements may be of any VTK
504 * cell type: the volume meshes the equations are solved on, and the results
505 * written at each saved time step.
506 */
507class VtkVtuData : public VtkData {
508public:
509 /**
510 * @brief Default constructor.
511 *
512 * Creates an empty VtkVtuData object with an empty vtkUnstructuredGrid grid.
513 */
514 VtkVtuData();
515
516 /**
517 * @brief Constructor.
518 *
519 * @param[in] file_name The name of the VTP file to read from or write to.
520 * @param[in] reader If true, the constructor reads the mesh data from the
521 * given file. If false, it creates an empty grid.
522 */
523 VtkVtuData(const std::string &file_name, bool reader = true);
524
525 /**
526 * @brief Create an empty grid.
527 */
528 virtual void create_grid() override;
529
530 /**
531 * @brief Write the mesh data to a file.
532 */
533 virtual void write() const override;
534
535protected:
536 /**
537 * @brief Read the mesh data from a file.
538 */
539 virtual void read_file_internal(const std::string &file_name) override;
540
541 /**
542 * @brief Get the VTK cell type of a volume element.
543 */
544 virtual int cell_type(int nsd, int np_elem) const override;
545
546 /**
547 * @brief Insert a new cell into the vtkUnstructuredGrid object.
548 */
549 virtual void insert_cell(int vtk_cell_type,
550 vtkSmartPointer<vtkIdList> elem_nodes) override;
551
552 /**
553 * The mesh, represented as a vtkUnstructuredGrid object.
554 */
555 vtkSmartPointer<vtkUnstructuredGrid> vtk_ugrid;
556};
557
558#endif
The Vector template class is used for storing int and double data.
Definition Vector.h:26
A mesh stored in one of the VTK XML file formats.
Definition VtkData.h:35
Array< double > get_point_data(const std::string &data_name) const
Get an array of point data from the mesh.
Definition VtkData.cpp:504
int num_points_
Number of points.
Definition VtkData.h:439
virtual void read_file(const std::string &file_name)
Read the mesh data from a VTK file.
Definition VtkData.cpp:27
int num_points_per_elem() const
Get the number of points per element.
Definition VtkData.cpp:90
int num_elems() const
Get the number of elements in the mesh.
Definition VtkData.cpp:86
Array< int > get_connectivity() const
Get the connectivity of the mesh elements.
Definition VtkData.cpp:52
int elem_type() const
Get the element type.
Definition VtkData.cpp:88
int num_elems_
Number of elements.
Definition VtkData.h:433
bool has_point_data(const std::string &data_name) const
Check if a given point data array exists.
Definition VtkData.cpp:317
int num_points_per_elem_
Number of points per element.
Definition VtkData.h:436
virtual void create_grid()=0
Create an empty grid.
void set_time_value(const double time)
Store a time value as field data.
Definition VtkData.cpp:293
int elem_type_
Type of elements in the mesh.
Definition VtkData.h:430
virtual ~VtkData()=default
Virtual destructor.
void set_point_data(const std::string &data_name, const Array< double > &data)
Set a double-valued point data array.
Definition VtkData.cpp:166
static VtkData * create_reader(const std::string &file_name)
Create an object to read a mesh from a VTK file.
Definition VtkData.cpp:549
static VtkData * create_writer(const std::string &file_name)
Create an object to write a mesh to a VTK file.
Definition VtkData.cpp:562
int num_points() const
Get the number of points in the mesh.
Definition VtkData.cpp:92
bool has_cell_data(const std::string &data_name) const
Check if a given cell data array exists.
Definition VtkData.cpp:304
void set_points(const Array< double > &points)
Set the point coordinates of the mesh.
Definition VtkData.cpp:240
virtual void write() const =0
Write the mesh data to a VTK file.
vtkSmartPointer< vtkPointSet > vtk_data
Definition VtkData.h:424
virtual void insert_cell(int vtk_cell_type, vtkSmartPointer< vtkIdList > elem_nodes)=0
Insert a new cell into the VTK data object.
void copy_points(Array< double > &points) const
Copy the mesh points to an Array.
Definition VtkData.cpp:330
virtual void read_file_internal(const std::string &file_name)=0
Read the mesh data from a file.
void set_connectivity(const int nsd, const Array< int > &conn)
Set the mesh connectivity to define the elements.
Definition VtkData.cpp:262
std::string file_name_
Filename that the mesh is read from, or written to.
Definition VtkData.h:427
void copy_cell_data(const std::string &data_name, Array< double > &mesh_data) const
Copy an array of cell data from the mesh into the given Array.
Definition VtkData.cpp:427
virtual int cell_type(int nsd, int np_elem) const =0
Get the VTK cell type for a given number of spatial dimensions and number of points per element.
VtkData()=default
Default constructor.
void copy_point_data(const std::string &data_name, Array< double > &mesh_data) const
Copy an array of point data from the mesh into the given Array.
Definition VtkData.cpp:350
std::pair< int, int > get_cell_data_dimensions(const std::string &data_name) const
Get the dimensions of a cell data array.
Definition VtkData.cpp:539
Array< double > get_points() const
Get the points of the mesh.
Definition VtkData.cpp:69
void set_element_data(const std::string &data_name, const Array< double > &data)
Set a double-valued element data array.
Definition VtkData.cpp:94
std::vector< std::string > get_point_data_names() const
Get a list of point data names.
Definition VtkData.cpp:527
A mesh stored in the VTK XML polygonal data format ('.vtp' files).
Definition VtkData.h:449
vtkSmartPointer< vtkPolyData > vtk_polydata
Definition VtkData.h:497
virtual void create_grid() override
Create an empty grid.
Definition VtkData.cpp:588
virtual void read_file_internal(const std::string &file_name) override
Read the mesh data from a file.
Definition VtkData.cpp:611
virtual void write() const override
Write the mesh data to a file.
Definition VtkData.cpp:598
virtual int cell_type(int nsd, int np_elem) const override
Get the VTK cell type of a surface element.
Definition VtkData.cpp:625
VtkVtpData()
Default constructor.
Definition VtkData.cpp:576
virtual void insert_cell(int vtk_cell_type, vtkSmartPointer< vtkIdList > elem_nodes) override
Insert a new cell into the vtkPolyData object.
Definition VtkData.cpp:652
A mesh stored in the VTK XML unstructured grid format ('.vtu' files).
Definition VtkData.h:507
vtkSmartPointer< vtkUnstructuredGrid > vtk_ugrid
Definition VtkData.h:555
VtkVtuData()
Default constructor.
Definition VtkData.cpp:659
virtual void write() const override
Write the mesh data to a file.
Definition VtkData.cpp:681
virtual void read_file_internal(const std::string &file_name) override
Read the mesh data from a file.
Definition VtkData.cpp:694
virtual void insert_cell(int vtk_cell_type, vtkSmartPointer< vtkIdList > elem_nodes) override
Insert a new cell into the vtkUnstructuredGrid object.
Definition VtkData.cpp:751
virtual void create_grid() override
Create an empty grid.
Definition VtkData.cpp:671
virtual int cell_type(int nsd, int np_elem) const override
Get the VTK cell type of a volume element.
Definition VtkData.cpp:708