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/enum_io_package.h" 29 #include "libmesh/utility.h" 31 #ifdef LIBMESH_HAVE_VTK 35 #include "libmesh/ignore_warnings.h" 37 #include "vtkXMLUnstructuredGridReader.h" 38 #include "vtkXMLPUnstructuredGridReader.h" 39 #include "vtkXMLUnstructuredGridWriter.h" 40 #include "vtkXMLPUnstructuredGridWriter.h" 41 #include "vtkUnstructuredGrid.h" 42 #include "vtkIntArray.h" 43 #include "vtkCellArray.h" 44 #include "vtkCellData.h" 45 #include "vtkDoubleArray.h" 46 #include "vtkGenericCell.h" 47 #include "vtkPointData.h" 48 #include "vtkPoints.h" 49 #include "vtkSmartPointer.h" 51 #ifdef LIBMESH_HAVE_MPI 53 #include "vtkMPICommunicator.h" 54 #include "vtkMPIController.h" 57 #include "libmesh/restore_warnings.h" 69 #define VTK_VERSION_LESS_THAN(major,minor,subminor) \ 70 ((LIBMESH_DETECTED_VTK_VERSION_MAJOR < (major) || \ 71 (LIBMESH_DETECTED_VTK_VERSION_MAJOR == (major) && (LIBMESH_DETECTED_VTK_VERSION_MINOR < (minor) || \ 72 (LIBMESH_DETECTED_VTK_VERSION_MINOR == (minor) && \ 73 LIBMESH_DETECTED_VTK_VERSION_SUBMINOR < (subminor))))) ? 1 : 0) 75 #endif // LIBMESH_HAVE_VTK 86 #ifdef LIBMESH_HAVE_VTK
97 #ifdef LIBMESH_HAVE_VTK
108 std::vector<Number> soln;
109 std::vector<std::string> names;
117 #ifdef LIBMESH_HAVE_VTK 126 std::map<ElemMappingType, VTKIO::ElementMaps> all_maps;
146 #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) 156 #if VTK_VERSION_LESS_THAN(9,0,0) 198 typedef vtkSmartPointer<vtkXMLPUnstructuredGridReader> MyReader;
199 MyReader reader = MyReader::New();
202 reader->SetFileName(
name.c_str());
220 vtkAbstractArray * abstract_elem_id =
221 _vtk_grid->GetCellData()->GetAbstractArray(
"libmesh_elem_id");
222 vtkAbstractArray * abstract_node_id =
223 _vtk_grid->GetPointData()->GetAbstractArray(
"libmesh_node_id");
224 vtkAbstractArray * abstract_subdomain_id =
225 _vtk_grid->GetCellData()->GetAbstractArray(
"subdomain_id");
230 vtkIntArray * elem_id = vtkIntArray::SafeDownCast(abstract_elem_id);
231 vtkIntArray * node_id = vtkIntArray::SafeDownCast(abstract_node_id);
232 vtkIntArray * subdomain_id = vtkIntArray::SafeDownCast(abstract_subdomain_id);
234 if (abstract_elem_id && !elem_id)
235 libmesh_warning(
"Found non-integral libmesh_elem_id array; forced to ignore it.\n" 236 "This is technically valid but probably broken.");
238 if (abstract_node_id && !node_id)
239 libmesh_warning(
"Found non-integral libmesh_node_id array; forced to ignore it.\n" 240 "This is technically valid but probably broken.");
242 if (abstract_subdomain_id && !subdomain_id)
243 libmesh_warning(
"Found non-integral subdomain_id array; forced to ignore it.\n" 244 "This is technically valid but probably broken.");
247 const unsigned int vtk_num_points =
static_cast<unsigned int>(
_vtk_grid->GetNumberOfPoints());
250 std::vector<dof_id_type> vtk_node_to_libmesh;
252 vtk_node_to_libmesh.resize(vtk_num_points);
255 for (
unsigned int i=0; i<vtk_num_points; ++i)
260 _vtk_grid->GetPoint(static_cast<vtkIdType>(i), pnt);
261 Point xyz(pnt[0], pnt[1], pnt[2]);
265 auto id = node_id->GetValue(i);
273 vtk_node_to_libmesh[i] = id;
280 const unsigned int vtk_num_cells =
static_cast<unsigned int>(
_vtk_grid->GetNumberOfCells());
284 vtkSmartPointer<vtkGenericCell> cell = vtkSmartPointer<vtkGenericCell>::New();
285 for (
unsigned int i=0; i<vtk_num_cells; ++i)
290 ElemType libmesh_elem_type = element_map.find(cell->GetCellType());
294 for (
auto j : elem->node_index_range())
296 const auto vtk_point_id = cell->GetPointId(j);
298 vtk_node_to_libmesh[vtk_point_id] : vtk_point_id;
304 std::vector<dof_id_type> conn;
305 elem->connectivity(0,
VTK, conn);
309 for (
unsigned int j=0,
310 n_conn = cast_int<unsigned int>(conn.size());
316 auto id = elem_id->GetValue(i);
319 " found in libmesh_elem_ids");
327 auto sbdid = subdomain_id->GetValue(i);
328 elem->subdomain_id() = sbdid;
337 for (
unsigned char i=0; i!=4; ++i)
343 "Cannot open dimension " 345 <<
" mesh file when configured without " 348 #endif // LIBMESH_DIM < 3 354 const std::vector<Number> & soln,
355 const std::vector<std::string> & names)
361 libmesh_do_once(
libMesh::err <<
"The .pvtu extension should be used when writing VTK files in libMesh.");
367 libmesh_error_msg_if(!names.empty() && soln.empty(),
368 "Empty soln vector in VTKIO::write_nodal_data().");
374 _vtk_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
375 vtkSmartPointer<vtkXMLPUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLPUnstructuredGridWriter>::New();
376 #ifdef LIBMESH_HAVE_MPI 378 vtkSmartPointer<vtkMPICommunicator> vtk_comm = vtkSmartPointer<vtkMPICommunicator>::New();
380 vtkMPICommunicatorOpaqueComm vtk_opaque_comm(&mpi_comm);
381 vtk_comm->InitializeExternal(&vtk_opaque_comm);
383 vtkSmartPointer<vtkMPIController> vtk_mpi_ctrl = vtkSmartPointer<vtkMPIController>::New();
384 vtk_mpi_ctrl->SetCommunicator(vtk_comm);
386 writer->SetController(vtk_mpi_ctrl);
397 if (names.size() > 0)
399 std::size_t num_vars = names.size();
400 std::vector<Number> local_values;
402 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 403 std::vector<Real> local_real_values;
406 for (std::size_t variable=0; variable<num_vars; ++variable)
410 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 412 local_real_values.resize(local_values.size());
413 std::transform(local_values.begin(), local_values.end(),
414 local_real_values.begin(),
415 [](
Number x) {
return x.real(); });
419 local_real_values.resize(local_values.size());
420 std::transform(local_values.begin(), local_values.end(),
421 local_real_values.begin(),
422 [](
Number x) {
return x.imag(); });
440 writer->SetGhostLevel(1);
445 #if VTK_VERSION_LESS_THAN(6,0,0) 451 writer->SetFileName(fname.c_str());
452 writer->SetDataModeToAscii();
457 #if !VTK_VERSION_LESS_THAN(5,6,0) 458 writer->SetCompressorTypeToZLib();
459 writer->SetDataModeToBinary();
461 libmesh_do_once(
libMesh::err <<
"Compression not implemented with old VTK libs!" << std::endl;);
490 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
491 vtkSmartPointer<vtkDoubleArray> pcoords = vtkSmartPointer<vtkDoubleArray>::New();
493 pcoords->SetNumberOfComponents(LIBMESH_DIM);
498 #if !VTK_VERSION_LESS_THAN(9,0,0) 499 bool have_weights =
false;
500 int weight_index = 0;
501 vtkSmartPointer<vtkDoubleArray> rational_weights;
505 rational_weights = vtkSmartPointer<vtkDoubleArray>::New();
506 rational_weights->SetName(
"RationalWeights");
507 rational_weights->SetNumberOfComponents(1);
513 vtkSmartPointer<vtkIntArray> node_id = vtkSmartPointer<vtkIntArray>::New();
514 node_id->SetName(
"libmesh_node_id");
515 node_id->SetNumberOfComponents(1);
517 unsigned int local_node_counter = 0;
519 for (
const auto & node_ptr :
mesh.local_node_ptr_range())
521 const Node & node = *node_ptr;
523 double pnt[3] = {0, 0, 0};
524 for (
unsigned int i=0; i<LIBMESH_DIM; ++i)
525 pnt[i] =
double(node(i));
531 #if VTK_VERSION_LESS_THAN(7,1,0) 532 pcoords->InsertNextTupleValue(pnt);
534 pcoords->InsertNextTuple(pnt);
536 #if !VTK_VERSION_LESS_THAN(9,0,0) 540 rational_weights->InsertTuple1(local_node_counter,
double(
weight));
544 node_id->InsertTuple1(local_node_counter, node.
id());
546 ++local_node_counter;
550 points->SetData(pcoords);
554 _vtk_grid->GetPointData()->AddArray(node_id);
556 #if !VTK_VERSION_LESS_THAN(9,0,0) 558 _vtk_grid->GetPointData()->SetRationalWeights(rational_weights);
570 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
571 vtkSmartPointer<vtkIdList> pts = vtkSmartPointer<vtkIdList>::New();
577 vtkAbstractArray * abstract_node_id =
578 _vtk_grid->GetPointData()->GetAbstractArray(
"libmesh_node_id");
579 vtkIntArray * node_id = vtkIntArray::SafeDownCast(abstract_node_id);
582 vtkSmartPointer<vtkIntArray> elem_id = vtkSmartPointer<vtkIntArray>::New();
583 elem_id->SetName(
"libmesh_elem_id");
584 elem_id->SetNumberOfComponents(1);
586 vtkSmartPointer<vtkIntArray> subdomain_id = vtkSmartPointer<vtkIntArray>::New();
587 subdomain_id->SetName(
"subdomain_id");
588 subdomain_id->SetNumberOfComponents(1);
590 vtkSmartPointer<vtkIntArray> elem_proc_id = vtkSmartPointer<vtkIntArray>::New();
591 elem_proc_id->SetName(
"processor_id");
592 elem_proc_id->SetNumberOfComponents(1);
594 unsigned active_element_counter = 0;
595 for (
const auto & elem :
mesh.active_local_element_ptr_range())
601 pts->SetNumberOfIds(elem->n_nodes());
604 std::vector<dof_id_type> conn;
605 elem->connectivity(0,
VTK, conn);
607 for (
unsigned int i=0,
608 n_conn = cast_int<unsigned int>(conn.size());
621 double pt[3] = {0., 0., 0.};
622 for (
unsigned int d=0; d<LIBMESH_DIM; ++d)
623 pt[d] =
double(the_node(d));
626 vtkIdType local =
_vtk_grid->GetPoints()->InsertNextPoint(pt);
630 cast_int<dof_id_type>(local);
632 node_id->InsertTuple1(local, global_node_id);
640 vtkIdType vtkcellid = cells->InsertNextCell(pts);
641 types[active_element_counter] = cast_int<int>(element_map.find(elem->type()));
643 elem_id->InsertTuple1(vtkcellid, elem->id());
644 subdomain_id->InsertTuple1(vtkcellid, elem->subdomain_id());
645 elem_proc_id->InsertTuple1(vtkcellid, elem->processor_id());
646 ++active_element_counter;
649 _vtk_grid->SetCells(types.data(), cells);
650 _vtk_grid->GetCellData()->AddArray(elem_id);
651 _vtk_grid->GetCellData()->AddArray(subdomain_id);
652 _vtk_grid->GetCellData()->AddArray(elem_proc_id);
656 const std::vector<Real> & local_values)
658 vtkSmartPointer<vtkDoubleArray> data = vtkSmartPointer<vtkDoubleArray>::New();
659 data->SetName(
name.c_str());
668 data->SetValue(i,
double(local_values[i]));
671 _vtk_grid->GetPointData()->AddArray(data);
675 std::size_t variable,
676 const std::vector<Number> & soln,
677 const std::vector<std::string> & names)
680 std::size_t num_vars = names.size();
683 local_values.clear();
691 local_values[local_node_it->second] = soln[k*num_vars + variable];
754 #else // !LIBMESH_HAVE_VTK 758 libmesh_error_msg(
"Cannot read VTK file: " <<
name \
759 <<
"\nYou must have VTK installed and correctly configured to read VTK meshes.");
765 const std::vector<Number> &,
766 const std::vector<std::string> &)
768 libmesh_error_msg(
"Cannot write VTK file: " << fname \
769 <<
"\nYou must have VTK installed and correctly configured to read VTK meshes.");
773 #endif // LIBMESH_HAVE_VTK std::string name(const ElemQuality q)
This function returns a string containing some name for q.
void set_compression(bool b)
Setter for compression flag.
void node_values_to_vtk(const std::string &name, const std::vector< Real > &local_values)
write the nodal values of soln to a vtkUnstructuredGrid
static std::map< ElemMappingType, ElementMaps > _element_maps
ElementMaps objects that are built statically and used by all instances of this class.
ElemType
Defines an enum for geometric element types.
std::map< dof_id_type, dof_id_type > _local_node_map
maps global node id to node id of partition
A Node is like a Point, but with more information.
bool ends_with(std::string_view superstring, std::string_view suffix)
Look for a substring at the very end of a string.
vtkSmartPointer< vtkUnstructuredGrid > _vtk_grid
Write the system vectors to vtk.
bool _compress
Flag to indicate whether the output should be compressed.
virtual void write(const std::string &) override
Output the mesh without solutions to a .pvtu file.
dof_id_type n_local_nodes() const
const Parallel::Communicator & comm() const
This class defines an abstract interface for Mesh output.
The libMesh namespace provides an interface to certain functionality in the library.
Helper object that holds a map from VTK to libMesh element types and vice-versa.
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.
This is the MeshBase class.
ElemMappingType default_mapping_type() const
Returns the default master space to physical space mapping basis functions to be used on newly added ...
virtual void read(const std::string &) override
This method implements reading a mesh from a specified file in VTK format.
static std::map< ElemMappingType, ElementMaps > build_element_maps()
Static function used to construct _element_maps.
void nodes_to_vtk()
write the nodes from the mesh into a vtkUnstructuredGrid and update the local_node_map.
dof_id_type n_active_local_elem() const
processor_id_type n_processors() const
unsigned char default_mapping_data() const
Returns any default data value used by the master space to physical space mapping.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
virtual const Node * query_node_ptr(const dof_id_type i) const =0
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...
vtkUnstructuredGrid * get_vtk_grid()
Get a pointer to the VTK unstructured grid data structure.
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
std::map< ElemType, vtkIdType > writing_map
virtual void clear()
Deletes all the element and node data that is currently stored.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
VTKIO(MeshBase &mesh)
Constructor.
void associate(ElemType libmesh_type, vtkIdType vtk_type)
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
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.
void cells_to_vtk()
write the cells from the mesh into a vtkUnstructuredGrid
unsigned int mesh_dimension() const
virtual const Point & point(const dof_id_type i) const =0
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...
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
virtual dof_id_type n_nodes() const =0