$extrastylesheet
ucd_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 
00023 // Local includes
00024 #include "libmesh/libmesh_config.h"
00025 #include "libmesh/ucd_io.h"
00026 #include "libmesh/mesh_base.h"
00027 #include "libmesh/face_quad4.h"
00028 #include "libmesh/face_tri3.h"
00029 #include "libmesh/cell_tet4.h"
00030 #include "libmesh/cell_hex8.h"
00031 #include "libmesh/cell_prism6.h"
00032 
00033 #ifdef LIBMESH_HAVE_GZSTREAM
00034 # include "gzstream.h" // For reading/writing compressed streams
00035 #endif
00036 
00037 
00038 namespace libMesh
00039 {
00040 
00041 
00042 
00043 
00044 // ------------------------------------------------------------
00045 // UCDIO class members
00046 void UCDIO::read (const std::string& file_name)
00047 {
00048   if (file_name.rfind(".gz") < file_name.size())
00049     {
00050 #ifdef LIBMESH_HAVE_GZSTREAM
00051 
00052       igzstream in_stream (file_name.c_str());
00053       this->read_implementation (in_stream);
00054 
00055 #else
00056 
00057       libmesh_error_msg("ERROR:  You must have the zlib.h header files and libraries to read and write compressed streams.");
00058 
00059 #endif
00060       return;
00061     }
00062 
00063   else
00064     {
00065       std::ifstream in_stream (file_name.c_str());
00066       this->read_implementation (in_stream);
00067       return;
00068     }
00069 }
00070 
00071 
00072 
00073 void UCDIO::write (const std::string& file_name)
00074 {
00075   if (file_name.rfind(".gz") < file_name.size())
00076     {
00077 #ifdef LIBMESH_HAVE_GZSTREAM
00078 
00079       ogzstream out_stream (file_name.c_str());
00080       this->write_implementation (out_stream);
00081 
00082 #else
00083 
00084       libmesh_error_msg("ERROR:  You must have the zlib.h header files and libraries to read and write compressed streams.");
00085 
00086 #endif
00087       return;
00088     }
00089 
00090   else
00091     {
00092       std::ofstream out_stream (file_name.c_str());
00093       this->write_implementation (out_stream);
00094       return;
00095     }
00096 }
00097 
00098 
00099 
00100 void UCDIO::read_implementation (std::istream& in)
00101 {
00102   // This is a serial-only process for now;
00103   // the Mesh should be read on processor 0 and
00104   // broadcast later
00105   libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
00106 
00107   // Check input buffer
00108   libmesh_assert (in.good());
00109 
00110   MeshBase& mesh = MeshInput<MeshBase>::mesh();
00111 
00112   // Keep track of what kinds of elements this file contains
00113   elems_of_dimension.clear();
00114   elems_of_dimension.resize(4, false);
00115 
00116   this->skip_comment_lines (in, '#');
00117 
00118   unsigned int nNodes=0, nElem=0, dummy=0;
00119 
00120   in >> nNodes   // Read the number of nodes from the stream
00121      >> nElem    // Read the number of elements from the stream
00122      >> dummy
00123      >> dummy
00124      >> dummy;
00125 
00126 
00127   // Read the nodal coordinates. Note that UCD format always
00128   // stores (x,y,z), and in 2D z=0. We don't need to store this,
00129   // however.  So, we read in x,y,z for each node and make a point
00130   // in the proper way based on what dimension we're in
00131   {
00132     Point xyz;
00133 
00134     for (unsigned int i=0; i<nNodes; i++)
00135       {
00136         libmesh_assert (in.good());
00137 
00138         in >> dummy   // Point number
00139            >> xyz(0)  // x-coordinate value
00140            >> xyz(1)  // y-coordinate value
00141            >> xyz(2); // z-coordinate value
00142 
00143         // Build the node
00144         mesh.add_point (xyz, i);
00145       }
00146   }
00147 
00148 
00149 
00150   // Read the elements from the stream. Notice that the UCD node-numbering
00151   // scheme is 1-based, and we just created a 0-based scheme above
00152   // (which is of course what we want). So, when we read in the nodal
00153   // connectivity for each element we need to take 1 off the value of
00154   // each node so that we get the right thing.
00155   {
00156     unsigned int material_id=0, node=0;
00157     std::string type;
00158 
00159     for (unsigned int i=0; i<nElem; i++)
00160       {
00161         Elem* elem = NULL;
00162 
00163         libmesh_assert (in.good());
00164 
00165         in >> dummy        // Cell number, means nothing to us
00166            >> material_id  // doesn't mean anything at present, might later
00167            >> type;        // string describing cell type:
00168         // either tri, quad, tet, hex, or prism for the
00169         // obvious cases
00170 
00171 
00172         // Now read the connectivity.
00173         if (type == "quad")
00174           elem = new Quad4;
00175         else if (type == "tri")
00176           elem = new Tri3;
00177         else if (type == "hex")
00178           elem = new Hex8;
00179         else if (type == "tet")
00180           elem = new Tet4;
00181         else if (type == "prism")
00182           elem = new Prism6;
00183         else
00184           libmesh_error_msg("Unsupported element type = " << type);
00185 
00186         for (unsigned int n=0; n<elem->n_nodes(); n++)
00187           {
00188             libmesh_assert (in.good());
00189 
00190             in >> node; // read the current node
00191             node -= 1;  // UCD is 1-based, so subtract
00192 
00193             libmesh_assert_less (node, mesh.n_nodes());
00194 
00195             elem->set_node(n) =
00196               mesh.node_ptr(node); // assign the node
00197           }
00198 
00199         elems_of_dimension[elem->dim()] = true;
00200 
00201         // Add the element to the mesh
00202         elem->set_id(i);
00203         mesh.add_elem (elem);
00204       }
00205 
00206     // Set the mesh dimension to the largest encountered for an element
00207     for (unsigned char i=0; i!=4; ++i)
00208       if (elems_of_dimension[i])
00209         mesh.set_mesh_dimension(i);
00210 
00211 #if LIBMESH_DIM < 3
00212     if (mesh.mesh_dimension() > LIBMESH_DIM)
00213       libmesh_error_msg("Cannot open dimension " \
00214                         << mesh.mesh_dimension() \
00215                         << " mesh file when configured without " \
00216                         << mesh.mesh_dimension() \
00217                         << "D support.");
00218 #endif
00219   }
00220 }
00221 
00222 
00223 
00224 void UCDIO::write_implementation (std::ostream& out_stream)
00225 {
00226   libmesh_assert (out_stream.good());
00227 
00228   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
00229 
00230   // UCD doesn't work in 1D
00231   libmesh_assert_not_equal_to (mesh.mesh_dimension(), 1);
00232   if(mesh.mesh_dimension() != 3)
00233     libmesh_error_msg("Error: Can't write boundary elements for meshes of dimension less than 3. " \
00234                       << "Mesh dimension = " << mesh.mesh_dimension());
00235 
00236   // Write header
00237   this->write_header(out_stream,mesh,mesh.n_elem(),0);
00238 
00239   // Write the node coordinates
00240   this->write_nodes(out_stream,mesh);
00241 
00242   // Write the elements
00243   this->write_interior_elems(out_stream,mesh);
00244 
00245   return;
00246 }
00247 
00248 void UCDIO::write_header(std::ostream& out_stream, const MeshBase& mesh,
00249                          dof_id_type n_elems, unsigned int n_vars )
00250 {
00251   libmesh_assert (out_stream.good());
00252   // TODO: We used to print out the SVN revision here when we did keyword expansions...
00253   out_stream << "# For a description of the UCD format see the AVS Developer's guide.\n"
00254              << "#\n";
00255 
00256   // Write the mesh info
00257   out_stream << mesh.n_nodes() << " "
00258              << n_elems  << " "
00259              << n_vars << " "
00260              << " 0 0\n";
00261   return;
00262 }
00263 
00264 void UCDIO::write_nodes(std::ostream& out_stream, const MeshBase& mesh)
00265 {
00266   MeshBase::const_node_iterator       it  = mesh.nodes_begin();
00267   const MeshBase::const_node_iterator end = mesh.nodes_end();
00268 
00269   unsigned int n=1; // 1-based node number for UCD
00270 
00271   // Write the node coordinates
00272   for (; it != end; ++it)
00273     {
00274       libmesh_assert (out_stream.good());
00275 
00276       out_stream << n++ << "\t";
00277       (*it)->write_unformatted(out_stream);
00278     }
00279 
00280   return;
00281 }
00282 
00283 void UCDIO::write_interior_elems(std::ostream& out_stream, const MeshBase& mesh)
00284 {
00285   std::string type[] =
00286     { "edge",  "edge",  "edge",
00287       "tri",   "tri",
00288       "quad",  "quad",  "quad",
00289       "tet",   "tet",
00290       "hex",   "hex",   "hex",
00291       "prism", "prism", "prism",
00292       "pyramid" };
00293 
00294   MeshBase::const_element_iterator it  = mesh.elements_begin();
00295   const MeshBase::const_element_iterator end = mesh.elements_end();
00296 
00297   unsigned int e=1; // 1-based element number for UCD
00298 
00299   // Write element information
00300   for (; it != end; ++it)
00301     {
00302       libmesh_assert (out_stream.good());
00303 
00304       // PB: I believe these are the only supported ElemTypes.
00305       const ElemType etype = (*it)->type();
00306       if( (etype != TRI3) && (etype != QUAD4) &&
00307           (etype != TET4) && (etype != HEX8) &&
00308           (etype != PRISM6) && (etype != PYRAMID5) )
00309         libmesh_error_msg("Error: Unsupported ElemType for UCDIO.");
00310 
00311       out_stream << e++ << " 0 " << type[etype] << "\t";
00312       // (*it)->write_ucd_connectivity(out_stream);
00313       (*it)->write_connectivity(out_stream, UCD);
00314     }
00315 
00316   return;
00317 }
00318 
00319 void UCDIO::write_nodal_data(const std::string& fname,
00320                              const std::vector<Number>&soln,
00321                              const std::vector<std::string>& names)
00322 {
00323   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
00324 
00325   const dof_id_type n_elem = mesh.n_elem();
00326 
00327   // Only processor 0 does the writing
00328   if (mesh.processor_id())
00329     return;
00330 
00331   std::ofstream out_stream(fname.c_str());
00332 
00333   // UCD doesn't work in 1D
00334   libmesh_assert (mesh.mesh_dimension() != 1);
00335 
00336   // Write header
00337   this->write_header(out_stream,mesh,n_elem,
00338                      cast_int<unsigned int>(names.size()));
00339 
00340   // Write the node coordinates
00341   this->write_nodes(out_stream,mesh);
00342 
00343   // Write the elements
00344   this->write_interior_elems(out_stream,mesh);
00345 
00346   // Write the solution
00347   this->write_soln(out_stream,mesh,names,soln);
00348 
00349   return;
00350 }
00351 
00352 void UCDIO::write_soln(std::ostream& out_stream, const MeshBase& mesh,
00353                        const std::vector<std::string>& names,
00354                        const std::vector<Number>&soln)
00355 {
00356   libmesh_assert (out_stream.good());
00357 
00358   // First write out how many variables and how many components per variable
00359   out_stream << names.size();
00360   for( unsigned int i = 0; i < names.size(); i++ )
00361     {
00362       libmesh_assert (out_stream.good());
00363       // Each named variable has only 1 component
00364       out_stream << " 1";
00365     }
00366   out_stream << std::endl;
00367 
00368   // Now write out variable names and units. Since we don't store units
00369   // We just write out dummy.
00370   for( std::vector<std::string>::const_iterator var = names.begin();
00371        var != names.end();
00372        ++var)
00373     {
00374       libmesh_assert (out_stream.good());
00375       out_stream << (*var) << ", dummy" << std::endl;
00376     }
00377 
00378   // Now, for each node, write out the solution variables
00379   std::size_t nv = names.size();
00380   for( std::size_t n = 1; // 1-based node number for UCD
00381        n <= mesh.n_nodes(); n++)
00382     {
00383       libmesh_assert (out_stream.good());
00384       out_stream << n;
00385 
00386       for( std::size_t var = 0; var != nv; var++ )
00387         {
00388           std::size_t idx = nv*(n-1) + var;
00389 
00390           out_stream << " " << soln[idx];
00391         }
00392       out_stream << std::endl;
00393     }
00394 
00395   return;
00396 }
00397 
00398 } // namespace libMesh