$extrastylesheet
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