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