libMesh
mesh_tetgen_wrapper.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 #include "libmesh/libmesh_config.h"
19 #ifdef LIBMESH_HAVE_TETGEN
20 
21 // C++ includes
22 #include <iostream>
23 
24 // Local includes
25 #include "libmesh/libmesh_common.h"
26 #include "libmesh/mesh_tetgen_wrapper.h"
27 
28 namespace libMesh
29 {
30 
32  tetgen_output(new tetgenio)
33 {
34  this->tetgen_data.mesh_dim = 3;
35  this->tetgen_data.numberofpointattributes = 0;
36  this->tetgen_data.firstnumber = 0;
37 }
38 
39 
40 
42 {
43 }
44 
45 
46 
47 void TetGenWrapper::set_node(unsigned i, REAL x, REAL y, REAL z)
48 {
49  unsigned index = i*3;
50  tetgen_data.pointlist[index++] = x;
51  tetgen_data.pointlist[index++] = y;
52  tetgen_data.pointlist[index++] = z;
53 }
54 
55 
56 
57 void TetGenWrapper::set_hole(unsigned i, REAL x, REAL y, REAL z)
58 {
59  unsigned index = i*3;
60  tetgen_data.holelist[index++] = x;
61  tetgen_data.holelist[index++] = y;
62  tetgen_data.holelist[index++] = z;
63 }
64 
65 
66 
68 {
69  // This is an int in tetgen, so use an int here even though it should be unsigned
70  tetgen_data.numberofpoints = i;
71 }
72 
73 
74 
75 void TetGenWrapper::get_output_node(unsigned i, REAL & x, REAL & y, REAL & z)
76 {
77  // Bounds checking...
78  if (i >= static_cast<unsigned>(tetgen_output->numberofpoints))
79  libmesh_error_msg("Error, requested point " \
80  << i \
81  << ", but there are only " \
82  << tetgen_output->numberofpoints \
83  << " points available.");
84 
85  x = tetgen_output->pointlist[3*i];
86  y = tetgen_output->pointlist[3*i+1];
87  z = tetgen_output->pointlist[3*i+2];
88 }
89 
90 
91 
93 {
94  return tetgen_output->numberoftetrahedra;
95 }
96 
97 
98 
100 {
101  return tetgen_output->numberoftrifaces;
102 }
103 
104 
105 
107 {
108  return tetgen_output->numberofpoints;
109 }
110 
111 
112 
113 int TetGenWrapper::get_element_node(unsigned i, unsigned j)
114 {
115  return tetgen_output->tetrahedronlist[i*4+j];
116 }
117 
118 
119 
120 int TetGenWrapper::get_triface_node(unsigned i, unsigned j)
121 {
122  return tetgen_output->trifacelist[i*3+j];
123 }
124 
125 
126 
128 {
129  libmesh_assert(tetgen_output->numberoftetrahedronattributes>0);
130  return tetgen_output->tetrahedronattributelist[tetgen_output->numberoftetrahedronattributes*i];
131 }
132 
133 
134 
136 {
137  // This is stored as an int in tetgen, so we store it that way as well.
138  this->set_numberofpoints(numofpoints);
139 
140  // Don't try to allocate an array of size zero, this is not portable...
141  if (this->tetgen_data.numberofpoints > 0)
142  {
143  // Is there previously-allocated memory here?
144  if (this->tetgen_data.pointlist != libmesh_nullptr)
145  libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
146 
147  // We allocate memory here, the tetgenio destructor will delete it.
148  this->tetgen_data.pointlist = new REAL[this->tetgen_data.numberofpoints * 3];
149  }
150 }
151 
152 
153 
154 void TetGenWrapper::set_switches(const std::string & s)
155 {
156  // A temporary buffer for passing to the C API, it requires
157  // a char *, not a const char *...
158  char buffer[256];
159 
160  // Make sure char buffer has enough room
161  if (s.size() >= sizeof(buffer)-1)
162  libmesh_error_msg("Fixed size buffer of length " \
163  << sizeof(buffer) \
164  << " not large enough to hold TetGen switches.");
165 
166  // Copy the string, don't forget to NULL-terminate!
167  buffer[ s.copy( buffer , sizeof( buffer ) - 1 ) ] = '\0' ;
168 
169  if (!tetgen_be.parse_commandline(buffer))
170  libMesh::out << "TetGen replies: Wrong switches!" << std::endl;
171 }
172 
173 
174 
176 {
177  // Call tetrahedralize from the TetGen library.
178  tetrahedralize(&tetgen_be, &tetgen_data, tetgen_output.get());
179 }
180 
181 
182 
184 {
185  // This is stored as an int in TetGen
186  this->tetgen_data.numberoffacets = i;
187 }
188 
189 
190 
192 {
193  // This is stored as an int in TetGen
194  this->tetgen_data.numberofholes = i;
195 }
196 
197 
198 
200 {
201  // This is stored as an int in TetGen
202  this->tetgen_data.numberofregions = i;
203 }
204 
205 
206 
207 void TetGenWrapper::allocate_facetlist(int numoffacets, int numofholes)
208 {
209  // These are both stored as ints in TetGen
210  this->set_numberoffacets(numoffacets);
211  this->set_numberofholes(numofholes);
212 
213  // Don't try to allocate an array of size zero, this is not portable...
214  if (this->tetgen_data.numberoffacets > 0)
215  {
216  // Is there previously-allocated memory here?
217  if (this->tetgen_data.facetlist != libmesh_nullptr)
218  libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
219 
220  // We allocate memory here, the tetgenio destructor cleans it up.
221  this->tetgen_data.facetlist = new tetgenio::facet[this->tetgen_data.numberoffacets];
222 
223  for (int i=0; i<numoffacets; i++)
224  this->tetgen_data.init(&(this->tetgen_data.facetlist[i]));
225  }
226 
227 
228  // Don't try to allocate an array of size zero, this is not portable...
229  if (this->tetgen_data.numberofholes > 0)
230  {
231  // Is there previously-allocated memory here?
232  if (this->tetgen_data.holelist != libmesh_nullptr)
233  libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
234 
235  this->tetgen_data.holelist = new REAL[this->tetgen_data.numberofholes * 3];
236  }
237 }
238 
239 
240 
242 {
243  this->set_numberofregions(numofregions);
244 
245  // Don't try to allocate an array of size zero, this is not portable...
246  if (this->tetgen_data.numberofregions > 0)
247  {
248  // Is there previously-allocated memory here?
249  if (this->tetgen_data.regionlist != libmesh_nullptr)
250  libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
251 
252  // We allocate memory here, the tetgenio destructor cleans it up.
253  this->tetgen_data.regionlist = new REAL[this->tetgen_data.numberofregions * 5];
254  }
255 }
256 
257 
258 
260 {
261  // numberofpolygons is stored as an int in TetGen
262  this->tetgen_data.facetlist[i].numberofpolygons = num;
263 }
264 
265 
266 
267 void TetGenWrapper::set_facet_numberofholes(unsigned i, int num)
268 {
269  // numberofholes is stored as an int in TetGen
270  this->tetgen_data.facetlist[i].numberofholes = num;
271 }
272 
273 
274 
275 
276 void TetGenWrapper::allocate_facet_polygonlist(unsigned i, int numofpolygons)
277 {
278  this->set_facet_numberofpolygons(i, numofpolygons);
279  this->set_facet_numberofholes(i, 0);
280 
281  // Don't try to create an array of size zero, this isn't portable
282  if (numofpolygons > 0)
283  {
284  // Is there previously-allocated memory here?
285  if (this->tetgen_data.facetlist[i].polygonlist != libmesh_nullptr)
286  libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
287 
288  // We allocate memory here, the tetgenio destructor cleans it up.
289  this->tetgen_data.facetlist[i].polygonlist = new tetgenio::polygon[numofpolygons];
290 
291  for (int j=0; j<this->tetgen_data.facetlist[i].numberofpolygons; j++)
292  this->tetgen_data.init(&(this->tetgen_data.facetlist[i].polygonlist[j]));
293  }
294 }
295 
296 
297 
298 void TetGenWrapper::set_polygon_numberofvertices(unsigned i, unsigned j, int num)
299 {
300  // numberofvertices is stored as an int in TetGen
301  this->tetgen_data.facetlist[i].polygonlist[j].numberofvertices = num;
302 }
303 
304 
305 
306 void TetGenWrapper::allocate_polygon_vertexlist(unsigned i, unsigned j, int numofvertices)
307 {
308  this->set_polygon_numberofvertices(i, j, numofvertices);
309 
310  // Don't try to create an array of size zero, this isn't portable
311  if (numofvertices > 0)
312  {
313  // Is there previously-allocated memory here?
314  if (this->tetgen_data.facetlist[i].polygonlist[j].vertexlist != libmesh_nullptr)
315  libmesh_error_msg("Cannot allocate on top of previously allocated memory!");
316 
317  // We allocate memory here, the tetgenio destructor cleans it up.
318  this->tetgen_data.facetlist[i].polygonlist[j].vertexlist = new int[numofvertices];
319  }
320 }
321 
322 
323 
324 
325 void TetGenWrapper::set_vertex(unsigned i, unsigned j, unsigned k, int nodeindex)
326 {
327  // vertexlist entries are stored as ints in TetGen
328  this->tetgen_data.facetlist[i].polygonlist[j].vertexlist[k] = nodeindex;
329 }
330 
331 
332 
333 void TetGenWrapper::set_region(unsigned i, REAL x, REAL y, REAL z,
334  REAL attribute, REAL vol_constraint)
335 {
336  unsigned index = i*5;
337  tetgen_data.regionlist[index++] = x;
338  tetgen_data.regionlist[index++] = y;
339  tetgen_data.regionlist[index++] = z;
340  tetgen_data.regionlist[index++] = attribute;
341  tetgen_data.regionlist[index++] = vol_constraint;
342 }
343 
344 } // namespace libMesh
345 
346 
347 #endif // LIBMESH_HAVE_TETGEN
void set_polygon_numberofvertices(unsigned i, unsigned j, int num)
Sets the number of vertices for polygon j, facet i in the TetGen input.
void set_numberofregions(int i)
Sets the number of regions in the TetGen input.
void set_numberofpoints(int i)
Sets the number of nodes in the TetGen input.
REAL get_element_attribute(unsigned i)
void set_facet_numberofpolygons(unsigned i, int num)
Sets the number of polygons for facet i in the TetGen input.
int get_element_node(unsigned i, unsigned j)
void get_output_node(unsigned i, REAL &x, REAL &y, REAL &z)
int get_triface_node(unsigned i, unsigned j)
UniquePtr< tetgenio > tetgen_output
TetGen output structure.
const class libmesh_nullptr_t libmesh_nullptr
void set_facet_numberofholes(unsigned i, int num)
Sets the number of holes for facet i in the TetGen input.
void set_numberoffacets(int i)
Sets the number of facets in the TetGen input.
void set_vertex(unsigned i, unsigned j, unsigned k, int nodeindex)
Sets index of ith facet, jth polygon, kth vertex in the TetGen input.
The libMesh namespace provides an interface to certain functionality in the library.
void allocate_polygon_vertexlist(unsigned i, unsigned j, int numofvertices)
Allocates memory, sets number of vertices for polygon j, facet i in the TetGen input.
void allocate_pointlist(int numofpoints)
Allocates memory, sets number of nodes in the TetGen input.
libmesh_assert(j)
PetscErrorCode Vec x
void set_node(unsigned i, REAL x, REAL y, REAL z)
Sets coordinates of point i in the TetGen input.
tetgenio tetgen_data
TetGen input structure.
void run_tetgen()
Starts the triangulation.
void set_switches(const std::string &s)
Method to set TetGen commandline switches -p Tetrahedralizes a piecewise linear complex (...
void allocate_facet_polygonlist(unsigned i, int numofpolygons)
Allocates memory, sets number of polygons for facet i in the TetGen input.
void set_hole(unsigned i, REAL x, REAL y, REAL z)
Sets coordinates of hole i in the TetGen input.
void set_numberofholes(int i)
Sets the number of holes in the TetGen input.
void allocate_regionlist(int numofregions)
Allocates memory, sets number of regions in the TetGen input.
OStreamProxy out
tetgenbehavior tetgen_be
TetGen control class (from the TetGen library).
void set_region(unsigned i, REAL x, REAL y, REAL z, REAL attribute, REAL vol_constraint)
Sets coordinates, attribute, and volume constraint for region i in the TetGen input.
void allocate_facetlist(int numoffacets, int numofholes)
Allocates memory, sets number of facets, holes in the TetGen input.