19 #include "libmesh/libmesh_config.h" 22 #include "libmesh/mesh_triangle_interface.h" 23 #include "libmesh/unstructured_mesh.h" 24 #include "libmesh/face_tri3.h" 25 #include "libmesh/face_tri6.h" 26 #include "libmesh/mesh_generation.h" 27 #include "libmesh/mesh_smoother_laplace.h" 28 #include "libmesh/boundary_info.h" 29 #include "libmesh/mesh_triangle_holes.h" 30 #include "libmesh/mesh_triangle_wrapper.h" 31 #include "libmesh/enum_elem_type.h" 32 #include "libmesh/enum_order.h" 33 #include "libmesh/enum_to_string.h" 34 #include "libmesh/utility.h" 36 #include "libmesh/meshfree_interpolation.h" 50 const unsigned int num_nearest_pts,
51 const unsigned int power,
52 const Real background_value,
53 const Real background_eff_dist):
55 _num_nearest_pts(num_nearest_pts),
57 _background_value(background_value),
58 _background_eff_dist(background_eff_dist),
69 const std::vector<Real> & input_vals)
71 std::vector<std::string> field_vars{
"f"};
74 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 75 std::vector<Number> input_complex_vals;
76 for (
const auto & input_val : input_vals)
77 input_complex_vals.push_back(
Complex (input_val, 0.0));
91 std::vector<Point> target_pts;
92 std::vector<Number> target_vals;
94 target_pts.push_back(p);
95 target_vals.resize(1);
114 _minimum_angle(20.0),
115 _triangulation_type(GENERATE_CONVEX_HULL),
116 _insert_extra_points(false),
117 _smooth_after_generating(true),
119 _auto_area_function(nullptr)
163 std::map<Point, dof_id_type> point_id_map;
165 for (
Node * node :
_mesh.node_ptr_range())
169 (point_id_map.count(*node),
170 "TriangulatorInterface does not support overlapping nodes found at " 171 <<
static_cast<Point&
>(*node));
173 point_id_map.emplace(*node, node->id());
180 for (
Elem * elem :
_mesh.element_ptr_range())
181 for (
auto n :
make_range(elem->n_vertices(), elem->n_nodes()))
182 point_id_map.erase(elem->point(n));
197 std::unordered_set<Node *> nodes_to_delete;
199 for (
Elem * elem :
_mesh.element_ptr_range())
200 for (
auto n :
make_range(elem->n_vertices(), elem->n_nodes()))
201 nodes_to_delete.insert(elem->node_ptr(n));
205 for (
auto & node :
_mesh.node_ptr_range())
206 if (!mh.contains(*node))
207 nodes_to_delete.insert(node);
216 const std::size_t np = mh.n_points();
219 const Point pt = mh.point(i);
220 const dof_id_type id0 = libmesh_map_find(point_id_map, pt);
222 const Point next_pt = mh.point((np+i+1)%np);
223 const dof_id_type id1 = libmesh_map_find(point_id_map, next_pt);
224 this->
segments.emplace_back(id0, id1);
229 for (
Node * node : nodes_to_delete)
246 for (
auto node_it =
_mesh.nodes_begin(),
247 node_end =
_mesh.nodes_end();
248 node_it != node_end;)
250 Node * node = *node_it;
254 if (node->
id() >= max_node_id)
259 Node * next_node = (node_it == node_end) ?
260 *
_mesh.nodes_begin() : *node_it;
262 this->
segments.emplace_back(node->
id(), next_node->
id());
267 std::vector<Point> outer_pts;
269 outer_pts.push_back(
_mesh.
point(segment.first));
295 std::vector<std::pair<unsigned int, unsigned int>> old_segments =
308 for (
auto old_segment : old_segments)
316 const Point new_point =
317 ((n_interpolated-i) * *(
Point *)(begin_node) +
318 (i+1) * *(
Point *)(end_node)) /
319 (n_interpolated + 1);
321 this->
segments.emplace_back(current_id,
323 current_id = next_node->
id();
325 this->
segments.emplace_back(current_id,
346 libmesh_not_implemented();
353 std::map<std::pair<Point, unsigned int>,
Point> all_midpoints;
354 unsigned int n_midpoints =
356 libmesh_assert_equal_to(this->
segments.size() * n_midpoints,
362 all_midpoints[{p,m}] =
369 if (!hole->n_midpoints())
372 n_midpoints = hole->n_midpoints();
373 else if (hole->n_midpoints() != n_midpoints)
374 libmesh_not_implemented_msg
375 (
"Differing boundary midpoint counts " <<
376 hole->n_midpoints() <<
" and " << n_midpoints);
383 const auto n_hole_points = hole->n_points();
389 const Point & p = hole->point(i+1);
390 all_midpoints[{p,m}] = hole->midpoint(n_midpoints-m-1, i);
392 const Point & p = hole->point(0);
393 all_midpoints[{p,m}] = hole->midpoint(n_midpoints-m-1, n_hole_points-1);
400 libmesh_not_implemented_msg
401 (
"Cannot construct triangles with more than 1 midpoint per edge");
406 for (
Elem * elem :
_mesh.element_ptr_range())
410 libmesh_assert_equal_to(elem->n_vertices(), 3);
411 libmesh_assert_not_equal_to(elem->default_order(),
FIRST);
416 if (elem->neighbor_ptr(n))
419 const Point & p = elem->point(n);
421 if (
const auto it = all_midpoints.find({p,0});
422 it != all_midpoints.end())
423 elem->point(n+3) = it->second;
439 if (hole->contains(hole2->point(i)))
441 (
"Found point " << hole2->point(i) <<
442 " on one hole boundary and another's interior");
446 if (!outer_bdy.
contains(hole->point(i)))
448 (
"Found point " << hole->point(i) <<
449 " on hole boundary but outside outer boundary");
461 unsigned int n_hole_points = 0;
464 for (
const auto & hole : *
_holes)
466 n_hole_points += hole->n_points();
471 libmesh_assert_greater(hole->segment_indices().size(), 1);
472 libmesh_assert_equal_to(hole->segment_indices().back(), hole->n_points());
475 return n_hole_points;
479 const unsigned int num_nearest_pts,
480 const unsigned int power,
481 const Real background_value,
482 const Real background_eff_dist)
484 _auto_area_function = std::make_unique<AutoAreaFunction>(comm, num_nearest_pts, power, background_value, background_eff_dist);
492 std::vector<Point> function_points;
493 std::vector<Real> function_sizes;
501 std::vector<Real> & function_sizes,
502 const Real & area_factor)
509 for (
unsigned int i = 0; i < bdry_mh.n_points(); i++)
511 function_points.push_back((bdry_mh.point(i) + bdry_mh.point((i + 1) % bdry_mh.n_points())) /
513 function_sizes.push_back(
514 (bdry_mh.point(i) - bdry_mh.point((i + 1) % bdry_mh.n_points())).norm());
520 for (
unsigned int i = 0; i < hole->n_points(); i++)
522 function_points.push_back(
523 (hole->point(i) + hole->point((i + 1) % hole->n_points())) /
Real(2.0));
524 function_sizes.push_back(
525 (hole->point(i) - hole->point((i + 1) % hole->n_points())).norm());
530 function_sizes.begin(), function_sizes.end(), [&area_factor](
Real & a) { a = a * a * area_factor * std::sqrt(3.0) / 4.0; });
FunctionBase< Real > * get_auto_area_function()
Get the auto area function.
bool _verify_hole_boundaries
Flag which tells if we want to check hole geometry.
void init_mfi(const std::vector< Point > &input_pts, const std::vector< Real > &input_vals)
Inverse distance interpolation.
bool _insert_extra_points
Flag which tells whether or not to insert additional nodes before triangulation.
A Node is like a Point, but with more information.
std::set< std::size_t > _bdy_ids
A set of ids to allow on the outer boundary loop.
void insert_any_extra_boundary_points()
Helper function to add extra points (midpoints of initial segments) to a PSLG triangulation.
An abstract class for defining a 2-dimensional hole.
virtual Real operator()(const Point &p, const Real) override
This is the base class from which all geometric element types are derived.
bool _initialized
When init() was called so that everything is ready for calls to operator() (...), then this bool is t...
void set_interpolate_boundary_points(int n_points)
Complicated setter, for compatibility with insert_extra_points()
int _interpolate_boundary_points
Flag which tells how many additional nodes should be inserted between each pair of original mesh poin...
UnstructuredMesh & _mesh
Reference to the mesh which is to be created by triangle.
The libMesh namespace provides an interface to certain functionality in the library.
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.
void elems_to_segments()
Helper function to create PSLG segments from our other boundary-defining options (1D mesh edges...
ElemType _elem_type
The type of elements to generate.
void calculate_auto_desired_area_samples(std::vector< Point > &function_points, std::vector< Real > &function_sizes, const Real &area_factor=1.5)
The external boundary and all hole boundaries are collected.
The UnstructuredMesh class is derived from the MeshBase class.
const std::vector< Hole * > * _holes
A pointer to a vector of Hole*s.
virtual void delete_node(Node *n)=0
Removes the Node n from the mesh.
std::unique_ptr< InverseDistanceInterpolation< 3 > > _auto_area_mfi
virtual ~AutoAreaFunction()
void increase_triangle_order()
Helper function to upconvert Tri3 to any higher order triangle type if requested via _elem_type...
bool _is_time_dependent
Cache whether or not this function is actually time-dependent.
unsigned int total_hole_points()
Helper function to count points in and verify holes.
std::vector< Point > segment_midpoints
When constructing a second-order triangulation from a second-order boundary, we may do the triangulat...
TriangulatorInterface(UnstructuredMesh &mesh)
The constructor.
virtual void clear_elems()=0
Deletes all the element data that is currently stored.
Triangulate the interior of a Planar Straight Line Graph, which is defined implicitly by the order of...
std::complex< Real > Complex
bool contains(Point p) const
Return true iff p lies inside the hole.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< std::pair< unsigned int, unsigned int > > segments
When constructing a PSLG, if the node numbers do not define the desired boundary segments implicitly ...
void nodes_to_segments(dof_id_type max_node_id)
Helper function to create PSLG segments from our node ordering, up to the maximum node id...
virtual void all_complete_order()
Calls the range-based version of this function with a range consisting of all elements in the mesh...
Another concrete instantiation of the hole, as general as ArbitraryHole, but based on an existing 1D ...
int get_interpolate_boundary_points() const
Complicated getter, for compatibility with insert_extra_points()
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...
void all_second_order(const bool full_ordered=true)
Calls the range-based version of this function with a range consisting of all elements in the mesh...
std::unique_ptr< AutoAreaFunction > _auto_area_function
The auto area function based on the spacing of boundary points.
AutoAreaFunction(const Parallel::Communicator &comm, const unsigned int num_nearest_pts, const unsigned int power, const Real background_value, const Real background_eff_dist)
Another concrete instantiation of the hole, this one should be sufficiently general for most non-poly...
virtual const Point & point(const dof_id_type i) const =0
void verify_holes(const Hole &outer_bdy)
Helper function to check holes for intersections if requested.
virtual dof_id_type max_node_id() const =0
virtual dof_id_type n_elem() const =0
void set_auto_area_function(const Parallel::Communicator &comm, const unsigned int num_nearest_pts, const unsigned int power, const Real background_value, const Real background_eff_dist)
Generate an auto area function based on spacing of boundary points.
virtual const Node * node_ptr(const dof_id_type i) const =0
TriangulationType _triangulation_type
The type of triangulation to perform: choices are: convex hull PSLG.
A Point defines a location in LIBMESH_DIM dimensional Real space.