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