$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 // Local includes 00023 #include "libmesh/tetgen_io.h" 00024 #include "libmesh/mesh_base.h" 00025 #include "libmesh/cell_tet4.h" 00026 #include "libmesh/cell_tet10.h" 00027 #include "libmesh/mesh_data.h" 00028 00029 namespace libMesh 00030 { 00031 00032 // ------------------------------------------------------------ 00033 // TetgenIO class members 00034 void TetGenIO::read (const std::string& name) 00035 { 00036 // This is a serial-only process for now; 00037 // the Mesh should be read on processor 0 and 00038 // broadcast later 00039 libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0); 00040 00041 std::string name_node, name_ele, dummy; 00042 00043 // tetgen only works in 3D 00044 MeshInput<MeshBase>::mesh().set_mesh_dimension(3); 00045 00046 #if LIBMESH_DIM < 3 00047 libmesh_error_msg("Cannot open dimension 3 mesh file when configured without 3D support."); 00048 #endif 00049 00050 // Check name for *.node or *.ele extension. 00051 // Set std::istream for node_stream and ele_stream. 00052 // 00053 if (name.rfind(".node") < name.size()) 00054 { 00055 name_node = name; 00056 dummy = name; 00057 std::size_t position = dummy.rfind(".node"); 00058 name_ele = dummy.replace(position, 5, ".ele"); 00059 } 00060 else if (name.rfind(".ele") < name.size()) 00061 { 00062 name_ele = name; 00063 dummy = name; 00064 std::size_t position = dummy.rfind(".ele"); 00065 name_node = dummy.replace(position, 4, ".node"); 00066 } 00067 else 00068 libmesh_error_msg("ERROR: Unrecognized file name: " << name); 00069 00070 00071 00072 // Set the streams from which to read in 00073 std::ifstream node_stream (name_node.c_str()); 00074 std::ifstream ele_stream (name_ele.c_str()); 00075 00076 if ( !node_stream.good() || !ele_stream.good() ) 00077 libmesh_error_msg("Error while opening either " \ 00078 << name_node \ 00079 << " or " \ 00080 << name_ele); 00081 00082 libMesh::out<< "TetGenIO found the tetgen files to read " <<std::endl; 00083 00084 // Skip the comment lines at the beginning 00085 this->skip_comment_lines (node_stream, '#'); 00086 this->skip_comment_lines (ele_stream, '#'); 00087 00088 // Read the nodes and elements from the streams 00089 this->read_nodes_and_elem (node_stream, ele_stream); 00090 libMesh::out<< "TetGenIO read in nodes and elements " <<std::endl; 00091 } 00092 00093 00094 00095 void TetGenIO::read_nodes_and_elem (std::istream& node_stream, 00096 std::istream& ele_stream) 00097 { 00098 _num_nodes = 0; 00099 _num_elements = 0; 00100 00101 // Read all the datasets. 00102 this->node_in (node_stream); 00103 this->element_in (ele_stream); 00104 00105 // Tell the MeshData object that we are finished 00106 // reading data. 00107 if (this->_mesh_data != NULL) 00108 this->_mesh_data->close_foreign_id_maps (); 00109 00110 // some more clean-up 00111 _assign_nodes.clear(); 00112 } 00113 00114 00115 00116 //---------------------------------------------------------------------- 00117 // Function to read in the node table. 00118 void TetGenIO::node_in (std::istream& node_stream) 00119 { 00120 // Check input buffer 00121 libmesh_assert (node_stream.good()); 00122 00123 // Get a reference to the mesh 00124 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00125 00126 unsigned int dimension=0, nAttributes=0, BoundaryMarkers=0; 00127 00128 node_stream >> _num_nodes // Read the number of nodes from the stream 00129 >> dimension // Read the dimension from the stream 00130 >> nAttributes // Read the number of attributes from stream 00131 >> BoundaryMarkers; // Read if or not boundary markers are included in *.node (0 or 1) 00132 00133 // Read the nodal coordinates from the node_stream (*.node file). 00134 unsigned int node_lab=0; 00135 Point xyz; 00136 Real dummy; 00137 00138 // If present, make room for node attributes to be stored. 00139 this->node_attributes.resize(nAttributes); 00140 for (unsigned i=0; i<nAttributes; ++i) 00141 this->node_attributes[i].resize(_num_nodes); 00142 00143 00144 for (unsigned int i=0; i<_num_nodes; i++) 00145 { 00146 // Check input buffer 00147 libmesh_assert (node_stream.good()); 00148 00149 node_stream >> node_lab // node number 00150 >> xyz(0) // x-coordinate value 00151 >> xyz(1) // y-coordinate value 00152 >> xyz(2); // z-coordinate value 00153 00154 // Read and store attributes from the stream. 00155 for (unsigned int j=0; j<nAttributes; j++) 00156 node_stream >> node_attributes[j][i]; 00157 00158 // Read (and discard) boundary marker if BoundaryMarker=1. 00159 // TODO: should we store this somehow? 00160 if (BoundaryMarkers == 1) 00161 node_stream >> dummy; 00162 00163 // Store the new position of the node under its label. 00164 //_assign_nodes.insert (std::make_pair(node_lab,i)); 00165 _assign_nodes[node_lab] = i; 00166 00167 // do this irrespective whether MeshData exists 00168 Node* newnode = mesh.add_point(xyz, i); 00169 00170 // Add node to the nodes vector & 00171 // tell the MeshData object the foreign node id. 00172 if (this->_mesh_data != NULL) 00173 this->_mesh_data->add_foreign_node_id (newnode, node_lab); 00174 } 00175 } 00176 00177 00178 00179 //---------------------------------------------------------------------- 00180 // Function to read in the element table. 00181 void TetGenIO::element_in (std::istream& ele_stream) 00182 { 00183 // Check input buffer 00184 libmesh_assert (ele_stream.good()); 00185 00186 // Get a reference to the mesh 00187 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00188 00189 // Read the elements from the ele_stream (*.ele file). 00190 unsigned int element_lab=0, n_nodes=0, nAttri=0; 00191 00192 ele_stream >> _num_elements // Read the number of tetrahedrons from the stream. 00193 >> n_nodes // Read the number of nodes per tetrahedron from the stream (defaults to 4). 00194 >> nAttri; // Read the number of attributes from stream. 00195 00196 // Vector that assigns element nodes to their correct position. 00197 // TetGen is normaly 0-based 00198 // (right now this is strictly not necessary since it is the identity map, 00199 // but in the future TetGen could change their numbering scheme.) 00200 static const unsigned int assign_elm_nodes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 00201 00202 // If present, make room for element attributes to be stored. 00203 this->element_attributes.resize(nAttri); 00204 for (unsigned i=0; i<nAttri; ++i) 00205 this->element_attributes[i].resize(_num_elements); 00206 00207 for (dof_id_type i=0; i<_num_elements; i++) 00208 { 00209 libmesh_assert (ele_stream.good()); 00210 00211 // TetGen only supports Tet4 and Tet10 elements. 00212 Elem* elem; 00213 00214 if (n_nodes==4) 00215 elem = new Tet4; 00216 00217 else if (n_nodes==10) 00218 elem = new Tet10; 00219 00220 else 00221 libmesh_error_msg("Elements with " << n_nodes << " nodes are not supported in the LibMesh tetgen module."); 00222 00223 elem->set_id(i); 00224 00225 mesh.add_elem (elem); 00226 00227 libmesh_assert(elem); 00228 libmesh_assert_equal_to (elem->n_nodes(), n_nodes); 00229 00230 // Read the element label 00231 ele_stream >> element_lab; 00232 00233 // Add the element to the mesh & 00234 // tell the MeshData object the foreign element id 00235 if (this->_mesh_data != NULL) 00236 this->_mesh_data->add_foreign_elem_id (elem, element_lab); 00237 00238 // Read node labels 00239 for (dof_id_type j=0; j<n_nodes; j++) 00240 { 00241 dof_id_type node_label; 00242 ele_stream >> node_label; 00243 00244 // Assign node to element 00245 elem->set_node(assign_elm_nodes[j]) = 00246 mesh.node_ptr(_assign_nodes[node_label]); 00247 } 00248 00249 // Read and store attributes from the stream. 00250 for (unsigned int j=0; j<nAttri; j++) 00251 ele_stream >> this->element_attributes[j][i]; 00252 } 00253 } 00254 00255 00260 void TetGenIO::write (const std::string& fname) 00261 { 00262 // libmesh_assert three dimensions (should be extended later) 00263 libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().mesh_dimension(), 3); 00264 00265 if (!(fname.rfind(".poly") < fname.size())) 00266 libmesh_error_msg("ERROR: Unrecognized file name: " << fname); 00267 00268 // Open the output file stream 00269 std::ofstream out_stream (fname.c_str()); 00270 00271 // Make sure it opened correctly 00272 if (!out_stream.good()) 00273 libmesh_file_error(fname.c_str()); 00274 00275 // Get a reference to the mesh 00276 const MeshBase& mesh = MeshOutput<MeshBase>::mesh(); 00277 00278 // Begin interfacing with the .poly file 00279 { 00280 // header: 00281 out_stream << "# poly file output generated by libmesh\n" 00282 << mesh.n_nodes() << " 3 0 0\n"; 00283 00284 // write the nodes: 00285 for (dof_id_type v=0; v<mesh.n_nodes(); v++) 00286 out_stream << v << " " 00287 << mesh.point(v)(0) << " " 00288 << mesh.point(v)(1) << " " 00289 << mesh.point(v)(2) << "\n"; 00290 } 00291 00292 { 00293 // write the connectivity: 00294 out_stream << "# Facets:\n" 00295 << mesh.n_elem() << " 0\n"; 00296 00297 // const_active_elem_iterator it (mesh.elements_begin()); 00298 // const const_active_elem_iterator end(mesh.elements_end()); 00299 00300 MeshBase::const_element_iterator it = mesh.active_elements_begin(); 00301 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 00302 00303 for ( ; it != end; ++it) 00304 out_stream << "1\n3 " // no. of facet polygons 00305 // << (*it)->n_nodes() << " " 00306 << (*it)->node(0) << " " 00307 << (*it)->node(1) << " " 00308 << (*it)->node(2) << "\n"; 00309 } 00310 00311 // end of the file 00312 out_stream << "0\n"; // no holes output! 00313 out_stream << "\n\n# end of file\n"; 00314 } 00315 00316 } // namespace libMesh