$extrastylesheet
tetgen_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 // 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