libMesh
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
libMesh::ElemCutter Class Reference

This class implements cutting a single element into a collection of subelements. More...

#include <elem_cutter.h>

Public Member Functions

 ElemCutter ()
 Constructor.
 
 ~ElemCutter ()
 Destructor.
 
bool is_inside (const Elem &elem, const std::vector< Real > &vertex_distance_func) const
 
bool is_outside (const Elem &elem, const std::vector< Real > &vertex_distance_func) const
 
bool is_cut (const Elem &elem, const std::vector< Real > &vertex_distance_func) const
 
void operator() (const Elem &elem_in, const std::vector< Real > &vertex_distance_func)
 This function implements cutting an element by a signed distance function.
 
const std::vector< Elem const * > & inside_elements () const
 
const std::vector< Elem const * > & outside_elements () const
 

Protected Member Functions

void find_intersection_points (const Elem &elem, const std::vector< Real > &vertex_distance_func)
 Finds the points where the cutting surface intersects the element edges.
 
void cut_1D (const Elem &elem, const std::vector< Real > &vertex_distance_func)
 cutting algorithm in 1D.
 
void cut_2D (const Elem &elem, const std::vector< Real > &vertex_distance_func)
 cutting algorithm in 2D.
 
void cut_3D (const Elem &elem, const std::vector< Real > &vertex_distance_func)
 cutting algorithm in 3D.
 

Protected Attributes

std::vector< Elem const * > _inside_elem
 
std::vector< Elem const * > _outside_elem
 
Parallel::Communicator _comm_self
 
std::unique_ptr< ReplicatedMesh_inside_mesh_2D
 
std::unique_ptr< TriangleInterface_triangle_inside
 
std::unique_ptr< ReplicatedMesh_outside_mesh_2D
 
std::unique_ptr< TriangleInterface_triangle_outside
 
std::unique_ptr< ReplicatedMesh_inside_mesh_3D
 
std::unique_ptr< TetGenMeshInterface_tetgen_inside
 
std::unique_ptr< ReplicatedMesh_outside_mesh_3D
 
std::unique_ptr< TetGenMeshInterface_tetgen_outside
 
std::vector< Point_intersection_pts
 

Detailed Description

This class implements cutting a single element into a collection of subelements.

This class depends on libmesh's Triangle and Tetgen interfaces, the former of which is only defined if libmesh is configured with –disable-strict-lgpl.

Author
Benjamin S. Kirk
Date
2013

Subdivides a single element using a mesh generator.

Definition at line 61 of file elem_cutter.h.

Constructor & Destructor Documentation

◆ ElemCutter()

libMesh::ElemCutter::ElemCutter ( )

Constructor.

Initializes pointer data without requiring a full ReplicatedMesh in this header file.

Definition at line 40 of file elem_cutter.C.

40 :
41 _inside_mesh_2D(std::make_unique<ReplicatedMesh>(_comm_self,2)),
42 _triangle_inside(std::make_unique<TriangleInterface>(*_inside_mesh_2D)),
43 _outside_mesh_2D(std::make_unique<ReplicatedMesh>(_comm_self,2)),
44 _triangle_outside(std::make_unique<TriangleInterface>(*_outside_mesh_2D)),
45 _inside_mesh_3D(std::make_unique<ReplicatedMesh>(_comm_self,3)),
46 _tetgen_inside(std::make_unique<TetGenMeshInterface>(*_inside_mesh_3D)),
47 _outside_mesh_3D(std::make_unique<ReplicatedMesh>(_comm_self,3)),
48 _tetgen_outside(std::make_unique<TetGenMeshInterface>(*_outside_mesh_3D))
49{
50 cut_cntr = 0;
51}
std::unique_ptr< TriangleInterface > _triangle_inside
std::unique_ptr< TetGenMeshInterface > _tetgen_inside
std::unique_ptr< ReplicatedMesh > _outside_mesh_2D
std::unique_ptr< TetGenMeshInterface > _tetgen_outside
std::unique_ptr< TriangleInterface > _triangle_outside
Parallel::Communicator _comm_self
std::unique_ptr< ReplicatedMesh > _inside_mesh_2D
std::unique_ptr< ReplicatedMesh > _outside_mesh_3D
std::unique_ptr< ReplicatedMesh > _inside_mesh_3D

◆ ~ElemCutter()

libMesh::ElemCutter::~ElemCutter ( )
default

Destructor.

Member Function Documentation

◆ cut_1D()

void libMesh::ElemCutter::cut_1D ( const Elem elem,
const std::vector< Real > &  vertex_distance_func 
)
protected

cutting algorithm in 1D.

Definition at line 212 of file elem_cutter.C.

214{
215 libmesh_not_implemented();
216}

Referenced by operator()().

◆ cut_2D()

void libMesh::ElemCutter::cut_2D ( const Elem elem,
const std::vector< Real > &  vertex_distance_func 
)
protected

cutting algorithm in 2D.

Definition at line 220 of file elem_cutter.C.

222{
223#ifndef LIBMESH_HAVE_TRIANGLE
224
225 // current implementation requires triangle!
226 libMesh::err << "ERROR: current libMesh ElemCutter 2D implementation requires\n"
227 << " the \"triangle\" library!\n"
228 << std::endl;
229 libmesh_not_implemented();
230
231#else // OK, LIBMESH_HAVE_TRIANGLE
232
233 // std::cout << "Inside cut face element!\n";
234
235 libmesh_assert (_inside_mesh_2D.get() != nullptr);
236 libmesh_assert (_outside_mesh_2D.get() != nullptr);
237
238 _inside_mesh_2D->clear();
239 _outside_mesh_2D->clear();
240
241 for (auto v : make_range(elem.n_vertices()))
242 {
243 if (vertex_distance_func[v] >= 0.)
244 _outside_mesh_2D->add_point (elem.point(v));
245
246 if (vertex_distance_func[v] <= 0.)
247 _inside_mesh_2D->add_point (elem.point(v));
248 }
249
250 for (const auto & pt : _intersection_pts)
251 {
252 _inside_mesh_2D->add_point(pt);
253 _outside_mesh_2D->add_point(pt);
254 }
255
256
257 // Customize the variables for the triangulation
258 // we will be cutting reference cell, and want as few triangles
259 // as possible, so jack this up larger than the area we will be
260 // triangulating so we are governed only by accurately defining
261 // the boundaries.
262 _triangle_inside->desired_area() = 100.;
263 _triangle_outside->desired_area() = 100.;
264
265 // allow for small angles
266 _triangle_inside->minimum_angle() = 5.;
267 _triangle_outside->minimum_angle() = 5.;
268
269 // Turn off Laplacian mesh smoothing after generation.
270 _triangle_inside->smooth_after_generating() = false;
271 _triangle_outside->smooth_after_generating() = false;
272
273 // Triangulate!
274 _triangle_inside->triangulate();
275 _triangle_outside->triangulate();
276
277 // std::ostringstream name;
278
279 // name << "cut_face_"
280 // << cut_cntr++
281 // << ".dat";
282 // _inside_mesh_2D->write ("in_" + name.str());
283 // _outside_mesh_2D->write ("out_" + name.str());
284
285 // finally, add the elements to our lists.
286 _inside_elem.clear();
287 _outside_elem.clear();
288
289 for (const auto & el : _inside_mesh_2D->element_ptr_range())
290 _inside_elem.push_back (el);
291
292 for (const auto & el : _outside_mesh_2D->element_ptr_range())
293 _outside_elem.push_back (el);
294
295#endif
296}
std::vector< Point > _intersection_pts
std::vector< Elem const * > _outside_elem
std::vector< Elem const * > _inside_elem
OStreamProxy err
libmesh_assert(ctx)
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176

References _inside_elem, _inside_mesh_2D, _intersection_pts, _outside_elem, _outside_mesh_2D, _triangle_inside, _triangle_outside, libMesh::err, libMesh::libmesh_assert(), libMesh::make_range(), libMesh::Elem::n_vertices(), and libMesh::Elem::point().

Referenced by operator()().

◆ cut_3D()

void libMesh::ElemCutter::cut_3D ( const Elem elem,
const std::vector< Real > &  vertex_distance_func 
)
protected

cutting algorithm in 3D.

Definition at line 300 of file elem_cutter.C.

302{
303#ifndef LIBMESH_HAVE_TETGEN
304
305 // current implementation requires tetgen!
306 libMesh::err << "ERROR: current libMesh ElemCutter 3D implementation requires\n"
307 << " the \"tetgen\" library!\n"
308 << std::endl;
309 libmesh_not_implemented();
310
311#else // OK, LIBMESH_HAVE_TETGEN
312
313 // std::cout << "Inside cut cell element!\n";
314
315 libmesh_assert (_inside_mesh_3D.get() != nullptr);
316 libmesh_assert (_outside_mesh_3D.get() != nullptr);
317
318 _inside_mesh_3D->clear();
319 _outside_mesh_3D->clear();
320
321 for (auto v : make_range(elem.n_vertices()))
322 {
323 if (vertex_distance_func[v] >= 0.)
324 _outside_mesh_3D->add_point (elem.point(v));
325
326 if (vertex_distance_func[v] <= 0.)
327 _inside_mesh_3D->add_point (elem.point(v));
328 }
329
330 for (const auto & pt : _intersection_pts)
331 {
332 _inside_mesh_3D->add_point(pt);
333 _outside_mesh_3D->add_point(pt);
334 }
335
336
337 // Triangulate!
338 _tetgen_inside->triangulate_pointset();
339 //_inside_mesh_3D->print_info();
340 _tetgen_outside->triangulate_pointset();
341 //_outside_mesh_3D->print_info();
342
343
344 // (below generates some horribly expensive meshes,
345 // but seems immune to the 0 volume problem).
346 // _tetgen_inside->pointset_convexhull();
347 // _inside_mesh_3D->find_neighbors();
348 // _inside_mesh_3D->print_info();
349 // _tetgen_inside->triangulate_conformingDelaunayMesh (1.e3, 100.);
350 // _inside_mesh_3D->print_info();
351
352 // _tetgen_outside->pointset_convexhull();
353 // _outside_mesh_3D->find_neighbors();
354 // _outside_mesh_3D->print_info();
355 // _tetgen_outside->triangulate_conformingDelaunayMesh (1.e3, 100.);
356 // _outside_mesh_3D->print_info();
357
358 std::ostringstream name;
359
360 name << "cut_cell_"
361 << cut_cntr++
362 << ".dat";
363 _inside_mesh_3D->write ("in_" + name.str());
364 _outside_mesh_3D->write ("out_" + name.str());
365
366 // finally, add the elements to our lists.
367 _inside_elem.clear();
368 _outside_elem.clear();
369
370 for (const auto & el : _inside_mesh_3D->element_ptr_range())
371 if (el->volume() > std::numeric_limits<Real>::epsilon())
372 _inside_elem.push_back (el);
373
374 for (const auto & el : _outside_mesh_3D->element_ptr_range())
375 if (el->volume() > std::numeric_limits<Real>::epsilon())
376 _outside_elem.push_back (el);
377
378#endif
379}
Real volume(const MeshBase &mesh, unsigned int dim=libMesh::invalid_uint)
Find the total volume of a mesh (interpreting that as area for dim = 2, or total arc length for dim =...
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

References _inside_elem, _inside_mesh_3D, _intersection_pts, _outside_elem, _outside_mesh_3D, _tetgen_inside, _tetgen_outside, libMesh::err, libMesh::libmesh_assert(), libMesh::make_range(), libMesh::Elem::n_vertices(), and libMesh::Elem::point().

Referenced by operator()().

◆ find_intersection_points()

void libMesh::ElemCutter::find_intersection_points ( const Elem elem,
const std::vector< Real > &  vertex_distance_func 
)
protected

Finds the points where the cutting surface intersects the element edges.

Definition at line 155 of file elem_cutter.C.

157{
158 _intersection_pts.clear();
159
160 for (auto e : elem.edge_index_range())
161 {
162 std::unique_ptr<const Elem> edge (elem.build_edge_ptr(e));
163
164 // find the element nodes el0, el1 that map
165 unsigned int
166 el0 = elem.get_node_index(edge->node_ptr(0)),
167 el1 = elem.get_node_index(edge->node_ptr(1));
168
169 libmesh_assert (elem.is_vertex(el0));
170 libmesh_assert (elem.is_vertex(el1));
171 libmesh_assert_less (el0, vertex_distance_func.size());
172 libmesh_assert_less (el1, vertex_distance_func.size());
173
174 const Real
175 d0 = vertex_distance_func[el0],
176 d1 = vertex_distance_func[el1];
177
178 // if this edge has a 0 crossing
179 if (d0*d1 < 0.)
180 {
181 libmesh_assert_not_equal_to (d0, d1);
182
183 // then find d_star in [0,1], the
184 // distance from el0 to el1 where the 0 lives.
185 const Real d_star = d0 / (d0 - d1);
186
187
188 // Prevent adding nodes trivially close to existing
189 // nodes.
190 const Real endpoint_tol = 0.01;
191
192 if ( (d_star > endpoint_tol) &&
193 (d_star < (1.-endpoint_tol)) )
194 {
195 const Point x_star = (edge->point(0)*(1-d_star) +
196 edge->point(1)*d_star);
197
198 /*
199 std::cout << "adding cut point (d_star, x_star) = "
200 << d_star << " , " << x_star << std::endl;
201 */
202
203 _intersection_pts.push_back (x_star);
204 }
205 }
206 }
207}

References _intersection_pts, libMesh::Elem::build_edge_ptr(), libMesh::Elem::edge_index_range(), libMesh::Elem::get_node_index(), libMesh::Elem::is_vertex(), libMesh::libmesh_assert(), and libMesh::Real.

Referenced by operator()().

◆ inside_elements()

const std::vector< Elem const * > & libMesh::ElemCutter::inside_elements ( ) const
inline
Returns
A list of general element pieces considered inside the cutting surface. These are subelements whose geometric union defines the spatial domain of the inside portion of the cut element.

Definition at line 117 of file elem_cutter.h.

118 { return _inside_elem; }

References _inside_elem.

◆ is_cut()

bool libMesh::ElemCutter::is_cut ( const Elem elem,
const std::vector< Real > &  vertex_distance_func 
) const
Returns
true if the element is cut by the interface defined implicitly by the vertex values of the signed vertex_distance_func.

Definition at line 89 of file elem_cutter.C.

91{
92 libmesh_assert_equal_to (elem.n_vertices(), vertex_distance_func.size());
93
94 Real
95 vmin = vertex_distance_func.front(),
96 vmax = vmin;
97
98 for (const auto & val : vertex_distance_func)
99 {
100 vmin = std::min (vmin, val);
101 vmax = std::max (vmax, val);
102 }
103
104 // if the distance function changes sign, we're cut.
105 return (vmin*vmax < 0.);
106}

References libMesh::Real.

Referenced by operator()().

◆ is_inside()

bool libMesh::ElemCutter::is_inside ( const Elem elem,
const std::vector< Real > &  vertex_distance_func 
) const
Returns
true if the element is completely inside the interface defined implicitly by the vertex values of the signed vertex_distance_func.

Definition at line 59 of file elem_cutter.C.

61{
62 libmesh_assert_equal_to (elem.n_vertices(), vertex_distance_func.size());
63
64 for (const auto & val : vertex_distance_func)
65 if (val > 0.)
66 return false;
67
68 // if the distance function is nonpositive, we are outside
69 return true;
70}

Referenced by operator()().

◆ is_outside()

bool libMesh::ElemCutter::is_outside ( const Elem elem,
const std::vector< Real > &  vertex_distance_func 
) const
Returns
true if the element is completely outside the interface defined implicitly by the vertex values of the signed vertex_distance_func.

Definition at line 74 of file elem_cutter.C.

76{
77 libmesh_assert_equal_to (elem.n_vertices(), vertex_distance_func.size());
78
79 for (const auto & val : vertex_distance_func)
80 if (val < 0.)
81 return false;
82
83 // if the distance function is nonnegative, we are outside
84 return true;
85}

Referenced by operator()().

◆ operator()()

void libMesh::ElemCutter::operator() ( const Elem elem_in,
const std::vector< Real > &  vertex_distance_func 
)

This function implements cutting an element by a signed distance function.

The input array vertex_distance_func contains the vertex values of a signed distance function, from which the cutting interface is inferred from the 0 level set. If all vertex values are positive, the element is outside the cutting surface and is not cut. Likewise if all vertex values are negative, the element is inside the cutting surface and is not cut.

Definition at line 110 of file elem_cutter.C.

113{
114 libmesh_assert_equal_to (vertex_distance_func.size(), elem.n_vertices());
115
116 _inside_elem.clear();
117 _outside_elem.clear();
118
119 // check for quick return?
120 {
121 // completely outside?
122 if (this->is_outside(elem, vertex_distance_func))
123 {
124 //std::cout << "element completely outside\n";
125 _outside_elem.push_back(& elem);
126 return;
127 }
128
129 // completely inside?
130 else if (this->is_inside(elem, vertex_distance_func))
131 {
132 //std::cout << "element completely inside\n";
133 _inside_elem.push_back(&elem);
134 return;
135 }
136
137 libmesh_assert (this->is_cut (elem, vertex_distance_func));
138 }
139
140 // we now know we are in a cut element, find the intersecting points.
141 this->find_intersection_points (elem, vertex_distance_func);
142
143 // and then dispatch the proper method
144 switch (elem.dim())
145 {
146 case 1: this->cut_1D(elem, vertex_distance_func); break;
147 case 2: this->cut_2D(elem, vertex_distance_func); break;
148 case 3: this->cut_3D(elem, vertex_distance_func); break;
149 default: libmesh_error_msg("Invalid element dimension: " << elem.dim());
150 }
151}
void find_intersection_points(const Elem &elem, const std::vector< Real > &vertex_distance_func)
Finds the points where the cutting surface intersects the element edges.
bool is_outside(const Elem &elem, const std::vector< Real > &vertex_distance_func) const
Definition elem_cutter.C:74
bool is_inside(const Elem &elem, const std::vector< Real > &vertex_distance_func) const
Definition elem_cutter.C:59
void cut_1D(const Elem &elem, const std::vector< Real > &vertex_distance_func)
cutting algorithm in 1D.
bool is_cut(const Elem &elem, const std::vector< Real > &vertex_distance_func) const
Definition elem_cutter.C:89
void cut_2D(const Elem &elem, const std::vector< Real > &vertex_distance_func)
cutting algorithm in 2D.
void cut_3D(const Elem &elem, const std::vector< Real > &vertex_distance_func)
cutting algorithm in 3D.

References _inside_elem, _outside_elem, cut_1D(), cut_2D(), cut_3D(), libMesh::Elem::dim(), find_intersection_points(), is_cut(), is_inside(), is_outside(), libMesh::libmesh_assert(), and libMesh::Elem::n_vertices().

◆ outside_elements()

const std::vector< Elem const * > & libMesh::ElemCutter::outside_elements ( ) const
inline
Returns
A list of general element pieces considered outside the cutting surface. These are subelements whose geometric union defines the spatial domain of the outside portion of the cut element.

Definition at line 125 of file elem_cutter.h.

126 { return _outside_elem; }

References _outside_elem.

Member Data Documentation

◆ _comm_self

Parallel::Communicator libMesh::ElemCutter::_comm_self
protected

Definition at line 158 of file elem_cutter.h.

◆ _inside_elem

std::vector<Elem const *> libMesh::ElemCutter::_inside_elem
protected

Definition at line 155 of file elem_cutter.h.

Referenced by cut_2D(), cut_3D(), inside_elements(), and operator()().

◆ _inside_mesh_2D

std::unique_ptr<ReplicatedMesh> libMesh::ElemCutter::_inside_mesh_2D
protected

Definition at line 160 of file elem_cutter.h.

Referenced by cut_2D().

◆ _inside_mesh_3D

std::unique_ptr<ReplicatedMesh> libMesh::ElemCutter::_inside_mesh_3D
protected

Definition at line 166 of file elem_cutter.h.

Referenced by cut_3D().

◆ _intersection_pts

std::vector<Point> libMesh::ElemCutter::_intersection_pts
protected

Definition at line 172 of file elem_cutter.h.

Referenced by cut_2D(), cut_3D(), and find_intersection_points().

◆ _outside_elem

std::vector<Elem const *> libMesh::ElemCutter::_outside_elem
protected

Definition at line 156 of file elem_cutter.h.

Referenced by cut_2D(), cut_3D(), operator()(), and outside_elements().

◆ _outside_mesh_2D

std::unique_ptr<ReplicatedMesh> libMesh::ElemCutter::_outside_mesh_2D
protected

Definition at line 163 of file elem_cutter.h.

Referenced by cut_2D().

◆ _outside_mesh_3D

std::unique_ptr<ReplicatedMesh> libMesh::ElemCutter::_outside_mesh_3D
protected

Definition at line 169 of file elem_cutter.h.

Referenced by cut_3D().

◆ _tetgen_inside

std::unique_ptr<TetGenMeshInterface> libMesh::ElemCutter::_tetgen_inside
protected

Definition at line 167 of file elem_cutter.h.

Referenced by cut_3D().

◆ _tetgen_outside

std::unique_ptr<TetGenMeshInterface> libMesh::ElemCutter::_tetgen_outside
protected

Definition at line 170 of file elem_cutter.h.

Referenced by cut_3D().

◆ _triangle_inside

std::unique_ptr<TriangleInterface> libMesh::ElemCutter::_triangle_inside
protected

Definition at line 161 of file elem_cutter.h.

Referenced by cut_2D().

◆ _triangle_outside

std::unique_ptr<TriangleInterface> libMesh::ElemCutter::_triangle_outside
protected

Definition at line 164 of file elem_cutter.h.

Referenced by cut_2D().


The documentation for this class was generated from the following files: