https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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.
 
void meshChanged ()
 Called on mesh change.
 
void trace (const std::shared_ptr< Ray > &ray)
 Traces a ray.
 
std::vector< unsigned long long int > results () const
 Get the various results reported by this object, indexed by TraceRayResult.
 
void setBackfaceCulling (const bool backface_culling)
 Enable or disable the use of element normals for backface culling through the getElemNormals() method.
 
const std::shared_ptr< Ray > *const & currentRay () const
 Gets the current Ray that is being traced.
 
const Elem *const & currentElem () const
 Gets the element that the current Ray is being traced in.
 
const Point & currentIntersectionPoint () const
 Gets the current intersection point for the Ray that is being traced.
 
const Point & currentIncomingPoint () const
 Gets the current incoming point for the Ray that is being traced.
 
const unsigned short & currentIncomingSide () const
 Gets the current incoming side for the Ray that is being traced.
 
const unsigned short & currentIntersectedSide () const
 Gets the side that the current Ray intersected.
 
const ElemExtrema & currentIntersectedExtrema () const
 Gets the element extrema (vertex/edge) that the current Ray intersected.
 
const Real & currentIntersectionDistance () const
 Gets the current intersection distance for the Ray that is being traced.
 
const BoundaryID & currentBoundaryID () const
 Gets the BoundaryID of the boundary that the Ray intersected and is being applied a boundary condition.
 
const SubdomainID & currentSubdomainID () const
 Gets the subdomain of the current element that the Ray is being traced in.
 
const std::vector< NeighborInfo > & getVertexNeighbors (const Elem *elem, const Node *vertex)
 Gets the neighbors at a vertex.
 
const std::vector< NeighborInfo > & getVertexNeighbors (const Elem *elem, const unsigned short vertex)
 Gets the neighbors at a vertex.
 
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.
 
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.
 
const std::vector< NeighborInfo > & getPointNeighbors (const Elem *elem, const Point &point)
 Get the point neighbors.
 
const std::vector< NeighborInfo > & getNeighbors (const Elem *elem, const ElemExtrema &extrema, const Point &point)
 Get the point/vertex/edge neighbors depending on extrema.
 

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.
 
void onBoundary (const std::shared_ptr< Ray > &ray, const bool external)
 Called when a Ray hits a boundary.
 
void onCompleteTrace (const std::shared_ptr< Ray > &ray)
 Called when a Ray is finished tracing (whenever !ray->shouldContinue())
 
void onContinueTrace (const std::shared_ptr< Ray > &)
 Called when a Ray is continuing to trace after segment.
 
void onTrajectoryChanged (const std::shared_ptr< Ray > &ray)
 Called when a Ray's trajectory changes.
 
void onSubdomainChanged (const std::shared_ptr< Ray > &ray, const bool same_ray)
 Called when the subdomain changes.
 
std::string failTraceMessage (const std::string &reason, const int line=-1)
 Creates a useful error string with current tracing information.
 
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.
 
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.
 
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.
 
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.
 
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)
 
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)
 
void applyOnExternalBoundary (const std::shared_ptr< Ray > &ray)
 Gets and applies external boundary conditions in _current_elem on side _intersected_side at _intersection_point.
 
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.
 
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.
 
void continueTraceOffProcessor (const std::shared_ptr< Ray > &ray)
 Sets up a ray to continue tracing off processor.
 
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.
 
void storeExitsElemResult (const ExitsElemResult result)
 Stores the result given by an intersection in _results as necessary.
 
Real subdomainHmax (const Elem *elem) const
 Get the approximate subdomain hmax for an element.
 
void postRayTracingObject (const std::shared_ptr< Ray > &ray, const RayTracingObject *rto)
 Called after executing a RayTracingObject (RayBCs and RayKernels)
 

Private Attributes

RayTracingStudy & _study
 The RayTracingStudy.
 
MooseMesh & _mesh
 The MooseMesh.
 
const unsigned int _dim
 The mesh dimension.
 
const BoundaryInfo & _boundary_info
 The BoundaryInfo for the mesh.
 
const processor_id_type _pid
 The processor id.
 
const THREAD_ID _tid
 The thread id.
 
bool _backface_culling
 Whether or not to use element normals for backface culling.
 
TraceData * _current_cached_trace
 The TraceData for the current cached trace (if any)
 
const std::shared_ptr< Ray > * _current_ray
 The current ray being traced.
 
const Elem * _current_elem
 The element the current Ray is being traced in.
 
const Elem * _last_elem
 The last element the current Ray was traced in.
 
SubdomainID _current_subdomain_id
 The current SubdomainID.
 
Real _current_subdomain_hmax
 The current subdomain hmax.
 
libMesh::ElemType _current_elem_type
 The current elem type (constant on subdomain), used to avoid elem->type() calls.
 
unsigned short _current_elem_n_sides
 The number of sides on the current elem, used to avoid elem->n_sides() virtual calls.
 
Point _incoming_point
 The incoming point of the current Ray.
 
unsigned short _incoming_side
 The incoming side of the current Ray.
 
bool _should_continue
 Whether or not the current Ray should continue.
 
Point _intersection_point
 The work point for the intersection of the current Ray.
 
unsigned short _intersected_side
 The work point for the intersected side of the current Ray.
 
ElemExtrema _intersected_extrema
 The work point for the intersected vertex/edge vertices of the current Ray, if any.
 
ElemExtrema _last_intersected_extrema
 The intersected vertex/edge vertices for the previous intersection, if any.
 
Real _intersection_distance
 The work point for the intersection distance of the current Ray.
 
BoundaryID _current_bnd_id
 The current BoundaryID (used when calling RayBoundaryConditionBase::onBoundary())
 
bool _exits_elem
 Whether or not the current trace exits an element.
 
const Point * _current_normals
 The normals for the current element for backface culling (pointer to the first normal - optional)
 
std::vector< BoundaryID > _boundary_ids
 Reusable vector for calling _boundary_info.boundary_ids()
 
std::vector< TraceRayBndElement > _boundary_elems
 Boundary elements that need RayBCs to be applied.
 
std::unordered_map< const Node *, std::vector< NeighborInfo > > _vertex_neighbors
 The cached vertex neighbors.
 
std::unordered_map< std::pair< const Node *, const Node * >, std::pair< bool, std::vector< NeighborInfo > > > _edge_neighbors
 The cached edge neighbors.
 
std::vector< NeighborInfo > _point_neighbor_helper
 Reusable for building neighbors.
 
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.
 
libMesh::ElemSideBuilder _elem_side_builder
 Helper for building element sides without excessive allocation.
 
std::vector< RayBoundaryConditionBase * > _on_boundary_ray_bcs
 Reusable for getting the RayBCs in onBoundary()
 
std::vector< std::size_t > _on_boundary_apply_index
 Reusable for which boundary elements to apply for a specific RayBC in onBoundary()
 
bool _has_ray_kernels
 Whether or not the RayTracingStudy has any RayKernels.
 
bool _is_rectangular_domain
 Whether or not the domain is rectangular (defined perfectly by its bounding box)
 
std::set< RayKernelBase * > _old_ray_kernels
 Helper for avoiding calling preTrace() on the same RayKernel multiple times.
 
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 };
@ HIT_VERTEX
Definition TraceRay.h:261

◆ 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 };
@ ENDED_STATIONARY
Definition TraceRay.h:72
@ FAILED_TRACES
Definition TraceRay.h:71
@ FACE_HITS
Definition TraceRay.h:59
@ VERTEX_HITS
Definition TraceRay.h:60
@ INTERSECTION_CALLS
Definition TraceRay.h:65
@ EDGE_HITS
Definition TraceRay.h:61
@ EDGE_NEIGHBOR_BUILDS
Definition TraceRay.h:68
@ POINT_NEIGHBOR_BUILDS
Definition TraceRay.h:70
@ EDGE_NEIGHBOR_LOOKUPS
Definition TraceRay.h:69
@ INTERSECTIONS
Definition TraceRay.h:58
@ BACKFACE_CULLING_FAILURES
Definition TraceRay.h:64
@ VERTEX_NEIGHBOR_LOOKUPS
Definition TraceRay.h:67
@ BACKFACE_CULLING_SUCCESSES
Definition TraceRay.h:63
@ MOVED_THROUGH_NEIGHBORS
Definition TraceRay.h:62
@ VERTEX_NEIGHBOR_BUILDS
Definition TraceRay.h:66

Constructor & Destructor Documentation

◆ TraceRay()

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

Definition at line 46 of file TraceRay.C.

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

◆ ~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 745 of file TraceRay.C.

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

Referenced by trace().

◆ 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 804 of file TraceRay.C.

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

Referenced by trace().

◆ 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 1696 of file TraceRay.C.

1697{
1698 traceAssert(ray->currentElem() == _current_elem, "Ray currentElem() invalid");
1699 traceAssert(ray->currentIncomingSide() == _incoming_side, "Ray currentIncomingSide() invalid");
1700 traceAssert(ray->currentPoint() == _incoming_point, "Ray currentPoint() invalid");
1701 traceAssert(_current_elem->processor_id() != _pid, "Off processor trace is not off processor");
1702 debugRay("Ray going off processor to ", _current_elem->processor_id());
1703
1704 ray->addProcessorCrossing();
1705
1707 {
1710 _current_cached_trace->lastPoint()._data = ray->data();
1712 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1713 }
1714
1715 if (_intersection_distance > 0)
1716 possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1717 possiblySaveDebugRayMesh();
1718}
bool auxDataOnCacheTraces() const
Whether or not to store the Ray aux data on the cached Ray traces.
bool dataOnCacheTraces() const
Whether or not to store the Ray data on the cached Ray traces.
TraceData * _current_cached_trace
The TraceData for the current cached trace (if any)
Definition TraceRay.h:452
Real _intersection_distance
The work point for the intersection distance of the current Ray.
Definition TraceRay.h:484
TracePointData & lastPoint()
Definition TraceData.h:57
void addPoint(const libMesh::Point &point)
Definition TraceData.h:55
std::vector< RayData > _aux_data
The aux data on the Ray after this segment is traced (optional)
Definition TraceData.h:36
std::vector< RayData > _data
The data on the Ray after this segment is traced (optional)
Definition TraceData.h:34

Referenced by trace().

◆ 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; }

◆ 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; }

◆ 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; }

◆ 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; }

◆ 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; }

◆ 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; }

◆ 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; }

◆ 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/3]

TraceRay::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

Definition at line 82 of file TraceRay.C.

90{
91 debugRay("Called exitsElem()");
92
93 traceAssert(elem_type == elem->type(), "elem_type incorrect");
94 traceAssert(intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
95 traceAssert(intersected_side == RayTracingCommon::invalid_side, "Side should be invalid");
96 traceAssert(intersected_extrema.isInvalid(), "Extrema should be invalid");
97 traceAssert(intersection_distance == RayTracingCommon::invalid_distance,
98 "Distance should be invalid");
99 if (_study.verifyRays() && incoming_side != RayTracingCommon::invalid_side &&
100 !_study.sideIsNonPlanar(elem, incoming_side))
101 traceAssert(_study.sideIsIncoming(elem, incoming_side, (*_current_ray)->direction(), _tid),
102 "Incoming side is non-entrant");
103
104 bool intersected;
105 switch (elem_type)
106 {
107 case HEX8:
108 intersected = exitsElem<Hex8, Hex8>(elem,
109 incoming_side,
110 intersection_point,
111 intersected_side,
112 intersected_extrema,
113 intersection_distance,
114 normals);
115 break;
116 case TET4:
117 intersected = exitsElem<Tet4, Tet4>(elem,
118 incoming_side,
119 intersection_point,
120 intersected_side,
121 intersected_extrema,
122 intersection_distance,
123 normals);
124 break;
125 case PYRAMID5:
126 intersected = exitsElem<Pyramid5, Pyramid5>(elem,
127 incoming_side,
128 intersection_point,
129 intersected_side,
130 intersected_extrema,
131 intersection_distance,
132 normals);
133 break;
134 case PRISM6:
135 intersected = exitsElem<Prism6, Prism6>(elem,
136 incoming_side,
137 intersection_point,
138 intersected_side,
139 intersected_extrema,
140 intersection_distance,
141 normals);
142 break;
143 case QUAD4:
144 intersected = exitsElem<Quad4, Quad4>(elem,
145 incoming_side,
146 intersection_point,
147 intersected_side,
148 intersected_extrema,
149 intersection_distance,
150 normals);
151 break;
152 case TRI3:
153 intersected = exitsElem<Tri3, Tri3>(elem,
154 incoming_side,
155 intersection_point,
156 intersected_side,
157 intersected_extrema,
158 intersection_distance,
159 normals);
160 break;
161 case HEX20:
162 intersected = exitsElem<Hex20, Hex8>(elem,
163 incoming_side,
164 intersection_point,
165 intersected_side,
166 intersected_extrema,
167 intersection_distance,
168 normals);
169 break;
170 case HEX27:
171 intersected = exitsElem<Hex27, Hex8>(elem,
172 incoming_side,
173 intersection_point,
174 intersected_side,
175 intersected_extrema,
176 intersection_distance,
177 normals);
178 break;
179 case QUAD8:
180 intersected = exitsElem<Quad8, Quad4>(elem,
181 incoming_side,
182 intersection_point,
183 intersected_side,
184 intersected_extrema,
185 intersection_distance,
186 normals);
187 break;
188 case QUAD9:
189 intersected = exitsElem<Quad9, Quad4>(elem,
190 incoming_side,
191 intersection_point,
192 intersected_side,
193 intersected_extrema,
194 intersection_distance,
195 normals);
196 break;
197 case TRI6:
198 intersected = exitsElem<Tri6, Tri3>(elem,
199 incoming_side,
200 intersection_point,
201 intersected_side,
202 intersected_extrema,
203 intersection_distance,
204 normals);
205 break;
206 case TRI7:
207 intersected = exitsElem<Tri7, Tri3>(elem,
208 incoming_side,
209 intersection_point,
210 intersected_side,
211 intersected_extrema,
212 intersection_distance,
213 normals);
214 break;
215 case TET10:
216 intersected = exitsElem<Tet10, Tet4>(elem,
217 incoming_side,
218 intersection_point,
219 intersected_side,
220 intersected_extrema,
221 intersection_distance,
222 normals);
223 break;
224 case TET14:
225 intersected = exitsElem<Tet14, Tet4>(elem,
226 incoming_side,
227 intersection_point,
228 intersected_side,
229 intersected_extrema,
230 intersection_distance,
231 normals);
232 break;
233 case PYRAMID13:
234 intersected = exitsElem<Pyramid13, Pyramid5>(elem,
235 incoming_side,
236 intersection_point,
237 intersected_side,
238 intersected_extrema,
239 intersection_distance,
240 normals);
241 break;
242 case PYRAMID14:
243 intersected = exitsElem<Pyramid14, Pyramid5>(elem,
244 incoming_side,
245 intersection_point,
246 intersected_side,
247 intersected_extrema,
248 intersection_distance,
249 normals);
250 break;
251 case PRISM15:
252 intersected = exitsElem<Prism15, Prism6>(elem,
253 incoming_side,
254 intersection_point,
255 intersected_side,
256 intersected_extrema,
257 intersection_distance,
258 normals);
259 break;
260 case PRISM18:
261 intersected = exitsElem<Prism18, Prism6>(elem,
262 incoming_side,
263 intersection_point,
264 intersected_side,
265 intersected_extrema,
266 intersection_distance,
267 normals);
268 break;
269 case EDGE2:
270 intersected = exitsElem<Edge2, Edge2>(elem,
271 incoming_side,
272 intersection_point,
273 intersected_side,
274 intersected_extrema,
275 intersection_distance,
276 normals);
277 break;
278 case EDGE3:
279 intersected = exitsElem<Edge3, Edge2>(elem,
280 incoming_side,
281 intersection_point,
282 intersected_side,
283 intersected_extrema,
284 intersection_distance,
285 normals);
286 break;
287 case EDGE4:
288 intersected = exitsElem<Edge4, Edge2>(elem,
289 incoming_side,
290 intersection_point,
291 intersected_side,
292 intersected_extrema,
293 intersection_distance,
294 normals);
295 break;
296 default:
298 "Element type ", Utility::enum_to_string(elem->type()), " not supported by TraceRay");
299 }
300
301 if (intersected)
302 {
303 if (intersected_extrema.atExtrema())
304 return intersected_extrema.atVertex() ? HIT_VERTEX : HIT_EDGE;
305 return HIT_FACE;
306 }
307
308 return NO_EXIT;
309}
bool sideIsNonPlanar(const Elem *elem, const unsigned short s) const
Whether or not the side \s on elem elem is non-planar.
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.
bool verifyRays() const
Whether or not to verify if Rays have valid information before being traced.
static const unsigned short invalid_side
Identifier for an invalid side index.
static const libMesh::Real invalid_distance
Identifier for an invalid distance.
static const libMesh::Point invalid_point(invalid_distance, invalid_distance, invalid_distance)
Identifier for an invalid point.
bool isInvalid() const
Definition ElemExtrema.h:48
bool atVertex() const
Definition ElemExtrema.h:56

Referenced by moveThroughNeighbor(), and trace().

◆ exitsElem() [2/3]

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

Definition at line 313 of file TraceRay.C.

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

◆ exitsElem() [3/3]

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 1832 of file TraceRay.C.

1833{
1834 const auto message = failTraceMessage(reason, line);
1835
1836 if (warning)
1837 {
1839 mooseWarning(message);
1840 (*_current_ray)->setShouldContinue(false);
1841 _should_continue = false;
1842 }
1843 else
1844 mooseError(message);
1845}
void mooseWarning(Args &&... args)
bool _should_continue
Whether or not the current Ray should continue.
Definition TraceRay.h:473
std::string failTraceMessage(const std::string &reason, const int line=-1)
Creates a useful error string with current tracing information.
Definition TraceRay.C:1784

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

◆ 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 1784 of file TraceRay.C.

1785{
1786 std::stringstream oss;
1787 oss << "Ray on processor " << _pid << " and thread " << _tid << " failed to trace";
1788 if (line != -1)
1789 oss << " at line " << line;
1790 oss << "\n\n" << reason << "\n\n";
1791 oss << ((*_current_ray))->getInfo() << "\n";
1792 oss << "Current trace information\n";
1793 oss << " _current_subdomain_id = ";
1794 if (_current_subdomain_id == Elem::invalid_subdomain_id)
1795 oss << "invalid subdomain id\n";
1796 else
1797 oss << _current_subdomain_id << "\n";
1798 oss << " _current_elem_type = " << Utility::enum_to_string(_current_elem_type) << "\n";
1799 oss << " _current_elem_n_sides = " << _current_elem_n_sides << "\n";
1800 oss << " _incoming_point = ";
1802 oss << "invalid point\n";
1803 else
1804 oss << _incoming_point << "\n";
1805 oss << " _incoming_side = ";
1807 oss << "invalid side\n";
1808 else
1809 oss << _incoming_side << "\n";
1810 oss << " _intersection_point = ";
1812 oss << "invalid point\n";
1813 else
1814 oss << _intersection_point << "\n";
1815 oss << " _intersected_side = ";
1817 oss << "invalid side\n";
1818 else
1819 oss << _intersected_side << "\n";
1820 oss << " _intersected_extrema = " << _intersected_extrema << "\n";
1821 oss << " _exits_elem = " << _exits_elem << "\n";
1822 if (_current_elem)
1823 oss << _current_elem->get_info();
1824 else
1825 oss << "_current_elem = invalid\n";
1826
1827 possiblySaveDebugRayMesh();
1828 return oss.str();
1829}
bool _exits_elem
Whether or not the current trace exits an element.
Definition TraceRay.h:489
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

Referenced by failTrace().

◆ 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 949 of file TraceRay.C.

952{
953 traceAssert(_current_elem->neighbor_ptr(_intersected_side), "Already on boundary");
954 traceAssert(boundary_side == RayTracingCommon::invalid_side, "Side should be invalid");
955 traceAssert(boundary_extrema.isInvalid(), "Extrema should be invalid");
956 traceAssert(!boundary_elem, "Elem should be invalid");
957 traceAssert(_current_elem->dim() != 1, "1D traces shouldn't make it here");
958 traceAssert(_current_elem->n_sides() == _current_elem_n_sides, "_current_elem_n_sides incorrect");
959 traceAssert(_intersected_extrema.atExtrema(), "Should be at extrema");
960 debugRay("Called findExternalBoundarySide() on side ", _intersected_side);
961 debugRay(" _intersected_side = ", _intersected_side);
962 debugRay(" _intersected_extrema", _intersected_extrema);
963
964 const auto & direction = (*_current_ray)->direction();
965 const auto at_edge = _intersected_extrema.atEdge();
966
967 // First, look for other sides on _current_elem that touch the intersected vertex/edge
968 // that are on the boundary and are outgoing
969 for (unsigned short s = 0; s < _current_elem_n_sides; ++s)
970 if (!_current_elem->neighbor_ptr(s) && s != _intersected_side &&
971 _current_elem->is_node_on_side(_intersected_extrema.first, s) &&
972 (!at_edge || _current_elem->is_node_on_side(_intersected_extrema.second, s)) &&
973 !_study.sideIsIncoming(_current_elem, s, direction, _tid))
974 {
975 debugRay(" Side ", s, " is a boundary side and the Ray exits");
976 boundary_side = s;
977 boundary_extrema = _intersected_extrema;
978 boundary_elem = _current_elem;
979 return;
980 }
981
982 // No luck in our element, so see if any neighbors at this vertex/edge are
983 // on the boundary and are outgoing
985 debugRay("Checking current element failed, now checking neighbors");
986
987 debugRay("Found ", neighbors.size(), " candidate neighbors (including self)");
988 for (const auto & neighbor_info : neighbors)
989 {
990 // This will be false when we have an edge neighbor that isn't a neighbor at
991 // _intersection_point
992 if (!neighbor_info._valid)
993 continue;
994
995 const Elem * neighbor = neighbor_info._elem;
996 // We've already checked ourself
997 if (neighbor == _current_elem)
998 continue;
999
1000 debugRay("Checking neighbor ", neighbor->id());
1001
1002 // Loop through the sides we touch and look for one that this Ray exits and is on the boundary
1003 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
1004 if (neighbor_info._side_normals[i] * direction > TRACE_TOLERANCE &&
1005 !neighbor->neighbor_ptr(neighbor_info._sides[i]))
1006 {
1008 neighbor, _intersection_point, neighbor_info._sides[i], _dim, boundary_extrema);
1009 traceAssert(boundary_extrema.atExtrema(), "Should be at extrema");
1010 boundary_side = neighbor_info._sides[i];
1011 boundary_elem = neighbor;
1012 return;
1013 }
1014 }
1015}
bool atEdge() const
Definition ElemExtrema.h:71

Referenced by trace().

◆ 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

Definition at line 1900 of file TraceRay.C.

1903{
1904 traceAssert(elem, "Invalid elem");
1905 traceAssert(vertices.first, "Must be valid");
1906 traceAssert(vertices.second, "Must be valid");
1907
1908 debugRay("Called getEdgeNeighbors() with:");
1909 debugRay(" elem->id() = ", elem->id(), " with centroid ", elem->vertex_average());
1910 debugRay(" vertices.first = ", vertices.first->id(), " at ", (Point)*vertices.first);
1911 debugRay(" vertices.second = ", vertices.second->id(), " at ", (Point)*vertices.second);
1912 debugRay(" point = ", point);
1913
1914 traceAssert(elem->get_node_index(vertices.first) != libMesh::invalid_uint,
1915 "Doesn't contain vertex");
1916 traceAssert(elem->get_node_index(vertices.second) != libMesh::invalid_uint,
1917 "Doesn't contain vertex");
1918 traceAssert(isWithinSegment(
1919 (Point)*vertices.first, (Point)*vertices.second, point, LOOSE_TRACE_TOLERANCE),
1920 "Point not within edge");
1921
1923
1924 const auto ordered_vertices = vertices.first->id() < vertices.second->id()
1925 ? vertices
1926 : std::make_pair(vertices.second, vertices.first);
1927
1928 // Look for the entry and build if necessary
1929 std::pair<bool, std::vector<NeighborInfo>> * entry;
1930 auto search = _edge_neighbors.find(ordered_vertices);
1931 if (search != _edge_neighbors.end())
1932 entry = &search->second;
1933 else
1934 {
1935 debugRay("Building edge neighbors");
1937 entry = &_edge_neighbors
1938 .emplace(ordered_vertices, std::make_pair(true, std::vector<NeighborInfo>()))
1939 .first->second;
1940 findEdgeNeighbors(elem,
1941 ordered_vertices.first,
1942 ordered_vertices.second,
1947 entry->second);
1948
1949 bool all_same_edge = true;
1950 for (auto & neighbor_info : entry->second)
1951 {
1952 traceAssert(neighbor_info._lower_bound <= neighbor_info._upper_bound,
1953 "Bound order incorrect");
1954
1955 // Fill the side normals
1956 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
1957 neighbor_info._side_normals[i] =
1958 _study.getSideNormal(neighbor_info._elem, neighbor_info._sides[i], _tid);
1959
1960 // See if the bounds are the same as the target edge
1961 if (neighbor_info._lower_bound != 0 || neighbor_info._upper_bound != 1)
1962 all_same_edge = false;
1963 }
1964 entry->first = all_same_edge;
1965 }
1966
1967 // Means that all neighbors are not on the exact same edge, so we must
1968 // validate/invalidate based on if the neighbor's edge contains our point
1969 if (!entry->first)
1970 {
1971 const auto edge_length =
1972 ((Point)*ordered_vertices.first - (Point)*ordered_vertices.second).norm();
1973 const auto point_location = ((Point)*ordered_vertices.first - point).norm() / edge_length;
1974 for (auto & info : entry->second)
1975 info._valid = (info._lower_bound - TRACE_TOLERANCE) < point_location &&
1976 point_location < (info._upper_bound + TRACE_TOLERANCE);
1977 }
1978
1979 return entry->second;
1980}
virtual const Point & getSideNormal(const Elem *elem, const unsigned short side, const THREAD_ID tid)
Get the outward normal for a given element side.
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::vector< const Elem * > _neighbor_active_neighbor_children
Definition TraceRay.h:511
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_untested_set
Definition TraceRay.h:509
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_set
Definition TraceRay.h:508
MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > _neighbor_next_untested_set
Definition TraceRay.h:510
MPI_Info info
bool isWithinSegment(const Point &segment1, const Point &segment2, const Point &point, const Real tolerance=TRACE_TOLERANCE)
Checks whether or not a point is within a line segment.
void findEdgeNeighbors(const Elem *const elem, const Node *const node1, const Node *const node2, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &neighbor_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &untested_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &next_untested_set, std::vector< const Elem * > active_neighbor_children, std::vector< NeighborInfo > &info)
auto norm(const T &a)
const unsigned int invalid_uint

Referenced by getEdgeNeighbors(), 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

Definition at line 1983 of file TraceRay.C.

1986{
1987 debugRay("Called getEdgeNeighbors(), local index version with:");
1988 debugRay(" vertices.first = ", vertices.first);
1989 debugRay(" vertices.second = ", vertices.second);
1990 traceAssert(vertices.first < elem->n_vertices(),
1991 "Invalid vertex with ray " + std::to_string((*_current_ray)->id()));
1992 traceAssert(vertices.second < elem->n_vertices(), "Invalid vertex");
1993
1994 return getEdgeNeighbors(
1995 elem, std::make_pair(elem->node_ptr(vertices.first), elem->node_ptr(vertices.second)), point);
1996}
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.
Definition TraceRay.C:1900

◆ 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 1999 of file TraceRay.C.

2000{
2001 if (!extrema.atExtrema())
2002 return getPointNeighbors(elem, point);
2003 if (extrema.atVertex())
2004 return getVertexNeighbors(elem, extrema.vertex());
2005 return getEdgeNeighbors(elem, extrema.edgeVertices(), point);
2006}
const std::vector< NeighborInfo > & getVertexNeighbors(const Elem *elem, const Node *vertex)
Gets the neighbors at a vertex.
Definition TraceRay.C:1848
const std::vector< NeighborInfo > & getPointNeighbors(const Elem *elem, const Point &point)
Get the point neighbors.
Definition TraceRay.C:2009
unsigned short vertex() const
Definition ElemExtrema.h:96
const std::pair< unsigned short, unsigned short > & edgeVertices() const

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

◆ 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 2009 of file TraceRay.C.

2010{
2011 traceAssert(elem, "Invalid elem");
2012
2013 debugRay("Called getPointNeighbors()");
2014 debugRay(" elem = ", elem->id());
2015 debugRay(" point = ", point);
2016
2018 _point_neighbor_helper.clear();
2019
2020 findPointNeighbors(elem,
2021 point,
2027
2028 // Fill the side normals
2029 for (auto & neighbor_info : _point_neighbor_helper)
2030 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
2031 neighbor_info._side_normals[i] =
2032 _study.getSideNormal(neighbor_info._elem, neighbor_info._sides[i], _tid);
2033
2035}
for(PetscInt i=0;i< nvars;++i)
std::vector< NeighborInfo > _point_neighbor_helper
Reusable for building neighbors.
Definition TraceRay.h:507
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...

Referenced by getNeighbors(), and trace().

◆ 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

Definition at line 1848 of file TraceRay.C.

1849{
1850 traceAssert(elem, "Elem must be valid");
1851 traceAssert(vertex, "Vertex must be valid");
1852
1853 debugRay("Called getVertexNeighbors() with:");
1854 debugRay(" elem->id() = ", elem->id(), " with centroid ", elem->vertex_average());
1855 debugRay(" vertex->id() = ", vertex->id(), ", at ", (Point)*vertex);
1856
1857 traceAssert(elem->get_node_index(vertex) != libMesh::invalid_uint, "Doesn't contain node");
1858 traceAssert(elem->is_vertex(elem->get_node_index(vertex)), "Node is not a vertex");
1859
1861
1862 // Return the entry if we have it cached
1863 auto search = _vertex_neighbors.find(vertex);
1864 if (search != _vertex_neighbors.end())
1865 return search->second;
1866
1868
1869 // Make a new entry
1870 debugRay("Building vertex neighbors");
1871 std::vector<NeighborInfo> & entry =
1872 _vertex_neighbors.emplace(vertex, std::vector<NeighborInfo>()).first->second;
1873
1874 findNodeNeighbors(elem,
1875 vertex,
1880 entry);
1881
1882 // Fill the side normals
1883 for (auto & neighbor_info : entry)
1884 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
1885 neighbor_info._side_normals[i] =
1886 _study.getSideNormal(neighbor_info._elem, neighbor_info._sides[i], _tid);
1887
1888 return entry;
1889}
std::unordered_map< const Node *, std::vector< NeighborInfo > > _vertex_neighbors
The cached vertex neighbors.
Definition TraceRay.h:500
void findNodeNeighbors(const Elem *const elem, const Node *const node, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &neighbor_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &untested_set, MooseUtils::StaticallyAllocatedSet< const Elem *, MAX_POINT_NEIGHBORS > &next_untested_set, std::vector< const Elem * > active_neighbor_children, std::vector< NeighborInfo > &info)

Referenced by getNeighbors(), getVertexNeighbors(), 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

Definition at line 1892 of file TraceRay.C.

1893{
1894 traceAssert(vertex < elem->n_vertices(), "Invalid vertex");
1895
1896 return getVertexNeighbors(elem, elem->node_ptr(vertex));
1897}

◆ meshChanged()

void TraceRay::meshChanged ( )

Called on mesh change.

Definition at line 74 of file TraceRay.C.

75{
76 // Invalidate the vertex and edge neighbor caches
77 _vertex_neighbors.clear();
78 _edge_neighbors.clear();
79}

◆ 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 697 of file TraceRay.C.

703{
704 if (!neighbor_info._valid)
705 return NO_EXIT;
706
707 const Elem * neighbor = neighbor_info._elem;
708 debugRay("Checking neighbor ", neighbor->id(), " with centroid ", neighbor->vertex_average());
709
710 // Find an entrant side (if any)
711 incoming_side = RayTracingCommon::invalid_side;
712 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
713 if (neighbor_info._side_normals[i] * (*_current_ray)->direction() < LOOSE_TRACE_TOLERANCE)
714 {
715 incoming_side = neighbor_info._sides[i];
716 break;
717 }
718
719 // No entrant sides on this neighbor were found
720 if (incoming_side == RayTracingCommon::invalid_side)
721 return NO_EXIT;
722
723 intersection_point = RayTracingCommon::invalid_point;
724 intersected_side = RayTracingCommon::invalid_side;
725 intersected_extrema.invalidate();
726 intersection_distance = RayTracingCommon::invalid_distance;
727
728 // See if there is a way through the neighbor element
729 debugRay("Called exitsElem() from moveThroughNeighbor()");
730 const auto exit_result =
731 exitsElem(neighbor,
732 neighbor->type(),
733 incoming_side,
734 intersection_point,
735 intersected_side,
736 intersected_extrema,
737 intersection_distance,
738 _backface_culling ? _study.getElemNormals(neighbor, _tid) : nullptr);
739 debugRay("Done with exitsElem() from moveThroughNeighbor()");
740
741 return exit_result;
742}
virtual const Point * getElemNormals(const Elem *, const THREAD_ID)
Gets the outward normals for a given element.
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.
Definition TraceRay.C:82
const std::vector< unsigned short > _sides
The sides on the element that the neighboring portion is contained in.
bool _valid
Whether or not this neighbor is valid (needed for neighbors that span an edge)
const Elem *const _elem
The element.
std::vector< Point > _side_normals
The normals of each side in _sides.

Referenced by moveThroughNeighbors().

◆ 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 584 of file TraceRay.C.

588{
590
591 debugRay("Called moveThroughNeighbors() with ", neighbors.size(), " neighbors, and:");
592 debugRay(" last_elem->id() = ", last_elem ? last_elem->id() : DofObject::invalid_id);
593 debugRay(" _incoming_point = ", _incoming_point);
594
595 traceAssert(!best_elem, "Best elem should be null");
596 traceAssert(best_elem_incoming_side == RayTracingCommon::invalid_side,
597 "Best elem side should be invalid");
598 traceAssert(_intersection_point == RayTracingCommon::invalid_point, "Point should be invalid");
599 traceAssert(_intersected_side == RayTracingCommon::invalid_side, "Side should be invalid");
600 traceAssert(_intersected_extrema.isInvalid(), "Extrema should be invalid");
602 "Distance should be invalid");
603
604 // Marker for the longest ray segment distance we've found in a neighbor. Start with a quite
605 // small number because at this point we're desperate and will take anything!
606 Real longest_distance = 1.0e-12;
607 // Temporaries for the intersection checks
608 unsigned short current_incoming_side;
609 Point current_intersection_point;
610 unsigned short current_intersected_side;
611 ElemExtrema current_intersected_extrema;
612 Real current_intersection_distance;
613 TraceRay::ExitsElemResult best_exit_result = NO_EXIT;
614
615 // The NeighborInfo for the last_elem
616 // (to store so we can try it later if we fail for everyone else)
617 const NeighborInfo * last_elem_info = nullptr;
618
619 for (const NeighborInfo & neighbor_info : neighbors)
620 {
621 // If we're at the element we want to do last, skip it and store the info so
622 // we can get to it later in case we fail at finding anything
623 if (neighbor_info._elem == last_elem)
624 {
625 debugRay("Skipping last elem ", last_elem->id());
626 last_elem_info = &neighbor_info;
627 continue;
628 }
629
630 const auto exit_result = moveThroughNeighbor(neighbor_info,
631 current_incoming_side,
632 current_intersection_point,
633 current_intersected_side,
634 current_intersected_extrema,
635 current_intersection_distance);
636
637 // Found one! See if it's the best way
638 if (exit_result != NO_EXIT)
639 {
640 debugRay("Ray can exit through neighbor ", neighbor_info._elem->id());
641
642 if (current_intersection_distance > longest_distance)
643 {
644 best_elem = neighbor_info._elem;
645 best_elem_incoming_side = current_incoming_side;
646 _intersection_point = current_intersection_point;
647 _intersected_side = current_intersected_side;
648 _intersected_extrema = current_intersected_extrema;
649 _intersection_distance = current_intersection_distance;
650 longest_distance = current_intersection_distance;
651 best_exit_result = exit_result;
652 }
653 }
654 }
655
656 // Didn't find someone to exit, so try the last_elem (if any)
657 if (!best_elem && last_elem_info)
658 {
659 const auto exit_result = moveThroughNeighbor(*last_elem_info,
660 current_incoming_side,
661 current_intersection_point,
662 current_intersected_side,
663 current_intersected_extrema,
664 current_intersection_distance);
665
666 if (exit_result != NO_EXIT && current_intersection_distance > longest_distance)
667 {
668 debugRay("Ray can exit through last_elem ", last_elem->id());
669
670 best_elem = last_elem;
671 best_elem_incoming_side = current_incoming_side;
672 _intersection_point = current_intersection_point;
673 _intersected_side = current_intersected_side;
674 _intersected_extrema = current_intersected_extrema;
675 _intersection_distance = current_intersection_distance;
676 best_exit_result = exit_result;
677 }
678 }
679
680 debugRay("moveThroughNeighbors() best result:");
681 debugRay(" best_elem = ", best_elem ? best_elem->id() : DofObject::invalid_id);
682 debugRay(" best_elem_incoming_side = ", best_elem_incoming_side);
683 debugRay(" _intersection_point = ", _intersection_point);
684 debugRay(" _intersected_side = ", _intersected_side);
685 debugRay(" _intersected_extrema = ", _intersected_extrema);
686 debugRay(" _intersection_distance = ", _intersection_distance);
687 if (best_elem)
688 {
689 debugRay("moveThroughNeighbors() next neighbor elem info:");
690 debugRay(best_elem->get_info());
691 }
692
693 return best_exit_result;
694}
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:697
ExitsElemResult
Enum for the different exit results for exitElem()
Definition TraceRay.h:258

Referenced by trace().

◆ onBoundary()

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

Called when a Ray hits a boundary.

Definition at line 2108 of file TraceRay.C.

2109{
2110 traceAssert(ray->currentPoint().absolute_fuzzy_equals(_intersection_point),
2111 "Ray currentPoint() not set before onBoundary()");
2112
2113 // Get the RayBCs on bnd_elems
2115
2116 // Store this information temprorarily because we are going to change it as we
2117 // apply each boundary condition
2118 const auto old_current_elem = _current_elem;
2119 const auto old_intersected_side = _intersected_side;
2120 const auto old_intersected_extrema = _intersected_extrema;
2121 const auto old_subdomain_id = _current_subdomain_id;
2122
2123 // For each RayBC we found, apply it on the boundaries that we need
2125 {
2126 // First, find the boundaries this RayBC is valid on that are also in _boundary_elems.
2127 // We do this ahead of time so that we can pass in to RayBC::apply if the same
2128 // boundary condition is being appled multiple times on different boundaries.
2129 // This is useful in situations like reflection where multiple reflections are
2130 // necessary at a corner to perfectly reflect.
2132 for (MooseIndex(_boundary_elems.size()) bnd_elems_i = 0; bnd_elems_i < _boundary_elems.size();
2133 ++bnd_elems_i)
2134 if (rbc->hasBoundary(_boundary_elems[bnd_elems_i].bnd_id))
2135 _on_boundary_apply_index.push_back(bnd_elems_i);
2136
2137 traceAssert(!_on_boundary_apply_index.empty(), "Must not be empty");
2138
2139 // Apply the RayBC on each of the relevant boundary elements
2140 for (const auto bnd_elems_i : _on_boundary_apply_index)
2141 {
2142 auto & bnd_elem = _boundary_elems[bnd_elems_i];
2143
2144 debugRay("Calling ",
2145 rbc->type(),
2146 "::onBoundary for \"",
2147 rbc->name(),
2148 "\" on elem ",
2149 bnd_elem.elem->id(),
2150 " and side ",
2151 bnd_elem.side,
2152 " for bnd_id ",
2153 bnd_elem.bnd_id);
2154
2155 _current_elem = bnd_elem.elem;
2156 _current_bnd_id = bnd_elem.bnd_id;
2157 _intersected_side = bnd_elem.side;
2158 _intersected_extrema = bnd_elem.extrema;
2159 _current_subdomain_id = _current_elem->subdomain_id();
2160
2161 rbc->onBoundary(_on_boundary_apply_index.size());
2162 postRayTracingObject(ray, rbc);
2163 }
2164 }
2165
2166 // Set this info back now that we're done applying BCs
2167 _current_elem = old_current_elem;
2168 _intersected_side = old_intersected_side;
2169 _intersected_extrema = old_intersected_extrema;
2170 _current_bnd_id = BoundaryInfo::invalid_id;
2171 _current_subdomain_id = old_subdomain_id;
2172
2173 // When on an external boundary, the Ray must have been changed or killed.
2174 // Otherwise, we don't know what to do with it now! If this didn't happen,
2175 // output a detailed error message.
2176 if (external && !ray->trajectoryChanged() && ray->shouldContinue())
2177 {
2178 std::stringstream oss;
2179 oss << "Don't know what to do with a Ray after it hit an external\n";
2180 oss << "boundary at point " << _intersection_point << "!\n\n";
2181 oss << "When hitting an external RayBC, a Ray must either:\n";
2182 oss << " Be killed by a RayBC\n";
2183 oss << " Have its trajectory changed by the RayBC\n";
2184 oss << "by at least one of the executed RayBCs.\n\n";
2185 oss << "You need to either:\n";
2186 oss << " Kill/change the Ray sooner with RayKernels, internal RayBCs, or a max distance\n";
2187 oss << " Kill/change the Ray on the boundary with a RayBC\n\n";
2188 if (!_on_boundary_ray_bcs.empty())
2189 {
2190 oss << "RayBCs executed that did not kill or change the Ray:\n";
2192 for (const auto & bnd_elem : _boundary_elems)
2193 if (rbc->hasBoundary(bnd_elem.bnd_id))
2194 oss << " " << rbc->typeAndName() << " on boundary " << bnd_elem.bnd_id << " ("
2195 << _mesh.getBoundaryName(bnd_elem.bnd_id) << ")\n";
2196 oss << "\n";
2197 }
2198 bool output_header = false;
2199 for (std::size_t i = 0; i < _boundary_elems.size(); ++i)
2200 {
2201 const auto bnd_id = _boundary_elems[i].bnd_id;
2202 bool found = false;
2204 if (rbc->hasBoundary(bnd_id))
2205 {
2206 found = true;
2207 break;
2208 }
2209
2210 if (!found)
2211 {
2212 if (!output_header)
2213 {
2214 oss << "Boundaries that did not have any RayBCs:\n";
2215 output_header = true;
2216 }
2217 oss << " " << bnd_id << " (" << _mesh.getBoundaryName(bnd_id) << ")\n";
2218 }
2219 }
2220
2221 failTrace(oss.str(), _study.tolerateFailure(), __LINE__);
2222 }
2223}
bool hasBoundary(const std::vector< BoundaryID > &boundary_ids1, const std::vector< BoundaryID > &boundary_ids2)
const std::string & getBoundaryName(const BoundaryID boundary_id) const
Base class for the RayBC syntax.
void getRayBCs(std::vector< RayBoundaryConditionBase * > &result, BoundaryID id, THREAD_ID tid)
Fills the active RayBCs associated with this study and a boundary into result.
void postRayTracingObject(const std::shared_ptr< Ray > &ray, const RayTracingObject *rto)
Called after executing a RayTracingObject (RayBCs and RayKernels)
Definition TraceRay.C:2234
std::vector< RayBoundaryConditionBase * > _on_boundary_ray_bcs
Reusable for getting the RayBCs in onBoundary()
Definition TraceRay.h:520
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
if(subdm)

Referenced by applyOnExternalBoundary(), and applyOnInternalBoundary().

◆ 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 1653 of file TraceRay.C.

1654{
1655 for (RayKernelBase * rk : _study.currentRayKernels(_tid))
1656 rk->postTrace();
1657
1658 debugRay("Called onCompleteTrace()\n", (*_current_ray)->getInfo());
1659 if (_intersection_distance > 0)
1660 possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1661 possiblySaveDebugRayMesh();
1662
1664 {
1666
1667 if (_intersection_distance > 0)
1668 {
1669 _current_cached_trace->addPoint(ray->currentPoint());
1671 _current_cached_trace->lastPoint()._data = ray->data();
1673 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1674 }
1675
1676 mooseAssert(ray->stationary() == _current_cached_trace->stationary(), "Stationary mismatch");
1677 }
1678}
Base object for the RayKernel syntax.
bool stationary() const
Definition TraceData.h:59
bool _last
Whether or not this was the last set of segments for this Ray.
Definition TraceData.h:76

Referenced by trace().

◆ 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 1681 of file TraceRay.C.

1682{
1683 traceAssert(ray->shouldContinue(), "Ray must continue");
1684
1686 {
1687 _current_cached_trace->addPoint(ray->currentPoint());
1689 _current_cached_trace->lastPoint()._data = ray->data();
1691 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1692 }
1693}
bool segmentsOnCacheTraces() const
Whether or not to cache individual element segments when _cache_traces = true.

Referenced by trace().

◆ onSegment()

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

Called on a single segment traced by a Ray.

Definition at line 2051 of file TraceRay.C.

2052{
2053 traceAssert((*_current_ray)->currentElem() == _current_elem, "Ray currentElem() incorrect");
2054 traceAssert((*_current_ray)->currentPoint() == _intersection_point,
2055 "Ray currentPoint() incorrect");
2056 traceAssert((*_current_ray)->currentIncomingSide() == _incoming_side,
2057 "Ray currentIncomingSide() incorrect");
2058#ifndef NDEBUG
2060 {
2061 if (_current_elem->has_affine_map())
2062 traceAssert(_current_elem->contains_point(_incoming_point),
2063 "_current_elem does not contain incoming point");
2064
2067 {
2070 "Intersected point is not on intersected side");
2071 traceAssert(!_study.sideIsIncoming(
2072 _current_elem, _intersected_side, (*_current_ray)->direction(), _tid),
2073 "Intersected side is not outgoing");
2074 }
2077 {
2079 .close_to_point(_incoming_point, LOOSE_TRACE_TOLERANCE),
2080 "Incoming point is not on incoming side");
2081 if (ray->intersections() != 0 && ray->maxDistance() != 0)
2082 traceAssert(_study.sideIsIncoming(
2083 _current_elem, _incoming_side, (*_current_ray)->direction(), _tid),
2084 "Incoming side is not incoming");
2085 }
2086 }
2087#endif
2088 traceAssert(MooseUtils::absoluteFuzzyEqual(_intersection_distance,
2090 "_intersection_distance is incorrect");
2091 traceAssert(_current_subdomain_id == _current_elem->subdomain_id(), "Subdomain incorrect");
2092 traceAssert(MooseUtils::absoluteFuzzyEqual((_incoming_point - _intersection_point).norm(),
2094 "Invalid intersection distance");
2095
2098
2099 const auto & rks = _study.currentRayKernels(_tid);
2100 for (auto & rk : rks)
2101 {
2102 rk->onSegment();
2103 postRayTracingObject(ray, rk);
2104 }
2105}
const std::vector< RayKernelBase * > & currentRayKernels(THREAD_ID tid) const
Gets the current RayKernels for a thread, which are set in segmentSubdomainSetup()
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.

Referenced by trace().

◆ 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 1750 of file TraceRay.C.

1751{
1752 debugRay("Calling onSubdomainChanged() on subdomain ", _current_elem->subdomain_id());
1753 debugRay(" _current_subdomain_id = ", _current_subdomain_id);
1754
1755 _current_subdomain_id = _current_elem->subdomain_id();
1759
1760 if (_has_ray_kernels)
1761 {
1762 auto & current_ray_kernels = _study.currentRayKernels(_tid);
1763
1764 // If we're still tracing the same Ray, keep track of our old RayKernels
1765 // so that we don't call preTrace() on them again
1766 if (same_ray)
1767 _old_ray_kernels.insert(current_ray_kernels.begin(), current_ray_kernels.end());
1768 // If we're not tracing the same Ray, we need to call preTrace() on everything
1769 else
1770 _old_ray_kernels.clear();
1771
1772 // Call segmentSubdomainSetup to get new kernels etc
1774
1775 // Call preTrace() on all of the RayKernels that need it
1776 for (RayKernelBase * rk : current_ray_kernels)
1777 // Haven't called preTrace() for this Ray on this RayKernel yet
1779 rk->preTrace();
1780 }
1781}
unsigned int count
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 subdomainHmax(const SubdomainID subdomain_id) const
Get the cached hmax for all elements in a subdomain.
Real _current_subdomain_hmax
The current subdomain hmax.
Definition TraceRay.h:463
bool _has_ray_kernels
Whether or not the RayTracingStudy has any RayKernels.
Definition TraceRay.h:525
std::set< RayKernelBase * > _old_ray_kernels
Helper for avoiding calling preTrace() on the same RayKernel multiple times.
Definition TraceRay.h:530

Referenced by trace().

◆ onTrajectoryChanged()

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

Called when a Ray's trajectory changes.

Parameters
rayThe ray

Definition at line 1721 of file TraceRay.C.

1722{
1723#ifndef NDEBUG
1726 ? !_current_elem->close_to_point(ray->currentPoint(), LOOSE_TRACE_TOLERANCE)
1727 : !_current_elem->contains_point(ray->currentPoint())))
1728 failTrace("Elem does not contain point after trajectory change",
1729 /* warning = */ false,
1730 __LINE__);
1731#endif
1732
1733 traceAssert(ray->shouldContinue(), "Ray should continue when trajectory is being changed");
1734
1735 ray->setTrajectoryChanged(false);
1736 ray->addTrajectoryChange();
1737
1739 {
1740 if (_intersection_distance > 0)
1741 _current_cached_trace->addPoint(ray->currentPoint());
1743 _current_cached_trace->lastPoint()._data = ray->data();
1745 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1746 }
1747}

Referenced by trace().

◆ 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 916 of file TraceRay.C.

920{
921 if (!_study.sideIsNonPlanar(elem, side))
922 traceAssert(extrema.isValid(elem, _intersection_point), "Extrema not correct");
923
924 for (const auto bnd_id : bnd_ids)
925 {
926 bool found = false;
927 for (const auto & bnd_elem : _boundary_elems)
928 if (bnd_elem.bnd_id == bnd_id)
929 {
930 found = true;
931 break;
932 }
933
934 if (!found)
935 {
936 debugRay(" Need to apply boundary on elem ",
937 elem->id(),
938 " and side ",
939 side,
940 " for bnd_id ",
941 bnd_id);
942
943 _boundary_elems.emplace_back(elem, side, bnd_id, extrema);
944 }
945 }
946}
bool isValid(const Elem *const elem, const Point &point) const
Definition ElemExtrema.C:49

Referenced by applyOnExternalBoundary(), and applyOnInternalBoundary().

◆ 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 2234 of file TraceRay.C.

2235{
2236 if (!ray->shouldContinue())
2237 {
2238 if (_should_continue)
2239 _should_continue = false;
2240 }
2241 else if (!_should_continue)
2242 failTrace(rto->typeAndName() +
2243 " set a Ray to continue that was previously set to not continue.\n\n" +
2244 "Once a Ray has been set to not continue, its continue status cannot change.",
2245 /* warning = */ false,
2246 __LINE__);
2247
2248 if (!_should_continue && ray->trajectoryChanged())
2249 failTrace(rto->typeAndName() +
2250 " changed the trajectory of a Ray that was set to not continue,\n" +
2251 "or set a Ray whose trajectory was changed to not continue.",
2252 /* warning = */ false,
2253 __LINE__);
2254}
std::string typeAndName() const

Referenced by onBoundary(), and onSegment().

◆ preExecute()

void TraceRay::preExecute ( )

Should be called immediately before calling any traces.

Definition at line 60 of file TraceRay.C.

61{
62 _current_subdomain_id = Elem::invalid_subdomain_id;
64
65 // Zero out all results
66 for (auto & val : _results)
67 val = 0;
68
71}
bool isRectangularDomain() const
Whether or not the domain is rectangular (if it is prefectly encompassed by its bounding box)
bool hasRayKernels(const THREAD_ID tid)
Whether or not there are currently any active RayKernel objects.
bool _is_rectangular_domain
Whether or not the domain is rectangular (defined perfectly by its bounding box)
Definition TraceRay.h:527

◆ 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; }

◆ 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.

105{ _backface_culling = backface_culling; }

Referenced by BackfaceCullingStudyTest::BackfaceCullingStudyTest().

◆ storeExitsElemResult()

void TraceRay::storeExitsElemResult ( const ExitsElemResult  result)
private

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

Definition at line 2038 of file TraceRay.C.

2039{
2040 if (result == HIT_FACE)
2042 else if (result == HIT_VERTEX)
2044 else if (result == HIT_EDGE)
2046 else
2047 mooseError("Should not call storeExitsElemResult() with result ", result);
2048}

Referenced by trace().

◆ 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 2226 of file TraceRay.C.

2227{
2228 const auto subdomain_id = elem->subdomain_id();
2229 return subdomain_id == _current_subdomain_id ? _current_subdomain_hmax
2230 : _study.subdomainHmax(subdomain_id);
2231}

Referenced by exitsElem().

◆ trace()

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

Traces a ray.

Definition at line 1018 of file TraceRay.C.

1019{
1020 mooseAssert(_study.currentlyPropagating(), "Should only use while propagating rays");
1021
1022 _current_ray = &ray;
1023 _current_elem = ray->currentElem();
1024 _last_elem = nullptr;
1025 _incoming_point = ray->currentPoint();
1026 _incoming_side = ray->currentIncomingSide();
1027 _should_continue = true;
1028
1029 _study.preTrace(_tid, ray);
1030
1031 traceAssert(_current_elem, "Current element is not set");
1032 traceAssert(_current_elem->active(), "Current element is not active");
1033 traceAssert(!ray->invalidCurrentPoint(), "Current point is invalid");
1034 traceAssert(ray->shouldContinue(), "Ray should not continue");
1035 if (_study.verifyRays() && !ray->invalidCurrentIncomingSide() && ray->maxDistance() > 0 &&
1038 failTrace("Ray incoming side is not incoming", /* warning = */ false, __LINE__);
1039
1040#ifdef DEBUG_RAY_IF
1041 if (DEBUG_RAY_IF)
1042 libMesh::err << "\n\n";
1043#endif
1044 debugRay("At top of trace for Ray");
1045 debugRay("Top of trace loop Ray info\n", ray->getInfo());
1046 debugRay("Top of trace loop starting elem info\n", ray->currentElem()->get_info());
1047
1048 // Invalidate this up front because it's copied immediately into _last_intersected_extrema
1050
1051#ifdef DEBUG_RAY_MESH_IF
1052 _debug_mesh = nullptr;
1054 if (DEBUG_RAY_MESH_IF)
1055 {
1056 _debug_mesh = new Mesh(_debug_comm, _dim);
1057 _debug_mesh->skip_partitioning(true);
1058 }
1059#endif
1060
1061 // Caching trace along the way: init for this Ray
1062 if (_study.shouldCacheTrace(ray))
1063 {
1064 debugRay("Trying to init threaded cached trace");
1065
1067
1068 // Add starting data
1070 _current_cached_trace->lastPoint()._data = ray->data();
1072 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1073 }
1074 else
1075 _current_cached_trace = nullptr;
1076
1077 // Need to call subdomain setup
1079 onSubdomainChanged(ray, /* same_ray = */ false);
1080 // If we didn't change subdomains, we still need to call this on the RayKernels
1081 else
1082 for (RayKernelBase * rk : _study.currentRayKernels(_tid))
1083 rk->preTrace();
1084
1085 // Ray tracing loop through each segment for a single Ray on this processor
1086 do
1087 {
1088#ifdef DEBUG_RAY_IF
1089 if (DEBUG_RAY_IF)
1090 libMesh::err << "\n\n";
1091#endif
1092 debugRay("At top of ray tracing loop");
1093 debugRay(" ray->id() = ", ray->id());
1094 debugRay(" _incoming_point = ", _incoming_point);
1095 debugRay(" _incoming_side = ", _incoming_side);
1096 debugRay(" _current_elem->id() = ", _current_elem->id());
1097 debugRay(" _current_elem->subdomain_id() = ", _current_elem->subdomain_id());
1098 debugRay(" _current_subdomain_id = ", _current_subdomain_id);
1099 debugRay(" _current_elem_type = ", Utility::enum_to_string(_current_elem_type));
1100 debugRay("Top of ray tracing loop Ray info\n", ray->getInfo());
1101 debugRay("Top of ray tracing loop current elem info\n", _current_elem->get_info());
1102
1103 traceAssert(_current_ray == &ray, "Current ray mismatch");
1104
1105 // Copy over in case we need to use it
1107 // Invalidate all intersections as we're tracing again
1108 _exits_elem = false;
1113
1114 // Stationary ray
1115 if (ray->stationary())
1116 {
1117 mooseAssert(ray->invalidDirection(), "Should have an invalid direction");
1118 _exits_elem = true;
1123 }
1124 // If we haven't hit a vertex or an edge, do the normal exit algorithm first.
1125 // In the case of a Ray that previously moved through point neighbors due to
1126 // being at a vertex/edge, this will be true because we do not communicate the
1127 // vertex/edge intersection. The previous processor already set us up for
1128 // the best intersection because it already computed it and chose to
1129 // send it our way as such
1131 {
1132 traceAssert(_current_elem->processor_id() == _pid, "Trace elem not on processor");
1133 debugRay("Didn't hit vertex or edge: doing normal exits elem check");
1134
1137
1138 const auto exits_elem_result = exitsElem(_current_elem,
1146
1147 if (exits_elem_result != NO_EXIT)
1148 {
1149 storeExitsElemResult(exits_elem_result);
1150 _exits_elem = true;
1151 ray->setCurrentPoint(_intersection_point);
1152 }
1153 }
1154 else
1155 {
1156 debugRay("Will not do normal exits elem check because at a vertex/edge");
1157 }
1158
1159 // At this point, we either did a regular exit check and it failed, or we hit a vertex/edge
1160 // on the previous intersection and didn't bother to do a regular exit check on
1161 // _current_elem
1162 if (!_exits_elem)
1163 {
1164 debugRay("Moving through neighbors");
1165
1166 // The element we want moveThroughNeighbors() to try last. That is - if all others fail,
1167 // this is the last resort. If we have a last intersection that tells us we're going
1168 // through a vertex or edge, we probably won't go back to that elem. If we don't, it means
1169 // that we failed the exitsElem() check on _current_elem and probably won't return to it
1170 // either.
1171 const Elem * move_through_neighbors_last = nullptr;
1172
1173 // Get the neighbors
1174 const std::vector<NeighborInfo> * neighbors = nullptr;
1175 // If we have previous vertex/edge information, use it
1177 {
1178 traceAssert(_last_elem, "Should be valid");
1179 move_through_neighbors_last = _last_elem;
1181 }
1182 // Without previous vertex/edge information, let's try to find some. We could just do
1183 // a pure point neighbor check at the current point, but we'd rather be able to cache
1184 // this information so that someone else can use it - this requires the more unique
1185 // identifier of which vertex/edge we are at.
1186 else
1187 {
1188 debugRay(" Searching for vertex/edge hit with incoming side ",
1190 " on elem ",
1191 _current_elem->id(),
1192 " at ",
1194
1195 move_through_neighbors_last = _current_elem;
1196
1197 // If we have side info: check for vertices on said side, otherwise, check everywhere
1201
1203 neighbors = &getVertexNeighbors(_current_elem, at_v);
1204 // If still nothing and in 3D, check if we're on an edge
1205 // TODO: Handle 2D with a similar check for if we're on a side
1206 else if (_dim == 3)
1207 {
1208 ElemExtrema extrema;
1211 else
1213
1214 if (extrema.atEdge())
1215 neighbors = &getEdgeNeighbors(_current_elem, extrema, _incoming_point);
1216 }
1217
1218 // If we still haven't found anything - let's try a last-ditch effort
1219 if (!neighbors || neighbors->empty())
1221
1222 // Couldn't find anything
1223 if (neighbors->empty())
1224 {
1225 failTrace("Could not find neighbors to move through", _study.tolerateFailure(), __LINE__);
1226 return;
1227 }
1228 }
1229
1230 // Move through a neighbor
1231 const Elem * best_neighbor = nullptr;
1232 auto best_neighbor_side = RayTracingCommon::invalid_side;
1233 const auto exits_elem_result = moveThroughNeighbors(
1234 *neighbors, move_through_neighbors_last, best_neighbor, best_neighbor_side);
1235
1236 // If we didn't find anything... we're out of luck
1237 if (exits_elem_result == NO_EXIT)
1238 {
1239 failTrace("Could not find intersection after trying to move through point neighbors",
1241 __LINE__);
1242 return;
1243 }
1244
1245 // At this point, we've successfully made it through an element and also started
1246 // through another element, so set that
1247 _exits_elem = true;
1249 _current_elem = best_neighbor;
1250 _incoming_side = best_neighbor_side;
1251 ray->setCurrentElem(best_neighbor);
1252 ray->setCurrentIncomingSide(best_neighbor_side);
1253 ray->setCurrentPoint(_intersection_point);
1254
1255 // Don't own this element - return exits trace for this Ray on this proc
1256 if (best_neighbor->processor_id() != _pid)
1257 {
1258 // We've already computed the next intersection but said intersection is
1259 // on an elem on another processor. Therefore, the next proc will re-trace
1260 // this Ray on the perfect elem that we've picked (best_neighbor)
1261 ray->setCurrentPoint(_incoming_point);
1263
1265 return;
1266 }
1267
1268 // Subdomain changed
1269 if (_current_elem->subdomain_id() != _current_subdomain_id)
1270 onSubdomainChanged(ray, /* same_ray = */ true);
1271
1272 // Do own this element - tally the result as we're the ones tracing it
1273 storeExitsElemResult(exits_elem_result);
1274 }
1275
1276 debugRay("Done with trace");
1277 debugRay(" _exits_elem: ", _exits_elem);
1278 debugRay(" _intersection_point: ", _intersection_point);
1279 debugRay(" _intersected_side: ", _intersected_side);
1280 debugRay(" _intersected_side centroid: ",
1283 : _current_elem->side_ptr(_intersected_side)->vertex_average());
1284 debugRay(" _intersected_extrema = ", _intersected_extrema);
1285 debugRay(" _intersection_distance = ", _intersection_distance);
1286
1287 // Increment intersections
1288 if (_intersection_distance > 0)
1289 {
1290 debugRay("Incrementing ray intersections by 1 to ", ray->intersections() + 1);
1291 ray->addIntersection();
1293 }
1294
1295 // Increment distance
1296 ray->addDistance(_intersection_distance);
1297 debugRay("Incremented ray distance by ", _intersection_distance);
1298
1299 // The effective max distance that the Ray should travel - minimum of the two
1300 const auto max_distance = std::min(ray->maxDistance(), _study.rayMaxDistance());
1301 debugRay("Max distance checks");
1302 debugRay(" _study.rayMaxDistance() = ", _study.rayMaxDistance());
1303 debugRay(" ray->maxDistance() = ", ray->maxDistance());
1304 debugRay(" max_distance (effective) = ", max_distance);
1305
1306 // At the maximum distance - distinguish between this and past the maximum
1307 // distance because in this case we're close enough to the intersection point
1308 // that we can keep it, its intersected side, and intersected extrema
1309 if (MooseUtils::absoluteFuzzyEqual(ray->distance(), max_distance))
1310 {
1311 debugRay("At max distance");
1312
1313 ray->setShouldContinue(false);
1314 _should_continue = false;
1315 }
1316 // Past the max distance - need to remove the additional distance we traveled,
1317 // change the point and invalidate the intersection data (moves the Ray back)
1318 else if (ray->distance() > max_distance)
1319 {
1320 debugRay("Past max distance");
1321
1322 // The distance past the max distance we have traveled
1323 const auto difference = ray->distance() - max_distance;
1324 traceAssert(difference > 0, "Negative distance change after past_max_distance");
1325
1326 debugRay("Removing distance ", difference);
1327 ray->addDistance(-difference);
1328 debugRay(" New ray->distance() = ", ray->distance());
1329
1330 _intersection_point -= ray->direction() * difference;
1331 _intersection_distance -= difference;
1334 ray->setCurrentPoint(_intersection_point);
1335
1336 ray->setShouldContinue(false);
1337 _should_continue = false;
1338
1339 traceAssert(_intersection_distance >= 0, "Negative _intersection_distance");
1340#ifndef NDEBUG
1342 failTrace("Does not contain point after past max distance",
1343 /* warning = */ false,
1344 __LINE__);
1345#endif
1346 }
1347
1348 if (!_study.currentRayKernels(_tid).empty())
1349 {
1350 debugRay("Calling onSegment() with");
1351 debugRay(" current_elem->id() = ", _current_elem->id());
1352 debugRay(" _incoming_point = ", _incoming_point);
1353 debugRay(" _incoming_side = ", _incoming_side);
1354 debugRay(" _intersection_point = ", _intersection_point);
1355 debugRay(" _intersected_side = ", _intersected_side);
1356 debugRay(" _intersected_extrema = ", _intersected_extrema);
1357 debugRay(" _intersection_distance = ", _intersection_distance);
1358 onSegment(ray);
1359
1361
1362 // RayKernel killed a Ray or we're at the end
1363 traceAssert(_should_continue == ray->shouldContinue(), "Should be the same");
1364 if (!_should_continue)
1365 {
1366 debugRay("RayKernel killed the ray or past max distance");
1367 traceAssert(!ray->trajectoryChanged(),
1368 "RayKernels should not change trajectories of Rays at end");
1369
1370 onCompleteTrace(ray);
1371 return;
1372 }
1373
1374 // RayKernel moved a Ray
1375 if (ray->trajectoryChanged())
1376 {
1377 debugRay("RayKernel changed the Ray's trajectory");
1378 debugRay(" new direction = ", ray->direction());
1379 debugRay(" old incoming point = ", _incoming_point);
1380 debugRay(" new incoming point = ", ray->currentPoint());
1381 possiblyAddDebugRayMeshPoint(_incoming_point, ray->currentPoint());
1382
1383 _incoming_point = ray->currentPoint();
1386 ray->setCurrentIncomingSide(_incoming_side);
1387
1388 const auto new_intersection_distance = (ray->currentPoint() - _incoming_point).norm();
1389 ray->addDistance(-_intersection_distance + new_intersection_distance);
1390 _intersection_distance = new_intersection_distance;
1391
1393 onContinueTrace(ray);
1394 continue;
1395 }
1396 else
1397 possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1398 }
1399 else
1400 {
1402
1403 if (!_should_continue)
1404 {
1405 debugRay("Killing due to at end without RayKernels");
1406 traceAssert(!ray->shouldContinue(), "Ray shouldn't continue");
1407
1408 onCompleteTrace(ray);
1409 return;
1410 }
1411 }
1412
1413 // If at a vertex/on an edge and not on the boundary, we may actually be on the boundary,
1414 // just not on a boundary side. Check for that here. If the domain is rectangular we will
1415 // do a quick check against the bounding box as if we're not on the boundary of the
1416 // bounding box for a rectangular problem, we can skip this.
1417 // TODO: see how much the tolerance for the bounding box check can be tightened
1418 if (_dim > 1 && _intersected_extrema.atExtrema() &&
1419 _current_elem->neighbor_ptr(_intersected_side) &&
1423 _dim,
1425 {
1426 auto boundary_side = RayTracingCommon::invalid_side;
1427 ElemExtrema boundary_extrema;
1428 const Elem * boundary_elem = nullptr;
1429
1430 findExternalBoundarySide(boundary_side, boundary_extrema, boundary_elem);
1431
1432 if (boundary_elem)
1433 {
1434 // At this point, the new incoming side is very difficult to find
1435 // and may require some re-tracing backwards. Let's not do that -
1436 // we don't need it to continue the trace. This is reason why
1437 // _incoming_side is not available in RayBCs.
1439 _current_elem = boundary_elem;
1440 _intersected_side = boundary_side;
1441 _intersected_extrema = boundary_extrema;
1442 ray->setCurrentElem(_current_elem);
1443
1444 debugRay("Found a neighbor boundary side with:");
1445 debugRay(" _current_elem->id() = ", _current_elem->id());
1446 debugRay(" _intersected_side = ", _intersected_side);
1447 debugRay(" _intersected_extrema = ", _intersected_extrema);
1448 }
1449 }
1450
1451 // The next element
1452 const Elem * neighbor = nullptr;
1453
1454 // Set up where to go next
1456 debugRay("Set _incoming point to ", _incoming_point);
1457
1458 debugRay("Looking for neighbor on side ", _intersected_side, " of elem ", _current_elem->id());
1459
1460 // Get the neighbor on that side
1461 // If the mesh has active elements of the same level, just grab the neighbor directly. In
1462 // this case, we can avoid a call to active() on the neighbor in getActiveNeighbor(), which
1463 // can be expensive depending on caching.
1464 neighbor = _study.hasSameLevelActiveElems()
1465 ? _current_elem->neighbor_ptr(_intersected_side)
1467
1468 // Found one - not on the boundary so set the next info
1469 if (neighbor)
1470 {
1471 traceAssert(neighbor->active(), "Inactive neighbor");
1472 traceAssert(_current_elem->subdomain_id() == _current_subdomain_id,
1473 "_current_subdomain_id invalid");
1474
1475 // If the mesh has active elements of the same level, don't use
1476 // neighbor->which_neighbor_am_i(), which calls active() and an n_sides() virtual call
1478 {
1479 // If the subdomain hasn't changed, we can guarantee n_sides is the same as
1480 // _current_elem. Prefer this because neighbor->n_sides() is an expensive virtual. Even
1481 // better, subdomain_id() isn't a virtual!
1482 const unsigned short n_sides = neighbor->subdomain_id() == _current_subdomain_id
1484 : neighbor->n_sides();
1485 traceAssert(n_sides == neighbor->n_sides(), "n_sides incorrect");
1486
1487 for (_incoming_side = 0; _incoming_side < n_sides; ++_incoming_side)
1488 if (neighbor->neighbor_ptr(_incoming_side) == _current_elem)
1489 break;
1490 }
1491 else
1492 _incoming_side = neighbor->which_neighbor_am_i(_current_elem);
1493
1495 _current_elem = neighbor;
1496 ray->setCurrentElem(neighbor);
1497 ray->setCurrentIncomingSide(_incoming_side);
1498
1499 debugRay("Next elem: ", neighbor->id(), " with centroid ", neighbor->vertex_average());
1500 debugRay("Next _incoming_side: ",
1502 " with centroid ",
1503 neighbor->side_ptr(_incoming_side)->vertex_average());
1504 traceAssert(_last_elem->subdomain_id() == _current_subdomain_id,
1505 "_current_subdomain_id invalid");
1506
1507 // Whether or not the subdomain changed
1508 const bool subdomain_changed = neighbor->subdomain_id() != _current_subdomain_id;
1509
1510 // See if we hit any internal sides leaving this element and apply
1511 // We require that all internal RayBCs be on internal sidesets that have different
1512 // subdomain ids on each side. Therefore, only check if at vertex/edge or if
1513 // the subdomain changes
1514 if (_study.hasInternalSidesets() && (subdomain_changed || _intersected_extrema.atExtrema()))
1515 {
1517
1518 // Internal RayBC killed a Ray
1519 if (!_should_continue)
1520 {
1521 traceAssert(!ray->shouldContinue(), "Should be the same");
1522 debugRay("Internal RayBC killed the ray");
1523
1524 onCompleteTrace(ray);
1525 return;
1526 }
1527
1528 // Internal RayBC changed the Ray
1529 if (ray->trajectoryChanged())
1530 {
1531 debugRay("Internal RayBC changed the trajectory:");
1532 debugRay(" new direction = ", ray->direction());
1533
1534 // Is this side still incoming?
1535 const auto normal = _study.getSideNormal(_current_elem, _incoming_side, _tid);
1536 const auto dot = normal * ray->direction();
1537 debugRay("Dot product with new direction and side = ", dot);
1538 if (dot > -TRACE_TOLERANCE)
1539 {
1540 _incoming_side = _last_elem->which_neighbor_am_i(_current_elem);
1542 neighbor = _last_elem;
1543 ray->setCurrentElem(_current_elem);
1544 ray->setCurrentIncomingSide(_incoming_side);
1545 debugRay(" Dot > 0 (Ray turned around): Setting _current_elem = ",
1546 _current_elem->id(),
1547 " and _incoming_side = ",
1549 }
1550
1552 }
1553
1554 traceAssert(ray->currentPoint().absolute_fuzzy_equals(_intersection_point, TRACE_TOLERANCE),
1555 "Internal RayBC changed the Ray point");
1556 }
1557
1558 // Neighbor is off processor
1559 // If we hit at a vertex/edge, we will continue and let the move through neighbor exit
1560 // figure out who to send to
1561 if (neighbor->processor_id() != _pid)
1562 {
1564 {
1565 debugRay("Neighbor is off processor but continuing to move through neighbors");
1566 }
1567 else
1568 {
1570 return;
1571 }
1572 }
1573
1574 // Neighbor is on processor, call subdomain setup if needed
1575 if (subdomain_changed)
1576 onSubdomainChanged(ray, /* same_ray = */ true);
1577 }
1578 // No neighbor found: on the boundary
1579 else
1580 {
1581 debugRay("No neighbor found - on the boundary");
1582
1583 // Apply boundary conditions
1585
1586 if (_current_elem == ray->currentElem())
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 possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1603
1605 // Direction changed
1606 if (_current_elem == ray->currentElem())
1607 {
1608 debugRay("RayBC reflected the ray");
1609 debugRay(" new direction = ", ray->direction());
1610 traceAssert(ray->direction() *
1613 "Reflected ray is not incoming");
1614
1617 ray->setCurrentPoint(_incoming_point);
1618 ray->setCurrentIncomingSide(_incoming_side);
1619 }
1620 // Position changed (PeriodicRayBC)
1621 else
1622 {
1623 debugRay("RayBC moved the ray");
1624 debugRay(" new point = ", ray->currentPoint());
1625 debugRay(" new pid = ", ray->currentElem()->processor_id());
1626 debugRay(" new elem id = ", ray->currentElem()->id());
1627 debugRay(" new side = ", ray->currentIncomingSide());
1628
1629 _current_elem = ray->currentElem();
1630 _incoming_point = ray->currentPoint();
1631 _incoming_side = ray->currentIncomingSide();
1633
1634 if (_current_elem->processor_id() != _pid)
1635 {
1637 return;
1638 }
1639 }
1641 }
1642 }
1643
1644 onContinueTrace(ray);
1645
1646 } while (true);
1647
1648 // If a trace made its way down here and didn't return... it failed
1649 failTrace("Could not find an intersection", _study.tolerateFailure(), __LINE__);
1650}
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.
virtual void postOnSegment(const THREAD_ID tid, const std::shared_ptr< Ray > &ray)
Called at the end of a Ray segment.
Real rayMaxDistance() const
Max distance any Ray can travel.
bool rayDependentSubdomainSetup() const
Whether or not to use Ray dependent subdomain setup.
virtual void preTrace(const THREAD_ID, const std::shared_ptr< Ray > &)
Called at the beginning of a trace for a ray.
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).
const BoundingBox & boundingBox() const
Get the nodal bounding box for the domain.
bool currentlyPropagating() const
Whether or not the study is propagating (tracing Rays)
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:949
unsigned int _debug_node_count
Definition TraceRay.h:535
Mesh * _debug_mesh
Definition TraceRay.h:533
void onTrajectoryChanged(const std::shared_ptr< Ray > &ray)
Called when a Ray's trajectory changes.
Definition TraceRay.C:1721
Parallel::Communicator _debug_comm
Definition TraceRay.h:534
void storeExitsElemResult(const ExitsElemResult result)
Stores the result given by an intersection in _results as necessary.
Definition TraceRay.C:2038
void onSegment(const std::shared_ptr< Ray > &ray)
Called on a single segment traced by a Ray.
Definition TraceRay.C:2051
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:584
void continueTraceOffProcessor(const std::shared_ptr< Ray > &ray)
Sets up a ray to continue tracing off processor.
Definition TraceRay.C:1696
void applyOnInternalBoundary(const std::shared_ptr< Ray > &ray)
Gets and applies internal boundary conditions (if any) from _current_elem, _last_elem,...
Definition TraceRay.C:804
void onSubdomainChanged(const std::shared_ptr< Ray > &ray, const bool same_ray)
Called when the subdomain changes.
Definition TraceRay.C:1750
ElemExtrema _last_intersected_extrema
The intersected vertex/edge vertices for the previous intersection, if any.
Definition TraceRay.h:482
void onCompleteTrace(const std::shared_ptr< Ray > &ray)
Called when a Ray is finished tracing (whenever !ray->shouldContinue())
Definition TraceRay.C:1653
void onContinueTrace(const std::shared_ptr< Ray > &)
Called when a Ray is continuing to trace after segment.
Definition TraceRay.C:1681
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:745
static const unsigned short invalid_vertex
Identifier for an invalid vertex index.
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.
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.
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 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 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.
OStreamProxy err(std::cerr)

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 getEdgeNeighbors(), and 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 getEdgeNeighbors(), getPointNeighbors(), and getVertexNeighbors().

◆ _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 getEdgeNeighbors(), getPointNeighbors(), and getVertexNeighbors().

◆ _neighbor_set

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

Definition at line 508 of file TraceRay.h.

Referenced by getEdgeNeighbors(), getPointNeighbors(), and getVertexNeighbors().

◆ _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 getEdgeNeighbors(), getPointNeighbors(), and getVertexNeighbors().

◆ _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(), getEdgeNeighbors(), getPointNeighbors(), getVertexNeighbors(), 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 getVertexNeighbors(), and meshChanged().


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