25 #include "libmesh/face.h" 26 #include "libmesh/cell_hex.h" 27 #include "libmesh/cell_prism.h" 28 #include "libmesh/cell_pyramid.h" 29 #include "libmesh/cell_tet.h" 30 #include "libmesh/remote_elem.h" 83 const Point & direction,
87 Point & intersection_point,
88 Real & intersection_distance,
90 #ifdef DEBUG_RAY_INTERSECTIONS
105 const Point & segment2,
119 const Point & segment2,
120 const Real segment_length,
136 const Elem *
const elem,
141 std::vector<const Elem *> active_neighbor_children,
142 std::vector<NeighborInfo> &
info);
145 const Elem *
const elem,
146 const Node *
const node,
150 std::vector<const Elem *> active_neighbor_children,
151 std::vector<NeighborInfo> &
info);
154 const Elem *
const elem,
155 const Node *
const node1,
156 const Node *
const node2,
160 std::vector<const Elem *> active_neighbor_children,
161 std::vector<NeighborInfo> &
info);
177 template <
typename KeepFunctor>
180 const Elem *
const elem,
184 std::vector<const Elem *> active_neighbor_children,
185 KeepFunctor & keep_functor)
187 mooseAssert(elem->active(),
"Inactive element");
189 neighbor_set.
clear();
190 untested_set.
clear();
191 next_untested_set.
clear();
193 untested_set.
insert(elem);
195 while (!untested_set.
empty())
198 for (
const Elem *
const test_elem : untested_set)
199 for (
const auto *
const current_neighbor : test_elem->neighbor_ptr_range())
200 if (current_neighbor && current_neighbor !=
remote_elem &&
201 current_neighbor != elem)
203 if (current_neighbor->active())
205 if (!neighbor_set.
contains(current_neighbor) && keep_functor(current_neighbor))
207 next_untested_set.
insert(current_neighbor);
208 neighbor_set.
insert(current_neighbor);
211 #ifdef LIBMESH_ENABLE_AMR 215 current_neighbor->active_family_tree_by_neighbor(active_neighbor_children, test_elem);
217 for (
const Elem * current_child : active_neighbor_children)
218 if (!neighbor_set.
contains(current_child) && keep_functor(current_child) &&
219 current_child != elem)
221 next_untested_set.
insert(current_child);
222 neighbor_set.
insert(current_child);
225 #endif // #ifdef LIBMESH_ENABLE_AMR 227 untested_set.swap(next_untested_set);
228 next_untested_set.
clear();
232 template <
typename T>
235 const Elem *
const elem,
236 const Node *
const vertex1,
237 const Node *
const vertex2,
238 const Real edge_length,
239 std::vector<NeighborInfo> &
info)
243 mooseAssert(dynamic_cast<const T *>(candidate),
"Incorrect elem type");
244 const T *
const T_candidate =
static_cast<const T *
>(candidate);
247 auto v1 = T_candidate->get_node_index(vertex1);
248 auto v2 = T_candidate->get_node_index(vertex2);
254 if (has_v1 && has_v2)
257 for (MooseIndex(T::num_edges) e = 0; e < T::num_edges; ++e)
258 if (T_candidate->is_node_on_edge(v1, e) && T_candidate->is_node_on_edge(v2, e))
260 std::vector<unsigned short>
sides(2);
261 sides[0] = T::edge_sides_map[e][0];
262 sides[1] = T::edge_sides_map[e][1];
263 info.emplace_back(candidate, std::move(
sides), 0, 1);
267 mooseError(
"Failed to find a side that the vertices are on");
270 const auto n_vertices = T_candidate->n_vertices();
274 if (has_v1 || has_v2)
277 const auto common_v = has_v1 ? v1 : v2;
280 MooseIndex(n_vertices) other_v;
281 for (other_v = 0; other_v < n_vertices; ++other_v)
282 if (other_v != common_v &&
283 isWithinSegment(*vertex1, *vertex2, edge_length, T_candidate->point(other_v)))
288 if (other_v != n_vertices)
290 for (MooseIndex(T::num_edges) e = 0; e < T::num_edges; ++e)
291 if (T_candidate->is_node_on_edge(common_v, e) && T_candidate->is_node_on_edge(other_v, e))
293 std::vector<unsigned short>
sides(2);
294 sides[0] = T::edge_sides_map[e][0];
295 sides[1] = T::edge_sides_map[e][1];
300 has_v1 ? 0 : (T_candidate->point(other_v) - (Point)*vertex1).norm() / edge_length,
301 has_v1 ? (T_candidate->point(other_v) - (Point)*vertex1).norm() / edge_length : 1);
304 mooseError(
"Failed to find a side that the vertices are on");
306 else if (T_candidate->level() < elem->level())
308 for (MooseIndex(T::num_edges) e = 0; e < T::num_edges; ++e)
309 if (T_candidate->is_node_on_edge(common_v, e) &&
311 T_candidate->point(T::edge_nodes_map[e][1]),
312 has_v1 ? *vertex2 : *vertex1))
314 other_v = T::edge_nodes_map[e][0] == common_v ? T::edge_nodes_map[e][1]
315 : T::edge_nodes_map[e][0];
316 std::vector<unsigned short>
sides(2);
317 sides[0] = T::edge_sides_map[e][0];
318 sides[1] = T::edge_sides_map[e][1];
323 has_v1 ? 0 : (T_candidate->point(other_v) - (Point)*vertex1).norm() / edge_length,
324 has_v1 ? (T_candidate->point(other_v) - (Point)*vertex1).norm() / edge_length : 1);
333 else if (T_candidate->level() < elem->level())
339 for (MooseIndex(T::num_edges) e = 0; e < T::num_edges; ++e)
343 T_candidate->point(T::edge_nodes_map[e][1]),
348 T_candidate->point(T::edge_nodes_map[e][1]),
356 if (v1_within && v2_within)
358 mooseAssert(v1_edge == v2_edge,
"Vertices should be contained in same edge");
360 std::vector<unsigned short>
sides(2);
361 sides[0] = T::edge_sides_map[v1_edge][0];
362 sides[1] = T::edge_sides_map[v1_edge][1];
363 info.emplace_back(candidate, std::move(
sides), 0, 1);
366 else if (v1_within || v2_within)
368 const auto in_edge = v1_within ? v1_edge : v2_edge;
369 const Point & check_point = v1_within ? *vertex2 : *vertex1;
371 std::vector<unsigned short>
sides(1);
372 Real lower_bound = 0;
373 Real upper_bound = 1;
375 if (candidate->side_ptr(T::edge_sides_map[in_edge][0])->contains_point(check_point))
376 sides[0] = T::edge_sides_map[in_edge][0];
377 else if (candidate->side_ptr(T::edge_sides_map[in_edge][1])->contains_point(check_point))
378 sides[0] = T::edge_sides_map[in_edge][1];
381 const Real point_bound = v1_within ? 0 : 1;
382 lower_bound = point_bound;
383 upper_bound = point_bound;
384 sides[0] = T::edge_sides_map[in_edge][0];
385 sides.push_back(T::edge_sides_map[in_edge][1]);
388 info.emplace_back(candidate, std::move(
sides), lower_bound, upper_bound);
398 for (v1 = 0; v1 < n_vertices; ++v1)
399 if (
isWithinSegment(*vertex1, *vertex2, edge_length, candidate->point(v1)))
401 for (v2 = v1 + 1; v2 < n_vertices; ++v2)
402 if (
isWithinSegment(*vertex1, *vertex2, edge_length, candidate->point(v2)))
408 if (v1 == n_vertices)
412 if (v2 >= n_vertices)
414 std::vector<unsigned short>
sides;
417 for (MooseIndex(T::num_sides) s = 0; s < T::num_sides; ++s)
418 if (T_candidate->is_node_on_side(v1, s))
422 mooseError(
"Failed to find sides that the vertex is on");
425 const auto bound = (T_candidate->point(v1) - (Point)*vertex1).norm() / edge_length;
426 info.emplace_back(candidate, std::move(
sides), bound, bound);
432 for (MooseIndex(T::num_edges) e = 0; e < T::num_edges; ++e)
433 if (T_candidate->is_node_on_edge(v1, e) && T_candidate->is_node_on_edge(v2, e))
435 auto lower_bound = (T_candidate->point(v1) - (Point)*vertex1).norm() / edge_length;
436 auto upper_bound = (T_candidate->point(v2) - (Point)*vertex1).norm() / edge_length;
437 if (lower_bound > upper_bound)
439 const auto temp = lower_bound;
440 lower_bound = upper_bound;
444 std::vector<unsigned short>
sides(2);
445 sides[0] = T::edge_sides_map[e][0];
446 sides[1] = T::edge_sides_map[e][1];
447 info.emplace_back(candidate, std::move(
sides), lower_bound, upper_bound);
451 mooseError(
"Failed to find sides that the vertices are on");
476 const Elem *
getActiveNeighbor(
const Elem * elem,
const unsigned short side,
const Point & point);
495 const Point & direction,
496 const Elem *
const elem,
497 const unsigned short v0,
498 const unsigned short v1,
499 const unsigned short v2,
500 Real & intersection_distance,
503 #ifdef DEBUG_RAY_INTERSECTIONS
534 const Point & direction,
535 const Elem *
const elem,
536 const unsigned short v00,
537 const unsigned short v10,
538 const unsigned short v11,
539 const unsigned short v01,
540 Real & intersection_distance,
543 #ifdef DEBUG_RAY_INTERSECTIONS
562 template <
typename T>
563 typename std::enable_if<std::is_base_of<libMesh::Face, T>::value,
bool>::type
565 const Point & start_point,
566 const Point & direction,
567 const unsigned short side,
568 const Real max_length,
569 Point & intersection_point,
570 Real & intersection_distance,
573 #ifdef DEBUG_RAY_INTERSECTIONS
580 mooseAssert(intersected_extrema.
isInvalid(),
"Should be invalid");
587 elem->point(T::side_nodes_map[side][0]),
588 elem->point(T::side_nodes_map[side][1]),
590 intersection_distance,
592 #ifdef DEBUG_RAY_INTERSECTIONS 600 intersected_extrema.
setVertex(T::side_nodes_map[side][segment_vertex]);
602 intersected_extrema.
vertexPoint(elem).absolute_fuzzy_equals(intersection_point,
623 template <
typename T>
624 typename std::enable_if<std::is_base_of<Hex, T>::value,
bool>::type
626 const Point & start_point,
627 const Point & direction,
628 const unsigned short side,
630 Point & intersection_point,
631 Real & intersection_distance,
634 #ifdef DEBUG_RAY_INTERSECTIONS
640 mooseAssert(elem->first_order_equivalent_type(elem->type()) ==
HEX8,
"Not a Hex");
642 mooseAssert(intersected_extrema.
isInvalid(),
"Should be invalid");
647 T::side_nodes_map[side][3],
648 T::side_nodes_map[side][2],
649 T::side_nodes_map[side][1],
650 T::side_nodes_map[side][0],
651 intersection_distance,
654 #ifdef DEBUG_RAY_INTERSECTIONS
661 intersection_point = start_point + intersection_distance * direction;
680 template <
typename T>
681 typename std::enable_if<std::is_base_of<Tet, T>::value,
bool>::type
683 const Point & start_point,
684 const Point & direction,
685 const unsigned short side,
687 Point & intersection_point,
688 Real & intersection_distance,
691 #ifdef DEBUG_RAY_INTERSECTIONS
697 mooseAssert(elem->first_order_equivalent_type(elem->type()) ==
TET4,
"Not a Tet");
699 mooseAssert(intersected_extrema.
isInvalid(),
"Should be invalid");
704 T::side_nodes_map[side][2],
705 T::side_nodes_map[side][1],
706 T::side_nodes_map[side][0],
707 intersection_distance,
710 #ifdef DEBUG_RAY_INTERSECTIONS
717 intersection_point = start_point + intersection_distance * direction;
736 template <
typename T>
737 typename std::enable_if<std::is_base_of<libMesh::Pyramid, T>::value,
bool>::type
739 const Point & start_point,
740 const Point & direction,
741 const unsigned short side,
743 Point & intersection_point,
744 Real & intersection_distance,
747 #ifdef DEBUG_RAY_INTERSECTIONS
753 mooseAssert(elem->first_order_equivalent_type(elem->type()) ==
PYRAMID5,
"Not a Pyramid");
755 mooseAssert(intersected_extrema.
isInvalid(),
"Should be invalid");
760 T::side_nodes_map[side][2],
761 T::side_nodes_map[side][1],
762 T::side_nodes_map[side][0],
763 intersection_distance,
766 #ifdef DEBUG_RAY_INTERSECTIONS
774 T::side_nodes_map[side][3],
775 T::side_nodes_map[side][2],
776 T::side_nodes_map[side][1],
777 T::side_nodes_map[side][0],
778 intersection_distance,
781 #ifdef DEBUG_RAY_INTERSECTIONS
788 intersection_point = start_point + intersection_distance * direction;
807 template <
typename T>
808 typename std::enable_if<std::is_base_of<libMesh::Prism, T>::value,
bool>::type
810 const Point & start_point,
811 const Point & direction,
812 const unsigned short side,
814 Point & intersection_point,
815 Real & intersection_distance,
818 #ifdef DEBUG_RAY_INTERSECTIONS
824 mooseAssert(elem->first_order_equivalent_type(elem->type()) ==
PRISM6,
"Not a Prism");
826 mooseAssert(intersected_extrema.
isInvalid(),
"Should be invalid");
828 const bool intersected = (side == 0 || side == 4) ?
intersectTriangle(start_point,
831 T::side_nodes_map[side][2],
832 T::side_nodes_map[side][1],
833 T::side_nodes_map[side][0],
834 intersection_distance,
837 #ifdef DEBUG_RAY_INTERSECTIONS
845 T::side_nodes_map[side][3],
846 T::side_nodes_map[side][2],
847 T::side_nodes_map[side][1],
848 T::side_nodes_map[side][0],
849 intersection_distance,
852 #ifdef DEBUG_RAY_INTERSECTIONS
859 intersection_point = start_point + intersection_distance * direction;
879 unsigned short atVertex(
const Elem * elem,
const Point & point);
888 unsigned short atVertexOnSide(
const Elem * elem,
const Point & point,
const unsigned short side);
893 template <
typename T>
894 inline typename std::enable_if<!std::is_base_of<libMesh::Pyramid, T>::value &&
895 !std::is_base_of<libMesh::Prism, T>::value,
896 unsigned short>::type
899 return T::nodes_per_side;
905 template <
typename T>
906 inline typename std::enable_if<std::is_base_of<Pyramid, T>::value,
unsigned short>::type
909 return T::nodes_per_side - (side != 4);
915 template <
typename T>
916 inline typename std::enable_if<std::is_base_of<libMesh::Prism, T>::value,
unsigned short>::type
919 return T::nodes_per_side - (side == 0 || side == 4);
935 template <
typename T>
936 typename std::enable_if<!std::is_base_of<Edge, T>::value,
unsigned short>::type
952 template <
typename T>
953 typename std::enable_if<std::is_base_of<Edge, T>::value,
unsigned short>::type
969 template <
typename T>
1000 const unsigned short side,
1013 const Point & point,
1014 const unsigned short side,
1015 const unsigned int dim,
1033 template <
typename T>
1034 typename std::enable_if<std::is_base_of<libMesh::Cell, T>::value,
bool>::type
withinEdgeOnSideTempl(
1035 const Elem *
const elem,
const Point & point,
const unsigned short side,
ElemExtrema & extrema);
1043 template <
typename T>
1044 typename std::enable_if<!std::is_base_of<libMesh::Cell, T>::value,
bool>::type
1047 mooseError(
"Should not call withinEdgeOnSideTempl() with a non-Cell derived Elem");
1056 const Point & point,
1057 const unsigned int dim,
1058 const Real tolerance);
const unsigned int invalid_uint
void mooseError(Args &&... args)
Helper for defining if at an element's edge, vertex, or neither.
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
bool contains(const T &value) const
std::string stringify(const T &t)
void setVertex(const unsigned short vertex)
Sets the "at vertex" state.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const libMesh::Point invalid_point(invalid_distance, invalid_distance, invalid_distance)
Identifier for an invalid point.
static const unsigned short invalid_edge
Identifier for an invalid edge index.
void insert(const T &value)
const Point & vertexPoint(const libMesh::Elem *elem) const
const RemoteElem * remote_elem