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