https://mooseframework.inl.gov
TraceRayTools.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #pragma once
11 
12 // MOOSE includes
13 #include "StaticallyAllocatedSet.h"
14 #include "Conversion.h"
15 #include "MooseTypes.h"
17 
18 // Local includes
19 #include "DebugRay.h"
20 #include "ElemExtrema.h"
21 #include "RayTracingCommon.h"
22 #include "NeighborInfo.h"
23 
24 // libMesh includes
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"
31 
32 namespace libMesh
33 {
34 class Mesh;
35 class Edge;
36 class Cell;
37 }
38 
39 namespace TraceRayTools
40 {
41 
43 extern const std::set<int> TRACEABLE_ELEMTYPES;
45 extern const std::set<int> ADAPTIVITY_TRACEABLE_ELEMTYPES;
46 
48 const Real TRACE_TOLERANCE = 1e-8;
51 
53 const int INVALID_INT = std::numeric_limits<int>::max();
54 
59 {
63 };
64 
82 bool lineLineIntersect2D(const Point & start,
83  const Point & direction,
84  const Real length,
85  const Point & v0,
86  const Point & v1,
87  Point & intersection_point,
88  Real & intersection_distance,
89  SegmentVertices & segment_vertex
90 #ifdef DEBUG_RAY_INTERSECTIONS
91  ,
92  const bool debug
93 #endif
94 );
95 
104 bool isWithinSegment(const Point & segment1,
105  const Point & segment2,
106  const Point & point,
107  const Real tolerance = TRACE_TOLERANCE);
108 
118 bool isWithinSegment(const Point & segment1,
119  const Point & segment2,
120  const Real segment_length,
121  const Point & point,
122  const Real tolerance = TRACE_TOLERANCE);
123 
135 void findPointNeighbors(
136  const Elem * const elem,
137  const Point & point,
141  std::vector<const Elem *> active_neighbor_children,
142  std::vector<NeighborInfo> & info);
143 
144 void findNodeNeighbors(
145  const Elem * const elem,
146  const Node * const node,
150  std::vector<const Elem *> active_neighbor_children,
151  std::vector<NeighborInfo> & info);
152 
153 void findEdgeNeighbors(
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);
162 
177 template <typename KeepFunctor>
178 void
180  const Elem * const elem,
184  std::vector<const Elem *> active_neighbor_children,
185  KeepFunctor & keep_functor)
186 {
187  mooseAssert(elem->active(), "Inactive element");
188 
189  neighbor_set.clear();
190  untested_set.clear();
191  next_untested_set.clear();
192 
193  untested_set.insert(elem);
194 
195  while (!untested_set.empty())
196  {
197  // Loop over all the elements in the patch that haven't already been tested
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) // we have a real neighbor on elem side
202  {
203  if (current_neighbor->active()) // ... if it is active
204  {
205  if (!neighbor_set.contains(current_neighbor) && keep_functor(current_neighbor))
206  {
207  next_untested_set.insert(current_neighbor);
208  neighbor_set.insert(current_neighbor);
209  }
210  }
211 #ifdef LIBMESH_ENABLE_AMR
212  else // ... the neighbor is *not* active,
213  { // ... so add *all* neighboring
214  // active children that touch p
215  current_neighbor->active_family_tree_by_neighbor(active_neighbor_children, test_elem);
216 
217  for (const Elem * current_child : active_neighbor_children)
218  if (!neighbor_set.contains(current_child) && keep_functor(current_child) &&
219  current_child != elem)
220  {
221  next_untested_set.insert(current_child);
222  neighbor_set.insert(current_child);
223  }
224  }
225 #endif // #ifdef LIBMESH_ENABLE_AMR
226  }
227  untested_set.swap(next_untested_set);
228  next_untested_set.clear();
229  }
230 }
231 
232 template <typename T>
233 bool
234 findEdgeNeighborsWithinEdgeInternal(const Elem * const candidate,
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)
240 {
241  // If we have the type already: use it so we can avoid all of the virtual
242  // calls that we would be making on Elem
243  mooseAssert(dynamic_cast<const T *>(candidate), "Incorrect elem type");
244  const T * const T_candidate = static_cast<const T *>(candidate);
245 
246  // Local index of our two vertices of interest (if any)
247  auto v1 = T_candidate->get_node_index(vertex1);
248  auto v2 = T_candidate->get_node_index(vertex2);
249  // Whether or not we have said vertices
250  const bool has_v1 = v1 != invalid_uint;
251  const bool has_v2 = v2 != invalid_uint;
252 
253  // If the candidate has both vertices, it shares the complete edge
254  if (has_v1 && has_v2)
255  {
256  // Add the sides that contain said edge
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))
259  {
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);
264  return true;
265  }
266 
267  mooseError("Failed to find a side that the vertices are on");
268  }
269 
270  const auto n_vertices = T_candidate->n_vertices();
271 
272  // If we only have one of the vertices, we can still be contained within the edge if we have
273  // another vertex that is within the edge
274  if (has_v1 || has_v2)
275  {
276  // Local index of the vertex that the candidate and the target edge have in common
277  const auto common_v = has_v1 ? v1 : v2;
278 
279  // See if another vertex that isn't the common node is contained
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)))
284  break;
285 
286  // If we have the common vertex and another vertex within the target edge, use the sides
287  // that contain both of those vertices
288  if (other_v != n_vertices)
289  {
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))
292  {
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];
296 
297  info.emplace_back(
298  candidate,
299  std::move(sides),
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);
302  return true;
303  }
304  mooseError("Failed to find a side that the vertices are on");
305  }
306  else if (T_candidate->level() < elem->level())
307  {
308  for (MooseIndex(T::num_edges) e = 0; e < T::num_edges; ++e)
309  if (T_candidate->is_node_on_edge(common_v, e) &&
310  isWithinSegment(T_candidate->point(T::edge_nodes_map[e][0]),
311  T_candidate->point(T::edge_nodes_map[e][1]),
312  has_v1 ? *vertex2 : *vertex1))
313  {
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];
319 
320  info.emplace_back(
321  candidate,
322  std::move(sides),
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);
325  return true;
326  }
327 
328  return false;
329  }
330  }
331  // When the candidate level is less, one of our vertices could be in a candidate's face and the
332  // other could be within one of the candidate's edges
333  else if (T_candidate->level() < elem->level())
334  {
335  auto v1_edge = RayTracingCommon::invalid_edge;
336  auto v2_edge = RayTracingCommon::invalid_edge;
337 
338  // See if any of the edges contain one of the vertices
339  for (MooseIndex(T::num_edges) e = 0; e < T::num_edges; ++e)
340  {
341  if (v1_edge == RayTracingCommon::invalid_edge &&
342  isWithinSegment(T_candidate->point(T::edge_nodes_map[e][0]),
343  T_candidate->point(T::edge_nodes_map[e][1]),
344  *vertex1))
345  v1_edge = e;
346  if (v2_edge == RayTracingCommon::invalid_edge &&
347  isWithinSegment(T_candidate->point(T::edge_nodes_map[e][0]),
348  T_candidate->point(T::edge_nodes_map[e][1]),
349  *vertex2))
350  v2_edge = e;
351  }
352 
353  const auto v1_within = v1_edge != RayTracingCommon::invalid_edge;
354  const auto v2_within = v2_edge != RayTracingCommon::invalid_edge;
355 
356  if (v1_within && v2_within)
357  {
358  mooseAssert(v1_edge == v2_edge, "Vertices should be contained in same edge");
359 
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);
364  return true;
365  }
366  else if (v1_within || v2_within)
367  {
368  const auto in_edge = v1_within ? v1_edge : v2_edge;
369  const Point & check_point = v1_within ? *vertex2 : *vertex1;
370 
371  std::vector<unsigned short> sides(1);
372  Real lower_bound = 0;
373  Real upper_bound = 1;
374 
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];
379  else
380  {
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]);
386  }
387 
388  info.emplace_back(candidate, std::move(sides), lower_bound, upper_bound);
389  return true;
390  }
391 
392  return false;
393  }
394  // If we have neither of the vertices, and the candidate's edge can't fully contain [vertex1,
395  // vertex2], check for other vertices that are contained within the edge
396  else
397  {
398  for (v1 = 0; v1 < n_vertices; ++v1)
399  if (isWithinSegment(*vertex1, *vertex2, edge_length, candidate->point(v1)))
400  {
401  for (v2 = v1 + 1; v2 < n_vertices; ++v2)
402  if (isWithinSegment(*vertex1, *vertex2, edge_length, candidate->point(v2)))
403  break;
404  break;
405  }
406 
407  // No vertices are contained within the edge
408  if (v1 == n_vertices)
409  return false;
410 
411  // Only one vertex contained: add the sides associated with that vertex
412  if (v2 >= n_vertices)
413  {
414  std::vector<unsigned short> sides;
415  sides.reserve(2);
416 
417  for (MooseIndex(T::num_sides) s = 0; s < T::num_sides; ++s)
418  if (T_candidate->is_node_on_side(v1, s))
419  sides.push_back(s);
420 
421  if (sides.empty())
422  mooseError("Failed to find sides that the vertex is on");
423 
424  // Bounds are the same because we only touch at a point
425  const auto bound = (T_candidate->point(v1) - (Point)*vertex1).norm() / edge_length;
426  info.emplace_back(candidate, std::move(sides), bound, bound);
427  return true;
428  }
429  // Two vertices contained: find the sides that contain both vertices
430  else
431  {
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))
434  {
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)
438  {
439  const auto temp = lower_bound;
440  lower_bound = upper_bound;
441  upper_bound = temp;
442  }
443 
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);
448  return true;
449  }
450 
451  mooseError("Failed to find sides that the vertices are on");
452  }
453  }
454 
455  return false;
456 }
457 
465 const Elem *
466 childContainingPointOnSide(const Elem * elem, const Point & point, const unsigned short side);
467 
476 const Elem * getActiveNeighbor(const Elem * elem, const unsigned short side, const Point & point);
477 
494 bool intersectTriangle(const Point & start,
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,
501  ElemExtrema & intersected_extrema,
502  const Real hmax
503 #ifdef DEBUG_RAY_INTERSECTIONS
504  ,
505  const bool debug
506 #endif
507 );
508 
533 bool intersectQuad(const Point & start,
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,
541  ElemExtrema & intersected_extrema,
542  const Real hmax
543 #ifdef DEBUG_RAY_INTERSECTIONS
544  ,
545  const bool debug
546 #endif
547 );
548 
562 template <typename T>
563 typename std::enable_if<std::is_base_of<libMesh::Face, T>::value, bool>::type
564 sideIntersectedByLine(const Elem * elem,
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,
571  ElemExtrema & intersected_extrema,
572  const Real /* hmax */
573 #ifdef DEBUG_RAY_INTERSECTIONS
574  ,
575  const bool debug
576 #endif
577 )
578 {
579  mooseAssert(intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
580  mooseAssert(intersected_extrema.isInvalid(), "Should be invalid");
581 
582  SegmentVertices segment_vertex = SEGMENT_VERTEX_NONE;
583 
584  const bool intersected = lineLineIntersect2D(start_point,
585  direction,
586  max_length,
587  elem->point(T::side_nodes_map[side][0]),
588  elem->point(T::side_nodes_map[side][1]),
589  intersection_point,
590  intersection_distance,
591  segment_vertex
592 #ifdef DEBUG_RAY_INTERSECTIONS
593  ,
594  debug
595 #endif
596  );
597 
598  if (segment_vertex != SEGMENT_VERTEX_NONE)
599  {
600  intersected_extrema.setVertex(T::side_nodes_map[side][segment_vertex]);
601  mooseAssert(
602  intersected_extrema.vertexPoint(elem).absolute_fuzzy_equals(intersection_point,
603  3 * TRACE_TOLERANCE),
604  "Doesn't intersect vertex at: " + Moose::stringify(intersected_extrema.vertexPoint(elem)) +
605  " tentative intersection point: " + Moose::stringify(intersection_point));
606  }
607 
608  return intersected;
609 }
610 
623 template <typename T>
624 typename std::enable_if<std::is_base_of<Hex, T>::value, bool>::type
625 sideIntersectedByLine(const Elem * elem,
626  const Point & start_point,
627  const Point & direction,
628  const unsigned short side,
629  const Real,
630  Point & intersection_point,
631  Real & intersection_distance,
632  ElemExtrema & intersected_extrema,
633  const Real hmax
634 #ifdef DEBUG_RAY_INTERSECTIONS
635  ,
636  const bool debug
637 #endif
638 )
639 {
640  mooseAssert(elem->first_order_equivalent_type(elem->type()) == HEX8, "Not a Hex");
641  mooseAssert(intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
642  mooseAssert(intersected_extrema.isInvalid(), "Should be invalid");
643 
644  const bool intersected = intersectQuad(start_point,
645  direction,
646  elem,
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,
652  intersected_extrema,
653  hmax
654 #ifdef DEBUG_RAY_INTERSECTIONS
655  ,
656  debug
657 #endif
658  );
659 
660  if (intersected)
661  intersection_point = start_point + intersection_distance * direction;
662 
663  return intersected;
664 }
665 
680 template <typename T>
681 typename std::enable_if<std::is_base_of<Tet, T>::value, bool>::type
682 sideIntersectedByLine(const Elem * elem,
683  const Point & start_point,
684  const Point & direction,
685  const unsigned short side,
686  const Real /* max_length */,
687  Point & intersection_point,
688  Real & intersection_distance,
689  ElemExtrema & intersected_extrema,
690  const Real hmax
691 #ifdef DEBUG_RAY_INTERSECTIONS
692  ,
693  const bool debug
694 #endif
695 )
696 {
697  mooseAssert(elem->first_order_equivalent_type(elem->type()) == TET4, "Not a Tet");
698  mooseAssert(intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
699  mooseAssert(intersected_extrema.isInvalid(), "Should be invalid");
700 
701  const bool intersected = intersectTriangle(start_point,
702  direction,
703  elem,
704  T::side_nodes_map[side][2],
705  T::side_nodes_map[side][1],
706  T::side_nodes_map[side][0],
707  intersection_distance,
708  intersected_extrema,
709  hmax
710 #ifdef DEBUG_RAY_INTERSECTIONS
711  ,
712  debug
713 #endif
714  );
715 
716  if (intersected)
717  intersection_point = start_point + intersection_distance * direction;
718 
719  return intersected;
720 }
721 
736 template <typename T>
737 typename std::enable_if<std::is_base_of<libMesh::Pyramid, T>::value, bool>::type
738 sideIntersectedByLine(const Elem * elem,
739  const Point & start_point,
740  const Point & direction,
741  const unsigned short side,
742  const Real /* max_length */,
743  Point & intersection_point,
744  Real & intersection_distance,
745  ElemExtrema & intersected_extrema,
746  const Real hmax
747 #ifdef DEBUG_RAY_INTERSECTIONS
748  ,
749  const bool debug
750 #endif
751 )
752 {
753  mooseAssert(elem->first_order_equivalent_type(elem->type()) == PYRAMID5, "Not a Pyramid");
754  mooseAssert(intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
755  mooseAssert(intersected_extrema.isInvalid(), "Should be invalid");
756 
757  const bool intersected = side < 4 ? intersectTriangle(start_point,
758  direction,
759  elem,
760  T::side_nodes_map[side][2],
761  T::side_nodes_map[side][1],
762  T::side_nodes_map[side][0],
763  intersection_distance,
764  intersected_extrema,
765  hmax
766 #ifdef DEBUG_RAY_INTERSECTIONS
767  ,
768  debug
769 #endif
770  )
771  : intersectQuad(start_point,
772  direction,
773  elem,
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,
779  intersected_extrema,
780  hmax
781 #ifdef DEBUG_RAY_INTERSECTIONS
782  ,
783  debug
784 #endif
785  );
786 
787  if (intersected)
788  intersection_point = start_point + intersection_distance * direction;
789 
790  return intersected;
791 }
792 
807 template <typename T>
808 typename std::enable_if<std::is_base_of<libMesh::Prism, T>::value, bool>::type
809 sideIntersectedByLine(const Elem * elem,
810  const Point & start_point,
811  const Point & direction,
812  const unsigned short side,
813  const Real /* max_length */,
814  Point & intersection_point,
815  Real & intersection_distance,
816  ElemExtrema & intersected_extrema,
817  const Real hmax
818 #ifdef DEBUG_RAY_INTERSECTIONS
819  ,
820  const bool debug
821 #endif
822 )
823 {
824  mooseAssert(elem->first_order_equivalent_type(elem->type()) == PRISM6, "Not a Prism");
825  mooseAssert(intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
826  mooseAssert(intersected_extrema.isInvalid(), "Should be invalid");
827 
828  const bool intersected = (side == 0 || side == 4) ? intersectTriangle(start_point,
829  direction,
830  elem,
831  T::side_nodes_map[side][2],
832  T::side_nodes_map[side][1],
833  T::side_nodes_map[side][0],
834  intersection_distance,
835  intersected_extrema,
836  hmax
837 #ifdef DEBUG_RAY_INTERSECTIONS
838  ,
839  debug
840 #endif
841  )
842  : intersectQuad(start_point,
843  direction,
844  elem,
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,
850  intersected_extrema,
851  hmax
852 #ifdef DEBUG_RAY_INTERSECTIONS
853  ,
854  debug
855 #endif
856  );
857 
858  if (intersected)
859  intersection_point = start_point + intersection_distance * direction;
860 
861  return intersected;
862 }
863 
867 bool isTraceableElem(const Elem * elem);
871 bool isAdaptivityTraceableElem(const Elem * elem);
872 
879 unsigned short atVertex(const Elem * elem, const Point & point);
880 
888 unsigned short atVertexOnSide(const Elem * elem, const Point & point, const unsigned short side);
889 
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
897 nodesPerSide(const unsigned short)
898 {
899  return T::nodes_per_side;
900 }
901 
905 template <typename T>
906 inline typename std::enable_if<std::is_base_of<Pyramid, T>::value, unsigned short>::type
907 nodesPerSide(const unsigned short side)
908 {
909  return T::nodes_per_side - (side != 4);
910 }
911 
915 template <typename T>
916 inline typename std::enable_if<std::is_base_of<libMesh::Prism, T>::value, unsigned short>::type
917 nodesPerSide(const unsigned short side)
918 {
919  return T::nodes_per_side - (side == 0 || side == 4);
920 }
921 
935 template <typename T>
936 typename std::enable_if<!std::is_base_of<Edge, T>::value, unsigned short>::type
937 atVertexOnSideTempl(const Elem * elem, const Point & point, const unsigned short side);
938 
952 template <typename T>
953 typename std::enable_if<std::is_base_of<Edge, T>::value, unsigned short>::type
954 atVertexOnSideTempl(const Elem * elem, const Point & point, const unsigned short side);
955 
969 template <typename T>
970 bool withinEdgeTempl(const Elem * elem,
971  const Point & point,
972  ElemExtrema & extrema,
973  const Real tolerance = TRACE_TOLERANCE);
974 
984 bool withinEdge(const Elem * elem,
985  const Point & point,
986  ElemExtrema & extrema,
987  const Real tolerance = TRACE_TOLERANCE);
988 
998 bool withinEdgeOnSide(const Elem * const elem,
999  const Point & point,
1000  const unsigned short side,
1001  ElemExtrema & extrema);
1002 
1012 bool withinExtremaOnSide(const Elem * const elem,
1013  const Point & point,
1014  const unsigned short side,
1015  const unsigned int dim,
1016  ElemExtrema & extrema);
1017 
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);
1036 
1043 template <typename T>
1044 typename std::enable_if<!std::is_base_of<libMesh::Cell, T>::value, bool>::type
1045 withinEdgeOnSideTempl(const Elem * const, const Point &, const unsigned short, ElemExtrema &)
1046 {
1047  mooseError("Should not call withinEdgeOnSideTempl() with a non-Cell derived Elem");
1048 }
1049 
1055 bool onBoundingBoxBoundary(const BoundingBox & bbox,
1056  const Point & point,
1057  const unsigned int dim,
1058  const Real tolerance);
1059 
1060 }
bool withinExtremaOnSide(const Elem *const elem, const Point &point, const unsigned short side, const unsigned int dim, ElemExtrema &extrema)
Determines if a point is within an Elem&#39;s extrema (at vertex/within edge) on a side.
bool intersectQuad(const Point &start, const Point &direction, const Elem *const elem, const unsigned short v00, const unsigned short v10, const unsigned short v11, const unsigned short v01, Real &intersection_distance, ElemExtrema &intersected_extrema, const Real hmax #ifdef DEBUG_RAY_INTERSECTIONS, const bool debug #endif)
Checks for the intersection of a ray and a quadrilateral, numbered as such:
const std::set< int > ADAPTIVITY_TRACEABLE_ELEMTYPES
The element types that are traceable with adaptivity.
Definition: TraceRayTools.C:45
const int INVALID_INT
Value for an invalid integer.
Definition: TraceRayTools.h:53
const Elem * childContainingPointOnSide(const Elem *elem, const Point &point, const unsigned short side)
Find the child of an elem that contains a point on a specified side of elem.
bool withinEdgeOnSide(const Elem *const elem, const Point &point, const unsigned short side, ElemExtrema &extrema)
Determines if a point is within an edge on the side of an element.
void findPointNeighbors(const Elem *const elem, const Point &point, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &neighbor_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &untested_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &next_untested_set, std::vector< const Elem *> active_neighbor_children, std::vector< NeighborInfo > &info)
Rewrite of the find_point_neighbors function in libMesh, instead using a statically allocated set: re...
const unsigned int invalid_uint
HEX8
void findNeighbors(const Elem *const elem, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &neighbor_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &untested_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &next_untested_set, std::vector< const Elem *> active_neighbor_children, KeepFunctor &keep_functor)
More generalized form of the find_point_neighbors function in libMesh.
bool withinEdgeTempl(const Elem *elem, const Point &point, ElemExtrema &extrema, const Real tolerance=TRACE_TOLERANCE)
Determines if a point is within edge on an element.
MPI_Info info
void mooseError(Args &&... args)
bool isTraceableElem(const Elem *elem)
bool isWithinSegment(const Point &segment1, const Point &segment2, const Point &point, const Real tolerance=TRACE_TOLERANCE)
Checks whether or not a point is within a line segment.
bool isAdaptivityTraceableElem(const Elem *elem)
std::enable_if<!std::is_base_of< libMesh::Pyramid, T >::value &&!std::is_base_of< libMesh::Prism, T >::value, unsigned short >::type nodesPerSide(const unsigned short)
Returns the number of nodes on a side for an Elem that is not a Pyramid or Prism. ...
std::enable_if< std::is_base_of< libMesh::Cell, T >::value, bool >::type withinEdgeOnSideTempl(const Elem *const elem, const Point &point, const unsigned short side, ElemExtrema &extrema)
Determines if a point is within an edge on the side of an element.
std::enable_if< std::is_base_of< libMesh::Face, T >::value, bool >::type sideIntersectedByLine(const Elem *elem, const Point &start_point, const Point &direction, const unsigned short side, const Real max_length, Point &intersection_point, Real &intersection_distance, ElemExtrema &intersected_extrema, const Real #ifdef DEBUG_RAY_INTERSECTIONS, const bool debug #endif)
SFINAE typed object for checking the intersection of a line segment with the face of a Face typed ele...
bool withinEdge(const Elem *elem, const Point &point, ElemExtrema &extrema, const Real tolerance=TRACE_TOLERANCE)
Determines if a point is within an edge on an element.
Helper for defining if at an element&#39;s edge, vertex, or neither.
Definition: ElemExtrema.h:25
const Real LOOSE_TRACE_TOLERANCE
Looser tolerance for use in error checking in difficult situations.
Definition: TraceRayTools.h:50
bool isInvalid() const
Definition: ElemExtrema.h:48
unsigned short atVertexOnSide(const Elem *elem, const Point &point, const unsigned short side)
Determines if a point is at a vertex on the side of en element.
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
const Real TRACE_TOLERANCE
The standard tolerance to use in tracing.
Definition: TraceRayTools.h:48
bool intersectTriangle(const Point &start, const Point &direction, const Elem *const elem, const unsigned short v0, const unsigned short v1, const unsigned short v2, Real &intersection_distance, ElemExtrema &intersected_extrema, const Real hmax #ifdef DEBUG_RAY_INTERSECTIONS, const bool debug #endif)
Checks for the intersection of a ray and a triangular face.
void findNodeNeighbors(const Elem *const elem, const Node *const node, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &neighbor_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &untested_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &next_untested_set, std::vector< const Elem *> active_neighbor_children, std::vector< NeighborInfo > &info)
TET4
char ** sides
std::enable_if<!std::is_base_of< Edge, T >::value, unsigned short >::type atVertexOnSideTempl(const Elem *elem, const Point &point, const unsigned short side)
Determines if a point is at a vertex on the side of an element.
const std::set< int > TRACEABLE_ELEMTYPES
The element types that are traceable.
Definition: TraceRayTools.C:42
bool contains(const T &value) const
std::string stringify(const T &t)
bool findEdgeNeighborsWithinEdgeInternal(const Elem *const candidate, const Elem *const elem, const Node *const vertex1, const Node *const vertex2, const Real edge_length, std::vector< NeighborInfo > &info)
void setVertex(const unsigned short vertex)
Sets the "at vertex" state.
Definition: ElemExtrema.h:118
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
PYRAMID5
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 findEdgeNeighbors(const Elem *const elem, const Node *const node1, const Node *const node2, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &neighbor_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &untested_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &next_untested_set, std::vector< const Elem *> active_neighbor_children, std::vector< NeighborInfo > &info)
PRISM6
bool onBoundingBoxBoundary(const BoundingBox &bbox, const Point &point, const unsigned int dim, const Real tolerance)
Whether or not point is on the boundary (min/max) of bbox.
unsigned short atVertex(const Elem *elem, const Point &point)
Determines if a point is at a vertex of an element.
bool lineLineIntersect2D(const Point &start, const Point &direction, const Real length, const Point &v0, const Point &v1, Point &intersection_point, Real &intersection_distance, SegmentVertices &segment_vertex #ifdef DEBUG_RAY_INTERSECTIONS, const bool debug #endif)
Checks for the intersection of the line u0 -> u1 with the line v0 -> v1, where u0 = start and u1 = st...
SegmentVertices
Enum for the possible vertices on a segment used in lineLineIntersect2D()
Definition: TraceRayTools.h:58
const Elem * getActiveNeighbor(const Elem *elem, const unsigned short side, const Point &point)
Get the active neighbor on side of elem that contains point.
const Point & vertexPoint(const libMesh::Elem *elem) const
Definition: ElemExtrema.C:16
const RemoteElem * remote_elem