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