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 intresults () 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 ElemExtremacurrentIntersectedExtrema () 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 BoundaryIDcurrentBoundaryID () const
 Gets the BoundaryID of the boundary that the Ray intersected and is being applied a boundary condition.
 
const SubdomainIDcurrentSubdomainID () 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.
 
template<typename T , typename FirstOrderT >
std::enable_if<!std::is_base_of< Edge, T >::value, bool >::type exitsElem (const Elem *elem, const unsigned short incoming_side, Point &intersection_point, unsigned short &intersected_side, ElemExtrema &intersected_extrema, Real &intersection_distance, const Point *normals)
 

Private Types

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

Private Member Functions

void onSegment (const std::shared_ptr< Ray > &ray)
 Called on a single segment traced by a Ray.
 
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 47 of file TraceRay.C.

48 : _study(study),
49 _mesh(study.getSubProblem().mesh()),
52 _pid(_study.comm().rank()),
53 _tid(tid),
54 _backface_culling(false),
55 _current_normals(nullptr),
57{
58}
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 BoundaryInfo & get_boundary_info() 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 746 of file TraceRay.C.

747{
748 debugRay("Called applyOnExternalBoundary() with");
749 debugRay(" _current_elem->id() = ", _current_elem->id());
750 debugRay(" _intersection_point = ", _intersection_point);
751 debugRay(" _intersected_side = ", _intersected_side);
752 debugRay(" _intersected_extrema = ", _intersected_extrema);
753
754 // Clear storage for the list of ConstBndElement that we need to apply RayBCs to
755 _boundary_elems.clear();
756
757 // If on the elem extrema (at a vertex or within an edge), check for external sidesets on
758 // neighbors (which will include _current_elem)
759 if (_dim != 1 && _intersected_extrema.atExtrema())
760 {
762 debugRay(" Found ", neighbors.size(), " vertex/edge neighbors (including self)");
763 traceAssert(std::count_if(neighbors.begin(),
764 neighbors.end(),
765 [this](const NeighborInfo & ni)
766 { return ni._elem == _current_elem; }),
767 "_current_elem not in neighbors");
768
769 for (const auto & neighbor_info : neighbors)
770 {
771 if (!neighbor_info._valid)
772 continue;
773
774 const Elem * elem = neighbor_info._elem;
775 const auto & sides = neighbor_info._sides;
776 const auto & side_normals = neighbor_info._side_normals;
777
778 for (MooseIndex(side_normals.size()) i = 0; i < side_normals.size(); ++i)
779 if (!elem->neighbor_ptr(sides[i]) // is a boundary side that has our point
780 && side_normals[i] * ray->direction() > TRACE_TOLERANCE) // and is entrant
781 {
782 // TODO: this could likely be optimized
783 ElemExtrema extrema;
784 withinExtremaOnSide(elem, _intersection_point, sides[i], _dim, extrema);
785
787 possiblyAddToBoundaryElems(elem, sides[i], _boundary_ids, extrema);
788 }
789 }
790 }
791 // Not on the periphery (at vertex/edge), so we just need to add the external
792 // sidesets from _current_elem on _intersected_side
793 else
794 {
798 }
799
800 debugRay("Calling external onBoundary() with ", _boundary_elems.size(), " boundaries");
801 onBoundary(ray, /* external = */ true);
802}
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:2000
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:2109
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:917
Point _intersection_point
The work point for the intersection of the current Ray.
Definition TraceRay.h:476
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
dof_id_type id() const
const Elem * neighbor_ptr(unsigned int i) const
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 805 of file TraceRay.C.

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

1698{
1699 traceAssert(ray->currentElem() == _current_elem, "Ray currentElem() invalid");
1700 traceAssert(ray->currentIncomingSide() == _incoming_side, "Ray currentIncomingSide() invalid");
1701 traceAssert(ray->currentPoint() == _incoming_point, "Ray currentPoint() invalid");
1702 traceAssert(_current_elem->processor_id() != _pid, "Off processor trace is not off processor");
1703 debugRay("Ray going off processor to ", _current_elem->processor_id());
1704
1705 ray->addProcessorCrossing();
1706
1708 {
1711 _current_cached_trace->lastPoint()._data = ray->data();
1713 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1714 }
1715
1716 if (_intersection_distance > 0)
1717 possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1718 possiblySaveDebugRayMesh();
1719}
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
processor_id_type processor_id() const
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/4]

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

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

Referenced by moveThroughNeighbor(), and trace().

◆ exitsElem() [2/4]

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

Determines if _current_ray moving in direction _direction exits elem.

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

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

◆ exitsElem() [3/4]

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

◆ exitsElem() [4/4]

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

Definition at line 314 of file TraceRay.C.

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

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

1834{
1835 const auto message = failTraceMessage(reason, line);
1836
1837 if (warning)
1838 {
1840 mooseWarning(message);
1841 (*_current_ray)->setShouldContinue(false);
1842 _should_continue = false;
1843 }
1844 else
1845 mooseError(message);
1846}
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:1785

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

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

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

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

1904{
1905 traceAssert(elem, "Invalid elem");
1906 traceAssert(vertices.first, "Must be valid");
1907 traceAssert(vertices.second, "Must be valid");
1908
1909 debugRay("Called getEdgeNeighbors() with:");
1910 debugRay(" elem->id() = ", elem->id(), " with centroid ", elem->vertex_average());
1911 debugRay(" vertices.first = ", vertices.first->id(), " at ", (Point)*vertices.first);
1912 debugRay(" vertices.second = ", vertices.second->id(), " at ", (Point)*vertices.second);
1913 debugRay(" point = ", point);
1914
1915 traceAssert(elem->get_node_index(vertices.first) != libMesh::invalid_uint,
1916 "Doesn't contain vertex");
1917 traceAssert(elem->get_node_index(vertices.second) != libMesh::invalid_uint,
1918 "Doesn't contain vertex");
1919 traceAssert(isWithinSegment(
1920 (Point)*vertices.first, (Point)*vertices.second, point, LOOSE_TRACE_TOLERANCE),
1921 "Point not within edge");
1922
1924
1925 const auto ordered_vertices = vertices.first->id() < vertices.second->id()
1926 ? vertices
1927 : std::make_pair(vertices.second, vertices.first);
1928
1929 // Look for the entry and build if necessary
1930 std::pair<bool, std::vector<NeighborInfo>> * entry;
1931 auto search = _edge_neighbors.find(ordered_vertices);
1932 if (search != _edge_neighbors.end())
1933 entry = &search->second;
1934 else
1935 {
1936 debugRay("Building edge neighbors");
1938 entry = &_edge_neighbors
1939 .emplace(ordered_vertices, std::make_pair(true, std::vector<NeighborInfo>()))
1940 .first->second;
1941 findEdgeNeighbors(elem,
1942 ordered_vertices.first,
1943 ordered_vertices.second,
1948 entry->second);
1949
1950 bool all_same_edge = true;
1951 for (auto & neighbor_info : entry->second)
1952 {
1953 traceAssert(neighbor_info._lower_bound <= neighbor_info._upper_bound,
1954 "Bound order incorrect");
1955
1956 // Fill the side normals
1957 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
1958 neighbor_info._side_normals[i] =
1959 _study.getSideNormal(neighbor_info._elem, neighbor_info._sides[i], _tid);
1960
1961 // See if the bounds are the same as the target edge
1962 if (neighbor_info._lower_bound != 0 || neighbor_info._upper_bound != 1)
1963 all_same_edge = false;
1964 }
1965 entry->first = all_same_edge;
1966 }
1967
1968 // Means that all neighbors are not on the exact same edge, so we must
1969 // validate/invalidate based on if the neighbor's edge contains our point
1970 if (!entry->first)
1971 {
1972 const auto edge_length =
1973 ((Point)*ordered_vertices.first - (Point)*ordered_vertices.second).norm();
1974 const auto point_location = ((Point)*ordered_vertices.first - point).norm() / edge_length;
1975 for (auto & info : entry->second)
1976 info._valid = (info._lower_bound - TRACE_TOLERANCE) < point_location &&
1977 point_location < (info._upper_bound + TRACE_TOLERANCE);
1978 }
1979
1980 return entry->second;
1981}
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
unsigned int get_node_index(const Node *node_ptr) const
Point vertex_average() const
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 1984 of file TraceRay.C.

1987{
1988 debugRay("Called getEdgeNeighbors(), local index version with:");
1989 debugRay(" vertices.first = ", vertices.first);
1990 debugRay(" vertices.second = ", vertices.second);
1991 traceAssert(vertices.first < elem->n_vertices(),
1992 "Invalid vertex with ray " + std::to_string((*_current_ray)->id()));
1993 traceAssert(vertices.second < elem->n_vertices(), "Invalid vertex");
1994
1995 return getEdgeNeighbors(
1996 elem, std::make_pair(elem->node_ptr(vertices.first), elem->node_ptr(vertices.second)), point);
1997}
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:1901
virtual unsigned int n_vertices() const=0
const Node * node_ptr(const unsigned int i) const

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

2001{
2002 if (!extrema.atExtrema())
2003 return getPointNeighbors(elem, point);
2004 if (extrema.atVertex())
2005 return getVertexNeighbors(elem, extrema.vertex());
2006 return getEdgeNeighbors(elem, extrema.edgeVertices(), point);
2007}
const std::vector< NeighborInfo > & getVertexNeighbors(const Elem *elem, const Node *vertex)
Gets the neighbors at a vertex.
Definition TraceRay.C:1849
const std::vector< NeighborInfo > & getPointNeighbors(const Elem *elem, const Point &point)
Get the point neighbors.
Definition TraceRay.C:2010
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 2010 of file TraceRay.C.

2011{
2012 traceAssert(elem, "Invalid elem");
2013
2014 debugRay("Called getPointNeighbors()");
2015 debugRay(" elem = ", elem->id());
2016 debugRay(" point = ", point);
2017
2019 _point_neighbor_helper.clear();
2020
2021 findPointNeighbors(elem,
2022 point,
2028
2029 // Fill the side normals
2030 for (auto & neighbor_info : _point_neighbor_helper)
2031 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
2032 neighbor_info._side_normals[i] =
2033 _study.getSideNormal(neighbor_info._elem, neighbor_info._sides[i], _tid);
2034
2036}
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 1849 of file TraceRay.C.

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

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

◆ meshChanged()

void TraceRay::meshChanged ( )

Called on mesh change.

Definition at line 75 of file TraceRay.C.

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

◆ moveThroughNeighbor()

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

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

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

Definition at line 698 of file TraceRay.C.

704{
705 if (!neighbor_info._valid)
706 return NO_EXIT;
707
708 const Elem * neighbor = neighbor_info._elem;
709 debugRay("Checking neighbor ", neighbor->id(), " with centroid ", neighbor->vertex_average());
710
711 // Find an entrant side (if any)
712 incoming_side = RayTracingCommon::invalid_side;
713 for (MooseIndex(neighbor_info._sides.size()) i = 0; i < neighbor_info._sides.size(); ++i)
714 if (neighbor_info._side_normals[i] * (*_current_ray)->direction() < LOOSE_TRACE_TOLERANCE)
715 {
716 incoming_side = neighbor_info._sides[i];
717 break;
718 }
719
720 // No entrant sides on this neighbor were found
721 if (incoming_side == RayTracingCommon::invalid_side)
722 return NO_EXIT;
723
724 intersection_point = RayTracingCommon::invalid_point;
725 intersected_side = RayTracingCommon::invalid_side;
726 intersected_extrema.invalidate();
727 intersection_distance = RayTracingCommon::invalid_distance;
728
729 // See if there is a way through the neighbor element
730 debugRay("Called exitsElem() from moveThroughNeighbor()");
731 const auto exit_result =
732 exitsElem(neighbor,
733 neighbor->type(),
734 incoming_side,
735 intersection_point,
736 intersected_side,
737 intersected_extrema,
738 intersection_distance,
739 _backface_culling ? _study.getElemNormals(neighbor, _tid) : nullptr);
740 debugRay("Done with exitsElem() from moveThroughNeighbor()");
741
742 return exit_result;
743}
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:83
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 585 of file TraceRay.C.

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

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

1655{
1656 for (RayKernelBase * rk : _study.currentRayKernels(_tid))
1657 rk->postTrace();
1658
1659 debugRay("Called onCompleteTrace()\n", (*_current_ray)->getInfo());
1660 if (_intersection_distance > 0)
1661 possiblyAddDebugRayMeshPoint(_incoming_point, _intersection_point);
1662 possiblySaveDebugRayMesh();
1663
1665 {
1667
1668 if (_intersection_distance > 0)
1669 {
1670 _current_cached_trace->addPoint(ray->currentPoint());
1672 _current_cached_trace->lastPoint()._data = ray->data();
1674 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1675 }
1676
1677 mooseAssert(ray->stationary() == _current_cached_trace->stationary(), "Stationary mismatch");
1678 }
1679}
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 1682 of file TraceRay.C.

1683{
1684 traceAssert(ray->shouldContinue(), "Ray must continue");
1685
1687 {
1688 _current_cached_trace->addPoint(ray->currentPoint());
1690 _current_cached_trace->lastPoint()._data = ray->data();
1692 _current_cached_trace->lastPoint()._aux_data = ray->auxData();
1693 }
1694}
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 2052 of file TraceRay.C.

2053{
2054 traceAssert((*_current_ray)->currentElem() == _current_elem, "Ray currentElem() incorrect");
2055 traceAssert((*_current_ray)->currentPoint() == _intersection_point,
2056 "Ray currentPoint() incorrect");
2057 traceAssert((*_current_ray)->currentIncomingSide() == _incoming_side,
2058 "Ray currentIncomingSide() incorrect");
2059#ifndef NDEBUG
2061 {
2064 "_current_elem does not contain incoming point");
2065
2068 {
2071 "Intersected point is not on intersected side");
2072 traceAssert(!_study.sideIsIncoming(
2073 _current_elem, _intersected_side, (*_current_ray)->direction(), _tid),
2074 "Intersected side is not outgoing");
2075 }
2078 {
2080 .close_to_point(_incoming_point, LOOSE_TRACE_TOLERANCE),
2081 "Incoming point is not on incoming side");
2082 if (ray->intersections() != 0 && ray->maxDistance() != 0)
2083 traceAssert(_study.sideIsIncoming(
2084 _current_elem, _incoming_side, (*_current_ray)->direction(), _tid),
2085 "Incoming side is not incoming");
2086 }
2087 }
2088#endif
2089 traceAssert(MooseUtils::absoluteFuzzyEqual(_intersection_distance,
2091 "_intersection_distance is incorrect");
2092 traceAssert(_current_subdomain_id == _current_elem->subdomain_id(), "Subdomain incorrect");
2093 traceAssert(MooseUtils::absoluteFuzzyEqual((_incoming_point - _intersection_point).norm(),
2095 "Invalid intersection distance");
2096
2099
2100 const auto & rks = _study.currentRayKernels(_tid);
2101 for (auto & rk : rks)
2102 {
2103 rk->onSegment();
2104 postRayTracingObject(ray, rk);
2105 }
2106}
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.
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
virtual bool has_affine_map() const

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

1752{
1753 debugRay("Calling onSubdomainChanged() on subdomain ", _current_elem->subdomain_id());
1754 debugRay(" _current_subdomain_id = ", _current_subdomain_id);
1755
1760
1761 if (_has_ray_kernels)
1762 {
1763 auto & current_ray_kernels = _study.currentRayKernels(_tid);
1764
1765 // If we're still tracing the same Ray, keep track of our old RayKernels
1766 // so that we don't call preTrace() on them again
1767 if (same_ray)
1768 _old_ray_kernels.insert(current_ray_kernels.begin(), current_ray_kernels.end());
1769 // If we're not tracing the same Ray, we need to call preTrace() on everything
1770 else
1771 _old_ray_kernels.clear();
1772
1773 // Call segmentSubdomainSetup to get new kernels etc
1775
1776 // Call preTrace() on all of the RayKernels that need it
1777 for (RayKernelBase * rk : current_ray_kernels)
1778 // Haven't called preTrace() for this Ray on this RayKernel yet
1780 rk->preTrace();
1781 }
1782}
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 1722 of file TraceRay.C.

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

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

921{
922 if (!_study.sideIsNonPlanar(elem, side))
923 traceAssert(extrema.isValid(elem, _intersection_point), "Extrema not correct");
924
925 for (const auto bnd_id : bnd_ids)
926 {
927 bool found = false;
928 for (const auto & bnd_elem : _boundary_elems)
929 if (bnd_elem.bnd_id == bnd_id)
930 {
931 found = true;
932 break;
933 }
934
935 if (!found)
936 {
937 debugRay(" Need to apply boundary on elem ",
938 elem->id(),
939 " and side ",
940 side,
941 " for bnd_id ",
942 bnd_id);
943
944 _boundary_elems.emplace_back(elem, side, bnd_id, extrema);
945 }
946 }
947}
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 2235 of file TraceRay.C.

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

Referenced by onBoundary(), and onSegment().

◆ preExecute()

void TraceRay::preExecute ( )

Should be called immediately before calling any traces.

Definition at line 61 of file TraceRay.C.

62{
63 _current_subdomain_id = Elem::invalid_subdomain_id;
65
66 // Zero out all results
67 for (auto & val : _results)
68 val = 0;
69
72}
bool 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 2039 of file TraceRay.C.

2040{
2041 if (result == HIT_FACE)
2043 else if (result == HIT_VERTEX)
2045 else if (result == HIT_EDGE)
2047 else
2048 mooseError("Should not call storeExitsElemResult() with result ", result);
2049}

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

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

Referenced by exitsElem().

◆ trace()

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

Traces a ray.

Definition at line 1019 of file TraceRay.C.

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