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