https://mooseframework.inl.gov
Public Types | Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
TraceRay Class Reference

Traces Rays through the mesh on a single processor. More...

#include <TraceRay.h>

Public Types

enum  TraceRayResult {
  INTERSECTIONS = 0, FACE_HITS = 1, VERTEX_HITS = 2, EDGE_HITS = 3,
  MOVED_THROUGH_NEIGHBORS = 4, BACKFACE_CULLING_SUCCESSES = 5, BACKFACE_CULLING_FAILURES = 6, INTERSECTION_CALLS = 7,
  VERTEX_NEIGHBOR_BUILDS = 8, VERTEX_NEIGHBOR_LOOKUPS = 9, EDGE_NEIGHBOR_BUILDS = 10, EDGE_NEIGHBOR_LOOKUPS = 11,
  POINT_NEIGHBOR_BUILDS = 12, FAILED_TRACES = 13, ENDED_STATIONARY = 14
}
 Enum for the various results reported by this object. More...
 

Public Member Functions

 TraceRay (RayTracingStudy &study, const THREAD_ID tid)
 
virtual ~TraceRay ()
 
void preExecute ()
 Should be called immediately before calling any traces. More...
 
void meshChanged ()
 Called on mesh change. More...
 
void trace (const std::shared_ptr< Ray > &ray)
 Traces a ray. More...
 
std::vector< unsigned long long intresults () const
 Get the various results reported by this object, indexed by TraceRayResult. More...
 
void setBackfaceCulling (const bool backface_culling)
 Enable or disable the use of element normals for backface culling through the getElemNormals() method. More...
 
const std::shared_ptr< Ray > *const & currentRay () const
 Gets the current Ray that is being traced. More...
 
const Elem *const & currentElem () const
 Gets the element that the current Ray is being traced in. More...
 
const Point & currentIntersectionPoint () const
 Gets the current intersection point for the Ray that is being traced. More...
 
const Point & currentIncomingPoint () const
 Gets the current incoming point for the Ray that is being traced. More...
 
const unsigned short & currentIncomingSide () const
 Gets the current incoming side for the Ray that is being traced. More...
 
const unsigned short & currentIntersectedSide () const
 Gets the side that the current Ray intersected. More...
 
const ElemExtremacurrentIntersectedExtrema () const
 Gets the element extrema (vertex/edge) that the current Ray intersected. More...
 
const RealcurrentIntersectionDistance () const
 Gets the current intersection distance for the Ray that is being traced. More...
 
const BoundaryIDcurrentBoundaryID () const
 Gets the BoundaryID of the boundary that the Ray intersected and is being applied a boundary condition. More...
 
const SubdomainIDcurrentSubdomainID () const
 Gets the subdomain of the current element that the Ray is being traced in. More...
 
const std::vector< NeighborInfo > & getVertexNeighbors (const Elem *elem, const Node *vertex)
 Gets the neighbors at a vertex. More...
 
const std::vector< NeighborInfo > & getVertexNeighbors (const Elem *elem, const unsigned short vertex)
 Gets the neighbors at a vertex. More...
 
const std::vector< NeighborInfo > & getEdgeNeighbors (const Elem *elem, const std::pair< const Node *, const Node *> &vertices, const Point &point)
 Get the neighbors at an edge. More...
 
const std::vector< NeighborInfo > & getEdgeNeighbors (const Elem *elem, const std::pair< unsigned short, unsigned short > &vertices, const Point &point)
 Get the neighbors at an edge. More...
 
const std::vector< NeighborInfo > & getPointNeighbors (const Elem *elem, const Point &point)
 Get the point neighbors. More...
 
const std::vector< NeighborInfo > & getNeighbors (const Elem *elem, const ElemExtrema &extrema, const Point &point)
 Get the point/vertex/edge neighbors depending on extrema. More...
 
template<typename T , typename FirstOrderT >
std::enable_if<!std::is_base_of< Edge, T >::value, bool >::type exitsElem (const Elem *elem, const unsigned short incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance, const Point *normals)
 

Private Types

enum  ExitsElemResult { NO_EXIT = 0, HIT_FACE = 1, HIT_VERTEX = 2, HIT_EDGE = 3 }
 Enum for the different exit results for exitElem() More...
 

Private Member Functions

void onSegment (const std::shared_ptr< Ray > &ray)
 Called on a single segment traced by a Ray. More...
 
void onBoundary (const std::shared_ptr< Ray > &ray, const bool external)
 Called when a Ray hits a boundary. More...
 
void onCompleteTrace (const std::shared_ptr< Ray > &ray)
 Called when a Ray is finished tracing (whenever !ray->shouldContinue()) More...
 
void onContinueTrace (const std::shared_ptr< Ray > &)
 Called when a Ray is continuing to trace after segment. More...
 
void onTrajectoryChanged (const std::shared_ptr< Ray > &ray)
 Called when a Ray's trajectory changes. More...
 
void onSubdomainChanged (const std::shared_ptr< Ray > &ray, const bool same_ray)
 Called when the subdomain changes. More...
 
std::string failTraceMessage (const std::string &reason, const int line=-1)
 Creates a useful error string with current tracing information. More...
 
void failTrace (const std::string &reason, const bool warning, const int line=-1)
 Specialized mooseError for a failed Ray trace with detailed information regarding the trace. More...
 
ExitsElemResult exitsElem (const Elem *elem, const ElemType elem_type, const unsigned short incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance, const Point *normals)
 Determines if _current_ray moving in direction _direction exits elem. More...
 
template<typename T , typename FirstOrderT >
std::enable_if<!std::is_base_of< Edge, T >::value, bool >::type exitsElem (const Elem *elem, const unsigned short incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance, const Point *normals)
 Determines if _current_ray moving in direction _direction exits elem. More...
 
template<typename T , typename FirstOrderT >
std::enable_if< std::is_base_of< Edge, T >::value, bool >::type exitsElem (const Elem *elem, const unsigned short incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance, const Point *normals)
 Determines if _current_ray moving in direction _direction exits elem. More...
 
ExitsElemResult moveThroughNeighbors (const std::vector< NeighborInfo > &neighbors, const Elem *last_elem, const Elem *&best_elem, unsigned short &best_elem_incoming_side)
 Moves the Ray though neighbors (vertex/edge/point) More...
 
ExitsElemResult moveThroughNeighbor (const NeighborInfo &neighbor_info, unsigned short &incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance)
 Sees if a Ray can move through a neighbor (vertex/edge/point) More...
 
void applyOnExternalBoundary (const std::shared_ptr< Ray > &ray)
 Gets and applies external boundary conditions in _current_elem on side _intersected_side at _intersection_point. More...
 
void applyOnInternalBoundary (const std::shared_ptr< Ray > &ray)
 Gets and applies internal boundary conditions (if any) from _current_elem, _last_elem, and any other point neighbors that have internal sidesets at _intersection_point. More...
 
void possiblyAddToBoundaryElems (const Elem *elem, const unsigned short side, const std::vector< BoundaryID > &bnd_ids, const ElemExtrema &extrema)
 Helper for possibly storing boundary information in _boundary_elems, which is storage for boundary elements (elem, side, bnd_id) that need to have RayBCs applied to them. More...
 
void continueTraceOffProcessor (const std::shared_ptr< Ray > &ray)
 Sets up a ray to continue tracing off processor. More...
 
void findExternalBoundarySide (unsigned short &boundary_side, ElemExtrema &boundary_extrema, const Elem *&boundary_elem)
 Finds (if any) an element side that is on the boundary and is outgoing at _intersection_point that is on the extrema _intersected_extrema for _current_elem. More...
 
void storeExitsElemResult (const ExitsElemResult result)
 Stores the result given by an intersection in _results as necessary. More...
 
Real subdomainHmax (const Elem *elem) const
 Get the approximate subdomain hmax for an element. More...
 
void postRayTracingObject (const std::shared_ptr< Ray > &ray, const RayTracingObject *rto)
 Called after executing a RayTracingObject (RayBCs and RayKernels) More...
 

Private Attributes

RayTracingStudy_study
 The RayTracingStudy. More...
 
MooseMesh_mesh
 The MooseMesh. More...
 
const unsigned int _dim
 The mesh dimension. More...
 
const BoundaryInfo & _boundary_info
 The BoundaryInfo for the mesh. More...
 
const processor_id_type _pid
 The processor id. More...
 
const THREAD_ID _tid
 The thread id. More...
 
bool _backface_culling
 Whether or not to use element normals for backface culling. More...
 
TraceData_current_cached_trace
 The TraceData for the current cached trace (if any) More...
 
const std::shared_ptr< Ray > * _current_ray
 The current ray being traced. More...
 
const Elem * _current_elem
 The element the current Ray is being traced in. More...
 
const Elem * _last_elem
 The last element the current Ray was traced in. More...
 
SubdomainID _current_subdomain_id
 The current SubdomainID. More...
 
Real _current_subdomain_hmax
 The current subdomain hmax. More...
 
libMesh::ElemType _current_elem_type
 The current elem type (constant on subdomain), used to avoid elem->type() calls. More...
 
unsigned short _current_elem_n_sides
 The number of sides on the current elem, used to avoid elem->n_sides() virtual calls. More...
 
Point _incoming_point
 The incoming point of the current Ray. More...
 
unsigned short _incoming_side
 The incoming side of the current Ray. More...
 
bool _should_continue
 Whether or not the current Ray should continue. More...
 
Point _intersection_point
 The work point for the intersection of the current Ray. More...
 
unsigned short _intersected_side
 The work point for the intersected side of the current Ray. More...
 
ElemExtrema _intersected_extrema
 The work point for the intersected vertex/edge vertices of the current Ray, if any. More...
 
ElemExtrema _last_intersected_extrema
 The intersected vertex/edge vertices for the previous intersection, if any. More...
 
Real _intersection_distance
 The work point for the intersection distance of the current Ray. More...
 
BoundaryID _current_bnd_id
 The current BoundaryID (used when calling RayBoundaryConditionBase::onBoundary()) More...
 
bool _exits_elem
 Whether or not the current trace exits an element. More...
 
const Point * _current_normals
 The normals for the current element for backface culling (pointer to the first normal - optional) More...
 
std::vector< BoundaryID_boundary_ids
 Reusable vector for calling _boundary_info.boundary_ids() More...
 
std::vector< TraceRayBndElement_boundary_elems
 Boundary elements that need RayBCs to be applied. More...
 
std::unordered_map< const Node *, std::vector< NeighborInfo > > _vertex_neighbors
 The cached vertex neighbors. More...
 
std::unordered_map< std::pair< const Node *, const Node * >, std::pair< bool, std::vector< NeighborInfo > > > _edge_neighbors
 The cached edge neighbors. More...
 
std::vector< NeighborInfo_point_neighbor_helper
 Reusable for building neighbors. More...
 
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_set
 
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_untested_set
 
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_next_untested_set
 
std::vector< const Elem * > _neighbor_active_neighbor_children
 
std::vector< unsigned long long int_results
 Results over all of the local traces, indexed by TraceRayResult. More...
 
libMesh::ElemSideBuilder _elem_side_builder
 Helper for building element sides without excessive allocation. More...
 
std::vector< RayBoundaryConditionBase * > _on_boundary_ray_bcs
 Reusable for getting the RayBCs in onBoundary() More...
 
std::vector< std::size_t > _on_boundary_apply_index
 Reusable for which boundary elements to apply for a specific RayBC in onBoundary() More...
 
bool _has_ray_kernels
 Whether or not the RayTracingStudy has any RayKernels. More...
 
bool _is_rectangular_domain
 Whether or not the domain is rectangular (defined perfectly by its bounding box) More...
 
std::set< RayKernelBase * > _old_ray_kernels
 Helper for avoiding calling preTrace() on the same RayKernel multiple times. More...
 
Mesh * _debug_mesh
 
Parallel::Communicator _debug_comm
 
unsigned int _debug_node_count
 

Detailed Description

Traces Rays through the mesh on a single processor.

Definition at line 46 of file TraceRay.h.

Member Enumeration Documentation

◆ ExitsElemResult

Enum for the different exit results for exitElem()

Enumerator
NO_EXIT 
HIT_FACE 
HIT_VERTEX 
HIT_EDGE 

Definition at line 257 of file TraceRay.h.

258  {
259  NO_EXIT = 0, // doesn't exit
260  HIT_FACE = 1, // exits through a face
261  HIT_VERTEX = 2, // exits through a vertex
262  HIT_EDGE = 3 // exits through an edge
263  };

◆ TraceRayResult

Enum for the various results reported by this object.

Enumerator
INTERSECTIONS 
FACE_HITS 
VERTEX_HITS 
EDGE_HITS 
MOVED_THROUGH_NEIGHBORS 
BACKFACE_CULLING_SUCCESSES 
BACKFACE_CULLING_FAILURES 
INTERSECTION_CALLS 
VERTEX_NEIGHBOR_BUILDS 
VERTEX_NEIGHBOR_LOOKUPS 
EDGE_NEIGHBOR_BUILDS 
EDGE_NEIGHBOR_LOOKUPS 
POINT_NEIGHBOR_BUILDS 
FAILED_TRACES 
ENDED_STATIONARY 

Definition at line 56 of file TraceRay.h.

57  {
58  INTERSECTIONS = 0, // intersections
59  FACE_HITS = 1, // intersections at an element face
60  VERTEX_HITS = 2, // intersections at an element vertex
61  EDGE_HITS = 3, // intersections at an element edge
62  MOVED_THROUGH_NEIGHBORS = 4, // intersections through point/vertex/edge neighbors
63  BACKFACE_CULLING_SUCCESSES = 5, // face intersection calls that backface culling worked on
64  BACKFACE_CULLING_FAILURES = 6, // face interesction calls that backface culling failed on
65  INTERSECTION_CALLS = 7, // face intersection calls made
66  VERTEX_NEIGHBOR_BUILDS = 8, // builds for neighbors at a vertex
67  VERTEX_NEIGHBOR_LOOKUPS = 9, // lookups for neighbors at a vertex
68  EDGE_NEIGHBOR_BUILDS = 10, // builds for neighbors on an edge
69  EDGE_NEIGHBOR_LOOKUPS = 11, // lookups for neighborson an edge
70  POINT_NEIGHBOR_BUILDS = 12, // builds for point neighbors (non edge/vertex)
71  FAILED_TRACES = 13, // rays that fail (allowed when _tolerate_failure == true),
72  ENDED_STATIONARY = 14 // rays the end because they are stationary
73  };

Constructor & Destructor Documentation

◆ TraceRay()

TraceRay::TraceRay ( RayTracingStudy study,
const THREAD_ID  tid 
)

Definition at line 47 of file TraceRay.C.

48  : _study(study),
49  _mesh(study.getSubProblem().mesh()),
50  _dim(_mesh.dimension()),
52  _pid(_study.comm().rank()),
53  _tid(tid),
54  _backface_culling(false),
55  _current_normals(nullptr),
57 {
58 }
virtual MooseMesh & mesh()=0
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
processor_id_type rank() const
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
const unsigned int _dim
The mesh dimension.
Definition: TraceRay.h:440
bool _backface_culling
Whether or not to use element normals for backface culling.
Definition: TraceRay.h:449
const Point * _current_normals
The normals for the current element for backface culling (pointer to the first normal - optional) ...
Definition: TraceRay.h:492
MeshBase & getMesh()
virtual unsigned int dimension() const
SubProblem & getSubProblem() const
const processor_id_type _pid
The processor id.
Definition: TraceRay.h:444
MooseMesh & _mesh
The MooseMesh.
Definition: TraceRay.h:438
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
const BoundaryInfo & _boundary_info
The BoundaryInfo for the mesh.
Definition: TraceRay.h:442

◆ ~TraceRay()

virtual TraceRay::~TraceRay ( )
inlinevirtual

Definition at line 51 of file TraceRay.h.

51 {}

Member Function Documentation

◆ applyOnExternalBoundary()

void TraceRay::applyOnExternalBoundary ( const std::shared_ptr< Ray > &  ray)
private

Gets and applies external boundary conditions in _current_elem on side _intersected_side at _intersection_point.

Definition at line 746 of file TraceRay.C.

Referenced by trace().

747 {
748  debugRay("Called applyOnExternalBoundary() with");
749  debugRay(" _current_elem->id() = ", _current_elem->id());
750  debugRay(" _intersection_point = ", _intersection_point);
751  debugRay(" _intersected_side = ", _intersected_side);
752  debugRay(" _intersected_extrema = ", _intersected_extrema);
753 
754  // Clear storage for the list of ConstBndElement that we need to apply RayBCs to
755  _boundary_elems.clear();
756 
757  // If on the elem extrema (at a vertex or within an edge), check for external sidesets on
758  // neighbors (which will include _current_elem)
759  if (_dim != 1 && _intersected_extrema.atExtrema())
760  {
762  debugRay(" Found ", neighbors.size(), " vertex/edge neighbors (including self)");
763  traceAssert(std::count_if(neighbors.begin(),
764  neighbors.end(),
765  [this](const NeighborInfo & ni)
766  { return ni._elem == _current_elem; }),
767  "_current_elem not in neighbors");
768 
769  for (const auto & neighbor_info : neighbors)
770  {
771  if (!neighbor_info._valid)
772  continue;
773 
774  const Elem * elem = neighbor_info._elem;
775  const auto & sides = neighbor_info._sides;
776  const auto & side_normals = neighbor_info._side_normals;
777 
778  for (MooseIndex(side_normals.size()) i = 0; i < side_normals.size(); ++i)
779  if (!elem->neighbor_ptr(sides[i]) // is a boundary side that has our point
780  && side_normals[i] * ray->direction() > TRACE_TOLERANCE) // and is entrant
781  {
782  // TODO: this could likely be optimized
783  ElemExtrema extrema;
784  withinExtremaOnSide(elem, _intersection_point, sides[i], _dim, extrema);
785 
786  _boundary_info.boundary_ids(elem, sides[i], _boundary_ids);
787  possiblyAddToBoundaryElems(elem, sides[i], _boundary_ids, extrema);
788  }
789  }
790  }
791  // Not on the periphery (at vertex/edge), so we just need to add the external
792  // sidesets from _current_elem on _intersected_side
793  else
794  {
798  }
799 
800  debugRay("Calling external onBoundary() with ", _boundary_elems.size(), " boundaries");
801  onBoundary(ray, /* external = */ true);
802 }
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.
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
void possiblyAddToBoundaryElems(const Elem *elem, const unsigned short side, const std::vector< BoundaryID > &bnd_ids, const ElemExtrema &extrema)
Helper for possibly storing boundary information in _boundary_elems, which is storage for boundary el...
Definition: TraceRay.C:917
Helper for defining if at an element&#39;s edge, vertex, or neither.
Definition: ElemExtrema.h:25
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Struct for containing the necessary information about a cached neighbor for ray tracing.
Definition: NeighborInfo.h:27
const unsigned int _dim
The mesh dimension.
Definition: TraceRay.h:440
void onBoundary(const std::shared_ptr< Ray > &ray, const bool external)
Called when a Ray hits a boundary.
Definition: TraceRay.C:2082
const Real TRACE_TOLERANCE
The standard tolerance to use in tracing.
Definition: TraceRayTools.h:48
std::vector< BoundaryID > _boundary_ids
Reusable vector for calling _boundary_info.boundary_ids()
Definition: TraceRay.h:495
dof_id_type id() const
char ** sides
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
bool atExtrema() const
Definition: ElemExtrema.h:44
const Elem * neighbor_ptr(unsigned int i) const
const std::vector< NeighborInfo > & getNeighbors(const Elem *elem, const ElemExtrema &extrema, const Point &point)
Get the point/vertex/edge neighbors depending on extrema.
Definition: TraceRay.C:1973
std::vector< TraceRayBndElement > _boundary_elems
Boundary elements that need RayBCs to be applied.
Definition: TraceRay.h:497
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
const BoundaryInfo & _boundary_info
The BoundaryInfo for the mesh.
Definition: TraceRay.h:442
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ applyOnInternalBoundary()

void TraceRay::applyOnInternalBoundary ( const std::shared_ptr< Ray > &  ray)
private

Gets and applies internal boundary conditions (if any) from _current_elem, _last_elem, and any other point neighbors that have internal sidesets at _intersection_point.

Definition at line 805 of file TraceRay.C.

Referenced by trace().

806 {
807  traceAssert(_last_elem, "Must be valid");
808 
809  debugRay("Called applyOnInternalBoundary() with");
810  debugRay(" intersection_point = ", _intersection_point);
811  debugRay(" _current_elem->id() = ", _current_elem->id());
812  debugRay(" _incoming_side = ", _incoming_side);
813  debugRay(" _last_elem->id() = ", _last_elem->id());
814  debugRay(" _intersected_side = ", _intersected_side);
815  debugRay(" _intersected_extrema = ", _intersected_extrema);
816  traceAssert(_study.hasInternalSidesets(), "Do not have internal sidesets");
818  "Intersection and incoming points should be the same");
819 
820  // Clear storage for the list of ConstBndElement that we need to apply RayBCs to
821  _boundary_elems.clear();
822 
823  ElemExtrema temp_extrema;
824 
825  // If on the elem extrema (at a vertex or within an edge), we need to check for internal
826  // sidesets on neighbors (which will include _last_elem and _current_elem)
827  if (_dim != 1 && _intersected_extrema.atExtrema())
828  {
829  debugRay("Checking point neighbors for internal sidesets");
830 
831  // Get the neighbors
833  debugRay(" Found ", neighbors.size(), " vertex/edge neighbors");
834  traceAssert(std::count_if(neighbors.begin(),
835  neighbors.end(),
836  [this](const NeighborInfo & ni)
837  { return ni._elem == _current_elem || ni._elem == _last_elem; }) == 2,
838  "_current_elem/_last_elem not in neighbors");
839 
840  for (const auto & neighbor_info : neighbors)
841  {
842  if (!neighbor_info._valid)
843  continue;
844 
845  const Elem * elem = neighbor_info._elem;
846 
847  // Grab the internal sidesets for this elem
848  const auto & sidesets = _study.getInternalSidesets(elem);
849  // It has none to contribute, so we can continue
850  if (sidesets.empty())
851  {
852  debugRay(" Elem ", elem->id(), " has no internal sidesets");
853  continue;
854  }
855 
856  // The sides on this elem that contain our point and their outward normals
857  const auto & sides = neighbor_info._sides;
858  const auto & side_normals = neighbor_info._side_normals;
859 
860  // See if any of the internal sidesets are relevant to this point
861  for (std::size_t i = 0; i < sides.size(); ++i)
862  {
863  const auto side = sides[i];
864  // Side has internal sidesets and is entrant
865  if (sidesets[side].size() && std::abs(side_normals[i] * ray->direction()) > TRACE_TOLERANCE)
866  {
867  // TODO: this could likely be optimized
868  temp_extrema.invalidate();
869  withinExtremaOnSide(elem, _intersection_point, side, _dim, temp_extrema);
870 
871  possiblyAddToBoundaryElems(elem, side, sidesets[side], temp_extrema);
872  }
873  }
874  }
875  }
876  // Not on the periphery (at vertex/edge), so we just need to add the sidesets from _current_elem
877  // on _incoming_side and _last_elem on _intersected_side
878  else
879  {
880  const auto & current_elem_sidesets = _study.getInternalSidesets(_current_elem);
881  if (current_elem_sidesets.size() && current_elem_sidesets[_incoming_side].size())
882  {
883  // This is possible but we need extrema checks on _incoming_elem to pass to the
884  // boundary conditions. For now, we just pass in _intersected_extrema which could
885  // be very wrong with adaptivity but is correct without it. I struggled with getting
886  // the actual extrema checks and we're not using this now so I bet this error will
887  // come back to haunt me in the future :-)
889  mooseError("Internal sidesets are not currently supported with adaptivity in tracing");
890 
891  // Special case for 1D
892  if (_dim == 1)
894 
897  current_elem_sidesets[_incoming_side],
898  _dim != 1 ? _intersected_extrema : temp_extrema);
899  }
900 
901  const auto & last_elem_sidesets = _study.getInternalSidesets(_last_elem);
902  if (last_elem_sidesets.size() && last_elem_sidesets[_intersected_side].size())
905  last_elem_sidesets[_intersected_side],
907  }
908 
909  if (!_boundary_elems.empty())
910  {
911  debugRay(" Calling internal onBoundary() with ", _boundary_elems.size(), " boundaries");
912  onBoundary(ray, /* external = */ false);
913  }
914 }
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.
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
const std::vector< std::vector< BoundaryID > > & getInternalSidesets(const Elem *elem) const
Get the internal sidesets (that have RayBC(s)) for each side for a given element. ...
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
bool hasSameLevelActiveElems() const
Whether or not the mesh has active elements of the same level.
void mooseError(Args &&... args)
void possiblyAddToBoundaryElems(const Elem *elem, const unsigned short side, const std::vector< BoundaryID > &bnd_ids, const ElemExtrema &extrema)
Helper for possibly storing boundary information in _boundary_elems, which is storage for boundary el...
Definition: TraceRay.C:917
Helper for defining if at an element&#39;s edge, vertex, or neither.
Definition: ElemExtrema.h:25
Struct for containing the necessary information about a cached neighbor for ray tracing.
Definition: NeighborInfo.h:27
const unsigned int _dim
The mesh dimension.
Definition: TraceRay.h:440
void onBoundary(const std::shared_ptr< Ray > &ray, const bool external)
Called when a Ray hits a boundary.
Definition: TraceRay.C:2082
const Real TRACE_TOLERANCE
The standard tolerance to use in tracing.
Definition: TraceRayTools.h:48
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
unsigned short _incoming_side
The incoming side of the current Ray.
Definition: TraceRay.h:471
dof_id_type id() const
char ** sides
const Elem * _last_elem
The last element the current Ray was traced in.
Definition: TraceRay.h:459
bool absolute_fuzzy_equals(const TypeVector< Real > &rhs, Real tol=TOLERANCE) const
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
bool atExtrema() const
Definition: ElemExtrema.h:44
void setVertex(const unsigned short vertex)
Sets the "at vertex" state.
Definition: ElemExtrema.h:118
const std::vector< NeighborInfo > & getNeighbors(const Elem *elem, const ElemExtrema &extrema, const Point &point)
Get the point/vertex/edge neighbors depending on extrema.
Definition: TraceRay.C:1973
std::vector< TraceRayBndElement > _boundary_elems
Boundary elements that need RayBCs to be applied.
Definition: TraceRay.h:497
void invalidate()
Invalidates the current state.
Definition: ElemExtrema.h:87
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
unsigned short atVertex(const Elem *elem, const Point &point)
Determines if a point is at a vertex of an element.
bool hasInternalSidesets() const
Whether or not the local mesh has internal sidesets that have RayBCs on them.
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ continueTraceOffProcessor()

void TraceRay::continueTraceOffProcessor ( const std::shared_ptr< Ray > &  ray)
private

Sets up a ray to continue tracing off processor.

Parameters
rayThe ray
elemThe element that is owned by another processor
incoming_sideThe incoming side elem
pointThe point on elem at which ray continues

Definition at line 1670 of file TraceRay.C.

Referenced by trace().

1671 {
1672  traceAssert(ray->currentElem() == _current_elem, "Ray currentElem() invalid");
1673  traceAssert(ray->currentIncomingSide() == _incoming_side, "Ray currentIncomingSide() invalid");
1674  traceAssert(ray->currentPoint() == _incoming_point, "Ray currentPoint() invalid");
1675  traceAssert(_current_elem->processor_id() != _pid, "Off processor trace is not off processor");
1676  debugRay("Ray going off processor to ", _current_elem->processor_id());
1677 
1678  ray->addProcessorCrossing();
1679 
1681  {
1683  if (_study.dataOnCacheTraces())
1684  _current_cached_trace->lastPoint()._data = ray->data();
1686  _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1687  }
1688 
1689  if (_intersection_distance > 0)
1690  possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1691  possiblySaveDebugRayMesh();
1692 }
TracePointData & lastPoint()
Definition: TraceData.h:57
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
std::vector< RayData > _aux_data
The aux data on the Ray after this segment is traced (optional)
Definition: TraceData.h:36
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
unsigned short _incoming_side
The incoming side of the current Ray.
Definition: TraceRay.h:471
bool auxDataOnCacheTraces() const
Whether or not to store the Ray aux data on the cached Ray traces.
const processor_id_type _pid
The processor id.
Definition: TraceRay.h:444
TraceData * _current_cached_trace
The TraceData for the current cached trace (if any)
Definition: TraceRay.h:452
void addPoint(const libMesh::Point &point)
Definition: TraceData.h:55
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
std::vector< RayData > _data
The data on the Ray after this segment is traced (optional)
Definition: TraceData.h:34
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484
processor_id_type processor_id() const
bool dataOnCacheTraces() const
Whether or not to store the Ray data on the cached Ray traces.
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ currentBoundaryID()

const BoundaryID& TraceRay::currentBoundaryID ( ) const
inline

Gets the BoundaryID of the boundary that the Ray intersected and is being applied a boundary condition.

Definition at line 155 of file TraceRay.h.

155 { return _current_bnd_id; }
BoundaryID _current_bnd_id
The current BoundaryID (used when calling RayBoundaryConditionBase::onBoundary()) ...
Definition: TraceRay.h:486

◆ currentElem()

const Elem* const& TraceRay::currentElem ( ) const
inline

Gets the element that the current Ray is being traced in.

Definition at line 114 of file TraceRay.h.

114 { return _current_elem; }
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457

◆ currentIncomingPoint()

const Point& TraceRay::currentIncomingPoint ( ) const
inline

Gets the current incoming point for the Ray that is being traced.

This is ONLY guaranteed to be valid during execution of RayKernels!

Definition at line 127 of file TraceRay.h.

127 { return _incoming_point; }
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469

◆ currentIncomingSide()

const unsigned short& TraceRay::currentIncomingSide ( ) const
inline

Gets the current incoming side for the Ray that is being traced.

This is only valid during onSegment() (when RayKernels are being called)

Definition at line 133 of file TraceRay.h.

133 { return _incoming_side; }
unsigned short _incoming_side
The incoming side of the current Ray.
Definition: TraceRay.h:471

◆ currentIntersectedExtrema()

const ElemExtrema& TraceRay::currentIntersectedExtrema ( ) const
inline

Gets the element extrema (vertex/edge) that the current Ray intersected.

Definition at line 144 of file TraceRay.h.

144 { return _intersected_extrema; }
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480

◆ currentIntersectedSide()

const unsigned short& TraceRay::currentIntersectedSide ( ) const
inline

Gets the side that the current Ray intersected.

If the ray ends within the current element, this will be RayTracingCommon::invalid_side.

Definition at line 140 of file TraceRay.h.

140 { return _intersected_side; }
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478

◆ currentIntersectionDistance()

const Real& TraceRay::currentIntersectionDistance ( ) const
inline

Gets the current intersection distance for the Ray that is being traced.

When within an element (executing with a RayKernel), this is the segment distance.

Definition at line 150 of file TraceRay.h.

150 { return _intersection_distance; }
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484

◆ currentIntersectionPoint()

const Point& TraceRay::currentIntersectionPoint ( ) const
inline

Gets the current intersection point for the Ray that is being traced.

If the Ray ends within the current element, this will be the point at which the Ray ends within the current element.

Definition at line 121 of file TraceRay.h.

121 { return _intersection_point; }
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ currentRay()

const std::shared_ptr<Ray>* const& TraceRay::currentRay ( ) const
inline

Gets the current Ray that is being traced.

Definition at line 110 of file TraceRay.h.

110 { return _current_ray; }
const std::shared_ptr< Ray > * _current_ray
The current ray being traced.
Definition: TraceRay.h:455

◆ currentSubdomainID()

const SubdomainID& TraceRay::currentSubdomainID ( ) const
inline

Gets the subdomain of the current element that the Ray is being traced in.

Definition at line 159 of file TraceRay.h.

159 { return _current_subdomain_id; }
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461

◆ exitsElem() [1/4]

ExitsElemResult TraceRay::exitsElem ( const Elem *  elem,
const ElemType  elem_type,
const unsigned short  incoming_side,
Point &  intersection_point,
unsigned short &  intersected_side,
ElemExtrema intersected_extrema,
Real intersection_distance,
const Point *  normals 
)
private

Determines if _current_ray moving in direction _direction exits elem.

Parameters
elemThe element to check
elem_typeThe type of elem (used to avoid virtual function calls on elem)
incoming_sideThe incoming side (if any)
intersection_pointTo be modified with the intersection point, if any
intersected_sideTo be modified with the intersected side, if any
intersected_extremaTo be modified with the intersected extremum (vertex/edge), if any
intersection_distanceTo be modified with the intersection distance, if any
normalsPointer to the normals for the current element, if any
Returns
Whether or not _current_ray exits elem

Referenced by moveThroughNeighbor(), and trace().

◆ exitsElem() [2/4]

template<typename T , typename FirstOrderT >
std::enable_if<!std::is_base_of<Edge, T>::value, bool>::type TraceRay::exitsElem ( const Elem *  elem,
const unsigned short  incoming_side,
Point &  intersection_point,
unsigned short &  intersected_side,
ElemExtrema intersected_extrema,
Real intersection_distance,
const Point *  normals 
)
private

Determines if _current_ray moving in direction _direction exits elem.

This function is templated to work only with elements that are faces or cells (2D or 3D)

Parameters
elemThe element to check
incoming_sideThe incoming side (if any)
intersection_pointTo be modified with the intersection point, if any
intersected_sideTo be modified with the intersected side, if any
intersected_extremaTo be modified with the intersected extremum (vertex/edge), if any
intersection_distanceTo be modified with the intersection distance, if any
normalsPointer to the normals for the current element, if any
Returns
Whether or not _current_ray exits elem through a face

◆ exitsElem() [3/4]

template<typename T , typename FirstOrderT >
std::enable_if< std::is_base_of< Edge, T >::value, bool >::type TraceRay::exitsElem ( const Elem elem,
const unsigned short  incoming_side,
Point intersection_point,
unsigned short &  intersected_side,
ElemExtrema intersected_extrema,
Real intersection_distance,
const Point normals 
)

Definition at line 314 of file TraceRay.C.

321 {
323 
324  debugRay("Called exitsElem() in 2D or 3D");
325 
326  const auto hmax = subdomainHmax(elem);
327 
328  // Current point and distance (maybe not the best!)
329  Point current_intersection_point;
330  Real current_intersection_distance;
331  ElemExtrema current_intersected_extrema;
332  // Scale the minimum intersection distance required by hmax
333  Real best_intersection_distance = TRACE_TOLERANCE * hmax;
334  // Whether or not we are going to try backface culling the first time around
335  // This depends on if the user set it to use culling
336  bool use_backface_culling = _backface_culling;
337  // If all sides have failed to find an intersection, whether or not we
338  // are going to see if the nonplanar skip side (only if it IS nonplanar)
339  // is also an exiting point
340  bool try_nonplanar_incoming_side = false;
341  // Easy access into the current direction
342  const auto & direction = (*_current_ray)->direction();
343  // The current side that we're checking
344  unsigned short s = 0;
345 
346  // Loop over the side loop. We need this in the cases that:
347  // - Backface culling is enabled and we were not able to find an intersection
348  // so we will go through all culled sides and see if we can find one
349  // - The incoming_side is non-planar and the ray also exits said side,
350  // which will be checked after all other sides fail
351  while (true)
352  {
353  debugRay(" use_backface_culling = ", use_backface_culling);
354  debugRay(" try_nonplanar_incoming_side = ", try_nonplanar_incoming_side);
355  // Loop over all of the sides
356  while (true)
357  {
358  debugRay(" Side ", s, " with centroid ", _elem_side_builder(*elem, s).vertex_average());
359 
360  // All of the checks that follow are done while we're still searching through
361  // all of the sides. try_nonplanar_incoming_side is our last possible check
362  // and does not involve looping through all of the sides, so skip these
363  // checks if we're at that point.
364  if (!try_nonplanar_incoming_side)
365  {
366  // Don't search backwards. If we have a non-planar incoming side, we will
367  // check it if all other sides have failed
368  if (s == incoming_side)
369  {
370  debugRay(" Skipping due to incoming side");
371  if (++s == T::num_sides)
372  break;
373  else
374  continue;
375  }
376 
377  // Using backface culling on this run through the sides
378  // If the direction is non-entrant, skip this side
379  if (use_backface_culling)
380  {
381  // Side is non-entrant per the culling, so skip
382  if (normals[s] * direction < -LOOSE_TRACE_TOLERANCE)
383  {
384  debugRay(" Skipping due to backface culling dot = ", normals[s] * direction);
385 
386  if (++s == T::num_sides)
387  break;
388  else
389  continue;
390 
392  }
393  }
394  // We're not using backface culling but it is enabled, which means
395  // we're on our second run through the sides because we could not
396  // find any intersections while culling the sides. Try again and
397  // check the sides that we previously skipped for intersections
398  else if (_backface_culling)
399  {
400  // Side was non-entrant per the culling, so try again
401  if (normals[s] * direction >= -LOOSE_TRACE_TOLERANCE)
402  {
403  debugRay(" Skipping because we already checked this side with culling enabled");
404  if (++s == T::num_sides)
405  break;
406  else
407  continue;
408  }
409  else
410  debugRay(" Side that was skipped due to culling");
411 
413  }
414  }
415 
416  // Look for an intersection!
417  current_intersection_point = RayTracingCommon::invalid_point;
418  current_intersected_extrema.invalidate();
419  const bool intersected = sideIntersectedByLine<FirstOrderT>(elem,
421  direction,
422  s,
424  current_intersection_point,
425  current_intersection_distance,
426  current_intersected_extrema,
427  hmax
428 #ifdef DEBUG_RAY_INTERSECTIONS
429  ,
430  DEBUG_RAY_IF
431 #endif
432  );
433 
434  // Do they intersect and is it further down the path than any other intersection?
435  // If so, keep track of the intersection with the furthest distance
436  if (intersected)
437  {
438  debugRay(" Intersected at point ",
439  current_intersection_point,
440  " with distance ",
441  current_intersection_distance);
442  debugRay(" Best intersection distance = ", best_intersection_distance);
443 
444 #ifndef NDEBUG
445  // Only validate intersections if the side is planar
447  !_elem_side_builder(*elem, s).contains_point(current_intersection_point))
448  failTrace("Intersected side does not contain intersection point",
450  __LINE__);
451 #endif
452 
453  // The intersection we just computed is further than any other intersection
454  // that was found so far - mark it as the best
455  if (current_intersection_distance > best_intersection_distance)
456  {
457  debugRay(" Best intersection so far");
458 
459  intersected_side = s;
460  intersection_distance = current_intersection_distance;
461  intersection_point = current_intersection_point;
462  intersected_extrema = current_intersected_extrema;
463  best_intersection_distance = current_intersection_distance;
464  }
465  }
466 
467  if (++s == T::num_sides || try_nonplanar_incoming_side)
468  break;
469  else
470  continue;
471  } // while(true)
472 
473  // Found an intersection
474  if (intersected_side != RayTracingCommon::invalid_side)
475  {
476  debugRay(" Exiting with intersection");
477  debugRay(" intersected_side = ", intersected_side);
478  debugRay(" intersection_distance = ", intersection_distance);
479  debugRay(" intersection_point = ", intersection_point);
480  debugRay(" intersected_extrema = ", intersected_extrema);
481 
482  return true;
483  }
484 
485  // This was our last possible check - no dice!
486  if (try_nonplanar_incoming_side)
487  return false;
488 
489  // We didn't find an intersection but we used backface culling. Try again without
490  // it, checking only the sides that we skipped due to culling
491  if (use_backface_culling)
492  {
493  debugRay(" Didn't find an intersection, retrying without backface culling");
494  use_backface_culling = false;
495  s = 0;
496  continue;
497  }
498 
499  // Have tried all sides (potentially with and without culling). If the incoming
500  // side is valid is non planar, see if we also exit out of it
502  _study.sideIsNonPlanar(elem, incoming_side))
503  {
504  debugRay(" Didn't find an intersection, trying non-planar incoming_side");
505  try_nonplanar_incoming_side = true;
506  s = incoming_side;
507  continue;
508  }
509 
510  // No intersection found!
511  return false;
512  } // while(true)
513 }
static const unsigned short invalid_side
Identifier for an invalid side index.
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
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 _backface_culling
Whether or not to use element normals for backface culling.
Definition: TraceRay.h:449
const Real TRACE_TOLERANCE
The standard tolerance to use in tracing.
Definition: TraceRayTools.h:48
libMesh::ElemSideBuilder _elem_side_builder
Helper for building element sides without excessive allocation.
Definition: TraceRay.h:517
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
bool verifyTraceIntersections() const
Whether or not trace verification is enabled in devel/dbg modes.
unsigned short _incoming_side
The incoming side of the current Ray.
Definition: TraceRay.h:471
Real subdomainHmax(const Elem *elem) const
Get the approximate subdomain hmax for an element.
Definition: TraceRay.C:2188
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514
bool sideIsNonPlanar(const Elem *elem, const unsigned short s) const
Whether or not the side on elem elem is non-planar.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void invalidate()
Invalidates the current state.
Definition: ElemExtrema.h:87
void failTrace(const std::string &reason, const bool warning, const int line=-1)
Specialized mooseError for a failed Ray trace with detailed information regarding the trace...
Definition: TraceRay.C:1806
static const libMesh::Point invalid_point(invalid_distance, invalid_distance, invalid_distance)
Identifier for an invalid point.
bool tolerateFailure() const
Whether or not to tolerate failure.
Real domainMaxLength() const
Get the inflated maximum length across the domain.

◆ exitsElem() [4/4]

template<typename T , typename FirstOrderT >
std::enable_if<std::is_base_of<Edge, T>::value, bool>::type TraceRay::exitsElem ( const Elem *  elem,
const unsigned short  incoming_side,
Point &  intersection_point,
unsigned short &  intersected_side,
ElemExtrema intersected_extrema,
Real intersection_distance,
const Point *  normals 
)
private

Determines if _current_ray moving in direction _direction exits elem.

This function is templated to work only with elements that are edges (1D).

Parameters
elemThe element to check
incoming_sideThe incoming side (if any)
intersection_pointTo be modified with the intersection point, if any
intersected_sideTo be modified with the intersected side, if any
intersected_extremaTo be modified with the intersected extremum (vertex/edge), if any
intersection_distanceTo be modified with the intersection distance, if any
normalsPointer to the normals for the current element, if any
Returns
Whether or not _current_ray exits elem through a face

◆ failTrace()

void TraceRay::failTrace ( const std::string &  reason,
const bool  warning,
const int  line = -1 
)
private

Specialized mooseError for a failed Ray trace with detailed information regarding the trace.

If warning = true, use mooseWarning instead. If line is provided, output will include the line number.

Definition at line 1806 of file TraceRay.C.

Referenced by exitsElem(), onBoundary(), onTrajectoryChanged(), postRayTracingObject(), and trace().

1807 {
1808  const auto message = failTraceMessage(reason, line);
1809 
1810  if (warning)
1811  {
1814  (*_current_ray)->setShouldContinue(false);
1815  _should_continue = false;
1816  }
1817  else
1819 }
std::string failTraceMessage(const std::string &reason, const int line=-1)
Creates a useful error string with current tracing information.
Definition: TraceRay.C:1758
void mooseError(Args &&... args)
void mooseWarning(Args &&... args)
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514
static const std::string message
bool _should_continue
Whether or not the current Ray should continue.
Definition: TraceRay.h:473

◆ failTraceMessage()

std::string TraceRay::failTraceMessage ( const std::string &  reason,
const int  line = -1 
)
private

Creates a useful error string with current tracing information.

If line is provided, will include the line number.

Definition at line 1758 of file TraceRay.C.

Referenced by failTrace().

1759 {
1760  std::stringstream oss;
1761  oss << "Ray on processor " << _pid << " and thread " << _tid << " failed to trace";
1762  if (line != -1)
1763  oss << " at line " << line;
1764  oss << "\n\n" << reason << "\n\n";
1765  oss << ((*_current_ray))->getInfo() << "\n";
1766  oss << "Current trace information\n";
1767  oss << " _current_subdomain_id = ";
1768  if (_current_subdomain_id == Elem::invalid_subdomain_id)
1769  oss << "invalid subdomain id\n";
1770  else
1771  oss << _current_subdomain_id << "\n";
1772  oss << " _current_elem_type = " << Utility::enum_to_string(_current_elem_type) << "\n";
1773  oss << " _current_elem_n_sides = " << _current_elem_n_sides << "\n";
1774  oss << " _incoming_point = ";
1776  oss << "invalid point\n";
1777  else
1778  oss << _incoming_point << "\n";
1779  oss << " _incoming_side = ";
1781  oss << "invalid side\n";
1782  else
1783  oss << _incoming_side << "\n";
1784  oss << " _intersection_point = ";
1786  oss << "invalid point\n";
1787  else
1788  oss << _intersection_point << "\n";
1789  oss << " _intersected_side = ";
1791  oss << "invalid side\n";
1792  else
1793  oss << _intersected_side << "\n";
1794  oss << " _intersected_extrema = " << _intersected_extrema << "\n";
1795  oss << " _exits_elem = " << _exits_elem << "\n";
1796  if (_current_elem)
1797  oss << _current_elem->get_info();
1798  else
1799  oss << "_current_elem = invalid\n";
1800 
1801  possiblySaveDebugRayMesh();
1802  return oss.str();
1803 }
static const unsigned short invalid_side
Identifier for an invalid side index.
unsigned short _current_elem_n_sides
The number of sides on the current elem, used to avoid elem->n_sides() virtual calls.
Definition: TraceRay.h:467
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
std::string get_info() const
libMesh::ElemType _current_elem_type
The current elem type (constant on subdomain), used to avoid elem->type() calls.
Definition: TraceRay.h:465
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
bool _exits_elem
Whether or not the current trace exits an element.
Definition: TraceRay.h:489
unsigned short _incoming_side
The incoming side of the current Ray.
Definition: TraceRay.h:471
const processor_id_type _pid
The processor id.
Definition: TraceRay.h:444
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
static const libMesh::Point invalid_point(invalid_distance, invalid_distance, invalid_distance)
Identifier for an invalid point.
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ findExternalBoundarySide()

void TraceRay::findExternalBoundarySide ( unsigned short &  boundary_side,
ElemExtrema boundary_extrema,
const Elem *&  boundary_elem 
)
private

Finds (if any) an element side that is on the boundary and is outgoing at _intersection_point that is on the extrema _intersected_extrema for _current_elem.

This is necessary when a Ray hits a point that is on the boundary but is not actually on a boundary side

Fills the found boundary side into boundary_side, the element said side is on into boundary_elem and the extrema on said elem into boundary_extrema

Definition at line 950 of file TraceRay.C.

Referenced by trace().

953 {
954  traceAssert(_current_elem->neighbor_ptr(_intersected_side), "Already on boundary");
955  traceAssert(boundary_side == RayTracingCommon::invalid_side, "Side should be invalid");
956  traceAssert(boundary_extrema.isInvalid(), "Extrema should be invalid");
957  traceAssert(!boundary_elem, "Elem should be invalid");
958  traceAssert(_current_elem->dim() != 1, "1D traces shouldn't make it here");
959  traceAssert(_current_elem->n_sides() == _current_elem_n_sides, "_current_elem_n_sides incorrect");
960  traceAssert(_intersected_extrema.atExtrema(), "Should be at extrema");
961  debugRay("Called findExternalBoundarySide() on side ", _intersected_side);
962  debugRay(" _intersected_side = ", _intersected_side);
963  debugRay(" _intersected_extrema", _intersected_extrema);
964 
965  const auto & direction = (*_current_ray)->direction();
966  const auto at_edge = _intersected_extrema.atEdge();
967 
968  // First, look for other sides on _current_elem that touch the intersected vertex/edge
969  // that are on the boundary and are outgoing
970  for (unsigned short s = 0; s < _current_elem_n_sides; ++s)
971  if (!_current_elem->neighbor_ptr(s) && s != _intersected_side &&
973  (!at_edge || _current_elem->is_node_on_side(_intersected_extrema.second, s)) &&
974  !_study.sideIsIncoming(_current_elem, s, direction, _tid))
975  {
976  debugRay(" Side ", s, " is a boundary side and the Ray exits");
977  boundary_side = s;
978  boundary_extrema = _intersected_extrema;
979  boundary_elem = _current_elem;
980  return;
981  }
982 
983  // No luck in our element, so see if any neighbors at this vertex/edge are
984  // on the boundary and are outgoing
986  debugRay("Checking current element failed, now checking neighbors");
987 
988  debugRay("Found ", neighbors.size(), " candidate neighbors (including self)");
989  for (const auto & neighbor_info : neighbors)
990  {
991  // This will be false when we have an edge neighbor that isn't a neighbor at
992  // _intersection_point
993  if (!neighbor_info._valid)
994  continue;
995 
996  const Elem * neighbor = neighbor_info._elem;
997  // We've already checked ourself
998  if (neighbor == _current_elem)
999  continue;
1000 
1001  debugRay("Checking neighbor ", neighbor->id());
1002 
1003  // Loop through the sides we touch and look for one that this Ray exits and is on the boundary
1004  for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
1005  if (neighbor_info._side_normals[i] * direction > TRACE_TOLERANCE &&
1006  !neighbor->neighbor_ptr(neighbor_info._sides[i]))
1007  {
1009  neighbor, _intersection_point, neighbor_info._sides[i], _dim, boundary_extrema);
1010  traceAssert(boundary_extrema.atExtrema(), "Should be at extrema");
1011  boundary_side = neighbor_info._sides[i];
1012  boundary_elem = neighbor;
1013  return;
1014  }
1015  }
1016 }
static const unsigned short invalid_side
Identifier for an invalid side index.
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.
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
unsigned short _current_elem_n_sides
The number of sides on the current elem, used to avoid elem->n_sides() virtual calls.
Definition: TraceRay.h:467
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const=0
bool isInvalid() const
Definition: ElemExtrema.h:48
const unsigned int _dim
The mesh dimension.
Definition: TraceRay.h:440
const Real TRACE_TOLERANCE
The standard tolerance to use in tracing.
Definition: TraceRayTools.h:48
dof_id_type id() const
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
bool atExtrema() const
Definition: ElemExtrema.h:44
virtual unsigned int n_sides() const=0
const Elem * neighbor_ptr(unsigned int i) const
const std::vector< NeighborInfo > & getNeighbors(const Elem *elem, const ElemExtrema &extrema, const Point &point)
Get the point/vertex/edge neighbors depending on extrema.
Definition: TraceRay.C:1973
virtual unsigned short dim() const=0
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
bool atEdge() const
Definition: ElemExtrema.h:71
bool sideIsIncoming(const Elem *const elem, const unsigned short side, const Point &direction, const THREAD_ID tid)
Whether or not side is incoming on element elem in direction direction.
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ getEdgeNeighbors() [1/2]

const std::vector<NeighborInfo>& TraceRay::getEdgeNeighbors ( const Elem *  elem,
const std::pair< const Node *, const Node *> &  vertices,
const Point &  point 
)

Get the neighbors at an edge.

Parameters
elemAn elem that contains the edge
verticesA pair of Nodes that are the vertices that contain the edge fully
pointThe point on the edge where neighbors are desired

Referenced by getNeighbors(), and trace().

◆ getEdgeNeighbors() [2/2]

const std::vector<NeighborInfo>& TraceRay::getEdgeNeighbors ( const Elem *  elem,
const std::pair< unsigned short, unsigned short > &  vertices,
const Point &  point 
)

Get the neighbors at an edge.

Parameters
elemAn elem that contains the edge
verticesA pair of local vertex IDs of the vertices that contain the edge fully
pointThe point on the edge where neighbors are desired

◆ getNeighbors()

const std::vector< NeighborInfo > & TraceRay::getNeighbors ( const Elem elem,
const ElemExtrema extrema,
const Point point 
)

Get the point/vertex/edge neighbors depending on extrema.

Definition at line 1973 of file TraceRay.C.

Referenced by applyOnExternalBoundary(), applyOnInternalBoundary(), findExternalBoundarySide(), and trace().

1974 {
1975  if (!extrema.atExtrema())
1976  return getPointNeighbors(elem, point);
1977  if (extrema.atVertex())
1978  return getVertexNeighbors(elem, extrema.vertex());
1979  return getEdgeNeighbors(elem, extrema.edgeVertices(), point);
1980 }
const std::vector< NeighborInfo > & getPointNeighbors(const Elem *elem, const Point &point)
Get the point neighbors.
Definition: TraceRay.C:1983
const std::vector< NeighborInfo > & getEdgeNeighbors(const Elem *elem, const std::pair< const Node *, const Node *> &vertices, const Point &point)
Get the neighbors at an edge.
unsigned short vertex() const
Definition: ElemExtrema.h:96
const std::pair< unsigned short, unsigned short > & edgeVertices() const
Definition: ElemExtrema.h:104
bool atExtrema() const
Definition: ElemExtrema.h:44
bool atVertex() const
Definition: ElemExtrema.h:56
const std::vector< NeighborInfo > & getVertexNeighbors(const Elem *elem, const Node *vertex)
Gets the neighbors at a vertex.

◆ getPointNeighbors()

const std::vector< NeighborInfo > & TraceRay::getPointNeighbors ( const Elem elem,
const Point point 
)

Get the point neighbors.

Parameters
elemThe elem
pointThe point

Definition at line 1983 of file TraceRay.C.

Referenced by getNeighbors(), and trace().

1984 {
1985  traceAssert(elem, "Invalid elem");
1986 
1987  debugRay("Called getPointNeighbors()");
1988  debugRay(" elem = ", elem->id());
1989  debugRay(" point = ", point);
1990 
1992  _point_neighbor_helper.clear();
1993 
1994  findPointNeighbors(elem,
1995  point,
1996  _neighbor_set,
2001 
2002  // Fill the side normals
2003  for (auto & neighbor_info : _point_neighbor_helper)
2004  for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
2005  neighbor_info._side_normals[i] =
2006  _study.getSideNormal(neighbor_info._elem, neighbor_info._sides[i], _tid);
2007 
2008  return _point_neighbor_helper;
2009 }
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
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...
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_set
Definition: TraceRay.h:508
dof_id_type id() const
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514
std::vector< const Elem * > _neighbor_active_neighbor_children
Definition: TraceRay.h:511
virtual const Point & getSideNormal(const Elem *elem, const unsigned short side, const THREAD_ID tid)
Get the outward normal for a given element side.
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_next_untested_set
Definition: TraceRay.h:510
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_untested_set
Definition: TraceRay.h:509
std::vector< NeighborInfo > _point_neighbor_helper
Reusable for building neighbors.
Definition: TraceRay.h:507

◆ getVertexNeighbors() [1/2]

const std::vector<NeighborInfo>& TraceRay::getVertexNeighbors ( const Elem *  elem,
const Node *  vertex 
)

Gets the neighbors at a vertex.

Parameters
elemAn elem that contains the vertex
vertexThe Node that is the vertex

Referenced by getNeighbors(), and trace().

◆ getVertexNeighbors() [2/2]

const std::vector<NeighborInfo>& TraceRay::getVertexNeighbors ( const Elem *  elem,
const unsigned short  vertex 
)

Gets the neighbors at a vertex.

Parameters
elemAn elem that contains the vertex
vertexThe local ID of the vertex on elem

◆ meshChanged()

void TraceRay::meshChanged ( )

Called on mesh change.

Definition at line 75 of file TraceRay.C.

76 {
77  // Invalidate the vertex and edge neighbor caches
78  _vertex_neighbors.clear();
79  _edge_neighbors.clear();
80 }
std::unordered_map< std::pair< const Node *, const Node * >, std::pair< bool, std::vector< NeighborInfo > > > _edge_neighbors
The cached edge neighbors.
Definition: TraceRay.h:504
std::unordered_map< const Node *, std::vector< NeighborInfo > > _vertex_neighbors
The cached vertex neighbors.
Definition: TraceRay.h:500

◆ moveThroughNeighbor()

TraceRay::ExitsElemResult TraceRay::moveThroughNeighbor ( const NeighborInfo neighbor_info,
unsigned short &  incoming_side,
Point intersection_point,
unsigned short &  intersected_side,
ElemExtrema intersected_extrema,
Real intersection_distance 
)
private

Sees if a Ray can move through a neighbor (vertex/edge/point)

Parameters
neighbor_infoThe NeighborInfo for the neighbor
incoming_sideTo be filled with the incoming side on the neighbor, if any
intersection_pointTo be filled with the intersection point on the neighbor, if any
intersected_sideTo be filled with the intersected side on the neighbor, if any
intersected_extremaTo be filled with the intersected extrema on the neighbor, if any
intersection_distanceTo be filled with the intersection distance, if any
Returns
The trace result

Definition at line 698 of file TraceRay.C.

Referenced by moveThroughNeighbors().

704 {
705  if (!neighbor_info._valid)
706  return NO_EXIT;
707 
708  const Elem * neighbor = neighbor_info._elem;
709  debugRay("Checking neighbor ", neighbor->id(), " with centroid ", neighbor->vertex_average());
710 
711  // Find an entrant side (if any)
712  incoming_side = RayTracingCommon::invalid_side;
713  for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
714  if (neighbor_info._side_normals[i] * (*_current_ray)->direction() < LOOSE_TRACE_TOLERANCE)
715  {
716  incoming_side = neighbor_info._sides[i];
717  break;
718  }
719 
720  // No entrant sides on this neighbor were found
721  if (incoming_side == RayTracingCommon::invalid_side)
722  return NO_EXIT;
723 
724  intersection_point = RayTracingCommon::invalid_point;
725  intersected_side = RayTracingCommon::invalid_side;
726  intersected_extrema.invalidate();
727  intersection_distance = RayTracingCommon::invalid_distance;
728 
729  // See if there is a way through the neighbor element
730  debugRay("Called exitsElem() from moveThroughNeighbor()");
731  const auto exit_result =
732  exitsElem(neighbor,
733  neighbor->type(),
734  incoming_side,
735  intersection_point,
736  intersected_side,
737  intersected_extrema,
738  intersection_distance,
739  _backface_culling ? _study.getElemNormals(neighbor, _tid) : nullptr);
740  debugRay("Done with exitsElem() from moveThroughNeighbor()");
741 
742  return exit_result;
743 }
static const unsigned short invalid_side
Identifier for an invalid side index.
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
ExitsElemResult exitsElem(const Elem *elem, const ElemType elem_type, const unsigned short incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance, const Point *normals)
Determines if _current_ray moving in direction _direction exits elem.
bool _valid
Whether or not this neighbor is valid (needed for neighbors that span an edge)
Definition: NeighborInfo.h:69
const Real LOOSE_TRACE_TOLERANCE
Looser tolerance for use in error checking in difficult situations.
Definition: TraceRayTools.h:50
static const libMesh::Real invalid_distance
Identifier for an invalid distance.
bool _backface_culling
Whether or not to use element normals for backface culling.
Definition: TraceRay.h:449
const std::vector< unsigned short > _sides
The sides on the element that the neighboring portion is contained in.
Definition: NeighborInfo.h:61
std::vector< Point > _side_normals
The normals of each side in _sides.
Definition: NeighborInfo.h:63
dof_id_type id() const
const Elem *const _elem
The element.
Definition: NeighborInfo.h:59
virtual const Point * getElemNormals(const Elem *, const THREAD_ID)
Gets the outward normals for a given element.
void invalidate()
Invalidates the current state.
Definition: ElemExtrema.h:87
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
static const libMesh::Point invalid_point(invalid_distance, invalid_distance, invalid_distance)
Identifier for an invalid point.
virtual ElemType type() const=0
Point vertex_average() const

◆ moveThroughNeighbors()

TraceRay::ExitsElemResult TraceRay::moveThroughNeighbors ( const std::vector< NeighborInfo > &  neighbors,
const Elem last_elem,
const Elem *&  best_elem,
unsigned short &  best_elem_incoming_side 
)
private

Moves the Ray though neighbors (vertex/edge/point)

Parameters
neighborsThe neighbors to try to move through
last_elemThe last element that was moved through - this one will be tried last
best_elemThe resulting element for which an intersection was found
best_elem_incoming_sideThe incoming side on the resulting element for which
Returns
The trace result

Definition at line 585 of file TraceRay.C.

Referenced by trace().

589 {
591 
592  debugRay("Called moveThroughNeighbors() with ", neighbors.size(), " neighbors, and:");
593  debugRay(" last_elem->id() = ", last_elem ? last_elem->id() : DofObject::invalid_id);
594  debugRay(" _incoming_point = ", _incoming_point);
595 
596  traceAssert(!best_elem, "Best elem should be null");
597  traceAssert(best_elem_incoming_side == RayTracingCommon::invalid_side,
598  "Best elem side should be invalid");
599  traceAssert(_intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
600  traceAssert(_intersected_side == RayTracingCommon::invalid_side, "Side should be invalid");
601  traceAssert(_intersected_extrema.isInvalid(), "Extrema should be invalid");
603  "Distance should be invalid");
604 
605  // Marker for the longest ray segment distance we've found in a neighbor. Start with a quite
606  // small number because at this point we're desperate and will take anything!
607  Real longest_distance = 1.0e-12;
608  // Temporaries for the intersection checks
609  unsigned short current_incoming_side;
610  Point current_intersection_point;
611  unsigned short current_intersected_side;
612  ElemExtrema current_intersected_extrema;
613  Real current_intersection_distance;
614  TraceRay::ExitsElemResult best_exit_result = NO_EXIT;
615 
616  // The NeighborInfo for the last_elem
617  // (to store so we can try it later if we fail for everyone else)
618  const NeighborInfo * last_elem_info = nullptr;
619 
620  for (const NeighborInfo & neighbor_info : neighbors)
621  {
622  // If we're at the element we want to do last, skip it and store the info so
623  // we can get to it later in case we fail at finding anything
624  if (neighbor_info._elem == last_elem)
625  {
626  debugRay("Skipping last elem ", last_elem->id());
627  last_elem_info = &neighbor_info;
628  continue;
629  }
630 
631  const auto exit_result = moveThroughNeighbor(neighbor_info,
632  current_incoming_side,
633  current_intersection_point,
634  current_intersected_side,
635  current_intersected_extrema,
636  current_intersection_distance);
637 
638  // Found one! See if it's the best way
639  if (exit_result != NO_EXIT)
640  {
641  debugRay("Ray can exit through neighbor ", neighbor_info._elem->id());
642 
643  if (current_intersection_distance > longest_distance)
644  {
645  best_elem = neighbor_info._elem;
646  best_elem_incoming_side = current_incoming_side;
647  _intersection_point = current_intersection_point;
648  _intersected_side = current_intersected_side;
649  _intersected_extrema = current_intersected_extrema;
650  _intersection_distance = current_intersection_distance;
651  longest_distance = current_intersection_distance;
652  best_exit_result = exit_result;
653  }
654  }
655  }
656 
657  // Didn't find someone to exit, so try the last_elem (if any)
658  if (!best_elem && last_elem_info)
659  {
660  const auto exit_result = moveThroughNeighbor(*last_elem_info,
661  current_incoming_side,
662  current_intersection_point,
663  current_intersected_side,
664  current_intersected_extrema,
665  current_intersection_distance);
666 
667  if (exit_result != NO_EXIT && current_intersection_distance > longest_distance)
668  {
669  debugRay("Ray can exit through last_elem ", last_elem->id());
670 
671  best_elem = last_elem;
672  best_elem_incoming_side = current_incoming_side;
673  _intersection_point = current_intersection_point;
674  _intersected_side = current_intersected_side;
675  _intersected_extrema = current_intersected_extrema;
676  _intersection_distance = current_intersection_distance;
677  best_exit_result = exit_result;
678  }
679  }
680 
681  debugRay("moveThroughNeighbors() best result:");
682  debugRay(" best_elem = ", best_elem ? best_elem->id() : DofObject::invalid_id);
683  debugRay(" best_elem_incoming_side = ", best_elem_incoming_side);
684  debugRay(" _intersection_point = ", _intersection_point);
685  debugRay(" _intersected_side = ", _intersected_side);
686  debugRay(" _intersected_extrema = ", _intersected_extrema);
687  debugRay(" _intersection_distance = ", _intersection_distance);
688  if (best_elem)
689  {
690  debugRay("moveThroughNeighbors() next neighbor elem info:");
691  debugRay(best_elem->get_info());
692  }
693 
694  return best_exit_result;
695 }
static const unsigned short invalid_side
Identifier for an invalid side index.
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
std::string get_info() const
Helper for defining if at an element&#39;s edge, vertex, or neither.
Definition: ElemExtrema.h:25
bool isInvalid() const
Definition: ElemExtrema.h:48
Struct for containing the necessary information about a cached neighbor for ray tracing.
Definition: NeighborInfo.h:27
static const libMesh::Real invalid_distance
Identifier for an invalid distance.
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
dof_id_type id() const
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514
ExitsElemResult moveThroughNeighbor(const NeighborInfo &neighbor_info, unsigned short &incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance)
Sees if a Ray can move through a neighbor (vertex/edge/point)
Definition: TraceRay.C:698
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
ExitsElemResult
Enum for the different exit results for exitElem()
Definition: TraceRay.h:257
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
static const libMesh::Point invalid_point(invalid_distance, invalid_distance, invalid_distance)
Identifier for an invalid point.
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ onBoundary()

void TraceRay::onBoundary ( const std::shared_ptr< Ray > &  ray,
const bool  external 
)
private

Called when a Ray hits a boundary.

Definition at line 2082 of file TraceRay.C.

Referenced by applyOnExternalBoundary(), and applyOnInternalBoundary().

2083 {
2084  traceAssert(ray->currentPoint().absolute_fuzzy_equals(_intersection_point),
2085  "Ray currentPoint() not set before onBoundary()");
2086 
2087  // Get the RayBCs on bnd_elems
2089 
2090  // Store this information temprorarily because we are going to change it as we
2091  // apply each boundary condition
2092  const auto old_current_elem = _current_elem;
2093  const auto old_intersected_side = _intersected_side;
2094  const auto old_intersected_extrema = _intersected_extrema;
2095  const auto old_subdomain_id = _current_subdomain_id;
2096 
2097  // For each RayBC we found, apply it on the boundaries that we need
2099  {
2100  // First, find the boundaries this RayBC is valid on that are also in _boundary_elems.
2101  // We do this ahead of time so that we can pass in to RayBC::apply if the same
2102  // boundary condition is being appled multiple times on different boundaries.
2103  // This is useful in situations like reflection where multiple reflections are
2104  // necessary at a corner to perfectly reflect.
2105  _on_boundary_apply_index.clear();
2106  for (MooseIndex(_boundary_elems.size()) bnd_elems_i = 0; bnd_elems_i < _boundary_elems.size();
2107  ++bnd_elems_i)
2108  if (rbc->hasBoundary(_boundary_elems[bnd_elems_i].bnd_id))
2109  _on_boundary_apply_index.push_back(bnd_elems_i);
2110 
2111  traceAssert(!_on_boundary_apply_index.empty(), "Must not be empty");
2112 
2113  // Apply the RayBC on each of the relevant boundary elements
2114  for (const auto bnd_elems_i : _on_boundary_apply_index)
2115  {
2116  auto & bnd_elem = _boundary_elems[bnd_elems_i];
2117  _current_elem = bnd_elem.elem;
2118  _current_bnd_id = bnd_elem.bnd_id;
2119  _intersected_side = bnd_elem.side;
2120  _intersected_extrema = bnd_elem.extrema;
2122 
2123  rbc->onBoundary(_on_boundary_apply_index.size());
2124  postRayTracingObject(ray, rbc);
2125  }
2126  }
2127 
2128  // Set this info back now that we're done applying BCs
2129  _current_elem = old_current_elem;
2130  _intersected_side = old_intersected_side;
2131  _intersected_extrema = old_intersected_extrema;
2132  _current_bnd_id = BoundaryInfo::invalid_id;
2133  _current_subdomain_id = old_subdomain_id;
2134 
2135  // When on an external boundary, the Ray must have been changed or killed.
2136  // Otherwise, we don't know what to do with it now! If this didn't happen,
2137  // output a detailed error message.
2138  if (external && !ray->trajectoryChanged() && ray->shouldContinue())
2139  {
2140  std::stringstream oss;
2141  oss << "Don't know what to do with a Ray after it hit an external\n";
2142  oss << "boundary at point " << _intersection_point << "!\n\n";
2143  oss << "When hitting an external RayBC, a Ray must either:\n";
2144  oss << " Be killed by a RayBC\n";
2145  oss << " Have its trajectory changed by the RayBC\n";
2146  oss << "by at least one of the executed RayBCs.\n\n";
2147  oss << "You need to either:\n";
2148  oss << " Kill/change the Ray sooner with RayKernels, internal RayBCs, or a max distance\n";
2149  oss << " Kill/change the Ray on the boundary with a RayBC\n\n";
2150  if (!_on_boundary_ray_bcs.empty())
2151  {
2152  oss << "RayBCs executed that did not kill or change the Ray:\n";
2154  for (const auto & bnd_elem : _boundary_elems)
2155  if (rbc->hasBoundary(bnd_elem.bnd_id))
2156  oss << " " << rbc->typeAndName() << " on boundary " << bnd_elem.bnd_id << " ("
2157  << _mesh.getBoundaryName(bnd_elem.bnd_id) << ")\n";
2158  oss << "\n";
2159  }
2160  bool output_header = false;
2161  for (std::size_t i = 0; i < _boundary_elems.size(); ++i)
2162  {
2163  const auto bnd_id = _boundary_elems[i].bnd_id;
2164  bool found = false;
2166  if (rbc->hasBoundary(bnd_id))
2167  {
2168  found = true;
2169  break;
2170  }
2171 
2172  if (!found)
2173  {
2174  if (!output_header)
2175  {
2176  oss << "Boundaries that did not have any RayBCs:\n";
2177  output_header = true;
2178  }
2179  oss << " " << bnd_id << " (" << _mesh.getBoundaryName(bnd_id) << ")\n";
2180  }
2181  }
2182 
2183  failTrace(oss.str(), _study.tolerateFailure(), __LINE__);
2184  }
2185 }
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
std::vector< std::size_t > _on_boundary_apply_index
Reusable for which boundary elements to apply for a specific RayBC in onBoundary() ...
Definition: TraceRay.h:522
const std::string & getBoundaryName(BoundaryID boundary_id)
void postRayTracingObject(const std::shared_ptr< Ray > &ray, const RayTracingObject *rto)
Called after executing a RayTracingObject (RayBCs and RayKernels)
Definition: TraceRay.C:2196
MooseMesh & _mesh
The MooseMesh.
Definition: TraceRay.h:438
std::vector< RayBoundaryConditionBase * > _on_boundary_ray_bcs
Reusable for getting the RayBCs in onBoundary()
Definition: TraceRay.h:520
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
subdomain_id_type subdomain_id() const
std::vector< TraceRayBndElement > _boundary_elems
Boundary elements that need RayBCs to be applied.
Definition: TraceRay.h:497
void getRayBCs(std::vector< RayBoundaryConditionBase *> &result, BoundaryID id, THREAD_ID tid)
Fills the active RayBCs associated with this study and a boundary into result.
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
void failTrace(const std::string &reason, const bool warning, const int line=-1)
Specialized mooseError for a failed Ray trace with detailed information regarding the trace...
Definition: TraceRay.C:1806
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461
bool tolerateFailure() const
Whether or not to tolerate failure.
BoundaryID _current_bnd_id
The current BoundaryID (used when calling RayBoundaryConditionBase::onBoundary()) ...
Definition: TraceRay.h:486
Base class for the RayBC syntax.
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ onCompleteTrace()

void TraceRay::onCompleteTrace ( const std::shared_ptr< Ray > &  ray)
private

Called when a Ray is finished tracing (whenever !ray->shouldContinue())

Parameters
rayThe ray that is finished tracing

Definition at line 1627 of file TraceRay.C.

Referenced by trace().

1628 {
1630  rk->postTrace();
1631 
1632  debugRay("Called onCompleteTrace()\n", (*_current_ray)->getInfo());
1633  if (_intersection_distance > 0)
1634  possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1635  possiblySaveDebugRayMesh();
1636 
1638  {
1639  _current_cached_trace->_last = true;
1640 
1641  if (_intersection_distance > 0)
1642  {
1643  _current_cached_trace->addPoint(ray->currentPoint());
1644  if (_study.dataOnCacheTraces())
1645  _current_cached_trace->lastPoint()._data = ray->data();
1647  _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1648  }
1649 
1650  mooseAssert(ray->stationary() == _current_cached_trace->stationary(), "Stationary mismatch");
1651  }
1652 }
bool stationary() const
Definition: TraceData.h:59
TracePointData & lastPoint()
Definition: TraceData.h:57
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
Base object for the RayKernel syntax.
Definition: RayKernelBase.h:27
const std::vector< RayKernelBase * > & currentRayKernels(THREAD_ID tid) const
Gets the current RayKernels for a thread, which are set in segmentSubdomainSetup() ...
std::vector< RayData > _aux_data
The aux data on the Ray after this segment is traced (optional)
Definition: TraceData.h:36
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
bool auxDataOnCacheTraces() const
Whether or not to store the Ray aux data on the cached Ray traces.
TraceData * _current_cached_trace
The TraceData for the current cached trace (if any)
Definition: TraceRay.h:452
void addPoint(const libMesh::Point &point)
Definition: TraceData.h:55
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
std::vector< RayData > _data
The data on the Ray after this segment is traced (optional)
Definition: TraceData.h:34
bool _last
Whether or not this was the last set of segments for this Ray.
Definition: TraceData.h:76
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484
bool dataOnCacheTraces() const
Whether or not to store the Ray data on the cached Ray traces.
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ onContinueTrace()

void TraceRay::onContinueTrace ( const std::shared_ptr< Ray > &  ray)
private

Called when a Ray is continuing to trace after segment.

Parameters
rayThe ray

Definition at line 1655 of file TraceRay.C.

Referenced by trace().

1656 {
1657  traceAssert(ray->shouldContinue(), "Ray must continue");
1658 
1660  {
1661  _current_cached_trace->addPoint(ray->currentPoint());
1662  if (_study.dataOnCacheTraces())
1663  _current_cached_trace->lastPoint()._data = ray->data();
1665  _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1666  }
1667 }
TracePointData & lastPoint()
Definition: TraceData.h:57
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
bool segmentsOnCacheTraces() const
Whether or not to cache individual element segments when _cache_traces = true.
std::vector< RayData > _aux_data
The aux data on the Ray after this segment is traced (optional)
Definition: TraceData.h:36
bool auxDataOnCacheTraces() const
Whether or not to store the Ray aux data on the cached Ray traces.
TraceData * _current_cached_trace
The TraceData for the current cached trace (if any)
Definition: TraceRay.h:452
void addPoint(const libMesh::Point &point)
Definition: TraceData.h:55
std::vector< RayData > _data
The data on the Ray after this segment is traced (optional)
Definition: TraceData.h:34
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484
bool dataOnCacheTraces() const
Whether or not to store the Ray data on the cached Ray traces.

◆ onSegment()

void TraceRay::onSegment ( const std::shared_ptr< Ray > &  ray)
private

Called on a single segment traced by a Ray.

Definition at line 2025 of file TraceRay.C.

Referenced by trace().

2026 {
2027  traceAssert((*_current_ray)->currentElem() == _current_elem, "Ray currentElem() incorrect");
2028  traceAssert((*_current_ray)->currentPoint() == _intersection_point,
2029  "Ray currentPoint() incorrect");
2030  traceAssert((*_current_ray)->currentIncomingSide() == _incoming_side,
2031  "Ray currentIncomingSide() incorrect");
2032 #ifndef NDEBUG
2034  {
2037  "_current_elem does not contain incoming point");
2038 
2041  {
2043  .close_to_point(_intersection_point, LOOSE_TRACE_TOLERANCE),
2044  "Intersected point is not on intersected side");
2045  traceAssert(!_study.sideIsIncoming(
2046  _current_elem, _intersected_side, (*_current_ray)->direction(), _tid),
2047  "Intersected side is not outgoing");
2048  }
2051  {
2053  .close_to_point(_incoming_point, LOOSE_TRACE_TOLERANCE),
2054  "Incoming point is not on incoming side");
2055  if (ray->intersections() != 0 && ray->maxDistance() != 0)
2056  traceAssert(_study.sideIsIncoming(
2057  _current_elem, _incoming_side, (*_current_ray)->direction(), _tid),
2058  "Incoming side is not incoming");
2059  }
2060  }
2061 #endif
2064  "_intersection_distance is incorrect");
2065  traceAssert(_current_subdomain_id == _current_elem->subdomain_id(), "Subdomain incorrect");
2068  "Invalid intersection distance");
2069 
2072 
2073  const auto & rks = _study.currentRayKernels(_tid);
2074  for (auto & rk : rks)
2075  {
2076  rk->onSegment();
2077  postRayTracingObject(ray, rk);
2078  }
2079 }
static const unsigned short invalid_side
Identifier for an invalid side index.
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
virtual bool has_affine_map() const
virtual void reinitSegment(const Elem *elem, const Point &start, const Point &end, const Real length, THREAD_ID tid)
Reinitialize objects for a Ray segment for ray tracing.
const Real LOOSE_TRACE_TOLERANCE
Looser tolerance for use in error checking in difficult situations.
Definition: TraceRayTools.h:50
const std::vector< RayKernelBase * > & currentRayKernels(THREAD_ID tid) const
Gets the current RayKernels for a thread, which are set in segmentSubdomainSetup() ...
void postRayTracingObject(const std::shared_ptr< Ray > &ray, const RayTracingObject *rto)
Called after executing a RayTracingObject (RayBCs and RayKernels)
Definition: TraceRay.C:2196
libMesh::ElemSideBuilder _elem_side_builder
Helper for building element sides without excessive allocation.
Definition: TraceRay.h:517
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
bool verifyTraceIntersections() const
Whether or not trace verification is enabled in devel/dbg modes.
unsigned short _incoming_side
The incoming side of the current Ray.
Definition: TraceRay.h:471
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
auto norm(const T &a) -> decltype(std::abs(a))
bool sideIsNonPlanar(const Elem *elem, const unsigned short s) const
Whether or not the side on elem elem is non-planar.
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
subdomain_id_type subdomain_id() const
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484
bool sideIsIncoming(const Elem *const elem, const unsigned short side, const Point &direction, const THREAD_ID tid)
Whether or not side is incoming on element elem in direction direction.
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ onSubdomainChanged()

void TraceRay::onSubdomainChanged ( const std::shared_ptr< Ray > &  ray,
const bool  same_ray 
)
private

Called when the subdomain changes.

Parameters
rayThe current Ray
same_rayWhether or not this is being called on the same Ray as previously

Definition at line 1724 of file TraceRay.C.

Referenced by trace().

1725 {
1726  debugRay("Calling onSubdomainChanged() on subdomain ", _current_elem->subdomain_id());
1727  debugRay(" _current_subdomain_id = ", _current_subdomain_id);
1728 
1733 
1734  if (_has_ray_kernels)
1735  {
1736  auto & current_ray_kernels = _study.currentRayKernels(_tid);
1737 
1738  // If we're still tracing the same Ray, keep track of our old RayKernels
1739  // so that we don't call preTrace() on them again
1740  if (same_ray)
1741  _old_ray_kernels.insert(current_ray_kernels.begin(), current_ray_kernels.end());
1742  // If we're not tracing the same Ray, we need to call preTrace() on everything
1743  else
1744  _old_ray_kernels.clear();
1745 
1746  // Call segmentSubdomainSetup to get new kernels etc
1748 
1749  // Call preTrace() on all of the RayKernels that need it
1750  for (RayKernelBase * rk : current_ray_kernels)
1751  // Haven't called preTrace() for this Ray on this RayKernel yet
1752  if (!_old_ray_kernels.count(rk))
1753  rk->preTrace();
1754  }
1755 }
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
unsigned short _current_elem_n_sides
The number of sides on the current elem, used to avoid elem->n_sides() virtual calls.
Definition: TraceRay.h:467
libMesh::ElemType _current_elem_type
The current elem type (constant on subdomain), used to avoid elem->type() calls.
Definition: TraceRay.h:465
Base object for the RayKernel syntax.
Definition: RayKernelBase.h:27
const std::vector< RayKernelBase * > & currentRayKernels(THREAD_ID tid) const
Gets the current RayKernels for a thread, which are set in segmentSubdomainSetup() ...
Real subdomainHmax(const SubdomainID subdomain_id) const
Get the cached hmax for all elements in a subdomain.
std::set< RayKernelBase * > _old_ray_kernels
Helper for avoiding calling preTrace() on the same RayKernel multiple times.
Definition: TraceRay.h:530
bool _has_ray_kernels
Whether or not the RayTracingStudy has any RayKernels.
Definition: TraceRay.h:525
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
virtual unsigned int n_sides() const=0
subdomain_id_type subdomain_id() const
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
virtual void segmentSubdomainSetup(const SubdomainID subdomain, const THREAD_ID tid, const RayID ray_id)
Setup for on subdomain change or subdomain AND ray change during ray tracing.
Real _current_subdomain_hmax
The current subdomain hmax.
Definition: TraceRay.h:463
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461
virtual ElemType type() const=0

◆ onTrajectoryChanged()

void TraceRay::onTrajectoryChanged ( const std::shared_ptr< Ray > &  ray)
private

Called when a Ray's trajectory changes.

Parameters
rayThe ray

Definition at line 1695 of file TraceRay.C.

Referenced by trace().

1696 {
1697 #ifndef NDEBUG
1700  ? !_current_elem->close_to_point(ray->currentPoint(), LOOSE_TRACE_TOLERANCE)
1701  : !_current_elem->contains_point(ray->currentPoint())))
1702  failTrace("Elem does not contain point after trajectory change",
1703  /* warning = */ false,
1704  __LINE__);
1705 #endif
1706 
1707  traceAssert(ray->shouldContinue(), "Ray should continue when trajectory is being changed");
1708 
1709  ray->setTrajectoryChanged(false);
1710  ray->addTrajectoryChange();
1711 
1713  {
1714  if (_intersection_distance > 0)
1715  _current_cached_trace->addPoint(ray->currentPoint());
1716  if (_study.dataOnCacheTraces())
1717  _current_cached_trace->lastPoint()._data = ray->data();
1719  _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1720  }
1721 }
TracePointData & lastPoint()
Definition: TraceData.h:57
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
bool segmentsOnCacheTraces() const
Whether or not to cache individual element segments when _cache_traces = true.
const Real LOOSE_TRACE_TOLERANCE
Looser tolerance for use in error checking in difficult situations.
Definition: TraceRayTools.h:50
std::vector< RayData > _aux_data
The aux data on the Ray after this segment is traced (optional)
Definition: TraceData.h:36
bool verifyTraceIntersections() const
Whether or not trace verification is enabled in devel/dbg modes.
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
bool auxDataOnCacheTraces() const
Whether or not to store the Ray aux data on the cached Ray traces.
TraceData * _current_cached_trace
The TraceData for the current cached trace (if any)
Definition: TraceRay.h:452
void addPoint(const libMesh::Point &point)
Definition: TraceData.h:55
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
bool atExtrema() const
Definition: ElemExtrema.h:44
virtual bool close_to_point(const Point &p, Real tol) const
std::vector< RayData > _data
The data on the Ray after this segment is traced (optional)
Definition: TraceData.h:34
void failTrace(const std::string &reason, const bool warning, const int line=-1)
Specialized mooseError for a failed Ray trace with detailed information regarding the trace...
Definition: TraceRay.C:1806
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484
bool dataOnCacheTraces() const
Whether or not to store the Ray data on the cached Ray traces.

◆ possiblyAddToBoundaryElems()

void TraceRay::possiblyAddToBoundaryElems ( const Elem elem,
const unsigned short  side,
const std::vector< BoundaryID > &  bnd_ids,
const ElemExtrema extrema 
)
private

Helper for possibly storing boundary information in _boundary_elems, which is storage for boundary elements (elem, side, bnd_id) that need to have RayBCs applied to them.

For each BoundaryID in bnd_ids, a ConstBndElement will be added if said BoundaryID does not already exist in _boundary_elems.

Parameters
elemThe element to possibly add
sideThe side to possibly add
bnd_idsThe BoundaryIDs to possibly add
extremaThe intersected elem extrema (vertex/edge), if any

Definition at line 917 of file TraceRay.C.

Referenced by applyOnExternalBoundary(), and applyOnInternalBoundary().

921 {
922  if (!_study.sideIsNonPlanar(elem, side))
923  traceAssert(extrema.isValid(elem, _intersection_point), "Extrema not correct");
924 
925  for (const auto bnd_id : bnd_ids)
926  {
927  bool found = false;
928  for (const auto & bnd_elem : _boundary_elems)
929  if (bnd_elem.bnd_id == bnd_id)
930  {
931  found = true;
932  break;
933  }
934 
935  if (!found)
936  {
937  debugRay(" Need to apply boundary on elem ",
938  elem->id(),
939  " and side ",
940  side,
941  " for bnd_id ",
942  bnd_id);
943 
944  _boundary_elems.emplace_back(elem, side, bnd_id, extrema);
945  }
946  }
947 }
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
bool isValid(const Elem *const elem, const Point &point) const
Definition: ElemExtrema.C:49
dof_id_type id() const
bool sideIsNonPlanar(const Elem *elem, const unsigned short s) const
Whether or not the side on elem elem is non-planar.
std::vector< TraceRayBndElement > _boundary_elems
Boundary elements that need RayBCs to be applied.
Definition: TraceRay.h:497
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

◆ postRayTracingObject()

void TraceRay::postRayTracingObject ( const std::shared_ptr< Ray > &  ray,
const RayTracingObject rto 
)
private

Called after executing a RayTracingObject (RayBCs and RayKernels)

Verifies the configuration of ray->shouldContinue() and ray->trajectoryChanged()

Definition at line 2196 of file TraceRay.C.

Referenced by onBoundary(), and onSegment().

2197 {
2198  if (!ray->shouldContinue())
2199  {
2200  if (_should_continue)
2201  _should_continue = false;
2202  }
2203  else if (!_should_continue)
2204  failTrace(rto->typeAndName() +
2205  " set a Ray to continue that was previously set to not continue.\n\n" +
2206  "Once a Ray has been set to not continue, its continue status cannot change.",
2207  /* warning = */ false,
2208  __LINE__);
2209 
2210  if (!_should_continue && ray->trajectoryChanged())
2211  failTrace(rto->typeAndName() +
2212  " changed the trajectory of a Ray that was set to not continue,\n" +
2213  "or set a Ray whose trajectory was changed to not continue.",
2214  /* warning = */ false,
2215  __LINE__);
2216 }
std::string typeAndName() const
void failTrace(const std::string &reason, const bool warning, const int line=-1)
Specialized mooseError for a failed Ray trace with detailed information regarding the trace...
Definition: TraceRay.C:1806
bool _should_continue
Whether or not the current Ray should continue.
Definition: TraceRay.h:473

◆ preExecute()

void TraceRay::preExecute ( )

Should be called immediately before calling any traces.

Definition at line 61 of file TraceRay.C.

62 {
63  _current_subdomain_id = Elem::invalid_subdomain_id;
65 
66  // Zero out all results
67  for (auto & val : _results)
68  val = 0;
69 
72 }
bool hasRayKernels(const THREAD_ID tid)
Whether or not there are currently any active RayKernel objects.
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
libMesh::ElemType _current_elem_type
The current elem type (constant on subdomain), used to avoid elem->type() calls.
Definition: TraceRay.h:465
bool isRectangularDomain() const
Whether or not the domain is rectangular (if it is prefectly encompassed by its bounding box) ...
INVALID_ELEM
bool _has_ray_kernels
Whether or not the RayTracingStudy has any RayKernels.
Definition: TraceRay.h:525
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514
bool _is_rectangular_domain
Whether or not the domain is rectangular (defined perfectly by its bounding box)
Definition: TraceRay.h:527
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461

◆ results()

std::vector<unsigned long long int> TraceRay::results ( ) const
inline

Get the various results reported by this object, indexed by TraceRayResult.

Definition at line 93 of file TraceRay.h.

93 { return _results; }
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514

◆ setBackfaceCulling()

void TraceRay::setBackfaceCulling ( const bool  backface_culling)
inline

Enable or disable the use of element normals for backface culling through the getElemNormals() method.

By default, the _study.getElemNormals() method is not implemented. This is because in order to be able to obtain the element normals often enough during a trace, one needs to implement a method to cache the normals. Otherwise, it is not worthwhile to use the normals during the trace because the time spent computing the normals on the fly will be greater than the time gain by using the normals in the tracing process.

Definition at line 105 of file TraceRay.h.

Referenced by BackfaceCullingStudyTest::BackfaceCullingStudyTest().

105 { _backface_culling = backface_culling; }
bool _backface_culling
Whether or not to use element normals for backface culling.
Definition: TraceRay.h:449

◆ storeExitsElemResult()

void TraceRay::storeExitsElemResult ( const ExitsElemResult  result)
private

Stores the result given by an intersection in _results as necessary.

Definition at line 2012 of file TraceRay.C.

Referenced by trace().

2013 {
2014  if (result == HIT_FACE)
2015  ++_results[FACE_HITS];
2016  else if (result == HIT_VERTEX)
2017  ++_results[VERTEX_HITS];
2018  else if (result == HIT_EDGE)
2019  ++_results[EDGE_HITS];
2020  else
2021  mooseError("Should not call storeExitsElemResult() with result ", result);
2022 }
void mooseError(Args &&... args)
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514

◆ subdomainHmax()

Real TraceRay::subdomainHmax ( const Elem elem) const
private

Get the approximate subdomain hmax for an element.

Uses the cached value of _current_subdomain_hmax if the element is in the cached subdomain.

Definition at line 2188 of file TraceRay.C.

Referenced by exitsElem().

2189 {
2190  const auto subdomain_id = elem->subdomain_id();
2191  return subdomain_id == _current_subdomain_id ? _current_subdomain_hmax
2192  : _study.subdomainHmax(subdomain_id);
2193 }
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
Real subdomainHmax(const SubdomainID subdomain_id) const
Get the cached hmax for all elements in a subdomain.
subdomain_id_type subdomain_id() const
Real _current_subdomain_hmax
The current subdomain hmax.
Definition: TraceRay.h:463
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461

◆ trace()

void TraceRay::trace ( const std::shared_ptr< Ray > &  ray)

Traces a ray.

Definition at line 1019 of file TraceRay.C.

1020 {
1021  mooseAssert(_study.currentlyPropagating(), "Should only use while propagating rays");
1022 
1023  _current_ray = &ray;
1024  _current_elem = ray->currentElem();
1025  _last_elem = nullptr;
1026  _incoming_point = ray->currentPoint();
1027  _incoming_side = ray->currentIncomingSide();
1028  _should_continue = true;
1029 
1030  _study.preTrace(_tid, ray);
1031 
1032  traceAssert(_current_elem, "Current element is not set");
1033  traceAssert(_current_elem->active(), "Current element is not active");
1034  traceAssert(!ray->invalidCurrentPoint(), "Current point is invalid");
1035  traceAssert(ray->shouldContinue(), "Ray should not continue");
1036  if (_study.verifyRays() && !ray->invalidCurrentIncomingSide() && ray->maxDistance() > 0 &&
1038  !_study.sideIsIncoming(_current_elem, _incoming_side, ray->direction(), _tid))
1039  failTrace("Ray incoming side is not incoming", /* warning = */ false, __LINE__);
1040 
1041 #ifdef DEBUG_RAY_IF
1042  if (DEBUG_RAY_IF)
1043  libMesh::err << "\n\n";
1044 #endif
1045  debugRay("At top of trace for Ray");
1046  debugRay("Top of trace loop Ray info\n", ray->getInfo());
1047  debugRay("Top of trace loop starting elem info\n", ray->currentElem()->get_info());
1048 
1049  // Invalidate this up front because it's copied immedtiately into _last_intersected_extrema
1051 
1052 #ifdef DEBUG_RAY_MESH_IF
1053  _debug_mesh = nullptr;
1054  _debug_node_count = 0;
1055  if (DEBUG_RAY_MESH_IF)
1056  {
1057  _debug_mesh = new Mesh(_debug_comm, _dim);
1059  }
1060 #endif
1061 
1062  // Caching trace along the way: init for this Ray
1063  if (_study.shouldCacheTrace(ray))
1064  {
1065  debugRay("Trying to init threaded cached trace");
1066 
1068 
1069  // Add starting data
1070  if (_study.dataOnCacheTraces())
1071  _current_cached_trace->lastPoint()._data = ray->data();
1073  _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1074  }
1075  else
1076  _current_cached_trace = nullptr;
1077 
1078  // Need to call subdomain setup
1080  onSubdomainChanged(ray, /* same_ray = */ false);
1081  // If we didn't change subdomains, we still need to call this on the RayKernels
1082  else
1084  rk->preTrace();
1085 
1086  // Ray tracing loop through each segment for a single Ray on this processor
1087  do
1088  {
1089 #ifdef DEBUG_RAY_IF
1090  if (DEBUG_RAY_IF)
1091  libMesh::err << "\n\n";
1092 #endif
1093  debugRay("At top of ray tracing loop");
1094  debugRay(" ray->id() = ", ray->id());
1095  debugRay(" _incoming_point = ", _incoming_point);
1096  debugRay(" _incoming_side = ", _incoming_side);
1097  debugRay(" _current_elem->id() = ", _current_elem->id());
1098  debugRay(" _current_elem->subdomain_id() = ", _current_elem->subdomain_id());
1099  debugRay(" _current_subdomain_id = ", _current_subdomain_id);
1100  debugRay(" _current_elem_type = ", Utility::enum_to_string(_current_elem_type));
1101  debugRay("Top of ray tracing loop Ray info\n", ray->getInfo());
1102  debugRay("Top of ray tracing loop current elem info\n", _current_elem->get_info());
1103 
1104  traceAssert(_current_ray == &ray, "Current ray mismatch");
1105 
1106  // Copy over in case we need to use it
1108  // Invalidate all intersections as we're tracing again
1109  _exits_elem = false;
1114 
1115  // Stationary ray
1116  if (ray->stationary())
1117  {
1118  mooseAssert(ray->invalidDirection(), "Should have an invalid direction");
1119  _exits_elem = true;
1124  }
1125  // If we haven't hit a vertex or an edge, do the normal exit algorithm first.
1126  // In the case of a Ray that previously moved through point neighbors due to
1127  // being at a vertex/edge, this will be true because we do not communicate the
1128  // vertex/edge intersection. The previous processor already set us up for
1129  // the best intersection because it already computed it and chose to
1130  // send it our way as such
1132  {
1133  traceAssert(_current_elem->processor_id() == _pid, "Trace elem not on processor");
1134  debugRay("Didn't hit vertex or edge: doing normal exits elem check");
1135 
1136  if (_backface_culling)
1138 
1139  const auto exits_elem_result = exitsElem(_current_elem,
1147 
1148  if (exits_elem_result != NO_EXIT)
1149  {
1150  storeExitsElemResult(exits_elem_result);
1151  _exits_elem = true;
1152  ray->setCurrentPoint(_intersection_point);
1153  }
1154  }
1155  else
1156  {
1157  debugRay("Will not do normal exits elem check because at a vertex/edge");
1158  }
1159 
1160  // At this point, we either did a regular exit check and it failed, or we hit a vertex/edge
1161  // on the previous intersection and didn't bother to do a regular exit check on
1162  // _current_elem
1163  if (!_exits_elem)
1164  {
1165  debugRay("Moving through neighbors");
1166 
1167  // The element we want moveThroughNeighbors() to try last. That is - if all others fail,
1168  // this is the last resort. If we have a last intersection that tells us we're going
1169  // through a vertex or edge, we probably won't go back to that elem. If we don't, it means
1170  // that we failed the exitsElem() check on _current_elem and probably won't return to it
1171  // either.
1172  const Elem * move_through_neighbors_last = nullptr;
1173 
1174  // Get the neighbors
1175  const std::vector<NeighborInfo> * neighbors = nullptr;
1176  // If we have previous vertex/edge information, use it
1178  {
1179  traceAssert(_last_elem, "Should be valid");
1180  move_through_neighbors_last = _last_elem;
1182  }
1183  // Without previous vertex/edge information, let's try to find some. We could just do
1184  // a pure point neighbor check at the current point, but we'd rather be able to cache
1185  // this information so that someone else can use it - this requires the more unique
1186  // identifier of which vertex/edge we are at.
1187  else
1188  {
1189  debugRay(" Searching for vertex/edge hit with incoming side ",
1191  " on elem ",
1192  _current_elem->id(),
1193  " at ",
1194  _incoming_point);
1195 
1196  move_through_neighbors_last = _current_elem;
1197 
1198  // If we have side info: check for vertices on said side, otherwise, check everywhere
1199  const auto at_v = _incoming_side != RayTracingCommon::invalid_side
1202 
1204  neighbors = &getVertexNeighbors(_current_elem, at_v);
1205  // If still nothing and in 3D, check if we're on an edge
1206  // TODO: Handle 2D with a similar check for if we're on a side
1207  else if (_dim == 3)
1208  {
1209  ElemExtrema extrema;
1212  else
1214 
1215  if (extrema.atEdge())
1216  neighbors = &getEdgeNeighbors(_current_elem, extrema, _incoming_point);
1217  }
1218 
1219  // If we still haven't found anything - let's try a last-ditch effort
1220  if (!neighbors || neighbors->empty())
1222 
1223  // Couldn't find anything
1224  if (neighbors->empty())
1225  {
1226  failTrace("Could not find neighbors to move through", _study.tolerateFailure(), __LINE__);
1227  return;
1228  }
1229  }
1230 
1231  // Move through a neighbor
1232  const Elem * best_neighbor = nullptr;
1233  auto best_neighbor_side = RayTracingCommon::invalid_side;
1234  const auto exits_elem_result = moveThroughNeighbors(
1235  *neighbors, move_through_neighbors_last, best_neighbor, best_neighbor_side);
1236 
1237  // If we didn't find anything... we're out of luck
1238  if (exits_elem_result == NO_EXIT)
1239  {
1240  failTrace("Could not find intersection after trying to move through point neighbors",
1242  __LINE__);
1243  return;
1244  }
1245 
1246  // At this point, we've successfully made it through an element and also started
1247  // through another element, so set that
1248  _exits_elem = true;
1250  _current_elem = best_neighbor;
1251  _incoming_side = best_neighbor_side;
1252  ray->setCurrentElem(best_neighbor);
1253  ray->setCurrentIncomingSide(best_neighbor_side);
1254  ray->setCurrentPoint(_intersection_point);
1255 
1256  // Don't own this element - return exits trace for this Ray on this proc
1257  if (best_neighbor->processor_id() != _pid)
1258  {
1259  // We've already computed the next intersection but said intersection is
1260  // on an elem on another processor. Therefore, the next proc will re-trace
1261  // this Ray on the perfect elem that we've picked (best_neighbor)
1262  ray->setCurrentPoint(_incoming_point);
1264 
1266  return;
1267  }
1268 
1269  // Subdomain changed
1271  onSubdomainChanged(ray, /* same_ray = */ true);
1272 
1273  // Do own this element - tally the result as we're the ones tracing it
1274  storeExitsElemResult(exits_elem_result);
1275  }
1276 
1277  debugRay("Done with trace");
1278  debugRay(" _exits_elem: ", _exits_elem);
1279  debugRay(" _intersection_point: ", _intersection_point);
1280  debugRay(" _intersected_side: ", _intersected_side);
1281  debugRay(" _intersected_side centroid: ",
1284  : _current_elem->side_ptr(_intersected_side)->vertex_average());
1285  debugRay(" _intersected_extrema = ", _intersected_extrema);
1286  debugRay(" _intersection_distance = ", _intersection_distance);
1287 
1288  // Increment intersections
1289  if (_intersection_distance > 0)
1290  {
1291  debugRay("Incrementing ray intersections by 1 to ", ray->intersections() + 1);
1292  ray->addIntersection();
1294  }
1295 
1296  // Increment distance
1297  ray->addDistance(_intersection_distance);
1298  debugRay("Incremented ray distance by ", _intersection_distance);
1299 
1300  // The effective max distance that the Ray should travel - minimum of the two
1301  const auto max_distance = std::min(ray->maxDistance(), _study.rayMaxDistance());
1302  debugRay("Max distance checks");
1303  debugRay(" _study.rayMaxDistance() = ", _study.rayMaxDistance());
1304  debugRay(" ray->maxDistance() = ", ray->maxDistance());
1305  debugRay(" max_distance (effective) = ", max_distance);
1306 
1307  // At the maximum distance - distinguish between this and past the maximum
1308  // distance because in this case we're close enough to the intersection point
1309  // that we can keep it, its intersected side, and intersected extrema
1310  if (MooseUtils::absoluteFuzzyEqual(ray->distance(), max_distance))
1311  {
1312  debugRay("At max distance");
1313 
1314  ray->setShouldContinue(false);
1315  _should_continue = false;
1316  }
1317  // Past the max distance - need to remove the additional distance we traveled,
1318  // change the point and invalidate the intersection data (moves the Ray back)
1319  else if (ray->distance() > max_distance)
1320  {
1321  debugRay("Past max distance");
1322 
1323  // The distance past the max distance we have traveled
1324  const auto difference = ray->distance() - max_distance;
1325  traceAssert(difference > 0, "Negative distance change after past_max_distance");
1326 
1327  debugRay("Removing distance ", difference);
1328  ray->addDistance(-difference);
1329  debugRay(" New ray->distance() = ", ray->distance());
1330 
1331  _intersection_point -= ray->direction() * difference;
1332  _intersection_distance -= difference;
1335  ray->setCurrentPoint(_intersection_point);
1336 
1337  ray->setShouldContinue(false);
1338  _should_continue = false;
1339 
1340  traceAssert(_intersection_distance >= 0, "Negative _intersection_distance");
1341 #ifndef NDEBUG
1343  failTrace("Does not contain point after past max distance",
1344  /* warning = */ false,
1345  __LINE__);
1346 #endif
1347  }
1348 
1349  if (!_study.currentRayKernels(_tid).empty())
1350  {
1351  debugRay("Calling onSegment() with");
1352  debugRay(" current_elem->id() = ", _current_elem->id());
1353  debugRay(" _incoming_point = ", _incoming_point);
1354  debugRay(" _incoming_side = ", _incoming_side);
1355  debugRay(" _intersection_point = ", _intersection_point);
1356  debugRay(" _intersected_side = ", _intersected_side);
1357  debugRay(" _intersected_extrema = ", _intersected_extrema);
1358  debugRay(" _intersection_distance = ", _intersection_distance);
1359  onSegment(ray);
1360 
1361  _study.postOnSegment(_tid, ray);
1362 
1363  // RayKernel killed a Ray or we're at the end
1364  traceAssert(_should_continue == ray->shouldContinue(), "Should be the same");
1365  if (!_should_continue)
1366  {
1367  debugRay("RayKernel killed the ray or past max distance");
1368  traceAssert(!ray->trajectoryChanged(),
1369  "RayKernels should not change trajectories of Rays at end");
1370 
1371  onCompleteTrace(ray);
1372  return;
1373  }
1374 
1375  // RayKernel moved a Ray
1376  if (ray->trajectoryChanged())
1377  {
1378  debugRay("RayKernel changed the Ray's trajectory");
1379  debugRay(" new direction = ", ray->direction());
1380  debugRay(" old incoming point = ", _incoming_point);
1381  debugRay(" new incoming point = ", ray->currentPoint());
1382  possiblyAddDebugRayMeshPoint(_incoming_point, ray->currentPoint());
1383 
1384  _incoming_point = ray->currentPoint();
1387  ray->setCurrentIncomingSide(_incoming_side);
1388 
1389  const auto new_intersection_distance = (ray->currentPoint() - _incoming_point).norm();
1390  ray->addDistance(-_intersection_distance + new_intersection_distance);
1391  _intersection_distance = new_intersection_distance;
1392 
1393  onTrajectoryChanged(ray);
1394  onContinueTrace(ray);
1395  continue;
1396  }
1397  else
1398  possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1399  }
1400  else
1401  {
1402  _study.postOnSegment(_tid, ray);
1403 
1404  if (!_should_continue)
1405  {
1406  debugRay("Killing due to at end without RayKernels");
1407  traceAssert(!ray->shouldContinue(), "Ray shouldn't continue");
1408 
1409  onCompleteTrace(ray);
1410  return;
1411  }
1412  }
1413 
1414  // If at a vertex/on an edge and not on the boundary, we may actually be on the boundary,
1415  // just not on a boundary side. Check for that here. If the domain is rectangular we will
1416  // do a quick check against the bounding box as if we're not on the boundary of the
1417  // bounding box for a rectangular problem, we can skip this.
1418  // TODO: see how much the tolerance for the bounding box check can be tightened
1419  if (_dim > 1 && _intersected_extrema.atExtrema() &&
1424  _dim,
1426  {
1427  auto boundary_side = RayTracingCommon::invalid_side;
1428  ElemExtrema boundary_extrema;
1429  const Elem * boundary_elem = nullptr;
1430 
1431  findExternalBoundarySide(boundary_side, boundary_extrema, boundary_elem);
1432 
1433  if (boundary_elem)
1434  {
1435  // At this point, the new incoming side is very difficult to find
1436  // and may require some re-tracing backwards. Let's not do that -
1437  // we don't need it to continue the trace. This is reason why
1438  // _incoming_side is not available in RayBCs.
1440  _current_elem = boundary_elem;
1441  _intersected_side = boundary_side;
1442  _intersected_extrema = boundary_extrema;
1443  ray->setCurrentElem(_current_elem);
1444 
1445  debugRay("Found a neighbor boundary side with:");
1446  debugRay(" _current_elem->id() = ", _current_elem->id());
1447  debugRay(" _intersected_side = ", _intersected_side);
1448  debugRay(" _intersected_extrema = ", _intersected_extrema);
1449  }
1450  }
1451 
1452  // The next element
1453  const Elem * neighbor = nullptr;
1454 
1455  // Set up where to go next
1457  debugRay("Set _incoming point to ", _incoming_point);
1458 
1459  debugRay("Looking for neighbor on side ", _intersected_side, " of elem ", _current_elem->id());
1460 
1461  // Get the neighbor on that side
1462  // If the mesh has active elements of the same level, just grab the neighbor directly. In
1463  // this case, we can avoid a call to active() on the neighbor in getActiveNeighbor(), which
1464  // can be expensive depending on caching.
1465  neighbor = _study.hasSameLevelActiveElems()
1468 
1469  // Found one - not on the boundary so set the next info
1470  if (neighbor)
1471  {
1472  traceAssert(neighbor->active(), "Inactive neighbor");
1474  "_current_subdomain_id invalid");
1475 
1476  // If the mesh has active elements of the same level, don't use
1477  // neighbor->which_neighbor_am_i(), which calls active() and an n_sides() virtual call
1479  {
1480  // If the subdomain hasn't changed, we can guarantee n_sides is the same as
1481  // _current_elem. Prefer this because neighbor->n_sides() is an expensive virtual. Even
1482  // better, subdomain_id() isn't a virtual!
1483  const unsigned short n_sides = neighbor->subdomain_id() == _current_subdomain_id
1485  : neighbor->n_sides();
1486  traceAssert(n_sides == neighbor->n_sides(), "n_sides incorrect");
1487 
1488  for (_incoming_side = 0; _incoming_side < n_sides; ++_incoming_side)
1489  if (neighbor->neighbor_ptr(_incoming_side) == _current_elem)
1490  break;
1491  }
1492  else
1493  _incoming_side = neighbor->which_neighbor_am_i(_current_elem);
1494 
1496  _current_elem = neighbor;
1497  ray->setCurrentElem(neighbor);
1498  ray->setCurrentIncomingSide(_incoming_side);
1499 
1500  debugRay("Next elem: ", neighbor->id(), " with centroid ", neighbor->vertex_average());
1501  debugRay("Next _incoming_side: ",
1503  " with centroid ",
1504  neighbor->side_ptr(_incoming_side)->vertex_average());
1505  traceAssert(_last_elem->subdomain_id() == _current_subdomain_id,
1506  "_current_subdomain_id invalid");
1507 
1508  // Whether or not the subdomain changed
1509  const bool subdomain_changed = neighbor->subdomain_id() != _current_subdomain_id;
1510 
1511  // See if we hit any internal sides leaving this element and apply
1512  // We require that all internal RayBCs be on internal sidesets that have different
1513  // subdomain ids on each side. Therefore, only check if at vertex/edge or if
1514  // the subdomain changes
1515  if (_study.hasInternalSidesets() && (subdomain_changed || _intersected_extrema.atExtrema()))
1516  {
1518 
1519  // Internal RayBC killed a Ray
1520  if (!_should_continue)
1521  {
1522  traceAssert(!ray->shouldContinue(), "Should be the same");
1523  debugRay("Internal RayBC killed the ray");
1524 
1525  onCompleteTrace(ray);
1526  return;
1527  }
1528 
1529  // Internal RayBC changed the Ray
1530  if (ray->trajectoryChanged())
1531  {
1532  debugRay("Internal RayBC changed the trajectory:");
1533  debugRay(" new direction = ", ray->direction());
1534 
1535  // Is this side still incoming?
1536  const auto normal = _study.getSideNormal(_current_elem, _incoming_side, _tid);
1537  const auto dot = normal * ray->direction();
1538  debugRay("Dot product with new direction and side = ", dot);
1539  if (dot > -TRACE_TOLERANCE)
1540  {
1543  neighbor = _last_elem;
1544  ray->setCurrentElem(_current_elem);
1545  ray->setCurrentIncomingSide(_incoming_side);
1546  debugRay(" Dot > 0 (Ray turned around): Setting _current_elem = ",
1547  _current_elem->id(),
1548  " and _incoming_side = ",
1549  _incoming_side);
1550  }
1551 
1552  onTrajectoryChanged(ray);
1553  }
1554 
1555  traceAssert(ray->currentPoint().absolute_fuzzy_equals(_intersection_point, TRACE_TOLERANCE),
1556  "Internal RayBC changed the Ray point");
1557  }
1558 
1559  // Neighbor is off processor
1560  // If we hit at a vertex/edge, we will continue and let the move through neighbor exit
1561  // figure out who to send to
1562  if (neighbor->processor_id() != _pid)
1563  {
1565  {
1566  debugRay("Neighbor is off processor but continuing to move through neighbors");
1567  }
1568  else
1569  {
1571  return;
1572  }
1573  }
1574 
1575  // Neighbor is on processor, call subdomain setup if needed
1576  if (subdomain_changed)
1577  onSubdomainChanged(ray, /* same_ray = */ true);
1578  }
1579  // No neighbor found: on the boundary
1580  else
1581  {
1582  debugRay("No neighbor found - on the boundary");
1583 
1584  // Apply boundary conditions
1586 
1587  traceAssert(ray->currentPoint().absolute_fuzzy_equals(_intersection_point, TRACE_TOLERANCE),
1588  "RayBC changed the Ray point");
1589 
1590  // Quit tracing if the Ray was killed by a BC
1591  if (!_should_continue)
1592  {
1593  traceAssert(!ray->shouldContinue(), "Should be the same");
1594  debugRay("Exiting due to death by BC");
1595 
1596  onCompleteTrace(ray);
1597  return;
1598  }
1599  // RayBC changed the direction of the Ray
1600  if (ray->trajectoryChanged())
1601  {
1602  debugRay("RayBC changed the trajectory");
1603  debugRay(" new direction = ", ray->direction());
1604  traceAssert(ray->direction() *
1607  "Reflected ray is not incoming");
1608  possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1609 
1613  ray->setCurrentPoint(_incoming_point);
1614  ray->setCurrentIncomingSide(_incoming_side);
1615  onTrajectoryChanged(ray);
1616  }
1617  }
1618 
1619  onContinueTrace(ray);
1620  } while (true);
1621 
1622  // If a trace made its way down here and didn't return... it failed
1623  failTrace("Could not find an intersection", _study.tolerateFailure(), __LINE__);
1624 }
const std::vector< NeighborInfo > & getPointNeighbors(const Elem *elem, const Point &point)
Get the point neighbors.
Definition: TraceRay.C:1983
static const unsigned short invalid_side
Identifier for an invalid side index.
TracePointData & lastPoint()
Definition: TraceData.h:57
const std::vector< NeighborInfo > & getEdgeNeighbors(const Elem *elem, const std::pair< const Node *, const Node *> &vertices, const Point &point)
Get the neighbors at an edge.
RayTracingStudy & _study
The RayTracingStudy.
Definition: TraceRay.h:436
virtual void postOnSegment(const THREAD_ID tid, const std::shared_ptr< Ray > &ray)
Called at the end of a Ray segment.
ExitsElemResult exitsElem(const Elem *elem, const ElemType elem_type, const unsigned short incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance, const Point *normals)
Determines if _current_ray moving in direction _direction exits elem.
unsigned short _current_elem_n_sides
The number of sides on the current elem, used to avoid elem->n_sides() virtual calls.
Definition: TraceRay.h:467
ElemExtrema _intersected_extrema
The work point for the intersected vertex/edge vertices of the current Ray, if any.
Definition: TraceRay.h:480
void onTrajectoryChanged(const std::shared_ptr< Ray > &ray)
Called when a Ray&#39;s trajectory changes.
Definition: TraceRay.C:1695
static const unsigned short invalid_vertex
Identifier for an invalid vertex index.
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 findExternalBoundarySide(unsigned short &boundary_side, ElemExtrema &boundary_extrema, const Elem *&boundary_elem)
Finds (if any) an element side that is on the boundary and is outgoing at _intersection_point that is...
Definition: TraceRay.C:950
void applyOnExternalBoundary(const std::shared_ptr< Ray > &ray)
Gets and applies external boundary conditions in _current_elem on side _intersected_side at _intersec...
Definition: TraceRay.C:746
bool hasSameLevelActiveElems() const
Whether or not the mesh has active elements of the same level.
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Mesh * _debug_mesh
Definition: TraceRay.h:533
std::string get_info() const
libMesh::ElemType _current_elem_type
The current elem type (constant on subdomain), used to avoid elem->type() calls.
Definition: TraceRay.h:465
void onSegment(const std::shared_ptr< Ray > &ray)
Called on a single segment traced by a Ray.
Definition: TraceRay.C:2025
void skip_partitioning(bool skip)
void onContinueTrace(const std::shared_ptr< Ray > &)
Called when a Ray is continuing to trace after segment.
Definition: TraceRay.C:1655
unsigned int _debug_node_count
Definition: TraceRay.h:535
void onSubdomainChanged(const std::shared_ptr< Ray > &ray, const bool same_ray)
Called when the subdomain changes.
Definition: TraceRay.C:1724
Base object for the RayKernel syntax.
Definition: RayKernelBase.h:27
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
const std::vector< RayKernelBase * > & currentRayKernels(THREAD_ID tid) const
Gets the current RayKernels for a thread, which are set in segmentSubdomainSetup() ...
Parallel::Communicator _debug_comm
Definition: TraceRay.h:534
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.
Real rayMaxDistance() const
Max distance any Ray can travel.
static const libMesh::Real invalid_distance
Identifier for an invalid distance.
ElemExtrema _last_intersected_extrema
The intersected vertex/edge vertices for the previous intersection, if any.
Definition: TraceRay.h:482
const unsigned int _dim
The mesh dimension.
Definition: TraceRay.h:440
bool _backface_culling
Whether or not to use element normals for backface culling.
Definition: TraceRay.h:449
std::vector< RayData > _aux_data
The aux data on the Ray after this segment is traced (optional)
Definition: TraceData.h:36
const BoundingBox & boundingBox() const
Get the nodal bounding box for the domain.
const Real TRACE_TOLERANCE
The standard tolerance to use in tracing.
Definition: TraceRayTools.h:48
Point _incoming_point
The incoming point of the current Ray.
Definition: TraceRay.h:469
const Point * _current_normals
The normals for the current element for backface culling (pointer to the first normal - optional) ...
Definition: TraceRay.h:492
bool _exits_elem
Whether or not the current trace exits an element.
Definition: TraceRay.h:489
bool verifyTraceIntersections() const
Whether or not trace verification is enabled in devel/dbg modes.
unsigned short _incoming_side
The incoming side of the current Ray.
Definition: TraceRay.h:471
bool verifyRays() const
Whether or not to verify if Rays have valid information before being traced.
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
dof_id_type id() const
bool auxDataOnCacheTraces() const
Whether or not to store the Ray aux data on the cached Ray traces.
unsigned int which_neighbor_am_i(const Elem *e) const
const processor_id_type _pid
The processor id.
Definition: TraceRay.h:444
std::vector< unsigned long long int > _results
Results over all of the local traces, indexed by TraceRayResult.
Definition: TraceRay.h:514
const Elem * _last_elem
The last element the current Ray was traced in.
Definition: TraceRay.h:459
ExitsElemResult moveThroughNeighbors(const std::vector< NeighborInfo > &neighbors, const Elem *last_elem, const Elem *&best_elem, unsigned short &best_elem_incoming_side)
Moves the Ray though neighbors (vertex/edge/point)
Definition: TraceRay.C:585
bool rayDependentSubdomainSetup() const
Whether or not to use Ray dependent subdomain setup.
TraceData * _current_cached_trace
The TraceData for the current cached trace (if any)
Definition: TraceRay.h:452
OStreamProxy err(std::cerr)
void onCompleteTrace(const std::shared_ptr< Ray > &ray)
Called when a Ray is finished tracing (whenever !ray->shouldContinue())
Definition: TraceRay.C:1627
auto norm(const T &a) -> decltype(std::abs(a))
bool sideIsNonPlanar(const Elem *elem, const unsigned short s) const
Whether or not the side on elem elem is non-planar.
const std::shared_ptr< Ray > * _current_ray
The current ray being traced.
Definition: TraceRay.h:455
virtual const Point * getElemNormals(const Elem *, const THREAD_ID)
Gets the outward normals for a given element.
const Elem * _current_elem
The element the current Ray is being traced in.
Definition: TraceRay.h:457
bool atExtrema() const
Definition: ElemExtrema.h:44
bool _is_rectangular_domain
Whether or not the domain is rectangular (defined perfectly by its bounding box)
Definition: TraceRay.h:527
TraceData & initThreadedCachedTrace(const std::shared_ptr< Ray > &ray, THREAD_ID tid)
Initialize a Ray in the threaded cached trace map to be filled with segments.
const Elem * neighbor_ptr(unsigned int i) const
virtual const Point & getSideNormal(const Elem *elem, const unsigned short side, const THREAD_ID tid)
Get the outward normal for a given element side.
const std::vector< NeighborInfo > & getNeighbors(const Elem *elem, const ElemExtrema &extrema, const Point &point)
Get the point/vertex/edge neighbors depending on extrema.
Definition: TraceRay.C:1973
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
bool currentlyPropagating() const
Whether or not the study is propagating (tracing Rays)
subdomain_id_type subdomain_id() const
void invalidate()
Invalidates the current state.
Definition: ElemExtrema.h:87
virtual void preTrace(const THREAD_ID, const std::shared_ptr< Ray > &)
Called at the beginning of a trace for a ray.
const THREAD_ID _tid
The thread id.
Definition: TraceRay.h:446
void applyOnInternalBoundary(const std::shared_ptr< Ray > &ray)
Gets and applies internal boundary conditions (if any) from _current_elem, _last_elem, and any other point neighbors that have internal sidesets at _intersection_point.
Definition: TraceRay.C:805
std::vector< RayData > _data
The data on the Ray after this segment is traced (optional)
Definition: TraceData.h:34
void failTrace(const std::string &reason, const bool warning, const int line=-1)
Specialized mooseError for a failed Ray trace with detailed information regarding the trace...
Definition: TraceRay.C:1806
unsigned short _intersected_side
The work point for the intersected side of the current Ray.
Definition: TraceRay.h:478
static const libMesh::Point invalid_point(invalid_distance, invalid_distance, invalid_distance)
Identifier for an invalid point.
SubdomainID _current_subdomain_id
The current SubdomainID.
Definition: TraceRay.h:461
bool tolerateFailure() const
Whether or not to tolerate failure.
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.
const std::vector< NeighborInfo > & getVertexNeighbors(const Elem *elem, const Node *vertex)
Gets the neighbors at a vertex.
void continueTraceOffProcessor(const std::shared_ptr< Ray > &ray)
Sets up a ray to continue tracing off processor.
Definition: TraceRay.C:1670
bool active() const
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition: TraceRay.h:484
processor_id_type processor_id() const
bool dataOnCacheTraces() const
Whether or not to store the Ray data on the cached Ray traces.
bool atEdge() const
Definition: ElemExtrema.h:71
void storeExitsElemResult(const ExitsElemResult result)
Stores the result given by an intersection in _results as necessary.
Definition: TraceRay.C:2012
bool _should_continue
Whether or not the current Ray should continue.
Definition: TraceRay.h:473
Real domainMaxLength() const
Get the inflated maximum length across the domain.
bool sideIsIncoming(const Elem *const elem, const unsigned short side, const Point &direction, const THREAD_ID tid)
Whether or not side is incoming on element elem in direction direction.
const Elem * getActiveNeighbor(const Elem *elem, const unsigned short side, const Point &point)
Get the active neighbor on side of elem that contains point.
bool hasInternalSidesets() const
Whether or not the local mesh has internal sidesets that have RayBCs on them.
virtual bool shouldCacheTrace(const std::shared_ptr< Ray > &) const
Virtual that allows for selection in if a Ray should be cached or not (only used when _cache_traces)...
Point _intersection_point
The work point for the intersection of the current Ray.
Definition: TraceRay.h:476

Member Data Documentation

◆ _backface_culling

bool TraceRay::_backface_culling
private

Whether or not to use element normals for backface culling.

Definition at line 449 of file TraceRay.h.

Referenced by exitsElem(), moveThroughNeighbor(), setBackfaceCulling(), and trace().

◆ _boundary_elems

std::vector<TraceRayBndElement> TraceRay::_boundary_elems
private

Boundary elements that need RayBCs to be applied.

Definition at line 497 of file TraceRay.h.

Referenced by applyOnExternalBoundary(), applyOnInternalBoundary(), onBoundary(), and possiblyAddToBoundaryElems().

◆ _boundary_ids

std::vector<BoundaryID> TraceRay::_boundary_ids
private

Reusable vector for calling _boundary_info.boundary_ids()

Definition at line 495 of file TraceRay.h.

Referenced by applyOnExternalBoundary().

◆ _boundary_info

const BoundaryInfo& TraceRay::_boundary_info
private

The BoundaryInfo for the mesh.

Definition at line 442 of file TraceRay.h.

Referenced by applyOnExternalBoundary().

◆ _current_bnd_id

BoundaryID TraceRay::_current_bnd_id
private

The current BoundaryID (used when calling RayBoundaryConditionBase::onBoundary())

Definition at line 486 of file TraceRay.h.

Referenced by currentBoundaryID(), and onBoundary().

◆ _current_cached_trace

TraceData* TraceRay::_current_cached_trace
private

The TraceData for the current cached trace (if any)

Definition at line 452 of file TraceRay.h.

Referenced by continueTraceOffProcessor(), onCompleteTrace(), onContinueTrace(), onTrajectoryChanged(), and trace().

◆ _current_elem

const Elem* TraceRay::_current_elem
private

◆ _current_elem_n_sides

unsigned short TraceRay::_current_elem_n_sides
private

The number of sides on the current elem, used to avoid elem->n_sides() virtual calls.

Definition at line 467 of file TraceRay.h.

Referenced by failTraceMessage(), findExternalBoundarySide(), onSubdomainChanged(), and trace().

◆ _current_elem_type

libMesh::ElemType TraceRay::_current_elem_type
private

The current elem type (constant on subdomain), used to avoid elem->type() calls.

Definition at line 465 of file TraceRay.h.

Referenced by failTraceMessage(), onSubdomainChanged(), preExecute(), and trace().

◆ _current_normals

const Point* TraceRay::_current_normals
private

The normals for the current element for backface culling (pointer to the first normal - optional)

Definition at line 492 of file TraceRay.h.

Referenced by trace().

◆ _current_ray

const std::shared_ptr<Ray>* TraceRay::_current_ray
private

The current ray being traced.

Definition at line 455 of file TraceRay.h.

Referenced by currentRay(), and trace().

◆ _current_subdomain_hmax

Real TraceRay::_current_subdomain_hmax
private

The current subdomain hmax.

Definition at line 463 of file TraceRay.h.

Referenced by onSubdomainChanged(), and subdomainHmax().

◆ _current_subdomain_id

SubdomainID TraceRay::_current_subdomain_id
private

The current SubdomainID.

Definition at line 461 of file TraceRay.h.

Referenced by currentSubdomainID(), failTraceMessage(), onBoundary(), onSegment(), onSubdomainChanged(), preExecute(), subdomainHmax(), and trace().

◆ _debug_comm

Parallel::Communicator TraceRay::_debug_comm
private

Definition at line 534 of file TraceRay.h.

Referenced by trace().

◆ _debug_mesh

Mesh* TraceRay::_debug_mesh
private

Definition at line 533 of file TraceRay.h.

Referenced by trace().

◆ _debug_node_count

unsigned int TraceRay::_debug_node_count
private

Definition at line 535 of file TraceRay.h.

Referenced by trace().

◆ _dim

const unsigned int TraceRay::_dim
private

The mesh dimension.

Definition at line 440 of file TraceRay.h.

Referenced by applyOnExternalBoundary(), applyOnInternalBoundary(), findExternalBoundarySide(), and trace().

◆ _edge_neighbors

std::unordered_map<std::pair<const Node *, const Node *>, std::pair<bool, std::vector<NeighborInfo> > > TraceRay::_edge_neighbors
private

The cached edge neighbors.

Definition at line 504 of file TraceRay.h.

Referenced by meshChanged().

◆ _elem_side_builder

libMesh::ElemSideBuilder TraceRay::_elem_side_builder
private

Helper for building element sides without excessive allocation.

Definition at line 517 of file TraceRay.h.

Referenced by exitsElem(), and onSegment().

◆ _exits_elem

bool TraceRay::_exits_elem
private

Whether or not the current trace exits an element.

Definition at line 489 of file TraceRay.h.

Referenced by failTraceMessage(), and trace().

◆ _has_ray_kernels

bool TraceRay::_has_ray_kernels
private

Whether or not the RayTracingStudy has any RayKernels.

Definition at line 525 of file TraceRay.h.

Referenced by onSubdomainChanged(), and preExecute().

◆ _incoming_point

Point TraceRay::_incoming_point
private

◆ _incoming_side

unsigned short TraceRay::_incoming_side
private

The incoming side of the current Ray.

Definition at line 471 of file TraceRay.h.

Referenced by applyOnInternalBoundary(), continueTraceOffProcessor(), currentIncomingSide(), exitsElem(), failTraceMessage(), onSegment(), and trace().

◆ _intersected_extrema

ElemExtrema TraceRay::_intersected_extrema
private

The work point for the intersected vertex/edge vertices of the current Ray, if any.

Definition at line 480 of file TraceRay.h.

Referenced by applyOnExternalBoundary(), applyOnInternalBoundary(), currentIntersectedExtrema(), failTraceMessage(), findExternalBoundarySide(), moveThroughNeighbors(), onBoundary(), onTrajectoryChanged(), and trace().

◆ _intersected_side

unsigned short TraceRay::_intersected_side
private

The work point for the intersected side of the current Ray.

Definition at line 478 of file TraceRay.h.

Referenced by applyOnExternalBoundary(), applyOnInternalBoundary(), currentIntersectedSide(), failTraceMessage(), findExternalBoundarySide(), moveThroughNeighbors(), onBoundary(), onSegment(), and trace().

◆ _intersection_distance

Real TraceRay::_intersection_distance
private

The work point for the intersection distance of the current Ray.

Definition at line 484 of file TraceRay.h.

Referenced by continueTraceOffProcessor(), currentIntersectionDistance(), moveThroughNeighbors(), onCompleteTrace(), onContinueTrace(), onSegment(), onTrajectoryChanged(), and trace().

◆ _intersection_point

Point TraceRay::_intersection_point
private

◆ _is_rectangular_domain

bool TraceRay::_is_rectangular_domain
private

Whether or not the domain is rectangular (defined perfectly by its bounding box)

Definition at line 527 of file TraceRay.h.

Referenced by preExecute(), and trace().

◆ _last_elem

const Elem* TraceRay::_last_elem
private

The last element the current Ray was traced in.

Definition at line 459 of file TraceRay.h.

Referenced by applyOnInternalBoundary(), and trace().

◆ _last_intersected_extrema

ElemExtrema TraceRay::_last_intersected_extrema
private

The intersected vertex/edge vertices for the previous intersection, if any.

Definition at line 482 of file TraceRay.h.

Referenced by trace().

◆ _mesh

MooseMesh& TraceRay::_mesh
private

The MooseMesh.

Definition at line 438 of file TraceRay.h.

Referenced by onBoundary().

◆ _neighbor_active_neighbor_children

std::vector<const Elem *> TraceRay::_neighbor_active_neighbor_children
private

Definition at line 511 of file TraceRay.h.

Referenced by getPointNeighbors().

◆ _neighbor_next_untested_set

MooseUtils::StaticallyAllocatedSet<const Elem *, MAX_POINT_NEIGHBORS> TraceRay::_neighbor_next_untested_set
private

Definition at line 510 of file TraceRay.h.

Referenced by getPointNeighbors().

◆ _neighbor_set

MooseUtils::StaticallyAllocatedSet<const Elem *, MAX_POINT_NEIGHBORS> TraceRay::_neighbor_set
private

Definition at line 508 of file TraceRay.h.

Referenced by getPointNeighbors().

◆ _neighbor_untested_set

MooseUtils::StaticallyAllocatedSet<const Elem *, MAX_POINT_NEIGHBORS> TraceRay::_neighbor_untested_set
private

Definition at line 509 of file TraceRay.h.

Referenced by getPointNeighbors().

◆ _old_ray_kernels

std::set<RayKernelBase *> TraceRay::_old_ray_kernels
private

Helper for avoiding calling preTrace() on the same RayKernel multiple times.

Definition at line 530 of file TraceRay.h.

Referenced by onSubdomainChanged().

◆ _on_boundary_apply_index

std::vector<std::size_t> TraceRay::_on_boundary_apply_index
private

Reusable for which boundary elements to apply for a specific RayBC in onBoundary()

Definition at line 522 of file TraceRay.h.

Referenced by onBoundary().

◆ _on_boundary_ray_bcs

std::vector<RayBoundaryConditionBase *> TraceRay::_on_boundary_ray_bcs
private

Reusable for getting the RayBCs in onBoundary()

Definition at line 520 of file TraceRay.h.

Referenced by onBoundary().

◆ _pid

const processor_id_type TraceRay::_pid
private

The processor id.

Definition at line 444 of file TraceRay.h.

Referenced by continueTraceOffProcessor(), failTraceMessage(), and trace().

◆ _point_neighbor_helper

std::vector<NeighborInfo> TraceRay::_point_neighbor_helper
private

Reusable for building neighbors.

Definition at line 507 of file TraceRay.h.

Referenced by getPointNeighbors().

◆ _results

std::vector<unsigned long long int> TraceRay::_results
private

Results over all of the local traces, indexed by TraceRayResult.

Definition at line 514 of file TraceRay.h.

Referenced by exitsElem(), failTrace(), getPointNeighbors(), moveThroughNeighbors(), preExecute(), results(), storeExitsElemResult(), and trace().

◆ _should_continue

bool TraceRay::_should_continue
private

Whether or not the current Ray should continue.

Definition at line 473 of file TraceRay.h.

Referenced by failTrace(), postRayTracingObject(), and trace().

◆ _study

RayTracingStudy& TraceRay::_study
private

◆ _tid

const THREAD_ID TraceRay::_tid
private

◆ _vertex_neighbors

std::unordered_map<const Node *, std::vector<NeighborInfo> > TraceRay::_vertex_neighbors
private

The cached vertex neighbors.

Definition at line 500 of file TraceRay.h.

Referenced by meshChanged().


The documentation for this class was generated from the following files: