20#include "libmesh/libmesh_config.h"
21#include "libmesh/vtk_io.h"
22#include "libmesh/mesh_base.h"
23#include "libmesh/equation_systems.h"
24#include "libmesh/numeric_vector.h"
25#include "libmesh/system.h"
26#include "libmesh/node.h"
27#include "libmesh/elem.h"
28#include "libmesh/cell_c0polyhedron.h"
29#include "libmesh/face_c0polygon.h"
30#include "libmesh/face_polygon.h"
31#include "libmesh/enum_io_package.h"
32#include "libmesh/utility.h"
34#ifdef LIBMESH_HAVE_VTK
38#include "libmesh/ignore_warnings.h"
40#include "vtkXMLUnstructuredGridReader.h"
41#include "vtkXMLPUnstructuredGridReader.h"
42#include "vtkXMLUnstructuredGridWriter.h"
43#include "vtkXMLPUnstructuredGridWriter.h"
44#include "vtkXMLFileReadTester.h"
45#include "vtkUnstructuredGrid.h"
46#include "vtkIntArray.h"
47#include "vtkCellArray.h"
48#include "vtkCellData.h"
49#include "vtkDoubleArray.h"
50#include "vtkGenericCell.h"
52#include "vtkPointData.h"
54#include "vtkSmartPointer.h"
56#ifdef LIBMESH_HAVE_MPI
58#include "vtkMPICommunicator.h"
59#include "vtkMPIController.h"
62#include "libmesh/restore_warnings.h"
75#define VTK_VERSION_LESS_THAN(major,minor,subminor) \
76 ((LIBMESH_DETECTED_VTK_VERSION_MAJOR < (major) || \
77 (LIBMESH_DETECTED_VTK_VERSION_MAJOR == (major) && (LIBMESH_DETECTED_VTK_VERSION_MINOR < (minor) || \
78 (LIBMESH_DETECTED_VTK_VERSION_MINOR == (minor) && \
79 LIBMESH_DETECTED_VTK_VERSION_SUBMINOR < (subminor))))) ? 1 : 0)
92#ifdef LIBMESH_HAVE_VTK
103#ifdef LIBMESH_HAVE_VTK
114 std::vector<Number> soln;
115 std::vector<std::string> names;
123#ifdef LIBMESH_HAVE_VTK
132 std::map<ElemMappingType, VTKIO::ElementMaps> all_maps;
152#if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0)
162#if VTK_VERSION_LESS_THAN(9,0,0)
201add_vtk_polyhedron(vtkUnstructuredGrid & vtk_grid,
203 const vtkIdType cell_id,
204 vtkIntArray * node_id,
205 const std::vector<dof_id_type> & vtk_node_to_libmesh)
212 vtkSmartPointer<vtkIdList> face_stream = vtkSmartPointer<vtkIdList>::New();
213 vtk_grid.GetFaceStream(cell_id, face_stream);
216 const vtkIdType n_faces = face_stream->GetId(pos++);
220 "Error: VTK polyhedron cell " << cell_id <<
" has only " << n_faces <<
221 " faces, but a polyhedron requires at least 4.");
223 std::vector<std::shared_ptr<Polygon>> sides(cast_int<std::size_t>(n_faces));
224 for (std::size_t s = 0; s != sides.size(); ++s)
226 const vtkIdType n_face_pts = face_stream->GetId(pos++);
227 auto side = std::make_shared<C0Polygon>(cast_int<unsigned int>(n_face_pts));
229 for (vtkIdType n = 0; n != n_face_pts; ++n)
231 const vtkIdType vtk_point_id = face_stream->GetId(pos++);
233 vtk_node_to_libmesh[vtk_point_id] :
234 cast_int<dof_id_type>(vtk_point_id);
235 side->set_node(cast_int<unsigned int>(n),
239 sides[s] = std::move(side);
246 std::unique_ptr<Node> mid_elem_node;
247 auto elem = std::make_unique<C0Polyhedron>(sides, mid_elem_node);
278 std::string file_type;
280 vtkSmartPointer<vtkXMLFileReadTester>
tester =
281 vtkSmartPointer<vtkXMLFileReadTester>::New();
282 tester->SetFileName(name.c_str());
286 "Error: " << name <<
" does not appear to be a VTK XML file.");
288 const char * file_type_cstr =
tester->GetFileDataType();
291 "Error: " << name <<
" does not specify a VTK XML data type.");
292 file_type = file_type_cstr;
295 if (file_type ==
"PUnstructuredGrid")
297 vtkSmartPointer<vtkXMLPUnstructuredGridReader> reader =
298 vtkSmartPointer<vtkXMLPUnstructuredGridReader>::New();
299 reader->SetFileName(name.c_str());
303 else if (file_type ==
"UnstructuredGrid")
305 vtkSmartPointer<vtkXMLUnstructuredGridReader> reader =
306 vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
307 reader->SetFileName(name.c_str());
313 (
"Error: " << name <<
" is a VTK XML file of type \"" << file_type
314 <<
"\", but libMesh's VTKIO reader only supports \"UnstructuredGrid\" "
315 "(.vtu) and \"PUnstructuredGrid\" (.pvtu) files.");
327 vtkAbstractArray * abstract_elem_id =
328 _vtk_grid->GetCellData()->GetAbstractArray(
"libmesh_elem_id");
329 vtkAbstractArray * abstract_node_id =
330 _vtk_grid->GetPointData()->GetAbstractArray(
"libmesh_node_id");
331 vtkAbstractArray * abstract_subdomain_id =
332 _vtk_grid->GetCellData()->GetAbstractArray(
"subdomain_id");
337 vtkIntArray * elem_id = vtkIntArray::SafeDownCast(abstract_elem_id);
338 vtkIntArray * node_id = vtkIntArray::SafeDownCast(abstract_node_id);
339 vtkIntArray * subdomain_id = vtkIntArray::SafeDownCast(abstract_subdomain_id);
341 if (abstract_elem_id && !elem_id)
342 libmesh_warning(
"Found non-integral libmesh_elem_id array; forced to ignore it.\n"
343 "This is technically valid but probably broken.");
345 if (abstract_node_id && !node_id)
346 libmesh_warning(
"Found non-integral libmesh_node_id array; forced to ignore it.\n"
347 "This is technically valid but probably broken.");
349 if (abstract_subdomain_id && !subdomain_id)
350 libmesh_warning(
"Found non-integral subdomain_id array; forced to ignore it.\n"
351 "This is technically valid but probably broken.");
354 const unsigned int vtk_num_points =
static_cast<unsigned int>(
_vtk_grid->GetNumberOfPoints());
357 std::vector<dof_id_type> vtk_node_to_libmesh;
359 vtk_node_to_libmesh.resize(vtk_num_points);
362 for (
unsigned int i=0; i<vtk_num_points; ++i)
367 _vtk_grid->GetPoint(
static_cast<vtkIdType
>(i), pnt);
368 Point xyz(pnt[0], pnt[1], pnt[2]);
372 auto id = node_id->GetValue(i);
380 vtk_node_to_libmesh[i] = id;
387 const unsigned int vtk_num_cells =
static_cast<unsigned int>(
_vtk_grid->GetNumberOfCells());
391 vtkSmartPointer<vtkGenericCell> cell = vtkSmartPointer<vtkGenericCell>::New();
392 for (
unsigned int i=0; i<vtk_num_cells; ++i)
396 std::unique_ptr<Elem> elem;
402 if (cell->GetCellType() == VTK_POLYHEDRON)
404 static_cast<vtkIdType
>(i),
405 node_id, vtk_node_to_libmesh);
409 ElemType libmesh_elem_type = element_map.find(cell->GetCellType());
413 for (
auto j : elem->node_index_range())
415 const auto vtk_point_id = cell->GetPointId(j);
417 vtk_node_to_libmesh[vtk_point_id] : vtk_point_id;
423 std::vector<dof_id_type> conn;
424 elem->connectivity(0,
VTK, conn);
428 for (
unsigned int j=0,
429 n_conn = cast_int<unsigned int>(conn.size());
436 auto id = elem_id->GetValue(i);
439 " found in libmesh_elem_ids");
447 auto sbdid = subdomain_id->GetValue(i);
448 elem->subdomain_id() = sbdid;
457 for (
unsigned char i=0; i!=4; ++i)
463 "Cannot open dimension "
465 <<
" mesh file when configured without "
474 const std::vector<Number> & soln,
475 const std::vector<std::string> & names)
481 libmesh_do_once(
libMesh::err <<
"The .pvtu extension should be used when writing VTK files in libMesh.");
487 libmesh_error_msg_if(!names.empty() && soln.empty(),
488 "Empty soln vector in VTKIO::write_nodal_data().");
494 _vtk_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
495 vtkSmartPointer<vtkXMLPUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLPUnstructuredGridWriter>::New();
496#ifdef LIBMESH_HAVE_MPI
498 vtkSmartPointer<vtkMPICommunicator> vtk_comm = vtkSmartPointer<vtkMPICommunicator>::New();
500 vtkMPICommunicatorOpaqueComm vtk_opaque_comm(&mpi_comm);
501 vtk_comm->InitializeExternal(&vtk_opaque_comm);
503 vtkSmartPointer<vtkMPIController> vtk_mpi_ctrl = vtkSmartPointer<vtkMPIController>::New();
504 vtk_mpi_ctrl->SetCommunicator(vtk_comm);
506 writer->SetController(vtk_mpi_ctrl);
517 if (names.size() > 0)
519 std::size_t num_vars = names.size();
520 std::vector<Number> local_values;
522#ifdef LIBMESH_USE_COMPLEX_NUMBERS
523 std::vector<Real> local_real_values;
526 for (std::size_t variable=0; variable<num_vars; ++variable)
530#ifdef LIBMESH_USE_COMPLEX_NUMBERS
532 local_real_values.resize(local_values.size());
533 std::transform(local_values.begin(), local_values.end(),
534 local_real_values.begin(),
535 [](
Number x) { return x.real(); });
539 local_real_values.resize(local_values.size());
540 std::transform(local_values.begin(), local_values.end(),
541 local_real_values.begin(),
542 [](
Number x) { return x.imag(); });
560 writer->SetGhostLevel(1);
565#if VTK_VERSION_LESS_THAN(6,0,0)
571 writer->SetFileName(fname.c_str());
572 writer->SetDataModeToAscii();
577#if !VTK_VERSION_LESS_THAN(5,6,0)
578 writer->SetCompressorTypeToZLib();
579 writer->SetDataModeToBinary();
581 libmesh_do_once(
libMesh::err <<
"Compression not implemented with old VTK libs!" << std::endl;);
610 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
611 vtkSmartPointer<vtkDoubleArray> pcoords = vtkSmartPointer<vtkDoubleArray>::New();
613 pcoords->SetNumberOfComponents(LIBMESH_DIM);
618#if !VTK_VERSION_LESS_THAN(9,0,0)
619 bool have_weights =
false;
620 int weight_index = 0;
621 vtkSmartPointer<vtkDoubleArray> rational_weights;
625 rational_weights = vtkSmartPointer<vtkDoubleArray>::New();
626 rational_weights->SetName(
"RationalWeights");
627 rational_weights->SetNumberOfComponents(1);
633 vtkSmartPointer<vtkIntArray> node_id = vtkSmartPointer<vtkIntArray>::New();
634 node_id->SetName(
"libmesh_node_id");
635 node_id->SetNumberOfComponents(1);
637 unsigned int local_node_counter = 0;
639 for (
const auto & node_ptr :
mesh.local_node_ptr_range())
641 const Node & node = *node_ptr;
643 double pnt[3] = {0, 0, 0};
644 for (
unsigned int i=0; i<LIBMESH_DIM; ++i)
645 pnt[i] =
double(node(i));
651#if VTK_VERSION_LESS_THAN(7,1,0)
652 pcoords->InsertNextTupleValue(pnt);
654 pcoords->InsertNextTuple(pnt);
656#if !VTK_VERSION_LESS_THAN(9,0,0)
660 rational_weights->InsertTuple1(local_node_counter,
double(weight));
664 node_id->InsertTuple1(local_node_counter, node.
id());
666 ++local_node_counter;
670 points->SetData(pcoords);
674 _vtk_grid->GetPointData()->AddArray(node_id);
676#if !VTK_VERSION_LESS_THAN(9,0,0)
678 _vtk_grid->GetPointData()->SetRationalWeights(rational_weights);
690 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
691 vtkSmartPointer<vtkIdList> pts = vtkSmartPointer<vtkIdList>::New();
697 vtkAbstractArray * abstract_node_id =
698 _vtk_grid->GetPointData()->GetAbstractArray(
"libmesh_node_id");
699 vtkIntArray * node_id = vtkIntArray::SafeDownCast(abstract_node_id);
702 vtkSmartPointer<vtkIntArray> elem_id = vtkSmartPointer<vtkIntArray>::New();
703 elem_id->SetName(
"libmesh_elem_id");
704 elem_id->SetNumberOfComponents(1);
706 vtkSmartPointer<vtkIntArray> subdomain_id = vtkSmartPointer<vtkIntArray>::New();
707 subdomain_id->SetName(
"subdomain_id");
708 subdomain_id->SetNumberOfComponents(1);
710 vtkSmartPointer<vtkIntArray> elem_proc_id = vtkSmartPointer<vtkIntArray>::New();
711 elem_proc_id->SetName(
"processor_id");
712 elem_proc_id->SetNumberOfComponents(1);
714 unsigned active_element_counter = 0;
715 for (
const auto & elem :
mesh.active_local_element_ptr_range())
721 pts->SetNumberOfIds(elem->n_nodes());
724 std::vector<dof_id_type> conn;
725 elem->connectivity(0,
VTK, conn);
727 for (
unsigned int i=0,
728 n_conn = cast_int<unsigned int>(conn.size());
741 double pt[3] = {0., 0., 0.};
742 for (
unsigned int d=0; d<LIBMESH_DIM; ++d)
743 pt[d] =
double(the_node(d));
746 vtkIdType local =
_vtk_grid->GetPoints()->InsertNextPoint(pt);
750 cast_int<dof_id_type>(local);
752 node_id->InsertTuple1(local, global_node_id);
760 vtkIdType vtkcellid = cells->InsertNextCell(pts);
761 types[active_element_counter] = cast_int<int>(element_map.find(elem->type()));
763 elem_id->InsertTuple1(vtkcellid, elem->id());
764 subdomain_id->InsertTuple1(vtkcellid, elem->subdomain_id());
765 elem_proc_id->InsertTuple1(vtkcellid, elem->processor_id());
766 ++active_element_counter;
769 _vtk_grid->SetCells(types.data(), cells);
770 _vtk_grid->GetCellData()->AddArray(elem_id);
771 _vtk_grid->GetCellData()->AddArray(subdomain_id);
772 _vtk_grid->GetCellData()->AddArray(elem_proc_id);
776 const std::vector<Real> & local_values)
778 vtkSmartPointer<vtkDoubleArray> data = vtkSmartPointer<vtkDoubleArray>::New();
779 data->SetName(name.c_str());
788 data->SetValue(i,
double(local_values[i]));
791 _vtk_grid->GetPointData()->AddArray(data);
795 std::size_t variable,
796 const std::vector<Number> & soln,
797 const std::vector<std::string> & names)
800 std::size_t num_vars = names.size();
803 local_values.clear();
811 local_values[local_node_it->second] = soln[k*num_vars + variable];
878 libmesh_error_msg(
"Cannot read VTK file: " << name \
879 <<
"\nYou must have VTK installed and correctly configured to read VTK meshes.");
885 const std::vector<Number> &,
886 const std::vector<std::string> &)
888 libmesh_error_msg(
"Cannot write VTK file: " << fname \
889 <<
"\nYou must have VTK installed and correctly configured to read VTK meshes.");
T get_extra_datum(const unsigned int index) const
Gets the value on this object of the extra datum associated with index, which should have been obtain...
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
This is the MeshBase class.
virtual const Point & point(const dof_id_type i) const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
unsigned int mesh_dimension() const
virtual dof_id_type n_nodes() const =0
ElemMappingType default_mapping_type() const
Returns the default master space to physical space mapping basis functions to be used on newly added ...
virtual const Node * query_node_ptr(const dof_id_type i) const =0
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
virtual Node * add_node(Node *n)=0
Add Node n to the end of the vertex array.
virtual void clear()
Deletes all the element and node data that is currently stored.
dof_id_type n_local_nodes() const
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
dof_id_type n_active_local_elem() const
unsigned char default_mapping_data() const
Returns any default data value used by the master space to physical space mapping.
This class defines an abstract interface for Mesh output.
A Node is like a Point, but with more information.
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
void node_values_to_vtk(const std::string &name, const std::vector< Real > &local_values)
write the nodal values of soln to a vtkUnstructuredGrid
void nodes_to_vtk()
write the nodes from the mesh into a vtkUnstructuredGrid and update the local_node_map.
std::map< dof_id_type, dof_id_type > _local_node_map
maps global node id to node id of partition
virtual void write(const std::string &) override
Output the mesh without solutions to a .pvtu file.
static std::map< ElemMappingType, ElementMaps > _element_maps
ElementMaps objects that are built statically and used by all instances of this class.
VTKIO(MeshBase &mesh)
Constructor.
bool _compress
Flag to indicate whether the output should be compressed.
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &) override
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
virtual void read(const std::string &) override
This method implements reading a mesh from a specified file in VTK format.
void cells_to_vtk()
write the cells from the mesh into a vtkUnstructuredGrid
void set_compression(bool b)
Setter for compression flag.
void get_local_node_values(std::vector< Number > &local_values, std::size_t variable, const std::vector< Number > &soln, const std::vector< std::string > &names)
Extract the values of soln that correspond to the nodes.
vtkUnstructuredGrid * get_vtk_grid()
Get a pointer to the VTK unstructured grid data structure.
static std::map< ElemMappingType, ElementMaps > build_element_maps()
Static function used to construct _element_maps.
vtkSmartPointer< vtkUnstructuredGrid > _vtk_grid
Write the system vectors to vtk.
bool ends_with(std::string_view superstring, std::string_view suffix)
Look for a substring at the very end of a string.
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
ElemType
Defines an enum for geometric element types.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void tester(const std::set< int > &s, int i)
Helper object that holds a map from VTK to libMesh element types and vice-versa.
std::map< ElemType, vtkIdType > writing_map
void associate(ElemType libmesh_type, vtkIdType vtk_type)