17 #include "libmesh/cell_hex8.h" 18 #include "libmesh/cell_hex20.h" 19 #include "libmesh/cell_hex27.h" 20 #include "libmesh/cell_prism6.h" 21 #include "libmesh/cell_prism15.h" 22 #include "libmesh/cell_prism18.h" 23 #include "libmesh/cell_pyramid5.h" 24 #include "libmesh/cell_pyramid13.h" 25 #include "libmesh/cell_pyramid14.h" 26 #include "libmesh/cell_tet4.h" 27 #include "libmesh/cell_tet10.h" 28 #include "libmesh/cell_tet14.h" 29 #include "libmesh/edge_edge2.h" 30 #include "libmesh/enum_to_string.h" 31 #include "libmesh/face_quad4.h" 32 #include "libmesh/face_tri3.h" 33 #include "libmesh/mesh.h" 34 #include "libmesh/remote_elem.h" 35 #include "libmesh/tensor_value.h" 43 HEX8,
HEX20,
HEX27,
QUAD4,
QUAD8,
QUAD9,
TET4,
TET10,
TET14,
TRI3,
TRI6,
49 const Point & direction,
53 Point & intersection_point,
54 Real & intersection_distance,
56 #ifdef DEBUG_RAY_INTERSECTIONS
65 debugRaySimple(
"Called lineLineIntersect2D()");
66 debugRaySimple(
" start = ", start);
67 debugRaySimple(
" direction = ", direction);
68 debugRaySimple(
" length = ", length);
69 debugRaySimple(
" v0 = ", v0);
70 debugRaySimple(
" v1 = ", v1);
72 const auto r = direction * length;
73 const auto s = v1 - v0;
75 const auto rxs = r(0) * s(1) - r(1) * s(0);
76 debugRaySimple(
" rxs = ", rxs);
82 const auto v0mu0 = v0 - start;
84 const auto t = (v0mu0(0) * s(1) - v0mu0(1) * s(0)) / rxs;
85 debugRaySimple(
" t = ", t);
88 debugRaySimple(
"lineLineIntersect2D did not intersect: t out of range");
92 const auto u = (v0mu0(0) * r(1) - v0mu0(1) * r(0)) / rxs;
93 debugRaySimple(
" u = ", u);
96 intersection_point = start + r * t;
97 intersection_distance = t * length;
104 debugRaySimple(
"lineLineIntersect2D intersected with:");
105 debugRaySimple(
" intersection_distance = ", intersection_point);
106 debugRaySimple(
" intersection_distance = ", intersection_distance);
113 debugRaySimple(
"lineLineIntersect2d() did not intersect: u out of range");
119 const Elem *
const elem,
124 std::vector<const Elem *> active_neighbor_children,
125 std::vector<NeighborInfo> &
info)
127 mooseAssert(elem->
contains_point(point),
"Doesn't contain point");
132 std::unique_ptr<const Elem> side_helper;
134 auto contains_point = [&point, &
info, &side_helper, &elem](
const Elem *
const candidate)
136 if (candidate->contains_point(point))
138 std::vector<unsigned short>
sides;
139 for (
const auto s : candidate->side_index_range())
141 candidate->build_side_ptr(side_helper, s);
142 if (side_helper->contains_point(point))
147 if (!
sides.empty() && candidate != elem)
149 info.emplace_back(candidate, std::move(
sides));
158 contains_point(elem);
164 active_neighbor_children,
170 std::set<const Elem *> point_neighbors;
172 for (
const auto & point_neighbor : point_neighbors)
173 if (!neighbor_set.
contains(point_neighbor) && point_neighbor != elem)
180 const Elem *
const elem,
181 const Node *
const node,
185 std::vector<const Elem *> active_neighbor_children,
186 std::vector<NeighborInfo> &
info)
193 std::unique_ptr<const Elem> side_helper;
195 auto contains_node = [&node, &elem, &
info, &side_helper](
const Elem *
const candidate)
198 const auto n = candidate->get_node_index(node);
201 std::vector<unsigned short>
sides;
202 for (
const auto s : candidate->side_index_range())
203 if (candidate->is_node_on_side(n, s))
207 mooseError(
"Failed to find a side containing node");
209 info.emplace_back(candidate, std::move(
sides));
214 if (candidate->level() < elem->level() && candidate->contains_point(*node))
216 std::vector<unsigned short>
sides;
217 for (
const auto s : candidate->side_index_range())
219 candidate->build_side_ptr(side_helper, s);
220 if (side_helper->contains_point(*node))
226 info.emplace_back(candidate, std::move(
sides));
238 elem, neighbor_set, untested_set, next_untested_set, active_neighbor_children, contains_node);
243 std::set<const Elem *> point_neighbors;
244 elem->find_point_neighbors(*node, point_neighbors);
245 for (
const auto & point_neighbor : point_neighbors)
246 for (
const auto & neighbor_node : point_neighbor->node_ref_range())
247 if (node == &neighbor_node && !neighbor_set.
contains(point_neighbor) &&
248 point_neighbor != elem)
255 const Elem *
const elem,
256 const Node *
const node1,
257 const Node *
const node2,
261 std::vector<const Elem *> active_neighbor_children,
262 std::vector<NeighborInfo> &
info)
274 auto within_edge = [&elem, &node1, &node2, &edge_length, &
info](
const Elem *
const candidate)
276 switch (candidate->type())
279 return findEdgeNeighborsWithinEdgeInternal<Hex8>(
280 candidate, elem, node1, node2, edge_length,
info);
282 return findEdgeNeighborsWithinEdgeInternal<Tet4>(
283 candidate, elem, node1, node2, edge_length,
info);
285 return findEdgeNeighborsWithinEdgeInternal<Pyramid5>(
286 candidate, elem, node1, node2, edge_length,
info);
288 return findEdgeNeighborsWithinEdgeInternal<Prism6>(
289 candidate, elem, node1, node2, edge_length,
info);
291 return findEdgeNeighborsWithinEdgeInternal<Hex20>(
292 candidate, elem, node1, node2, edge_length,
info);
294 return findEdgeNeighborsWithinEdgeInternal<Hex27>(
295 candidate, elem, node1, node2, edge_length,
info);
297 return findEdgeNeighborsWithinEdgeInternal<Tet10>(
298 candidate, elem, node1, node2, edge_length,
info);
300 return findEdgeNeighborsWithinEdgeInternal<Tet14>(
301 candidate, elem, node1, node2, edge_length,
info);
303 return findEdgeNeighborsWithinEdgeInternal<Pyramid13>(
304 candidate, elem, node1, node2, edge_length,
info);
306 return findEdgeNeighborsWithinEdgeInternal<Pyramid14>(
307 candidate, elem, node1, node2, edge_length,
info);
309 return findEdgeNeighborsWithinEdgeInternal<Prism15>(
310 candidate, elem, node1, node2, edge_length,
info);
312 return findEdgeNeighborsWithinEdgeInternal<Prism18>(
313 candidate, elem, node1, node2, edge_length,
info);
317 " not supported in TraceRayTools::findEdgeNeighbors()");
325 elem, neighbor_set, untested_set, next_untested_set, active_neighbor_children, within_edge);
331 mooseAssert(!elem->
active(),
"Should be inactive");
332 mooseAssert(elem->
side_ptr(side)->contains_point(point),
"Side should contain point");
342 if (child->close_to_point(point, 5.e-5))
351 mooseError(
"Failed to find child containing point on side");
358 if (!neighbor || neighbor->active())
368 const Point & direction,
369 const Elem *
const elem,
370 const unsigned short v0,
371 const unsigned short v1,
372 const unsigned short v2,
373 Real & intersection_distance,
376 #ifdef DEBUG_RAY_INTERSECTIONS
382 debugRaySimple(
"intersectTriangle() called:");
383 debugRaySimple(
" start = ", start);
384 debugRaySimple(
" direction = ", direction);
385 debugRaySimple(
" elem->id() = ", elem->
id());
386 debugRaySimple(
" v0 = ", v0,
" at ", elem->
point(v0));
387 debugRaySimple(
" v1 = ", v1,
" at ", elem->
point(v1));
388 debugRaySimple(
" v2 = ", v2,
" at ", elem->
point(v2));
389 debugRaySimple(
" hmax = ", hmax);
390 mooseAssert(elem->
is_vertex(v0),
"Not a vertex");
391 mooseAssert(elem->
is_vertex(v1),
"Not a vertex");
392 mooseAssert(elem->
is_vertex(v2),
"Not a vertex");
397 const auto inv_hmax = 1.0 / hmax;
399 const auto & v0_point = elem->
point(v0);
401 const auto edge1 = (elem->
point(v1) - v0_point) * inv_hmax;
402 const auto edge2 = (elem->
point(v2) - v0_point) * inv_hmax;
404 const auto pvec = direction.
cross(edge2);
406 auto det = edge1 * pvec;
407 debugRaySimple(
" det = ", det);
410 debugRaySimple(
"intersectTriangle() did not intersect: det < tol");
414 const auto tvec = (start - v0_point) * inv_hmax;
415 const auto u = tvec * pvec;
416 debugRaySimple(
" u = ", u);
417 debugRaySimple(
" u / det = ", u / det);
420 debugRaySimple(
"intersectTriangle() did not intersect: u out of range");
424 const auto qvec = tvec.cross(edge1);
425 const auto v = direction * qvec;
426 debugRaySimple(
" v = ",
v);
427 debugRaySimple(
" v / det = ",
v / det);
428 debugRaySimple(
" (u + v) / det = ", (u +
v) / det);
431 debugRaySimple(
"intersectTriangle() did not intersect: v out of range");
435 const auto possible_distance = (edge2 * qvec) / det;
436 debugRaySimple(
" possible_distance = ", possible_distance);
439 debugRaySimple(
"intersectTriangle() did not intersect: distance too small");
445 intersection_distance = possible_distance * hmax;
456 intersected_extrema.
setEdge(v0, v2);
463 intersected_extrema.
setEdge(v0, v1);
466 intersected_extrema.
setEdge(v1, v2);
468 debugRaySimple(
"intersectTriangle() intersected with:");
469 debugRaySimple(
" intersection_distance = ", intersection_distance);
470 debugRaySimple(
" intersected_extrema = ", intersected_extrema);
477 const Point & direction,
478 const Elem *
const elem,
479 const unsigned short v00,
480 const unsigned short v10,
481 const unsigned short v11,
482 const unsigned short v01,
483 Real & intersection_distance,
486 #ifdef DEBUG_RAY_INTERSECTIONS
492 mooseAssert(intersected_extrema.
isInvalid(),
"Should be invalid");
493 debugRaySimple(
"intersectQuad() called:");
494 debugRaySimple(
" start = ", start);
495 debugRaySimple(
" direction = ", direction);
496 debugRaySimple(
" elem->id() = ", elem->
id());
497 debugRaySimple(
" v00 = ", v00,
" at ", elem->
point(v00));
498 debugRaySimple(
" v10 = ", v10,
" at ", elem->
point(v10));
499 debugRaySimple(
" v11 = ", v11,
" at ", elem->
point(v11));
500 debugRaySimple(
" v01 = ", v01,
" at ", elem->
point(v01));
516 intersection_distance,
519 #ifdef DEBUG_RAY_INTERSECTIONS
532 intersection_distance,
535 #ifdef DEBUG_RAY_INTERSECTIONS
544 if (intersects && intersected_extrema.
atEdge(v00, v11))
572 template <
typename T>
577 const Real tolerance )
579 mooseAssert(extrema.
isInvalid(),
"Should be invalid");
581 for (
int e = 0; e < T::num_edges; ++e)
583 elem->
point(T::edge_nodes_map[e][1]),
587 extrema.
setEdge(T::edge_nodes_map[e][0], T::edge_nodes_map[e][1]);
598 const Real tolerance )
600 switch (elem->
type())
605 return withinEdgeTempl<Hex8>(elem, point, extrema, tolerance);
609 return withinEdgeTempl<Tet4>(elem, point, extrema, tolerance);
613 return withinEdgeTempl<Pyramid5>(elem, point, extrema, tolerance);
617 return withinEdgeTempl<Prism6>(elem, point, extrema, tolerance);
621 " not supported in TraceRayTools::withinEdge()");
630 switch (elem->
type())
635 return atVertexOnSideTempl<Hex8>(elem, point, side);
639 return atVertexOnSideTempl<Quad4>(elem, point, side);
643 return atVertexOnSideTempl<Tri3>(elem, point, side);
647 return atVertexOnSideTempl<Tet4>(elem, point, side);
651 return atVertexOnSideTempl<Pyramid5>(elem, point, side);
655 return atVertexOnSideTempl<Prism6>(elem, point, side);
659 return atVertexOnSideTempl<Edge2>(elem, point, side);
663 " not supported in TraceRayTools::atVertexOnSide()");
669 template <
typename T>
670 typename std::enable_if<!std::is_base_of<Edge, T>::value,
unsigned short>::type
673 mooseAssert(side < elem->n_sides(),
"Invalid side");
675 "Side does not contain point");
677 for (
int i = 0; i < nodesPerSide<T>(side); ++i)
679 return T::side_nodes_map[side][i];
684 template <
typename T>
685 typename std::enable_if<std::is_base_of<Edge, T>::value,
unsigned short>::type
688 mooseAssert(side < elem->n_sides(),
"Invalid side");
690 "Side does not contain point");
701 const unsigned short side,
704 switch (elem->
type())
709 return withinEdgeOnSideTempl<Hex8>(elem, point, side, extrema);
713 return withinEdgeOnSideTempl<Tet4>(elem, point, side, extrema);
717 return withinEdgeOnSideTempl<Pyramid5>(elem, point, side, extrema);
721 return withinEdgeOnSideTempl<Prism6>(elem, point, side, extrema);
725 " not supported in TraceRayTools::withinEdgeOnSide()");
731 template <
typename T>
732 typename std::enable_if<std::is_base_of<Cell, T>::value,
bool>::type
735 const unsigned short side,
738 mooseAssert(side < elem->n_sides(),
"Invalid side");
740 "Side does not contain point");
741 mooseAssert(extrema.
isInvalid(),
"Should be invalid");
743 int last_n = T::side_nodes_map[side][nodesPerSide<T>(side) - 1];
745 for (
int side_v = 0; side_v < nodesPerSide<T>(side); ++side_v)
748 extrema.
setEdge(last_n, T::side_nodes_map[side][side_v]);
750 "Edge doesn't contain point");
754 last_n = T::side_nodes_map[side][side_v];
762 const unsigned short side,
763 const unsigned int dim,
766 mooseAssert(extrema.
isInvalid(),
"Extrema should be invalid");
767 mooseAssert(
dim == elem->
dim(),
"Incorrect dim");
780 const Point & segment2,
782 const Real tolerance )
786 const auto segment_length = (segment1 - segment2).
norm();
787 return isWithinSegment(segment1, segment2, segment_length, point, tolerance);
792 const Point & segment2,
793 const Real segment_length,
795 const Real tolerance )
799 "Invalid segment length");
801 const auto diff1 = point - segment1;
802 const auto diff2 = point - segment2;
804 if (diff1 * diff2 > tolerance * segment_length)
807 return std::abs(diff1.norm() + diff2.norm() - segment_length) < tolerance * segment_length;
813 const unsigned int dim,
814 const Real tolerance)
816 for (
unsigned int d = 0;
d <
dim; ++
d)
static const unsigned short invalid_vertex
Identifier for an invalid vertex index.
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void setEdge(const unsigned short v1, const unsigned short v2)
Sets the "at edge" state.
const unsigned int invalid_uint
unsigned int get_node_index(const Node *node_ptr) const
void mooseError(Args &&... args)
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const=0
Helper for defining if at an element's edge, vertex, or neither.
std::unique_ptr< const libMesh::Elem > buildEdge(const Elem *elem) const
virtual unsigned int n_children() const=0
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
unsigned int which_neighbor_am_i(const Elem *e) const
const Point & min() const
void find_point_neighbors(const Point &p, std::set< const Elem * > &neighbor_set) const
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const
bool contains(const T &value) const
bool absolute_fuzzy_equals(const TypeVector< Real > &rhs, Real tol=TOLERANCE) const
std::string enum_to_string(const T e)
const Elem * neighbor_ptr(unsigned int i) const
void setVertex(const unsigned short vertex)
Sets the "at vertex" state.
virtual unsigned int n_vertices() const=0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
void invalidate()
Invalidates the current state.
virtual unsigned short dim() const=0
virtual bool is_vertex(const unsigned int i) const=0
const Point & max() const
virtual ElemType type() const=0
const Point & point(const unsigned int i) const
const Elem * child_ptr(unsigned int i) const