$extrastylesheet
mesh_tetgen_wrapper.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 #include "libmesh/libmesh_config.h"
00019 #ifdef LIBMESH_HAVE_TETGEN
00020 
00021 // C++ includes
00022 #include <iostream>
00023 
00024 // Local includes
00025 #include "libmesh/libmesh_common.h"
00026 #include "libmesh/mesh_tetgen_wrapper.h"
00027 
00028 namespace libMesh
00029 {
00030 //
00031 // TetGenWrapper member functions
00032 //
00033 
00034 TetGenWrapper::TetGenWrapper()
00035 {
00036   tetgen_output = new tetgenio;
00037 
00038   this->tetgen_data.mesh_dim                = 3;
00039   this->tetgen_data.numberofpointattributes = 0;
00040   this->tetgen_data.firstnumber             = 0;
00041 }
00042 
00043 
00044 
00045 TetGenWrapper::~TetGenWrapper()
00046 {
00047   delete tetgen_output;
00048 }
00049 
00050 
00051 
00052 void TetGenWrapper::set_node(unsigned i, REAL x, REAL y, REAL z)
00053 {
00054   unsigned index = i*3;
00055   tetgen_data.pointlist[index++] = x;
00056   tetgen_data.pointlist[index++] = y;
00057   tetgen_data.pointlist[index++] = z;
00058 }
00059 
00060 
00061 
00062 void TetGenWrapper::set_hole(unsigned i, REAL x, REAL y, REAL z)
00063 {
00064   unsigned index = i*3;
00065   tetgen_data.holelist[index++] = x;
00066   tetgen_data.holelist[index++] = y;
00067   tetgen_data.holelist[index++] = z;
00068 }
00069 
00070 
00071 
00072 void TetGenWrapper::set_numberofpoints(int i)
00073 {
00074   // This is an int in tetgen, so use an int here even though it should be unsigned
00075   tetgen_data.numberofpoints = i;
00076 }
00077 
00078 
00079 
00080 void TetGenWrapper::get_output_node(unsigned i, REAL& x, REAL& y, REAL& z)
00081 {
00082   // Bounds checking...
00083   if (i >= static_cast<unsigned>(tetgen_output->numberofpoints))
00084     libmesh_error_msg("Error, requested point "        \
00085                       << i                             \
00086                       << ", but there are only "       \
00087                       << tetgen_output->numberofpoints \
00088                       << " points available.");
00089 
00090   x = tetgen_output->pointlist[3*i];
00091   y = tetgen_output->pointlist[3*i+1];
00092   z = tetgen_output->pointlist[3*i+2];
00093 }
00094 
00095 
00096 
00097 int TetGenWrapper::get_numberoftetrahedra()
00098 {
00099   return tetgen_output->numberoftetrahedra;
00100 }
00101 
00102 
00103 
00104 int TetGenWrapper::get_numberoftrifaces()
00105 {
00106   return tetgen_output->numberoftrifaces;
00107 }
00108 
00109 
00110 
00111 int TetGenWrapper::get_numberofpoints()
00112 {
00113   return tetgen_output->numberofpoints;
00114 }
00115 
00116 
00117 
00118 int TetGenWrapper::get_element_node(unsigned i, unsigned j)
00119 {
00120   return tetgen_output->tetrahedronlist[i*4+j];
00121 }
00122 
00123 
00124 
00125 int TetGenWrapper::get_triface_node(unsigned i, unsigned j)
00126 {
00127   return tetgen_output->trifacelist[i*3+j];
00128 }
00129 
00130 
00131 
00132 REAL TetGenWrapper::get_element_attribute(unsigned i)
00133 {
00134   libmesh_assert(tetgen_output->numberoftetrahedronattributes>0);
00135   return tetgen_output->tetrahedronattributelist[tetgen_output->numberoftetrahedronattributes*i];
00136 }
00137 
00138 
00139 
00140 void TetGenWrapper::allocate_pointlist(int numofpoints)
00141 {
00142   // This is stored as an int in tetgen, so we store it that way as well.
00143   this->set_numberofpoints(numofpoints);
00144 
00145   // Don't try to allocate an array of size zero, this is not portable...
00146   if (this->tetgen_data.numberofpoints > 0)
00147     {
00148       // Is there previously-allocated memory here?
00149       if (this->tetgen_data.pointlist != NULL)
00150         libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
00151 
00152       // We allocate memory here, the tetgenio destructor will delete it.
00153       this->tetgen_data.pointlist = new REAL[this->tetgen_data.numberofpoints * 3];
00154     }
00155 }
00156 
00157 
00158 
00159 void TetGenWrapper::set_switches(const std::string& s)
00160 {
00161   // A temporary buffer for passing to the C API, it requires
00162   // a char*, not a const char*...
00163   char buffer[256];
00164 
00165   // Make sure char buffer has enough room
00166   if (s.size() >= sizeof(buffer)-1)
00167     libmesh_error_msg("Fixed size buffer of length "                  \
00168                       << sizeof(buffer)                               \
00169                       << " not large enough to hold TetGen switches.");
00170 
00171   // Copy the string, don't forget to NULL-terminate!
00172   buffer[ s.copy( buffer , sizeof( buffer ) - 1 ) ] = '\0' ;
00173 
00174   if (!tetgen_be.parse_commandline(buffer))
00175     libMesh::out << "TetGen replies: Wrong switches!" << std::endl;
00176 }
00177 
00178 
00179 
00180 void TetGenWrapper::run_tetgen()
00181 {
00182   // Call tetrahedralize from the TetGen library.
00183   tetrahedralize(&tetgen_be, &tetgen_data, tetgen_output);
00184 }
00185 
00186 
00187 
00188 void TetGenWrapper::set_numberoffacets(int i)
00189 {
00190   // This is stored as an int in TetGen
00191   this->tetgen_data.numberoffacets = i;
00192 }
00193 
00194 
00195 
00196 void TetGenWrapper::set_numberofholes(int i)
00197 {
00198   // This is stored as an int in TetGen
00199   this->tetgen_data.numberofholes = i;
00200 }
00201 
00202 
00203 
00204 void TetGenWrapper::set_numberofregions(int i)
00205 {
00206   // This is stored as an int in TetGen
00207   this->tetgen_data.numberofregions = i;
00208 }
00209 
00210 
00211 
00212 void TetGenWrapper::allocate_facetlist(int numoffacets, int numofholes)
00213 {
00214   // These are both stored as ints in TetGen
00215   this->set_numberoffacets(numoffacets);
00216   this->set_numberofholes(numofholes);
00217 
00218   // Don't try to allocate an array of size zero, this is not portable...
00219   if (this->tetgen_data.numberoffacets > 0)
00220     {
00221       // Is there previously-allocated memory here?
00222       if (this->tetgen_data.facetlist != NULL)
00223         libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
00224 
00225       // We allocate memory here, the tetgenio destructor cleans it up.
00226       this->tetgen_data.facetlist = new tetgenio::facet[this->tetgen_data.numberoffacets];
00227 
00228       for (int i=0; i<numoffacets; i++)
00229         this->tetgen_data.init(&(this->tetgen_data.facetlist[i]));
00230     }
00231 
00232 
00233   // Don't try to allocate an array of size zero, this is not portable...
00234   if (this->tetgen_data.numberofholes > 0)
00235     {
00236       // Is there previously-allocated memory here?
00237       if (this->tetgen_data.holelist != NULL)
00238         libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
00239 
00240       this->tetgen_data.holelist = new REAL[this->tetgen_data.numberofholes * 3];
00241     }
00242 }
00243 
00244 
00245 
00246 void TetGenWrapper::allocate_regionlist(int numofregions)
00247 {
00248   this->set_numberofregions(numofregions);
00249 
00250   // Don't try to allocate an array of size zero, this is not portable...
00251   if (this->tetgen_data.numberofregions > 0)
00252     {
00253       // Is there previously-allocated memory here?
00254       if (this->tetgen_data.regionlist != NULL)
00255         libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
00256 
00257       // We allocate memory here, the tetgenio destructor cleans it up.
00258       this->tetgen_data.regionlist = new REAL[this->tetgen_data.numberofregions * 5];
00259     }
00260 }
00261 
00262 
00263 
00264 void TetGenWrapper::set_facet_numberofpolygons(unsigned i, int num)
00265 {
00266   // numberofpolygons is stored as an int in TetGen
00267   this->tetgen_data.facetlist[i].numberofpolygons = num;
00268 }
00269 
00270 
00271 
00272 void TetGenWrapper::set_facet_numberofholes(unsigned i, int num)
00273 {
00274   // numberofholes is stored as an int in TetGen
00275   this->tetgen_data.facetlist[i].numberofholes = num;
00276 }
00277 
00278 
00279 
00280 
00281 void TetGenWrapper::allocate_facet_polygonlist(unsigned i, int numofpolygons)
00282 {
00283   this->set_facet_numberofpolygons(i, numofpolygons);
00284   this->set_facet_numberofholes(i, 0);
00285 
00286   // Don't try to create an array of size zero, this isn't portable
00287   if (numofpolygons > 0)
00288     {
00289       // Is there previously-allocated memory here?
00290       if (this->tetgen_data.facetlist[i].polygonlist != NULL)
00291         libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
00292 
00293       // We allocate memory here, the tetgenio destructor cleans it up.
00294       this->tetgen_data.facetlist[i].polygonlist = new tetgenio::polygon[numofpolygons];
00295 
00296       for (int j=0; j<this->tetgen_data.facetlist[i].numberofpolygons; j++)
00297         this->tetgen_data.init(&(this->tetgen_data.facetlist[i].polygonlist[j]));
00298     }
00299 }
00300 
00301 
00302 
00303 void TetGenWrapper::set_polygon_numberofvertices(unsigned i, unsigned j, int num)
00304 {
00305   // numberofvertices is stored as an int in TetGen
00306   this->tetgen_data.facetlist[i].polygonlist[j].numberofvertices = num;
00307 }
00308 
00309 
00310 
00311 void TetGenWrapper::allocate_polygon_vertexlist(unsigned i, unsigned j, int numofvertices)
00312 {
00313   this->set_polygon_numberofvertices(i, j, numofvertices);
00314 
00315   // Don't try to create an array of size zero, this isn't portable
00316   if (numofvertices > 0)
00317     {
00318       // Is there previously-allocated memory here?
00319       if (this->tetgen_data.facetlist[i].polygonlist[j].vertexlist != NULL)
00320         libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
00321 
00322       // We allocate memory here, the tetgenio destructor cleans it up.
00323       this->tetgen_data.facetlist[i].polygonlist[j].vertexlist = new int[numofvertices];
00324     }
00325 }
00326 
00327 
00328 
00329 
00330 void TetGenWrapper::set_vertex(unsigned i, unsigned j, unsigned k, int nodeindex)
00331 {
00332   // vertexlist entries are stored as ints in TetGen
00333   this->tetgen_data.facetlist[i].polygonlist[j].vertexlist[k] = nodeindex;
00334 }
00335 
00336 
00337 
00338 void TetGenWrapper::set_region(unsigned i, REAL x, REAL y, REAL z,
00339                                REAL attribute, REAL vol_constraint)
00340 {
00341   unsigned index = i*5;
00342   tetgen_data.regionlist[index++] = x;
00343   tetgen_data.regionlist[index++] = y;
00344   tetgen_data.regionlist[index++] = z;
00345   tetgen_data.regionlist[index++] = attribute;
00346   tetgen_data.regionlist[index++] = vol_constraint;
00347 }
00348 
00349 } // namespace libMesh
00350 
00351 
00352 #endif // LIBMESH_HAVE_TETGEN