$extrastylesheet
vtk_io.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 // C++ includes
00020 #include <fstream>
00021 
00022 // Local includes
00023 #include "libmesh/libmesh_config.h"
00024 #include "libmesh/vtk_io.h"
00025 #include "libmesh/mesh_base.h"
00026 #include "libmesh/equation_systems.h"
00027 #include "libmesh/edge_edge2.h"
00028 #include "libmesh/edge_edge3.h"
00029 #include "libmesh/face_tri3.h"
00030 #include "libmesh/face_tri6.h"
00031 #include "libmesh/face_quad4.h"
00032 #include "libmesh/face_quad8.h"
00033 #include "libmesh/face_quad9.h"
00034 #include "libmesh/cell_tet4.h"
00035 #include "libmesh/cell_tet10.h"
00036 #include "libmesh/cell_prism6.h"
00037 #include "libmesh/cell_prism15.h"
00038 #include "libmesh/cell_prism18.h"
00039 #include "libmesh/cell_pyramid5.h"
00040 #include "libmesh/cell_hex8.h"
00041 #include "libmesh/cell_hex20.h"
00042 #include "libmesh/cell_hex27.h"
00043 #include "libmesh/numeric_vector.h"
00044 #include "libmesh/system.h"
00045 #include "libmesh/mesh_data.h"
00046 
00047 #ifdef LIBMESH_HAVE_VTK
00048 
00049 // Tell VTK not to use old header files
00050 #define VTK_LEGACY_REMOVE
00051 
00052 // I get a lot of "warning: extra ';' inside a class [-Wextra-semi]" from clang
00053 // on VTK header files.
00054 #include "libmesh/ignore_warnings.h"
00055 
00056 #include "vtkXMLUnstructuredGridReader.h"
00057 #include "vtkXMLUnstructuredGridWriter.h"
00058 #include "vtkXMLPUnstructuredGridWriter.h"
00059 #include "vtkUnstructuredGrid.h"
00060 #include "vtkGenericGeometryFilter.h"
00061 #include "vtkCellArray.h"
00062 #include "vtkCellData.h"
00063 #include "vtkConfigure.h"
00064 #include "vtkDoubleArray.h"
00065 #include "vtkPointData.h"
00066 #include "vtkPoints.h"
00067 #include "vtkSmartPointer.h"
00068 
00069 #include "libmesh/restore_warnings.h"
00070 
00071 // A convenient macro for comparing VTK versions.  Returns 1 if the
00072 // current VTK version is < major.minor.subminor and zero otherwise.
00073 //
00074 // It relies on the VTK version numbers detected during configure.  Note that if
00075 // LIBMESH_HAVE_VTK is not defined, none of the LIBMESH_DETECTED_VTK_VERSION_* variables will
00076 // be defined either.
00077 #define VTK_VERSION_LESS_THAN(major,minor,subminor)                     \
00078   ((LIBMESH_DETECTED_VTK_VERSION_MAJOR < (major) ||                     \
00079     (LIBMESH_DETECTED_VTK_VERSION_MAJOR == (major) && (LIBMESH_DETECTED_VTK_VERSION_MINOR < (minor) || \
00080                                                        (LIBMESH_DETECTED_VTK_VERSION_MINOR == (minor) && \
00081                                                         LIBMESH_DETECTED_VTK_VERSION_SUBMINOR < (subminor))))) ? 1 : 0)
00082 
00083 
00084 
00085 
00086 #endif //LIBMESH_HAVE_VTK
00087 
00088 namespace libMesh
00089 {
00090 
00091 #ifdef LIBMESH_HAVE_VTK
00092 vtkIdType VTKIO::get_elem_type(ElemType type)
00093 {
00094   vtkIdType celltype = VTK_EMPTY_CELL; // initialize to something to avoid compiler warning
00095 
00096   switch(type)
00097     {
00098     case EDGE2:
00099       celltype = VTK_LINE;
00100       break;
00101     case EDGE3:
00102       celltype = VTK_QUADRATIC_EDGE;
00103       break;// 1
00104     case TRI3:
00105     case TRI3SUBDIVISION:
00106       celltype = VTK_TRIANGLE;
00107       break;// 3
00108     case TRI6:
00109       celltype = VTK_QUADRATIC_TRIANGLE;
00110       break;// 4
00111     case QUAD4:
00112       celltype = VTK_QUAD;
00113       break;// 5
00114     case QUAD8:
00115       celltype = VTK_QUADRATIC_QUAD;
00116       break;// 6
00117     case TET4:
00118       celltype = VTK_TETRA;
00119       break;// 8
00120     case TET10:
00121       celltype = VTK_QUADRATIC_TETRA;
00122       break;// 9
00123     case HEX8:
00124       celltype = VTK_HEXAHEDRON;
00125       break;// 10
00126     case HEX20:
00127       celltype = VTK_QUADRATIC_HEXAHEDRON;
00128       break;// 12
00129     case HEX27:
00130       celltype = VTK_TRIQUADRATIC_HEXAHEDRON;
00131       break;
00132     case PRISM6:
00133       celltype = VTK_WEDGE;
00134       break;// 13
00135     case PRISM15:
00136       celltype = VTK_QUADRATIC_WEDGE;
00137       break;// 14
00138     case PRISM18:
00139       celltype = VTK_BIQUADRATIC_QUADRATIC_WEDGE;
00140       break;// 15
00141     case PYRAMID5:
00142       celltype = VTK_PYRAMID;
00143       break;// 16
00144 #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0)
00145     case QUAD9:
00146       celltype = VTK_BIQUADRATIC_QUAD;
00147       break;
00148 #else
00149     case QUAD9:
00150 #endif
00151     case EDGE4:
00152     case INFEDGE2:
00153     case INFQUAD4:
00154     case INFQUAD6:
00155     case INFHEX8:
00156     case INFHEX16:
00157     case INFHEX18:
00158     case INFPRISM6:
00159     case INFPRISM12:
00160     case NODEELEM:
00161     case INVALID_ELEM:
00162     default:
00163       libmesh_error_msg("Element type " << type << " not implemented.");
00164     }
00165   return celltype;
00166 }
00167 
00168 
00169 
00170 void VTKIO::nodes_to_vtk()
00171 {
00172   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
00173 
00174   // containers for points and coordinates of points
00175   vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
00176   vtkSmartPointer<vtkDoubleArray> pcoords = vtkSmartPointer<vtkDoubleArray>::New();
00177   pcoords->SetNumberOfComponents(LIBMESH_DIM);
00178   points->SetNumberOfPoints(mesh.n_local_nodes()); // it seems that it needs this to prevent a segfault
00179 
00180   unsigned int local_node_counter = 0;
00181 
00182   MeshBase::const_node_iterator nd = mesh.local_nodes_begin();
00183   MeshBase::const_node_iterator nd_end = mesh.local_nodes_end();
00184   for (; nd != nd_end; nd++, ++local_node_counter)
00185     {
00186       Node* node = (*nd);
00187 
00188       double pnt[LIBMESH_DIM];
00189       for (unsigned int i=0; i<LIBMESH_DIM; ++i)
00190         pnt[i] = (*node)(i);
00191 
00192       // Fill mapping between global and local node numbers
00193       _local_node_map[node->id()] = local_node_counter;
00194 
00195       // add point
00196       pcoords->InsertNextTupleValue(pnt);
00197     }
00198 
00199   // add coordinates to points
00200   points->SetData(pcoords);
00201 
00202   // add points to grid
00203   _vtk_grid->SetPoints(points);
00204 }
00205 
00206 
00207 
00208 void VTKIO::cells_to_vtk()
00209 {
00210   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
00211 
00212   vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
00213   vtkSmartPointer<vtkIdList> pts = vtkSmartPointer<vtkIdList>::New();
00214 
00215   std::vector<int> types(mesh.n_active_local_elem());
00216   unsigned active_element_counter = 0;
00217 
00218   vtkSmartPointer<vtkIntArray> elem_id = vtkSmartPointer<vtkIntArray>::New();
00219   elem_id->SetName("libmesh_elem_id");
00220   elem_id->SetNumberOfComponents(1);
00221 
00222   vtkSmartPointer<vtkIntArray> subdomain_id = vtkSmartPointer<vtkIntArray>::New();
00223   subdomain_id->SetName("subdomain_id");
00224   subdomain_id->SetNumberOfComponents(1);
00225 
00226   MeshBase::const_element_iterator it = mesh.active_local_elements_begin();
00227   const MeshBase::const_element_iterator end = mesh.active_local_elements_end();
00228   for (; it != end; ++it, ++active_element_counter)
00229     {
00230       Elem *elem = *it;
00231 
00232       pts->SetNumberOfIds(elem->n_nodes());
00233 
00234       // get the connectivity for this element
00235       std::vector<dof_id_type> conn;
00236       elem->connectivity(0, VTK, conn);
00237 
00238       for (unsigned int i=0; i<conn.size(); ++i)
00239         {
00240           // If the node ID is not found in the _local_node_map, we'll
00241           // add it to the _vtk_grid.  NOTE[JWP]: none of the examples
00242           // I have actually enters this section of code...
00243           if (_local_node_map.find(conn[i]) == _local_node_map.end())
00244             {
00245               dof_id_type global_node_id = elem->node(i);
00246 
00247               const Node* the_node = mesh.node_ptr(global_node_id);
00248 
00249               // Error checking...
00250               if (the_node == NULL)
00251                 libmesh_error_msg("Error getting pointer to node " << global_node_id << "!");
00252 
00253               // InsertNextPoint accepts either a double or float array of length 3.
00254               Real pt[3] = {0., 0., 0.};
00255               for (unsigned int d=0; d<LIBMESH_DIM; ++d)
00256                 pt[d] = (*the_node)(d);
00257 
00258               // Insert the point into the _vtk_grid
00259               vtkIdType local = _vtk_grid->GetPoints()->InsertNextPoint(pt);
00260 
00261               // Update the _local_node_map with the ID returned by VTK
00262               _local_node_map[global_node_id] =
00263                 cast_int<dof_id_type>(local);
00264             }
00265 
00266           // Otherwise, the node ID was found in the _local_node_map, so
00267           // insert it into the vtkIdList.
00268           pts->InsertId(i, _local_node_map[conn[i]]);
00269         }
00270 
00271       vtkIdType vtkcellid = cells->InsertNextCell(pts);
00272       types[active_element_counter] =
00273         cast_int<int>(this->get_elem_type(elem->type()));
00274       elem_id->InsertTuple1(vtkcellid, elem->id());
00275       subdomain_id->InsertTuple1(vtkcellid, elem->subdomain_id());
00276     } // end loop over active elements
00277 
00278   _vtk_grid->SetCells(&types[0], cells);
00279   _vtk_grid->GetCellData()->AddArray(elem_id);
00280   _vtk_grid->GetCellData()->AddArray(subdomain_id);
00281 }
00282 
00283 
00284 
00285 /*
00286  * FIXME: This is known to write nonsense on AMR meshes
00287  * and it strips the imaginary parts of complex Numbers
00288  */
00289 void VTKIO::system_vectors_to_vtk(const EquationSystems& es, vtkUnstructuredGrid*& grid)
00290 {
00291   if (MeshOutput<MeshBase>::mesh().processor_id() == 0)
00292     {
00293       std::map<std::string, std::vector<Number> > vecs;
00294       for (unsigned int i=0; i<es.n_systems(); ++i)
00295         {
00296           const System& sys = es.get_system(i);
00297           System::const_vectors_iterator v_end = sys.vectors_end();
00298           System::const_vectors_iterator it = sys.vectors_begin();
00299           for (; it!= v_end; ++it)
00300             {
00301               // for all vectors on this system
00302               std::vector<Number> values;
00303               // libMesh::out<<"it "<<it->first<<std::endl;
00304 
00305               it->second->localize_to_one(values, 0);
00306               // libMesh::out<<"finish localize"<<std::endl;
00307               vecs[it->first] = values;
00308             }
00309         }
00310 
00311       std::map<std::string, std::vector<Number> >::iterator it = vecs.begin();
00312 
00313       for (; it!=vecs.end(); ++it)
00314         {
00315           vtkSmartPointer<vtkDoubleArray> data = vtkSmartPointer<vtkDoubleArray>::New();
00316           data->SetName(it->first.c_str());
00317           libmesh_assert_equal_to (it->second.size(), es.get_mesh().n_nodes());
00318           data->SetNumberOfValues(it->second.size());
00319 
00320           for (unsigned int i=0; i<it->second.size(); ++i)
00321             {
00322 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00323               libmesh_do_once (libMesh::err << "Only writing the real part for complex numbers!\n"
00324                                << "if you need this support contact " << LIBMESH_PACKAGE_BUGREPORT
00325                                << std::endl);
00326               data->SetValue(i, it->second[i].real());
00327 #else
00328               data->SetValue(i, it->second[i]);
00329 #endif
00330 
00331             }
00332           grid->GetPointData()->AddArray(data);
00333         }
00334     }
00335 }
00336 
00337 
00338 
00339 // write out mesh data to the VTK file, this might come in handy to display
00340 // boundary conditions and material data
00341 // void VTKIO::meshdata_to_vtk(const MeshData& meshdata,
00342 //                             vtkUnstructuredGrid* grid)
00343 // {
00344 //   vtkPointData* pointdata = vtkPointData::New();
00345 //
00346 //   const unsigned int n_vn = meshdata.n_val_per_node();
00347 //   const unsigned int n_dat = meshdata.n_node_data();
00348 //
00349 //   pointdata->SetNumberOfTuples(n_dat);
00350 // }
00351 
00352 #endif // LIBMESH_HAVE_VTK
00353 
00354 
00355 
00356 
00357 // Constructor for reading
00358 VTKIO::VTKIO (MeshBase& mesh, MeshData* mesh_data) :
00359   MeshInput<MeshBase> (mesh),
00360   MeshOutput<MeshBase>(mesh),
00361   _mesh_data(mesh_data),
00362   _compress(false),
00363   _local_node_map()
00364 {
00365   _vtk_grid = NULL;
00366   libmesh_experimental();
00367 }
00368 
00369 
00370 
00371 // Constructor for writing
00372 VTKIO::VTKIO (const MeshBase& mesh, MeshData* mesh_data) :
00373   MeshOutput<MeshBase>(mesh),
00374   _mesh_data(mesh_data),
00375   _compress(false),
00376   _local_node_map()
00377 {
00378   _vtk_grid = NULL;
00379   libmesh_experimental();
00380 }
00381 
00382 
00383 
00384 vtkUnstructuredGrid* VTKIO::get_vtk_grid()
00385 {
00386   return _vtk_grid;
00387 }
00388 
00389 
00390 
00391 void VTKIO::set_compression(bool b)
00392 {
00393   this->_compress = b;
00394 }
00395 
00396 
00397 
00398 void VTKIO::read (const std::string& name)
00399 {
00400   // This is a serial-only process for now;
00401   // the Mesh should be read on processor 0 and
00402   // broadcast later
00403   libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
00404 
00405   // Keep track of what kinds of elements this file contains
00406   elems_of_dimension.clear();
00407   elems_of_dimension.resize(4, false);
00408 
00409 #ifndef LIBMESH_HAVE_VTK
00410   libmesh_error_msg("Cannot read VTK file: " << name \
00411                     << "\nYou must have VTK installed and correctly configured to read VTK meshes.");
00412 
00413 #else
00414   // Use a typedef, because these names are just crazy
00415   typedef vtkSmartPointer<vtkXMLUnstructuredGridReader> MyReader;
00416   MyReader reader = MyReader::New();
00417 
00418   // Pass the filename along to the reader
00419   reader->SetFileName( name.c_str() );
00420 
00421   // Force reading
00422   reader->Update();
00423 
00424   // read in the grid
00425   _vtk_grid = reader->GetOutput();
00426   // _vtk_grid->Update(); // FIXME: Necessary?
00427 
00428   // Get a reference to the mesh
00429   MeshBase& mesh = MeshInput<MeshBase>::mesh();
00430 
00431   // Clear out any pre-existing data from the Mesh
00432   mesh.clear();
00433 
00434   // Get the number of points from the _vtk_grid object
00435   const unsigned int vtk_num_points = static_cast<unsigned int>(_vtk_grid->GetNumberOfPoints());
00436 
00437   // always numbered nicely??, so we can loop like this
00438   // I'm pretty sure it is numbered nicely
00439   for (unsigned int i=0; i<vtk_num_points; ++i)
00440     {
00441       // add to the id map
00442       // and add the actual point
00443       double * pnt = _vtk_grid->GetPoint(static_cast<vtkIdType>(i));
00444       Point xyz(pnt[0], pnt[1], pnt[2]);
00445       Node* newnode = mesh.add_point(xyz, i);
00446 
00447       // Add node to the nodes vector &
00448       // tell the MeshData object the foreign node id.
00449       if (this->_mesh_data != NULL)
00450         this->_mesh_data->add_foreign_node_id (newnode, i);
00451     }
00452 
00453   // Get the number of cells from the _vtk_grid object
00454   const unsigned int vtk_num_cells = static_cast<unsigned int>(_vtk_grid->GetNumberOfCells());
00455 
00456   for (unsigned int i=0; i<vtk_num_cells; ++i)
00457     {
00458       vtkCell* cell = _vtk_grid->GetCell(i);
00459       Elem* elem = NULL;
00460       switch (cell->GetCellType())
00461         {
00462         case VTK_LINE:
00463           elem = new Edge2;
00464           break;
00465         case VTK_QUADRATIC_EDGE:
00466           elem = new Edge3;
00467           break;
00468         case VTK_TRIANGLE:
00469           elem = new Tri3();
00470           break;
00471         case VTK_QUADRATIC_TRIANGLE:
00472           elem = new Tri6();
00473           break;
00474         case VTK_QUAD:
00475           elem = new Quad4();
00476           break;
00477         case VTK_QUADRATIC_QUAD:
00478           elem = new Quad8();
00479           break;
00480 #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0)
00481         case VTK_BIQUADRATIC_QUAD:
00482           elem = new Quad9();
00483           break;
00484 #endif
00485         case VTK_TETRA:
00486           elem = new Tet4();
00487           break;
00488         case VTK_QUADRATIC_TETRA:
00489           elem = new Tet10();
00490           break;
00491         case VTK_WEDGE:
00492           elem = new Prism6();
00493           break;
00494         case VTK_QUADRATIC_WEDGE:
00495           elem = new Prism15();
00496           break;
00497         case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
00498           elem = new Prism18();
00499           break;
00500         case VTK_HEXAHEDRON:
00501           elem = new Hex8();
00502           break;
00503         case VTK_QUADRATIC_HEXAHEDRON:
00504           elem = new Hex20();
00505           break;
00506         case VTK_TRIQUADRATIC_HEXAHEDRON:
00507           elem = new Hex27();
00508           break;
00509         case VTK_PYRAMID:
00510           elem = new Pyramid5();
00511           break;
00512         default:
00513           libmesh_error_msg("Element type not implemented in vtkinterface " << cell->GetCellType());
00514         }
00515 
00516       // get the straightforward numbering from the VTK cells
00517       for (unsigned int j=0; j<elem->n_nodes(); ++j)
00518         elem->set_node(j) =
00519           mesh.node_ptr(cast_int<dof_id_type>(cell->GetPointId(j)));
00520 
00521       // then get the connectivity
00522       std::vector<dof_id_type> conn;
00523       elem->connectivity(0, VTK, conn);
00524 
00525       // then reshuffle the nodes according to the connectivity, this
00526       // two-time-assign would evade the definition of the vtk_mapping
00527       for (unsigned int j=0; j<conn.size(); ++j)
00528         elem->set_node(j) = mesh.node_ptr(conn[j]);
00529 
00530       elem->set_id(i);
00531 
00532       elems_of_dimension[elem->dim()] = true;
00533 
00534       mesh.add_elem(elem);
00535     } // end loop over VTK cells
00536 
00537   // Set the mesh dimension to the largest encountered for an element
00538   for (unsigned char i=0; i!=4; ++i)
00539     if (elems_of_dimension[i])
00540       mesh.set_mesh_dimension(i);
00541 
00542 #if LIBMESH_DIM < 3
00543   if (mesh.mesh_dimension() > LIBMESH_DIM)
00544     libmesh_error_msg("Cannot open dimension "  \
00545                       << mesh.mesh_dimension()              \
00546                       << " mesh file when configured without "  \
00547                       << mesh.mesh_dimension()                  \
00548                       << "D support.");
00549 #endif
00550 
00551 #endif // LIBMESH_HAVE_VTK
00552 }
00553 
00554 
00555 
00556 void VTKIO::write_nodal_data (const std::string& fname,
00557 #ifdef LIBMESH_HAVE_VTK
00558                               const std::vector<Number>& soln,
00559                               const std::vector<std::string>& names
00560 #else
00561                               const std::vector<Number>&,
00562                               const std::vector<std::string>&
00563 #endif
00564                               )
00565 {
00566 #ifndef LIBMESH_HAVE_VTK
00567 
00568   libmesh_error_msg("Cannot write VTK file: " << fname                  \
00569                     << "\nYou must have VTK installed and correctly configured to read VTK meshes.");
00570 
00571 #else
00572 
00573   const MeshBase & mesh = MeshOutput<MeshBase>::mesh();
00574 
00575   // Is this really important?  If so, it should be more than an assert...
00576   // libmesh_assert(fname.substr(fname.rfind("."), fname.size()) == ".pvtu");
00577 
00578   // we only use Unstructured grids
00579   _vtk_grid = vtkUnstructuredGrid::New();
00580   vtkSmartPointer<vtkXMLPUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLPUnstructuredGridWriter>::New();
00581 
00582   // add nodes to the grid and update _local_node_map
00583   _local_node_map.clear();
00584   this->nodes_to_vtk();
00585 
00586   // add cells to the grid
00587   this->cells_to_vtk();
00588 
00589   // add nodal solutions to the grid, if solutions are given
00590   if (names.size() > 0)
00591     {
00592       std::size_t num_vars = names.size();
00593       dof_id_type num_nodes = mesh.n_nodes();
00594 
00595       for (std::size_t variable=0; variable<num_vars; ++variable)
00596         {
00597           vtkSmartPointer<vtkDoubleArray> data = vtkSmartPointer<vtkDoubleArray>::New();
00598           data->SetName(names[variable].c_str());
00599 
00600           // number of local and ghost nodes
00601           data->SetNumberOfValues(_local_node_map.size());
00602 
00603           // loop over all nodes and get the solution for the current
00604           // variable, if the node is in the current partition
00605           for (dof_id_type k=0; k<num_nodes; ++k)
00606             {
00607               if (_local_node_map.find(k) == _local_node_map.end())
00608                 continue; // not a local node
00609 
00610               if (!soln.empty())
00611                 {
00612 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00613                   libmesh_do_once (libMesh::err << "Only writing the real part for complex numbers!\n"
00614                                    << "if you need this support contact " << LIBMESH_PACKAGE_BUGREPORT
00615                                    << std::endl);
00616                   data->SetValue(_local_node_map[k], soln[k*num_vars + variable].real());
00617 #else
00618                   data->SetValue(_local_node_map[k], soln[k*num_vars + variable]);
00619 #endif
00620                 }
00621               else
00622                 {
00623                   data->SetValue(_local_node_map[k], 0);
00624                 }
00625             }
00626           _vtk_grid->GetPointData()->AddArray(data);
00627         }
00628     }
00629 
00630   // Tell the writer how many partitions exist and on which processor
00631   // we are currently
00632   writer->SetNumberOfPieces(MeshOutput<MeshBase>::mesh().n_processors());
00633   writer->SetStartPiece(MeshOutput<MeshBase>::mesh().processor_id());
00634   writer->SetEndPiece(MeshOutput<MeshBase>::mesh().processor_id());
00635 
00636   // partitions overlap by one node
00637   // FIXME: According to this document
00638   // http://paraview.org/Wiki/images/5/51/SC07_tut107_ParaView_Handouts.pdf
00639   // the ghosts are cells rather than nodes.
00640   writer->SetGhostLevel(1);
00641 
00642   // Not sure exactly when this changed, but SetInput() is not a
00643   // method on vtkXMLPUnstructuredGridWriter as of VTK 6.1.0
00644 #if VTK_VERSION_LESS_THAN(6,0,0)
00645   writer->SetInput(_vtk_grid);
00646 #else
00647   writer->SetInputData(_vtk_grid);
00648 #endif
00649 
00650   writer->SetFileName(fname.c_str());
00651   writer->SetDataModeToAscii();
00652 
00653   // compress the output, if desired (switches also to binary)
00654   if (this->_compress)
00655     {
00656 #if !VTK_VERSION_LESS_THAN(5,6,0)
00657       writer->SetCompressorTypeToZLib();
00658 #else
00659       libmesh_do_once(libMesh::err << "Compression not implemented with old VTK libs!" << std::endl;);
00660 #endif
00661     }
00662 
00663   writer->Write();
00664 
00665   _vtk_grid->Delete();
00666 #endif
00667 }
00668 
00669 
00670 
00671 // Output the mesh without solutions to a .pvtu file
00672 void VTKIO::write (const std::string& name)
00673 {
00674   std::vector<Number> soln;
00675   std::vector<std::string> names;
00676   this->write_nodal_data(name, soln, names);
00677 }
00678 
00679 
00680 
00681 } // namespace libMesh