FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
export_vtk.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include "kernel/shape.hpp"
11#include <kernel/geometry/conformal_mesh.hpp>
12#include <kernel/geometry/mesh_part.hpp>
13#include <kernel/geometry/structured_mesh.hpp>
14#include <kernel/util/dist.hpp>
15#include <kernel/util/dist_file_io.hpp>
17
18// includes, STL
19#include <deque>
20#include <fstream>
21#include <functional>
22#include <vector>
23
24namespace FEAT
25{
26 namespace Geometry
27 {
29 namespace Intern
30 {
31 template<typename Shape_>
32 struct VTKShape;
33
34 template<>
35 struct VTKShape<Shape::Simplex<1>>
36 {
37 static constexpr int type = 3; // VTK_LINE
38 static inline int map(int i)
39 {
40 return i;
41 }
42 };
43
44 template<>
45 struct VTKShape<Shape::Simplex<2>>
46 {
47 static constexpr int type = 5; // VTK_TRIANGLE
48 static inline int map(int i)
49 {
50 return i;
51 }
52 };
53
54 template<>
55 struct VTKShape<Shape::Simplex<3>>
56 {
57 static constexpr int type = 10; // VTK_TETRA
58 static inline int map(int i)
59 {
60 return i;
61 }
62 };
63
64 template<>
65 struct VTKShape<Shape::Hypercube<1>>
66 {
67 static constexpr int type = 3; // VTK_LINE
68 static inline int map(int i)
69 {
70 return i;
71 }
72 };
73
74 template<>
75 struct VTKShape<Shape::Hypercube<2>>
76 {
77 static constexpr int type = 9; // VTK_QUAD
78 static inline int map(int i)
79 {
80 // bit-stunt: {0, 1, 2, 3} -> {0, 1, 3, 2}
81 return (i ^ ((i >> 1) & 1));
82 }
83 };
84
85 template<>
86 struct VTKShape<Shape::Hypercube<3>>
87 {
88 static constexpr int type = 12; // VTK_HEXAHEDRON
89 static inline int map(int i)
90 {
91 // bit-stunt: {0, 1, ..., 7} -> {0, 1, 3, 2, 4, 5, 7, 6}
92 return (i ^ ((i >> 1) & 1));
93 }
94 };
95 } // namespace Intern
97
117 template<typename Mesh_, int cell_dim_ = Mesh_::ShapeType::dimension>
119 {
120 public:
122 using MeshType = Mesh_;
124 using ShapeType = typename MeshType::ShapeType;
128 using VTKShapeType = Intern::VTKShape<CellShapeType>;
129
130 protected:
132 using VarDeque = std::deque<std::pair<String, std::vector<double>>>;
133
134 // NOTE(mmuegge): Depending on wether we are writing a mesh or a meshpart,
135 // we may need to do some additional handling of indices.
136 // The accessor functions allow us to do so,
137 // while presenting a consistent interface to the actual file writing logic.
138
140 std::function<double(Index, int)> _vertices;
142 std::function<Index(Index, int)> _cells;
157
158 public:
170 explicit ExportVTK(const MeshType& mesh, int var_prec = 0) :
171 _num_verts(mesh.get_num_entities(0)),
172 _num_cells(mesh.get_num_entities(cell_dim_)),
173 _var_prec(Math::max(0, var_prec))
174 {
175 const auto& vertex_set = mesh.get_vertex_set();
176 const auto& index_set = mesh.template get_index_set<cell_dim_, 0>();
177
178 _vertices = [&](Index i, int j) { return vertex_set[i][j]; };
179 _cells = [&](Index i, int j) { return index_set(i, j); };
180 }
181
197 explicit ExportVTK(const MeshType& mesh, const MeshPart<MeshType>& part, int var_prec = 0) :
198 _num_verts(part.get_num_entities(0)),
199 _num_cells(part.get_num_entities(cell_dim_)),
200 _var_prec(Math::max(0, var_prec))
201 {
202 const auto& vertex_set = mesh.get_vertex_set();
203 const auto& vertex_target_set = part.template get_target_set<0>();
204 const auto& cell_target_set = part.template get_target_set<cell_dim_>();
205
206 _vertices = [&](Index i, int j) { return vertex_set[vertex_target_set[i]][j]; };
207
208 if(part.has_topology())
209 {
210 // The meshpart has its own topology. Use that.
211 const auto& index_set = part.template get_index_set<cell_dim_, 0>();
212 _cells = [&](Index i, int j) { return index_set(i, j); };
213 }
214 else
215 {
216 // The meshpart has no own topology. Use the mesh topology.
217 const auto& index_set = mesh.template get_index_set<cell_dim_, 0>();
218
219 // The mesh index-set returns indices of vertices the mesh's index-space,
220 // but the .vtu will be written in the meshparts index-space.
221 // We thus need to search for the corresponding index on the meshpart for any vertex index.
222 _cells = [&](Index i, int j)
223 {
224 const Index vertex = index_set(cell_target_set[i], j);
225 for(Index k(0); k < vertex_target_set.get_num_entities(); k++)
226 {
227 if(vertex_target_set[k] == vertex)
228 {
229 return k;
230 }
231 }
232
233 XABORTM("Lookup of vertex index failed!");
234 };
235 }
236 }
237
239 virtual ~ExportVTK() = default;
240
242 ExportVTK(const ExportVTK& other) = default;
243
245 ExportVTK(ExportVTK&& other) noexcept = default;
246
248 ExportVTK& operator=(const ExportVTK& other) = default;
249
252
256 void clear()
257 {
258 _cell_scalars.clear();
259 _vertex_scalars.clear();
260 _vertex_vectors.clear();
261 _cell_vectors.clear();
262 }
263
281 template<typename T_>
282 void add_vertex_scalar(const String& name, const T_* data, double scaling_factor = 1.0)
283 {
284 XASSERTM(data != nullptr, "data array is nullptr");
285 std::vector<double> d(_num_verts);
286 for(Index i(0); i < _num_verts; ++i)
287 {
288 d[i] = scaling_factor * double(data[i]);
289 }
290 _vertex_scalars.emplace_back(name, std::move(d));
291 }
292
312 template<typename T_>
314 const String& name,
315 const T_* x,
316 const T_* y = nullptr,
317 const T_* z = nullptr,
318 double scaling_factor = 1.0)
319 {
320 XASSERTM(x != nullptr, "x-data array is nullptr");
321 std::vector<double> d(3 * _num_verts);
322
323 if(y != nullptr && z != nullptr)
324 {
325 for(Index i(0); i < _num_verts; ++i)
326 {
327 d[(3 * i) + 0] = scaling_factor * double(x[i]);
328 d[(3 * i) + 1] = scaling_factor * double(y[i]);
329 d[(3 * i) + 2] = scaling_factor * double(z[i]);
330 }
331 }
332 else if(y != nullptr)
333 {
334 for(Index i(0); i < _num_verts; ++i)
335 {
336 d[(3 * i) + 0] = scaling_factor * double(x[i]);
337 d[(3 * i) + 1] = scaling_factor * double(y[i]);
338 d[(3 * i) + 2] = 0.0;
339 }
340 }
341 else
342 {
343 for(Index i(0); i < _num_verts; ++i)
344 {
345 d[(3 * i) + 0] = scaling_factor * double(x[i]);
346 d[(3 * i) + 1] = 0.0;
347 d[(3 * i) + 2] = 0.0;
348 }
349 }
350 _vertex_vectors.emplace_back(name, std::move(d));
351 }
352
373 template<typename VectorType_>
374 void add_vertex_vector(const String& name, const VectorType_& v, double scaling_factor = 1.0)
375 {
376 std::vector<double> d(3 * _num_verts);
377
378 for(Index i(0); i < _num_verts; ++i)
379 {
380 for(Index j(0); j < 3; ++j)
381 {
382 d[(Index(3) * i) + j] = double(0);
383 }
384
385 for(int j(0); j < v.BlockSize; ++j)
386 {
387 d[(Index(3) * i) + Index(j)] = scaling_factor * double(v(i)[j]);
388 }
389 }
390 _vertex_vectors.emplace_back(name, std::move(d));
391 }
392
410 template<typename T_>
411 void add_cell_scalar(const String& name, const T_* data, double scaling_factor = 1.0)
412 {
413 XASSERTM(data != nullptr, "data array is nullptr");
414 std::vector<double> d(_num_cells);
415 for(Index i(0); i < _num_cells; ++i)
416 {
417 d[i] = scaling_factor * double(data[i]);
418 }
419 _cell_scalars.emplace_back(name, std::move(d));
420 }
421
441 template<typename T_>
443 const String& name,
444 const T_* x,
445 const T_* y = nullptr,
446 const T_* z = nullptr,
447 double scaling_factor = 1.0)
448 {
449 XASSERTM(x != nullptr, "x-data array is nullptr");
450 std::vector<double> d(3 * _num_cells);
451
452 if(y != nullptr && z != nullptr)
453 {
454 for(Index i(0); i < _num_cells; ++i)
455 {
456 d[(3 * i) + 0] = scaling_factor * double(x[i]);
457 d[(3 * i) + 1] = scaling_factor * double(y[i]);
458 d[(3 * i) + 2] = scaling_factor * double(z[i]);
459 }
460 }
461 else if(y != nullptr)
462 {
463 for(Index i(0); i < _num_cells; ++i)
464 {
465 d[(3 * i) + 0] = scaling_factor * double(x[i]);
466 d[(3 * i) + 1] = scaling_factor * double(y[i]);
467 d[(3 * i) + 2] = 0.0;
468 }
469 }
470 else
471 {
472 for(Index i(0); i < _num_cells; ++i)
473 {
474 d[(3 * i) + 0] = scaling_factor * double(x[i]);
475 d[(3 * i) + 1] = 0.0;
476 d[(3 * i) + 2] = 0.0;
477 }
478 }
479 _cell_vectors.emplace_back(name, std::move(d));
480 }
481
502 template<typename VectorType_>
503 void add_cell_vector(const String& name, const VectorType_& v, double scaling_factor = 1.0)
504 {
505 std::vector<double> d(3 * _num_cells);
506
507 for(Index i(0); i < _num_cells; ++i)
508 {
509 for(Index j(0); j < 3; ++j)
510 {
511 d[(Index(3) * i) + j] = double(0);
512 }
513
514 for(int j(0); j < v.BlockSize; ++j)
515 {
516 d[(Index(3) * i) + Index(j)] = scaling_factor * double(v(i)[j]);
517 }
518 }
519 _cell_vectors.emplace_back(name, std::move(d));
520 }
521
528 void write(const String& filename) const
529 {
530 // try to open the output file
531 String vtu_name(filename + ".vtu");
532 std::ofstream ofs(vtu_name.c_str());
533 if(!(ofs.is_open() && ofs.good()))
534 {
535 throw FileError("Failed to create '" + vtu_name + "'");
536 }
537
538 // write
539 write_vtu(ofs);
540
541 // and close
542 ofs.close();
543 }
544
564 void write(const String& filename, const int rank, const int nparts)
565 {
566 // call the standard serial write version if nparts < 1
567 if(nparts <= 1)
568 {
569 write(filename);
570 return;
571 }
572
573 // verify rank
574 XASSERTM((rank >= 0) && (rank < nparts), "Invalid rank");
575
576 // Add rank cell array since we're parallel if we come to here
577 std::vector<double> rank_array((std::size_t(_num_cells)), double(rank));
578 add_cell_scalar("rank", rank_array.data());
579
580 // compute number of non-zero digits in (nparts-1) for padding
581 const std::size_t ndigits = Math::ilog10(std::size_t(nparts - 1));
582
583 // write serial VTU file: "filename.#rank.vtu"
584 write(filename + "." + stringify(rank).pad_front(ndigits, '0'));
585
586 // we're done unless we have rank = 0
587 if(rank != 0)
588 {
589 return;
590 }
591
592 // try to open our output file
593 String pvtu_name(filename + ".pvtu");
594 std::ofstream ofs(pvtu_name.c_str());
595 if(!(ofs.is_open() && ofs.good()))
596 {
597 throw FileError("Failed to create '" + pvtu_name + "'");
598 }
599
600 // extract the file title from our filename
601 std::size_t p = filename.find_last_of("\\/");
602 String file_title = filename.substr(p == FEAT::String::npos ? 0 : ++p);
603
604 // write PVTU file
605 write_pvtu(ofs, file_title, nparts);
606
607 // and close
608 ofs.close();
609 }
610
623 void write(const String& filename, const Dist::Comm& comm)
624 {
625 // Add rank cell array since we're parallel if we come to here
626 std::vector<double> rank_array(std::size_t(_num_cells), double(comm.rank()));
627 add_cell_scalar("rank", rank_array.data());
628
629 // compute number of non-zero digits in (nparts-1) for padding
630 const auto ndigits = std::size_t(Math::max(Math::ilog10(comm.size() - 1), 1));
631
632 // write serial VTU file into a stringstream
633 std::stringstream stream;
634 write_vtu(stream);
635
636 // generate pattern for filename: "filename.#rank.vtu"
637 String pattern = filename + "." + String(ndigits, '*') + ".vtu";
638
639 // write distributed VTU files
640 DistFileIO::write_sequence(stream, pattern, comm);
641
642 // we're done unless we have rank = 0
643 if(comm.rank() != 0)
644 {
645 return;
646 }
647
648 // try to open our output file
649 String pvtu_name(filename + ".pvtu");
650 std::ofstream ofs(pvtu_name.c_str());
651 if(!(ofs.is_open() && ofs.good()))
652 {
653 throw FileError("Failed to create '" + pvtu_name + "'");
654 }
655
656 // extract the file title from our filename
657 std::size_t p = filename.find_last_of("\\/");
658 String file_title = filename.substr(p == FEAT::String::npos ? 0 : ++p);
659
660 // write PVTU file
661 write_pvtu(ofs, file_title, comm.size());
662
663 // and close
664 ofs.close();
665 }
666
673 void write_vtu(std::ostream& os) const
674 {
675 // fetch basic information
676 const int num_coords = MeshType::world_dim;
677 const int verts_per_cell = Shape::FaceTraits<CellShapeType, 0>::count;
678
679 // write VTK header
680 os << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\">\n)";
681 os << "<!-- Generated by FEAT v" << version_major << "." << version_minor;
682 os << "." << version_patch << " -->\n";
683
684 // write mesh header
685 os << "<UnstructuredGrid>\n";
686 os << "<Piece NumberOfPoints=\"" << _num_verts << "\" NumberOfCells=\"" << _num_cells << "\">\n";
687
688 // write point data
689 if((!_vertex_scalars.empty()) || (!_vertex_vectors.empty()))
690 {
691 os << "<PointData>\n";
692
693 // write vertex variables
694 for(const auto& var : _vertex_scalars)
695 {
696 os << "<DataArray type=\"Float64\" Name=\"" << var.first << "\" Format=\"ascii\">\n";
697 for(Index j(0); j < _num_verts; ++j)
698 {
699 os << stringify_fp_sci(var.second[j], _var_prec) << "\n";
700 }
701 os << "</DataArray>\n";
702 }
703 // write vertex fields
704 for(const auto& var : _vertex_vectors)
705 {
706 os << "<DataArray type=\"Float64\" Name=\"" << var.first;
707 os << "\" NumberOfComponents=\"3\" Format=\"ascii\">\n";
708 for(Index j(0); j < _num_verts; ++j)
709 {
710 os << stringify_fp_sci(var.second[(3 * j) + 0], _var_prec) << " ";
711 os << stringify_fp_sci(var.second[(3 * j) + 1], _var_prec) << " ";
712 os << stringify_fp_sci(var.second[(3 * j) + 2], _var_prec) << "\n";
713 }
714 os << "</DataArray>\n";
715 }
716
717 os << "</PointData>\n";
718 }
719
720 // write cell data
721 if(!_cell_scalars.empty() || !_cell_vectors.empty())
722 {
723 os << "<CellData>\n";
724 if(!_cell_scalars.empty())
725 {
726 for(const auto& var : _cell_scalars)
727 {
728 os << "<DataArray type=\"Float64\" Name=\"" << var.first << "\" Format=\"ascii\">\n";
729 for(Index j(0); j < _num_cells; ++j)
730 {
731 os << stringify_fp_sci(var.second[j], _var_prec) << "\n";
732 }
733 os << "</DataArray>\n";
734 }
735 }
736
737 if(!_cell_vectors.empty())
738 {
739 // write cell fields
740 for(const auto& var : _cell_vectors)
741 {
742 os << "<DataArray type=\"Float64\" Name=\"" << var.first;
743 os << "\" NumberOfComponents=\"3\" Format=\"ascii\">\n";
744 for(Index j(0); j < _num_cells; ++j)
745 {
746 os << stringify_fp_sci(var.second[(3 * j) + 0], _var_prec) << " ";
747 os << stringify_fp_sci(var.second[(3 * j) + 1], _var_prec) << " ";
748 os << stringify_fp_sci(var.second[(3 * j) + 2], _var_prec) << "\n";
749 }
750 os << "</DataArray>\n";
751 }
752 }
753 os << "</CellData>\n";
754 }
755
756 // write vertices
757 os << "<Points>\n";
758 os << "<DataArray type=\"Float32\" NumberOfComponents=\"3\" Format=\"ascii\">\n";
759 for(Index i(0); i < _num_verts; ++i)
760 {
761 os << _vertices(i, 0);
762 for(int j(1); j < num_coords; ++j)
763 {
764 os << " " << _vertices(i, j);
765 }
766 for(int j(num_coords); j < 3; ++j)
767 {
768 os << " 0";
769 }
770 os << "\n";
771 }
772 os << "</DataArray>\n";
773 os << "</Points>\n";
774
775 // write cells
776 os << "<Cells>\n";
777 os << "<DataArray type=\"UInt32\" Name=\"connectivity\">\n";
778 for(Index i(0); i < _num_cells; ++i)
779 {
780 os << _cells(i, VTKShapeType::map(0));
781 for(int j(1); j < verts_per_cell; ++j)
782 {
783 os << " " << _cells(i, VTKShapeType::map(j));
784 }
785 os << "\n";
786 }
787 os << "</DataArray>\n";
788 os << "<DataArray type=\"UInt32\" Name=\"offsets\">\n";
789 for(Index i(0); i < _num_cells; ++i)
790 {
791 os << ((i + 1) * verts_per_cell) << "\n";
792 }
793 os << "</DataArray>\n";
794 os << "<DataArray type=\"UInt32\" Name=\"types\">\n";
795 for(Index i(0); i < _num_cells; ++i)
796 {
797 os << VTKShapeType::type << "\n";
798 }
799 os << "</DataArray>\n";
800 os << "</Cells>\n";
801
802 // finish
803 os << "</Piece>\n";
804 os << "</UnstructuredGrid>\n";
805 os << "</VTKFile>\n";
806 }
807
820 void write_pvtu(std::ostream& os, const String& file_title, const int nparts) const
821 {
822 // write VTK header
823 os << "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\">\n";
824 os << "<!-- Generated by FEAT v" << version_major << "." << version_minor;
825 os << "." << version_patch << " -->\n";
826 os << "<PUnstructuredGrid GhostLevel=\"0\">\n";
827
828 // write vertex data
829 if((!_vertex_scalars.empty()) || (!_vertex_vectors.empty()))
830 {
831 os << "<PPointData>\n";
832
833 // write vertex variables
834 for(const auto& vertex_scalar : _vertex_scalars)
835 {
836 os << "<PDataArray type=\"Float64\" Name=\"" << vertex_scalar.first << "\" />\n";
837 }
838 // write vertex fields
839 for(const auto& vertex_vector : _vertex_vectors)
840 {
841 os << "<PDataArray type=\"Float64\" Name=\"" << vertex_vector.first;
842 os << "\" NumberOfComponents=\"3\" />\n";
843 }
844
845 os << "</PPointData>\n";
846 }
847
848 // write cell variables
849 if(!_cell_scalars.empty() || !_cell_vectors.empty())
850 {
851 os << "<PCellData>\n";
852 // write cell scalars
853 for(const auto& cell_scalar : _cell_scalars)
854 {
855 os << "<PDataArray type=\"Float64\" Name=\"" << cell_scalar.first << "\" />\n";
856 }
857 // write cell fields
858 for(const auto& cell_vector : _cell_vectors)
859 {
860 os << "<PDataArray type=\"Float64\" Name=\"" << cell_vector.first;
861 os << "\" NumberOfComponents=\"3\" />\n";
862 }
863 os << "</PCellData>\n";
864 }
865
866 // write vertices
867 os << "<PPoints>\n";
868 os << "<PDataArray type=\"Float32\" NumberOfComponents=\"3\" />\n";
869 os << "</PPoints>\n";
870
871 // compute number of non-zero digits in (nparts-1) for padding
872 const std::size_t ndigits = Math::ilog10(std::size_t(nparts - 1));
873
874 // now let's write our piece data
875 for(int i(0); i < nparts; ++i)
876 {
877 os << "<Piece Source=\"" << file_title << "." << stringify(i).pad_front(ndigits, '0');
878 os << ".vtu\" />\n";
879 }
880
881 // finish
882 os << "</PUnstructuredGrid>\n";
883 os << "</VTKFile>\n";
884 }
885 }; // class ExportVTK
886 } // namespace Geometry
887} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Communicator class.
Definition: dist.hpp:1349
int size() const
Returns the size of this communicator.
Definition: dist.hpp:1506
int rank() const
Returns the rank of this process in this communicator.
Definition: dist.hpp:1494
static void write_sequence(std::stringstream &stream, const String &pattern, const Dist::Comm &comm, bool truncate=true)
Writes a rank-indexed text file sequence.
Base class for file related errors.
Definition: exception.hpp:173
VTK exporter class template.
Definition: export_vtk.hpp:119
ExportVTK(const MeshType &mesh, const MeshPart< MeshType > &part, int var_prec=0)
Constructor.
Definition: export_vtk.hpp:197
virtual ~ExportVTK()=default
destructor
VarDeque _vertex_scalars
vertex variable list
Definition: export_vtk.hpp:148
void add_vertex_vector(const String &name, const T_ *x, const T_ *y=nullptr, const T_ *z=nullptr, double scaling_factor=1.0)
Adds a vector-field vertex variable to the exporter.
Definition: export_vtk.hpp:313
Index _num_verts
number of vertices in mesh
Definition: export_vtk.hpp:144
ExportVTK & operator=(ExportVTK &&other)=default
Move-assignment constructor.
int _var_prec
precision of variables
Definition: export_vtk.hpp:156
std::function< double(Index, int)> _vertices
Accessor function for vertices.
Definition: export_vtk.hpp:140
void write(const String &filename, const Dist::Comm &comm)
Writes out the data to a parallel XML-PVTU file.
Definition: export_vtk.hpp:623
void write(const String &filename, const int rank, const int nparts)
Writes out the data to a parallel XML-PVTU file.
Definition: export_vtk.hpp:564
void clear()
Clears all vertex and cell variables in the exporter.
Definition: export_vtk.hpp:256
void write(const String &filename) const
Writes out the data to a serial XML-VTU file.
Definition: export_vtk.hpp:528
typename MeshType::ShapeType ShapeType
our shape type
Definition: export_vtk.hpp:124
void write_vtu(std::ostream &os) const
Writes out the mesh and variable data in serial XML-VTU format.
Definition: export_vtk.hpp:673
typename Shape::FaceTraits< ShapeType, cell_dim_ >::ShapeType CellShapeType
shape type of exported cells
Definition: export_vtk.hpp:126
VarDeque _vertex_vectors
vertex field list
Definition: export_vtk.hpp:150
void write_pvtu(std::ostream &os, const String &file_title, const int nparts) const
Writes out the partition data in parallel XML-PVTU format.
Definition: export_vtk.hpp:820
ExportVTK(const ExportVTK &other)=default
Copy constructor.
Index _num_cells
number of cells in mesh
Definition: export_vtk.hpp:146
void add_cell_vector(const String &name, const T_ *x, const T_ *y=nullptr, const T_ *z=nullptr, double scaling_factor=1.0)
Adds a vector-field cell variable to the exporter.
Definition: export_vtk.hpp:442
ExportVTK(ExportVTK &&other) noexcept=default
Move constructor.
VarDeque _cell_scalars
cell variable list
Definition: export_vtk.hpp:152
Intern::VTKShape< CellShapeType > VTKShapeType
our VTK shape type
Definition: export_vtk.hpp:128
void add_vertex_vector(const String &name, const VectorType_ &v, double scaling_factor=1.0)
Adds a vector-field vertex variable given by a LAFEM::***VectorBlocked to the exporter.
Definition: export_vtk.hpp:374
ExportVTK & operator=(const ExportVTK &other)=default
Copy-assignment constructor.
ExportVTK(const MeshType &mesh, int var_prec=0)
Constructor.
Definition: export_vtk.hpp:170
void add_cell_scalar(const String &name, const T_ *data, double scaling_factor=1.0)
Adds a scalar cell variable to the exporter.
Definition: export_vtk.hpp:411
VarDeque _cell_vectors
cell field list
Definition: export_vtk.hpp:154
void add_vertex_scalar(const String &name, const T_ *data, double scaling_factor=1.0)
Adds a scalar vertex variable to the exporter.
Definition: export_vtk.hpp:282
std::function< Index(Index, int)> _cells
Accessor function for cells.
Definition: export_vtk.hpp:142
std::deque< std::pair< String, std::vector< double > > > VarDeque
our variable container
Definition: export_vtk.hpp:132
void add_cell_vector(const String &name, const VectorType_ &v, double scaling_factor=1.0)
Adds a vector-field cell variable given by a LAFEM::***VectorBlocked to the exporter.
Definition: export_vtk.hpp:503
Class template for partial meshes.
Definition: mesh_part.hpp:90
bool has_topology() const
Checks if this MeshPart has a mesh topology.
Definition: mesh_part.hpp:297
String class implementation.
Definition: string.hpp:46
String pad_front(size_type len, char c=' ') const
Pads the front of the string up to a desired length.
Definition: string.hpp:392
@ other
generic/other permutation strategy
T_ ilog10(T_ x)
Computes the integral base-10 logarithm of an integer, i.e. its number of non-zero decimal digits.
Definition: math.hpp:231
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
static constexpr int version_major
FEAT major version number.
static constexpr int version_patch
FEAT patch version number.
static constexpr int version_minor
FEAT minor version number.
String stringify_fp_sci(DataType_ value, int precision=0, int width=0, bool sign=false)
Prints a floating point value to a string in scientific notation.
Definition: string.hpp:1088
std::uint64_t Index
Index data type.
Face traits tag struct template.
Definition: shape.hpp:106