mesh_tetgen_wrapper.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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"
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 != 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 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 != 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 != 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 != 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 != 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 != 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)
REAL get_element_attribute(unsigned i)
void set_facet_numberofpolygons(unsigned i, int num)
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)
void set_facet_numberofholes(unsigned i, int num)
void set_vertex(unsigned i, unsigned j, unsigned k, int nodeindex)
void allocate_polygon_vertexlist(unsigned i, unsigned j, int numofvertices)
void allocate_pointlist(int numofpoints)
void set_node(unsigned i, REAL x, REAL y, REAL z)
void set_switches(const std::string &s)
std::unique_ptr< tetgenio > tetgen_output
void allocate_facet_polygonlist(unsigned i, int numofpolygons)
void set_hole(unsigned i, REAL x, REAL y, REAL z)
void allocate_regionlist(int numofregions)
void set_region(unsigned i, REAL x, REAL y, REAL z, REAL attribute, REAL vol_constraint)
void allocate_facetlist(int numoffacets, int numofholes)
OStreamProxy out(std::cout)