18 #include "libmesh/libmesh_config.h" 25 #include "libmesh/mesh_tet_interface.h" 27 #include "libmesh/boundary_info.h" 28 #include "libmesh/elem.h" 29 #include "libmesh/mesh_modification.h" 30 #include "libmesh/mesh_serializer.h" 31 #include "libmesh/mesh_tools.h" 32 #include "libmesh/remote_elem.h" 33 #include "libmesh/unstructured_mesh.h" 38 std::unordered_set<Elem *>
39 flood_component (std::unordered_set<Elem *> & all_components,
44 std::unordered_set<Elem *> current_component;
46 std::unordered_set<Elem *> elements_to_consider = {elem};
48 while (!elements_to_consider.empty())
50 std::unordered_set<Elem *> next_elements_to_consider;
52 for (
Elem * considering : elements_to_consider)
54 all_components.insert(considering);
55 current_component.insert(considering);
57 for (
auto s :
make_range(considering->n_sides()))
63 "Tet generation encountered a 2D element with a null neighbor, but a\n" 64 "boundary must be a 2D closed manifold (surface).\n");
66 if (all_components.find(neigh) == all_components.end())
67 next_elements_to_consider.insert(neigh);
70 elements_to_consider = next_elements_to_consider;
73 return current_component;
78 Real six_times_signed_tet_volume (
const Point & p1,
82 return p1(0)*p2(1)*p3(2)
92 Real six_times_signed_volume (
const std::unordered_set<Elem *> component)
96 for (
const Elem * elem: component)
98 libmesh_assert_equal_to(elem->
dim(), 2);
100 six_vol += six_times_signed_tet_volume(elem->
point(0),
115 _desired_volume(0), _smooth_after_generating(false),
125 (std::unique_ptr<std::vector<std::unique_ptr<UnstructuredMesh>>> holes)
127 _holes = std::move(holes);
149 #ifdef LIBMESH_ENABLE_UNIQUE_ID 156 std::unordered_set<Elem *> elems_to_delete;
158 std::vector<std::unique_ptr<Elem>> elems_to_add;
161 for (
auto * elem :
mesh.active_element_ptr_range())
163 libmesh_error_msg_if (elem->
dim() < 2,
164 "Cannot use meshes with 0D or 1D elements to define a volume");
168 if (elem->
dim() == 2)
173 elems_to_delete.insert(elem);
183 libmesh_not_implemented_msg
184 (
"Tetrahedralizaton of adapted meshes is not currently supported");
189 Elem * side_elem = elems_to_add.back().get();
200 side_elem->
set_id(max_orig_id + max_sides*elem->
id() + s);
201 #ifdef LIBMESH_ENABLE_UNIQUE_ID 220 typedef std::pair<Elem *, unsigned char> val_type;
221 typedef std::unordered_multimap<key_type, val_type> map_type;
222 map_type side_to_elem_map;
224 std::unique_ptr<Elem> my_side, their_side;
226 for (
auto & elem : elems_to_add)
233 auto bounds = side_to_elem_map.equal_range(key);
234 if (bounds.first != bounds.second)
237 while (bounds.first != bounds.second)
239 Elem * potential_neighbor = bounds.first->second.first;
240 const unsigned int ns = bounds.first->second.second;
241 potential_neighbor->
side_ptr(their_side, ns);
242 if (*my_side == *their_side)
246 side_to_elem_map.erase (bounds.first);
253 side_to_elem_map.emplace
254 (key, std::make_pair(elem.get(), cast_int<unsigned char>(s)));
261 for (
auto & elem : elems_to_add)
268 for (
Elem * elem : elems_to_delete)
273 for (
auto & elem : elems_to_add)
291 std::vector<std::unordered_set<Elem *>> components;
292 std::unordered_set<Elem *> in_component;
294 for (
auto * elem :
mesh.element_ptr_range())
295 if (!in_component.count(elem))
296 components.emplace_back(flood_component(in_component, elem));
298 const std::unordered_set<Elem *> * biggest_component =
nullptr;
299 Real biggest_six_vol = 0;
300 for (
const auto & component : components)
302 Real six_vol = six_times_signed_volume(component);
303 if (std::abs(six_vol) > std::abs(biggest_six_vol))
305 biggest_six_vol = six_vol;
306 biggest_component = &component;
310 if (!biggest_component)
311 libmesh_error_msg(
"No non-zero-volume component found among " <<
312 components.size() <<
" boundary components");
314 for (
const auto & component : components)
315 if (&component != biggest_component)
317 for (
Elem * elem: component)
322 for (
Elem * elem: component)
324 if (biggest_six_vol < 0)
347 for (
auto & elem : this->
_mesh.element_ptr_range())
358 if (neigh ==
nullptr)
376 libMesh::err <<
"Error! Conforming Delaunay mesh tetrahedralization requires a convex hull." << std::endl;
380 libMesh::err <<
"Non-TRI3 elements were found in the input Mesh. ";
381 libMesh::err <<
"A constrained Delaunay triangulation requires a convex hull of TRI3 elements." << std::endl;
384 libmesh_error_msg(
"Consider calling TetGenMeshInterface::pointset_convexhull() followed by Mesh::find_neighbors() first.");
392 for (
auto & elem : this->
_mesh.element_ptr_range())
unique_id_type & set_unique_id()
virtual unique_id_type parallel_max_unique_id() const =0
unsigned check_hull_integrity()
This function checks the integrity of the current set of elements in the Mesh to see if they comprise...
IntRange< unsigned short > side_index_range() const
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly ecreated (or read) mesh for use.
virtual dof_id_type low_order_key(const unsigned int s) const =0
This is the base class from which all geometric element types are derived.
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
MeshTetInterface(UnstructuredMesh &mesh)
Constructor.
void set_interior_parent(Elem *p)
Sets the pointer to the element's interior_parent.
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
The UnstructuredMesh class is derived from the MeshBase class.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
virtual ~MeshTetInterface()
Default destructor in base class.
virtual dof_id_type max_elem_id() const =0
static BoundingBox volume_to_surface_mesh(UnstructuredMesh &mesh)
Remove volume elements from the given mesh, after converting their outer boundary faces to surface el...
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
void attach_hole_list(std::unique_ptr< std::vector< std::unique_ptr< UnstructuredMesh >>> holes)
Attaches a vector of Mesh pointers defining holes which will be meshed around.
virtual void flip(BoundaryInfo *boundary_info)=0
Flips the element (by swapping node and neighbor pointers) to have a mapping Jacobian of opposite sig...
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Defines a Cartesian bounding box by the two corner extremum.
virtual unsigned int n_sides() const =0
const Elem * neighbor_ptr(unsigned int i) const
unsigned int level() const
virtual unsigned int n_vertices() const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
virtual unsigned short dim() const =0
Temporarily serialize a DistributedMesh for non-distributed-mesh capable code paths.
void process_hull_integrity_result(unsigned result)
This function prints an informative message and crashes based on the output of the check_hull_integri...
virtual bool is_replicated() const
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...
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
void union_with(const Point &p)
Enlarges this bounding box to include the given point.
virtual dof_id_type n_elem() const =0
UnstructuredMesh & _mesh
Local reference to the mesh we are working with.
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
const Point & point(const unsigned int i) const
void delete_2D_hull_elements()
Delete original convex hull elements from the Mesh after performing a Delaunay tetrahedralization.
const RemoteElem * remote_elem