$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 <iomanip> 00021 #include <fstream> 00022 #include <vector> 00023 00024 #include <sys/types.h> // getpid 00025 #include <unistd.h> 00026 00027 // Local includes 00028 #include "libmesh/libmesh_logging.h" 00029 #include "libmesh/mesh_base.h" 00030 #include "libmesh/mesh_communication.h" 00031 00032 #include "libmesh/namebased_io.h" 00033 00034 #include "libmesh/diva_io.h" 00035 #include "libmesh/exodusII_io.h" 00036 #include "libmesh/gmv_io.h" 00037 #include "libmesh/tecplot_io.h" 00038 #include "libmesh/tetgen_io.h" 00039 #include "libmesh/ucd_io.h" 00040 #include "libmesh/unv_io.h" 00041 #include "libmesh/matlab_io.h" 00042 #include "libmesh/off_io.h" 00043 #include "libmesh/medit_io.h" 00044 #include "libmesh/nemesis_io.h" 00045 #include "libmesh/gmsh_io.h" 00046 #include "libmesh/fro_io.h" 00047 #include "libmesh/xdr_io.h" 00048 #include "libmesh/legacy_xdr_io.h" 00049 #include "libmesh/vtk_io.h" 00050 #include "libmesh/abaqus_io.h" 00051 #include "libmesh/checkpoint_io.h" 00052 00053 #include "libmesh/equation_systems.h" 00054 00055 00056 00057 namespace libMesh 00058 { 00059 00060 00061 00062 // ------------------------------------------------------------ 00063 // NameBasedIO members 00064 void NameBasedIO::read (const std::string& name) 00065 { 00066 MeshBase& mymesh = MeshInput<MeshBase>::mesh(); 00067 00068 // See if the file exists. Perform this check on all processors 00069 // so that the code is terminated properly in the case that the 00070 // file does not exist. 00071 00072 // For Nemesis files, the name we try to read will have suffixes 00073 // identifying processor rank 00074 if (name.rfind(".nem") + 4 == name.size() || 00075 name.rfind(".n") + 2 == name.size()) 00076 { 00077 std::ostringstream full_name; 00078 00079 // Find the length of a string which represents the highest processor ID 00080 full_name << (mymesh.n_processors()); 00081 int field_width = cast_int<int>(full_name.str().size()); 00082 00083 // reset the string stream 00084 full_name.str(""); 00085 00086 // And build up the full filename 00087 full_name << name 00088 << '.' << mymesh.n_processors() 00089 << '.' << std::setfill('0') << std::setw(field_width) << mymesh.processor_id(); 00090 00091 std::ifstream in (full_name.str().c_str()); 00092 00093 if (!in.good()) 00094 libmesh_error_msg("ERROR: cannot locate specified file:\n\t" << full_name.str()); 00095 } 00096 else if(name.rfind(".cp")) {} // Do error checking in the reader 00097 else 00098 { 00099 std::ifstream in (name.c_str()); 00100 00101 if (!in.good()) 00102 libmesh_error_msg("ERROR: cannot locate specified file:\n\t" << name); 00103 } 00104 00105 // Look for parallel formats first 00106 if (is_parallel_file_format(name)) 00107 { 00108 // no need to handle bz2 files here -- the Xdr class does that. 00109 if ((name.rfind(".xda") < name.size()) || 00110 (name.rfind(".xdr") < name.size())) 00111 { 00112 XdrIO xdr_io(mymesh); 00113 00114 // .xda* ==> bzip2/gzip/ASCII flavors 00115 if (name.rfind(".xda") < name.size()) 00116 { 00117 xdr_io.binary() = false; 00118 xdr_io.read (name); 00119 } 00120 else // .xdr* ==> true binary XDR file 00121 { 00122 xdr_io.binary() = true; 00123 xdr_io.read (name); 00124 } 00125 00126 // The xdr_io object gets constructed with legacy() == false. 00127 // if legacy() == true then it means that a legacy file was detected and 00128 // thus processor 0 performed the read. We therefore need to broadcast the 00129 // mesh. Further, for this flavor of mesh solution data ordering is tied 00130 // to the node ordering, so we better not reorder the nodes! 00131 if (xdr_io.legacy()) 00132 { 00133 mymesh.allow_renumbering(false); 00134 MeshCommunication().broadcast(mymesh); 00135 } 00136 00137 // libHilbert-enabled libMesh builds should construct files 00138 // with a canonical node ordering, which libHilbert-enabled 00139 // builds will be able to read in again regardless of any 00140 // renumbering. So in that case we're free to renumber. 00141 // However, if either the writer or the reader of this file 00142 // don't have libHilbert, then we'll have to skip 00143 // renumbering because we need the numbering to remain 00144 // consistent with any solution file we read in next. 00145 #ifdef LIBMESH_HAVE_LIBHILBERT 00146 // if (!xdr_io.libhilbert_ordering()) 00147 // skip_renumber_nodes_and_elements = true; 00148 #else 00149 mymesh.allow_renumbering(false); 00150 #endif 00151 } 00152 else if (name.rfind(".nem") < name.size() || 00153 name.rfind(".n") < name.size()) 00154 Nemesis_IO(mymesh).read (name); 00155 else if (name.rfind(".cp") < name.size()) 00156 { 00157 if(name.rfind(".cpa") < name.size()) 00158 CheckpointIO(mymesh, false).read(name); 00159 else 00160 CheckpointIO(mymesh, true).read(name); 00161 } 00162 } 00163 00164 // Serial mesh formats 00165 else 00166 { 00167 START_LOG("read()", "NameBasedIO"); 00168 00169 // Read the file based on extension. Only processor 0 00170 // needs to read the mesh. It will then broadcast it and 00171 // the other processors will pick it up 00172 if (mymesh.processor_id() == 0) 00173 { 00174 std::ostringstream pid_suffix; 00175 pid_suffix << '_' << getpid(); 00176 // Nasty hack for reading/writing zipped files 00177 std::string new_name = name; 00178 if (name.size() - name.rfind(".bz2") == 4) 00179 { 00180 #ifdef LIBMESH_HAVE_BZIP 00181 new_name.erase(new_name.end() - 4, new_name.end()); 00182 new_name += pid_suffix.str(); 00183 std::string system_string = "bunzip2 -f -k -c "; 00184 system_string += name + " > " + new_name; 00185 START_LOG("system(bunzip2)", "NameBasedIO"); 00186 if (std::system(system_string.c_str())) 00187 libmesh_file_error(system_string); 00188 STOP_LOG("system(bunzip2)", "NameBasedIO"); 00189 #else 00190 libmesh_error_msg("ERROR: need bzip2/bunzip2 to open .bz2 file " << name); 00191 #endif 00192 } 00193 else if (name.size() - name.rfind(".xz") == 3) 00194 { 00195 #ifdef LIBMESH_HAVE_XZ 00196 new_name.erase(new_name.end() - 3, new_name.end()); 00197 new_name += pid_suffix.str(); 00198 std::string system_string = "xz -f -d -k -c "; 00199 system_string += name + " > " + new_name; 00200 START_LOG("system(xz -d)", "XdrIO"); 00201 if (std::system(system_string.c_str())) 00202 libmesh_file_error(system_string); 00203 STOP_LOG("system(xz -d)", "XdrIO"); 00204 #else 00205 libmesh_error_msg("ERROR: need xz to open .xz file " << name); 00206 #endif 00207 } 00208 00209 if (new_name.rfind(".mat") < new_name.size()) 00210 MatlabIO(mymesh).read(new_name); 00211 00212 else if (new_name.rfind(".ucd") < new_name.size()) 00213 UCDIO(mymesh).read (new_name); 00214 00215 else if ((new_name.rfind(".off") < new_name.size()) || 00216 (new_name.rfind(".ogl") < new_name.size()) || 00217 (new_name.rfind(".oogl") < new_name.size())) 00218 OFFIO(mymesh).read (new_name); 00219 00220 else if (new_name.rfind(".mgf") < new_name.size()) 00221 LegacyXdrIO(mymesh,true).read_mgf (new_name); 00222 00223 else if (new_name.rfind(".unv") < new_name.size()) 00224 UNVIO(mymesh).read (new_name); 00225 00226 else if ((new_name.rfind(".node") < new_name.size()) || 00227 (new_name.rfind(".ele") < new_name.size())) 00228 TetGenIO(mymesh).read (new_name); 00229 00230 else if (new_name.rfind(".exd") < new_name.size() || 00231 new_name.rfind(".e") < new_name.size()) 00232 ExodusII_IO(mymesh).read (new_name); 00233 00234 else if (new_name.rfind(".msh") < new_name.size()) 00235 GmshIO(mymesh).read (new_name); 00236 00237 else if (new_name.rfind(".gmv") < new_name.size()) 00238 GMVIO(mymesh).read (new_name); 00239 00240 else if (new_name.rfind(".vtu") < new_name.size()) 00241 VTKIO(mymesh).read(new_name); 00242 00243 else if (new_name.rfind(".inp") < new_name.size()) 00244 AbaqusIO(mymesh).read(new_name); 00245 00246 else 00247 { 00248 libmesh_error_msg(" ERROR: Unrecognized file extension: " \ 00249 << name \ 00250 << "\n I understand the following:\n\n" \ 00251 << " *.e -- Sandia's ExodusII format\n" \ 00252 << " *.exd -- Sandia's ExodusII format\n" \ 00253 << " *.gmv -- LANL's General Mesh Viewer format\n" \ 00254 << " *.mat -- Matlab triangular ASCII file\n" \ 00255 << " *.n -- Sandia's Nemesis format\n" \ 00256 << " *.nem -- Sandia's Nemesis format\n" \ 00257 << " *.off -- OOGL OFF surface format\n" \ 00258 << " *.ucd -- AVS's ASCII UCD format\n" \ 00259 << " *.unv -- I-deas Universal format\n" \ 00260 << " *.vtu -- Paraview VTK format\n" \ 00261 << " *.inp -- Abaqus .inp format\n" \ 00262 << " *.xda -- libMesh ASCII format\n" \ 00263 << " *.xdr -- libMesh binary format\n" \ 00264 << " *.gz -- any above format gzipped\n" \ 00265 << " *.bz2 -- any above format bzip2'ed\n" \ 00266 << " *.xz -- any above format xzipped\n" \ 00267 << " *.cpa -- libMesh Checkpoint ASCII format\n" \ 00268 << " *.cpr -- libMesh Checkpoint binary format\n"); 00269 } 00270 00271 // If we temporarily decompressed a file, remove the 00272 // uncompressed version 00273 if (name.size() - name.rfind(".bz2") == 4) 00274 std::remove(new_name.c_str()); 00275 if (name.size() - name.rfind(".xz") == 3) 00276 std::remove(new_name.c_str()); 00277 } 00278 00279 00280 STOP_LOG("read()", "NameBasedIO"); 00281 00282 // Send the mesh & bcs (which are now only on processor 0) to the other 00283 // processors 00284 MeshCommunication().broadcast (mymesh); 00285 } 00286 } 00287 00288 00289 void NameBasedIO::write (const std::string& name) 00290 { 00291 MeshBase& mymesh = MeshInput<MeshBase>::mesh(); 00292 00293 // parallel formats are special -- they may choose to write 00294 // separate files, let's not try to handle the zipping here. 00295 if (is_parallel_file_format(name)) 00296 { 00297 // no need to handle bz2 files here -- the Xdr class does that. 00298 if (name.rfind(".xda") < name.size()) 00299 XdrIO(mymesh).write(name); 00300 00301 else if (name.rfind(".xdr") < name.size()) 00302 XdrIO(mymesh,true).write(name); 00303 00304 else if (name.rfind(".nem") < name.size() || 00305 name.rfind(".n") < name.size()) 00306 Nemesis_IO(mymesh).write(name); 00307 } 00308 00309 // serial file formats 00310 else 00311 { 00312 // Nasty hack for reading/writing zipped files 00313 std::string new_name = name; 00314 pid_t pid_0 = 0; 00315 if (mymesh.processor_id() == 0) 00316 pid_0 = getpid(); 00317 mymesh.comm().broadcast(pid_0); 00318 std::ostringstream pid_suffix; 00319 pid_suffix << '_' << pid_0; 00320 00321 if (name.size() - name.rfind(".bz2") == 4) 00322 { 00323 new_name.erase(new_name.end() - 4, new_name.end()); 00324 new_name += pid_suffix.str(); 00325 } 00326 else if (name.size() - name.rfind(".xz") == 3) 00327 { 00328 new_name.erase(new_name.end() - 3, new_name.end()); 00329 new_name += pid_suffix.str(); 00330 } 00331 00332 // New scope so that io will close before we try to zip the file 00333 { 00334 // Write the file based on extension 00335 if (new_name.rfind(".dat") < new_name.size()) 00336 TecplotIO(mymesh).write (new_name); 00337 00338 else if (new_name.rfind(".plt") < new_name.size()) 00339 TecplotIO(mymesh,true).write (new_name); 00340 00341 else if (new_name.rfind(".ucd") < new_name.size()) 00342 UCDIO (mymesh).write (new_name); 00343 00344 else if (new_name.rfind(".gmv") < new_name.size()) 00345 if (mymesh.n_partitions() > 1) 00346 GMVIO(mymesh).write (new_name); 00347 else 00348 { 00349 GMVIO io(mymesh); 00350 io.partitioning() = false; 00351 io.write (new_name); 00352 } 00353 00354 else if (new_name.rfind(".ugrid") < new_name.size()) 00355 DivaIO(mymesh).write(new_name); 00356 else if (new_name.rfind(".e") < new_name.size()) 00357 ExodusII_IO(mymesh).write(new_name); 00358 else if (new_name.rfind(".mgf") < new_name.size()) 00359 LegacyXdrIO(mymesh,true).write_mgf(new_name); 00360 00361 else if (new_name.rfind(".unv") < new_name.size()) 00362 UNVIO(mymesh).write (new_name); 00363 00364 else if (new_name.rfind(".mesh") < new_name.size()) 00365 MEDITIO(mymesh).write (new_name); 00366 00367 else if (new_name.rfind(".poly") < new_name.size()) 00368 TetGenIO(mymesh).write (new_name); 00369 00370 else if (new_name.rfind(".msh") < new_name.size()) 00371 GmshIO(mymesh).write (new_name); 00372 00373 else if (new_name.rfind(".fro") < new_name.size()) 00374 FroIO(mymesh).write (new_name); 00375 00376 else if (new_name.rfind(".vtu") < new_name.size()) 00377 VTKIO(mymesh).write (new_name); 00378 00379 else 00380 { 00381 libMesh::err 00382 << " ERROR: Unrecognized file extension: " << name 00383 << "\n I understand the following:\n\n" 00384 << " *.dat -- Tecplot ASCII file\n" 00385 << " *.e -- Sandia's ExodusII format\n" 00386 << " *.exd -- Sandia's ExodusII format\n" 00387 << " *.fro -- ACDL's surface triangulation file\n" 00388 << " *.gmv -- LANL's GMV (General Mesh Viewer) format\n" 00389 << " *.mesh -- MEdit mesh format\n" 00390 << " *.mgf -- MGF binary mesh format\n" 00391 << " *.msh -- GMSH ASCII file\n" 00392 << " *.n -- Sandia's Nemesis format\n" 00393 << " *.nem -- Sandia's Nemesis format\n" 00394 << " *.plt -- Tecplot binary file\n" 00395 << " *.poly -- TetGen ASCII file\n" 00396 << " *.ucd -- AVS's ASCII UCD format\n" 00397 << " *.ugrid -- Kelly's DIVA ASCII format\n" 00398 << " *.unv -- I-deas Universal format\n" 00399 << " *.vtu -- VTK (paraview-readable) format\n" 00400 << " *.xda -- libMesh ASCII format\n" 00401 << " *.xdr -- libMesh binary format,\n" 00402 << std::endl 00403 << "\n Exiting without writing output\n"; 00404 } 00405 } 00406 00407 // Nasty hack for reading/writing zipped files 00408 if (name.size() - name.rfind(".bz2") == 4) 00409 { 00410 START_LOG("system(bzip2)", "NameBasedIO"); 00411 if (mymesh.processor_id() == 0) 00412 { 00413 std::string system_string = "bzip2 -f -c "; 00414 system_string += new_name + " > " + name; 00415 if (std::system(system_string.c_str())) 00416 libmesh_file_error(system_string); 00417 std::remove(new_name.c_str()); 00418 } 00419 mymesh.comm().barrier(); 00420 STOP_LOG("system(bzip2)", "NameBasedIO"); 00421 } 00422 if (name.size() - name.rfind(".xz") == 3) 00423 { 00424 START_LOG("system(xz)", "NameBasedIO"); 00425 if (mymesh.processor_id() == 0) 00426 { 00427 std::string system_string = "xz -f -c "; 00428 system_string += new_name + " > " + name; 00429 if (std::system(system_string.c_str())) 00430 libmesh_file_error(system_string); 00431 std::remove(new_name.c_str()); 00432 } 00433 mymesh.comm().barrier(); 00434 STOP_LOG("system(xz)", "NameBasedIO"); 00435 } 00436 } 00437 00438 } 00439 00440 00441 void NameBasedIO::write_nodal_data (const std::string& name, 00442 const std::vector<Number>& v, 00443 const std::vector<std::string>& vn) 00444 { 00445 MeshBase& mymesh = MeshInput<MeshBase>::mesh(); 00446 00447 // Write the file based on extension 00448 if (name.rfind(".dat") < name.size()) 00449 TecplotIO(mymesh).write_nodal_data (name, v, vn); 00450 00451 else if (name.rfind(".e") < name.size()) 00452 ExodusII_IO(mymesh).write_nodal_data(name, v, vn); 00453 00454 else if (name.rfind(".gmv") < name.size()) 00455 { 00456 if (mymesh.n_subdomains() > 1) 00457 GMVIO(mymesh).write_nodal_data (name, v, vn); 00458 else 00459 { 00460 GMVIO io(mymesh); 00461 io.partitioning() = false; 00462 io.write_nodal_data (name, v, vn); 00463 } 00464 } 00465 00466 else if (name.rfind(".mesh") < name.size()) 00467 MEDITIO(mymesh).write_nodal_data (name, v, vn); 00468 00469 else if (name.rfind(".msh") < name.size()) 00470 GmshIO(mymesh).write_nodal_data (name, v, vn); 00471 00472 else if (name.rfind(".nem") < name.size() || 00473 name.rfind(".n") < name.size()) 00474 Nemesis_IO(mymesh).write_nodal_data(name, v, vn); 00475 00476 else if (name.rfind(".plt") < name.size()) 00477 TecplotIO(mymesh,true).write_nodal_data (name, v, vn); 00478 00479 else if (name.rfind(".pvtu") < name.size()) 00480 VTKIO(mymesh).write_nodal_data (name, v, vn); 00481 00482 else if (name.rfind(".ucd") < name.size()) 00483 UCDIO (mymesh).write_nodal_data (name, v, vn); 00484 00485 else 00486 { 00487 libMesh::err 00488 << " ERROR: Unrecognized file extension: " << name 00489 << "\n I understand the following:\n\n" 00490 << " *.dat -- Tecplot ASCII file\n" 00491 << " *.e -- Sandia's ExodusII format\n" 00492 << " *.exd -- Sandia's ExodusII format\n" 00493 << " *.gmv -- LANL's GMV (General Mesh Viewer) format\n" 00494 << " *.mesh -- MEdit mesh format\n" 00495 << " *.msh -- GMSH ASCII file\n" 00496 << " *.n -- Sandia's Nemesis format\n" 00497 << " *.nem -- Sandia's Nemesis format\n" 00498 << " *.plt -- Tecplot binary file\n" 00499 << " *.pvtu -- Paraview VTK file\n" 00500 << " *.ucd -- AVS's ASCII UCD format\n" 00501 << "\n Exiting without writing output\n"; 00502 } 00503 } 00504 00505 00506 void NameBasedIO::write_equation_systems (const std::string& filename, 00507 const EquationSystems& es, 00508 const std::set<std::string>* system_names) 00509 { 00510 // XDA/XDR require a separate code path, and currently only support 00511 // writing complete restarts 00512 if (!system_names) 00513 { 00514 if (filename.rfind(".xda") < filename.size()) 00515 { 00516 es.write(filename,WRITE, 00517 EquationSystems::WRITE_DATA | 00518 EquationSystems::WRITE_ADDITIONAL_DATA); 00519 return; 00520 } 00521 else if (filename.rfind(".xdr") < filename.size()) 00522 { 00523 es.write(filename,ENCODE, 00524 EquationSystems::WRITE_DATA | 00525 EquationSystems::WRITE_ADDITIONAL_DATA); 00526 return; 00527 } 00528 } 00529 00530 // Other formats just use the default "write nodal values" path 00531 MeshOutput<MeshBase>::write_equation_systems 00532 (filename, es, system_names); 00533 } 00534 00535 00536 00537 } // namespace libMesh