15 #include "libmesh/mesh_tools.h" 16 #include "libmesh/unstructured_mesh.h" 26 packCell(
const std::size_t y_index,
const std::size_t z_index)
29 return (static_cast<std::uint64_t>(y_index) << 32) |
static_cast<std::uint64_t
>(z_index);
33 cellIndex(
const Real value,
const Real min_value,
const Real cell_size,
const std::size_t num_cells)
39 const auto index =
static_cast<long long>(std::floor((
value - min_value) / cell_size));
42 if (index >= static_cast<long long>(num_cells))
44 return static_cast<std::size_t
>(index);
58 _surface_tolerance(surface_tolerance),
60 _point_locator(_mesh.sub_point_locator())
63 mooseAssert(
mesh.is_serial(),
"Input manifold mesh must be serialized.");
64 mooseAssert(
mesh.mesh_dimension() == 2,
"Manifold mesh must be a surface.");
85 unsigned int num_hits = 0;
87 for (
const auto triangle_index : candidates)
89 const auto tri =
_mesh.elem_ptr(triangle_index);
116 auto umesh =
dynamic_cast<UnstructuredMesh *
>(&
_mesh);
121 "The inputted surface mesh cannot be treated as manifold for the following reasons:\n",
132 const auto extent_y =
134 const auto extent_z =
138 const auto target_cells =
140 const auto aspect =
std::sqrt(extent_y / extent_z);
145 1,
static_cast<std::size_t
>(std::ceil(static_cast<Real>(target_cells) /
_num_y_cells)));
152 for (
const auto elem :
_mesh.active_element_ptr_range())
154 const auto triangle_index = elem->id();
155 const auto bbox = elem->loose_bounding_box();
167 for (
const auto iy :
make_range(y_start, y_stop + 1))
168 for (
const auto iz :
make_range(z_start, z_stop + 1))
195 static const Point direction(1.0, 0.0, 0.0);
199 const Point h = direction.
cross(edge2);
200 const Real determinant = edge1 * h;
201 const Real characteristic_length =
std::max(edge1.norm(), edge2.norm());
207 const Real inv_determinant = 1.0 / determinant;
209 const Real u = inv_determinant * (s * h);
210 if (u < 0.0 || u > 1.0)
213 const Point q = s.cross(edge1);
214 const Real v = inv_determinant * (direction * q);
215 if (v < 0.0 || u + v > 1.0)
218 const Real t = inv_determinant * (edge2 * q);
226 const Point intersection =
point + t * direction;
245 Real total_angle = 0.0;
246 for (
const auto elem :
_mesh.active_element_ptr_range())
253 std::vector<dof_id_type>
284 std::ostringstream err_msg;
286 err_msg <<
"- At least one non-Tri3 element was found.\n" << std::endl;
288 err_msg <<
"- At least one triangle without three neighbors was found.\n" << std::endl;
290 err_msg <<
"- The surface mesh was empty\n" << std::endl;
292 err_msg <<
"- At least one triangle neighbor without a return neighbor link was found.\n";
294 err_msg <<
"- At least one triangle neighbor without expected node links was found.\n";
296 err_msg <<
"- At least one triangle neighbor with an inconsistent orientation was found.\n";
298 err_msg <<
"- At least one triangle neighbor with inconsistent node and neighbor links was " 301 err_msg <<
"- At least one input triangle is degenerate, with near-zero area relative to the " 304 err_msg <<
"- Mesh is degenerate, with zero thickness in at least one direction.\n";
305 return err_msg.str();
bool containsBySolidAngle(const Point &point) const
Robust fallback containment query based on accumulated solid angle.
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
const std::unique_ptr< libMesh::PointLocatorBase > _point_locator
Pre-built point locator for fast proximity-to-surface detection.
Real _z_min
Minimum global z coordinate used to map query points into yz-grid bins.
Real _z_cell_size
Width of one yz-grid cell in the z direction.
Real _y_cell_size
Width of one yz-grid cell in the y direction.
RayIntersection
Result of intersecting the positive x-direction ray with a triangle.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
bool pointOnSurface(const Point &point) const
Detect whether a query point lies on or extremely near the manifold surface.
Real solidAngle(const Point &point, const Point &v0, const Point &v1, const Point &v2)
Compute the signed solid angle subtended by one oriented triangle at the query point.
std::string improveAndValidate()
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
Real _y_min
Minimum global y coordinate used to map query points into yz-grid bins.
MeshTetInterface(UnstructuredMesh &mesh)
const Real _surface_tolerance
Absolute tolerance used throughout validation and geometric classification.
auto max(const L &left, const R &right)
void triangulate() override
std::size_t _num_z_cells
Number of yz-grid bins in the z direction.
const Node & node_ref(const unsigned int i) const
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
const Point & min() const
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const
Real pointSegmentDistanceSq(const Point &point, const Point &a, const Point &b)
Compute the squared distance from a point to a 3-D line segment.
std::uint64_t packCell(const std::size_t y_index, const std::size_t z_index)
std::unordered_map< dof_id_type, std::vector< dof_id_type > > _ray_grid
Lookup from packed yz-grid cell index to triangles that could intersect the +x query ray...
void buildCandidateGrid()
Build the yz-plane lookup grid used to accelerate +x ray queries.
bool pointInsideBoundingBox(const Point &point) const
Cheap global bounding-box rejection for containment queries.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::size_t cellIndex(const Real value, const Real min_value, const Real cell_size, const std::size_t num_cells)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
const libMesh::BoundingBox & boundingBox() const
std::size_t numTriangles() const
TriangleManifold(MeshBase &mesh, const Real surface_tolerance)
Build a manifold classifier from a prepared surface mesh.
IntRange< T > make_range(T beg, T end)
std::set< SurfaceIntegrity > improve_hull_integrity()
std::vector< dof_id_type > rayCandidates(const Point &point) const
Get the subset of triangles whose yz extents may intersect the query ray.
SurfaceChecker(UnstructuredMesh &mesh)
const Point & max() const
auto min(const L &left, const R &right)
RayIntersection rayIntersectsTriangle(const Point &point, const libMesh::Elem &tri) const
Intersect a positive x-direction ray with a single triangle.
bool contains(const Point &point) const
void finalize()
Complete post-parse validation and acceleration-structure setup.
std::size_t _num_y_cells
Number of yz-grid bins in the y direction.