libMesh
Loading...
Searching...
No Matches
miscellaneous_ex6.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
19
20// <h1>Miscellaneous Example 6 - Meshing with LibMesh's TetGen and Triangle Interfaces</h1>
21// \author John W. Peterson
22// \date 2011
23//
24// LibMesh provides interfaces to both Triangle and TetGen for generating
25// Delaunay triangulations and tetrahedralizations in two and three dimensions
26// (respectively).
27
28// Local header files
29#include "libmesh/elem.h"
30#include "libmesh/face_tri3.h"
31#include "libmesh/mesh.h"
32#include "libmesh/mesh_generation.h"
33#include "libmesh/mesh_tetgen_interface.h"
34#include "libmesh/mesh_triangle_holes.h"
35#include "libmesh/mesh_triangle_interface.h"
36#include "libmesh/node.h"
37#include "libmesh/replicated_mesh.h"
38#include "libmesh/utility.h" // libmesh_map_find()
39
40// Bring in everything from the libMesh namespace
41using namespace libMesh;
42
43// Major functions called by main
46
47// Helper routine for tetrahedralize_domain(). Adds the points and elements
48// of a convex hull generated by TetGen to the input mesh
49void add_cube_convex_hull_to_mesh(MeshBase & mesh, Point lower_limit, Point upper_limit);
50
51
52
53
54// Begin the main program.
55int main (int argc, char ** argv)
56{
57 // Initialize libMesh and any dependent libraries, like in example 2.
58 LibMeshInit init (argc, argv);
59
60 libmesh_example_requires(2 <= LIBMESH_DIM, "2D support");
61
62 libMesh::out << "Triangulating an L-shaped domain with holes" << std::endl;
63
64 // 1.) 2D triangulation of L-shaped domain with three holes of different shape
65 triangulate_domain(init.comm());
66
67 libmesh_example_requires(3 <= LIBMESH_DIM, "3D support");
68
69 libMesh::out << "Tetrahedralizing a prismatic domain with a hole" << std::endl;
70
71 // 2.) 3D tetrahedralization of rectangular domain with hole.
72 tetrahedralize_domain(init.comm());
73
74 return 0;
75}
76
77
78
79
81{
82#ifdef LIBMESH_HAVE_TRIANGLE
83 // Use typedefs for slightly less typing.
84 typedef TriangleInterface::Hole Hole;
85 typedef TriangleInterface::PolygonHole PolygonHole;
86 typedef TriangleInterface::ArbitraryHole ArbitraryHole;
87
88 // Libmesh mesh that will eventually be created.
89 Mesh mesh(comm, 2);
90
91 // The points which make up the L-shape:
92 mesh.add_point(Point(0., 0.));
93 mesh.add_point(Point(0., -1.));
94 mesh.add_point(Point(-1., -1.));
95 mesh.add_point(Point(-1., 1.));
96 mesh.add_point(Point(1., 1.));
97 mesh.add_point(Point(1., 0.));
98
99 // Declare the TriangleInterface object. This is where
100 // we can set parameters of the triangulation and where the
101 // actual triangulate function lives.
103
104 // Customize the variables for the triangulation
105 t.desired_area() = .01;
106
107 // A Planar Straight Line Graph (PSLG) is essentially a list
108 // of segments which have to exist in the final triangulation.
109 // For an L-shaped domain, Triangle will compute the convex
110 // hull of boundary points if we do not specify the PSLG.
111 // The PSLG algorithm is also required for triangulating domains
112 // containing holes
113 t.triangulation_type() = TriangleInterface::PSLG;
114
115 // Turn on/off Laplacian mesh smoothing after generation.
116 // By default this is on.
117 t.smooth_after_generating() = true;
118
119 // Define holes...
120
121 // hole_1 is a circle (discretized by 50 points)
122 PolygonHole hole_1(Point(-0.5, 0.5), // center
123 0.25, // radius
124 50); // n. points
125
126 // hole_2 is itself a triangle
127 PolygonHole hole_2(Point(0.5, 0.5), // center
128 0.1, // radius
129 3); // n. points
130
131 // hole_3 is an ellipse of 100 points which we define here
132 Point ellipse_center(-0.5, -0.5);
133 const unsigned int n_ellipse_points=100;
134 std::vector<Point> ellipse_points(n_ellipse_points);
135 const Real
136 dtheta = 2*libMesh::pi / static_cast<Real>(n_ellipse_points),
137 a = .1,
138 b = .2;
139
140 for (unsigned int i=0; i<n_ellipse_points; ++i)
141 ellipse_points[i]= Point(ellipse_center(0)+a*cos(i*dtheta),
142 ellipse_center(1)+b*sin(i*dtheta));
143
144 ArbitraryHole hole_3(ellipse_center, ellipse_points);
145
146 // Create the vector of Hole*'s ...
147 std::vector<Hole *> holes;
148 holes.push_back(&hole_1);
149 holes.push_back(&hole_2);
150 holes.push_back(&hole_3);
151
152 // ... and attach it to the triangulator object
153 t.attach_hole_list(&holes);
154
155 // Triangulate!
156 t.triangulate();
157
158#ifdef LIBMESH_HAVE_EXODUS_API
159 // Write the result to file
160 mesh.write("delaunay_l_shaped_hole.e");
161#endif
162
163#else
164 // Avoid compiler warnings
165 libmesh_ignore(comm);
166#endif // LIBMESH_HAVE_TRIANGLE
167}
168
169
170
172{
173#ifdef LIBMESH_HAVE_TETGEN
174 // The algorithm is broken up into several steps:
175 // 1.) A convex hull is constructed for a rectangular hole.
176 // 2.) A convex hull is constructed for the domain exterior.
177 // 3.) Neighbor information is updated so TetGen knows there is a convex hull
178 // 4.) A vector of hole points is created.
179 // 5.) The domain is tetrahedralized, the mesh is written out, etc.
180
181 // The mesh we will eventually generate
182 ReplicatedMesh mesh(comm, 3);
183
184 // Lower and Upper bounding box limits for a rectangular hole within the unit cube.
185 Point hole_lower_limit(0.2, 0.2, 0.4);
186 Point hole_upper_limit(0.8, 0.8, 0.6);
187
188 // 1.) Construct a convex hull for the hole
189 add_cube_convex_hull_to_mesh(mesh, hole_lower_limit, hole_upper_limit);
190
191 // 2.) Generate elements comprising the outer boundary of the domain.
193 Point(0., 0., 0.),
194 Point(1., 1., 1.));
195
196 // 3.) Update neighbor information so that TetGen can verify there is a convex hull.
198
199 // 4.) Set up vector of hole points
200 std::vector<Point> hole(1);
201 hole[0] = Point(0.5*(hole_lower_limit + hole_upper_limit));
202
203 // 5.) Set parameters and tetrahedralize the domain
204
205 // 0 means "use TetGen default value"
206 double quality_constraint = 2.0;
207
208 // The volume constraint determines the max-allowed tetrahedral
209 // volume in the Mesh. TetGen will split cells which are larger than
210 // this size
211 double volume_constraint = 0.001;
212
213 // Construct the Delaunay tetrahedralization
215
216 // In debug mode, set the tetgen switches
217 // -V (verbose) and
218 // -CC (check consistency and constrained Delaunay)
219 // In optimized mode, only switch Q (quiet) is set.
220 // For more options, see tetgen website:
221 // (http://wias-berlin.de/software/tetgen/1.5/doc/manual/manual005.html#cmd-m)
222#ifdef DEBUG
223 t.set_switches("VCC");
224#endif
226 quality_constraint,
227 volume_constraint);
228
229 // Find neighbors, etc in preparation for writing out the Mesh
231
232 // Finally, write out the result
233#ifdef LIBMESH_HAVE_EXODUS_API
234 mesh.write("hole_3D.e");
235#endif
236
237#else
238 // Avoid compiler warnings
239 libmesh_ignore(comm);
240#endif // LIBMESH_HAVE_TETGEN
241}
242
243
244
245
246
247
248
249
250
251
252
253
254
256 Point lower_limit,
257 Point upper_limit)
258{
259#ifdef LIBMESH_HAVE_TETGEN
260 ReplicatedMesh cube_mesh(mesh.comm(), 3);
261
262 unsigned n_elem = 1;
263
265 n_elem, n_elem, n_elem, // n. elements in each direction
266 lower_limit(0), upper_limit(0),
267 lower_limit(1), upper_limit(1),
268 lower_limit(2), upper_limit(2),
269 HEX8);
270
271 // The pointset_convexhull() algorithm will ignore the Hex8s
272 // in the Mesh, and just construct the triangulation
273 // of the convex hull.
274 TetGenMeshInterface t(cube_mesh);
276
277 // Now add all nodes from the boundary of the cube_mesh to the input mesh.
278
279 // Map from "node id in cube_mesh" -> "node id in mesh". Initially inserted
280 // with a dummy value, later to be assigned a value by the input mesh.
281 std::map<unsigned, unsigned> node_id_map;
282 typedef std::map<unsigned, unsigned>::iterator iterator;
283
284 for (auto & elem : cube_mesh.element_ptr_range())
285 for (auto s : elem->side_index_range())
286 if (elem->neighbor_ptr(s) == nullptr)
287 {
288 // Add the node IDs of this side to the set
289 std::unique_ptr<Elem> side = elem->side_ptr(s);
290
291 for (auto n : side->node_index_range())
292 node_id_map.emplace(side->node_id(n), /*dummy_value=*/0);
293 }
294
295 // For each node in the map, insert it into the input mesh and keep
296 // track of the ID assigned.
297 for (iterator it=node_id_map.begin(); it != node_id_map.end(); ++it)
298 {
299 // Id of the node in the cube mesh
300 unsigned id = (*it).first;
301
302 // Pointer to node in the cube mesh
303 Node & old_node = cube_mesh.node_ref(id);
304
305 // Add geometric point to input mesh
306 Node * new_node = mesh.add_point (old_node);
307
308 // Track ID value of new_node in map
309 (*it).second = new_node->id();
310 }
311
312 // With the points added and the map data structure in place, we are
313 // ready to add each TRI3 element of the cube_mesh to the input Mesh
314 // with proper node assignments
315 for (auto & old_elem : cube_mesh.element_ptr_range())
316 if (old_elem->type() == TRI3)
317 {
318 Elem * new_elem = mesh.add_elem(Elem::build(TRI3));
319
320 // Assign nodes in new elements. Since this is an example,
321 // we'll do it in several steps.
322 for (auto i : old_elem->node_index_range())
323 {
324 // Mapping to node ID in input mesh
325 unsigned int new_node_id = libmesh_map_find(node_id_map, old_elem->node_id(i));
326
327 // Node pointer assigned from input mesh
328 new_elem->set_node(i, mesh.node_ptr(new_node_id));
329 }
330 }
331#else
332 // Avoid compiler warnings
333 libmesh_ignore(mesh, lower_limit, upper_limit);
334#endif // LIBMESH_HAVE_TETGEN
335}
dof_id_type id() const
Definition dof_object.h:819
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual Node *& set_node(const unsigned int i)
Definition elem.h:2567
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
This is the MeshBase class.
Definition mesh_base.h:81
virtual const Node & node_ref(const dof_id_type i) const
Definition mesh_base.h:745
virtual const Node * node_ptr(const dof_id_type i) const =0
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition mesh_base.C:824
virtual void write(const std::string &name) const =0
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true, const bool assert_valid=true)=0
Locate element face (edge in 2D) neighbors.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
A Node is like a Point, but with more information.
Definition node.h:55
const Parallel::Communicator & comm() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
Class TetGenMeshInterface provides an interface for tetrahedralization of meshes using the TetGen lib...
void triangulate_conformingDelaunayMesh_carvehole(const std::vector< Point > &holes, double quality_constraint=0., double volume_constraint=0.)
Method invokes TetGen library to compute a Delaunay tetrahedralization from the nodes point set.
void pointset_convexhull()
Method invokes TetGen library to compute a Delaunay tetrahedralization from the nodes point set.
void set_switches(std::string new_switches)
Method to set switches to tetgen, allowing for different behaviours.
A C++ interface between LibMesh and the Triangle library written by J.R.
virtual void triangulate() override
Internally, this calls Triangle's triangulate routine.
Another concrete instantiation of the hole, this one should be sufficiently general for most non-poly...
An abstract class for defining a 2-dimensional hole.
A concrete instantiation of the Hole class that describes polygonal (triangular, square,...
TriangulationType & triangulation_type()
Sets and/or gets the desired triangulation type.
bool & smooth_after_generating()
Sets/gets flag which tells whether to do two steps of Laplace mesh smoothing after generating the gri...
void attach_hole_list(const std::vector< Hole * > *holes)
Attaches a vector of Hole* pointers which will be meshed around.
Real & desired_area()
Sets and/or gets the desired triangle area.
static const Real b
MeshBase & mesh
void add_cube_convex_hull_to_mesh(MeshBase &mesh, Point lower_limit, Point upper_limit)
void triangulate_domain(const Parallel::Communicator &comm)
void tetrahedralize_domain(const Parallel::Communicator &comm)
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
The libMesh namespace provides an interface to certain functionality in the library.
void libmesh_ignore(const Args &...)
OStreamProxy out
const Real pi
.
Definition libmesh.h:292
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
int main()