16#include "libmesh/elem.h"
17#include "libmesh/parallel_algebra.h"
18#include "libmesh/parallel_sync.h"
19#include "libmesh/enum_point_locator_type.h"
20#include "libmesh/mesh_tools.h"
23 const std::vector<std::shared_ptr<Ray>> & rays,
24 std::vector<std::shared_ptr<Ray>> & local_rays,
25 const bool do_exchange)
26 : ParallelObject(study.comm()),
30 _do_exchange(do_exchange),
32 _parallel_study(*_study.parallelStudy()),
34 _local_rays(local_rays),
58 std::unordered_map<processor_id_type, std::vector<std::shared_ptr<Ray>>> rays_to_send;
60 for (processor_id_type pid = 0; pid <
comm().
size(); ++pid)
64 for (
auto & ray :
_rays)
65 if (pid_bbox.contains_point(ray->currentPoint()))
66 rays_to_send[pid].push_back(ray);
71 [&](processor_id_type ,
const std::vector<std::shared_ptr<Ray>> & rays)
73 for (
auto & ray : rays)
79 Parallel::push_parallel_packed_range(
comm(), rays_to_send, &
_parallel_study, claim_functor);
111 const bool smallest =
id % 2 == 0;
114 const Elem * extremum_elem = elem;
121 for (
const auto & neighbor : neighbors)
123 mooseAssert(neighbor->active(),
"Inactive neighbor");
125 if ((smallest && neighbor->id() < extremum_elem->id()) ||
126 (!smallest && neighbor->id() > extremum_elem->id()))
127 if (neighbor->contains_point(point))
128 extremum_elem = neighbor;
132 if (extremum_elem->processor_id() ==
_pid)
134 mooseAssert(extremum_elem->active(),
"Inactive element");
135 return extremum_elem;
145 mooseAssert(
_mesh.
queryElemPtr(elem->id()) == elem,
"Mesh doesn't contain elem");
146 mooseAssert(elem->active(),
"Inactive element");
151 if (!(!ray->invalidCurrentIncomingSide() &&
154 for (
const auto s : elem->side_index_range())
158 starting_incoming_side = s;
162 ray->setStart(ray->currentPoint(), elem, starting_incoming_side);
182 const auto bbox = MeshTools::create_local_bounding_box(
_mesh.
getMesh());
185 std::vector<std::pair<Point, Point>> bb_points = {
static_cast<std::pair<Point, Point>
>(bbox)};
190 for (processor_id_type pid = 0; pid <
comm().
size(); ++pid)
192 BoundingBox pid_bbox =
static_cast<BoundingBox
>(bb_points[pid]);
193 pid_bbox.scale(0.01);
204 for (
const auto & elem :
_mesh.
getMesh().active_element_ptr_range())
207 for (
unsigned int v = 0;
v < elem->n_vertices(); ++
v)
209 const auto & node = elem->node_ptr(
v);
210 for (
const auto & neighbor_id : libmesh_map_find(node_to_elem_map, node->id()))
212 if (neighbor_id == elem->id())
216 if (std::count(fill.begin(), fill.end(), neighbor) == 0)
217 fill.emplace_back(neighbor);
232 std::map<RayID, char> local_map;
233 auto add_to_local_map =
234 [
this, &local_map](
const std::vector<std::shared_ptr<Ray>> & rays,
const bool claimed_rays)
236 for (
const auto & ray : rays)
238 const auto id =
getID(ray);
241 auto emplace_pair = local_map.emplace(
id, claimed_rays);
244 if (!emplace_pair.second && claimed_rays)
246 mooseAssert(!emplace_pair.first->second,
247 "Ray was claimed more than once on a single processor");
248 emplace_pair.first->second =
true;
254 add_to_local_map(
_rays,
false);
258 std::map<processor_id_type, std::vector<std::pair<RayID, char>>> send_info;
259 if (local_map.size())
260 send_info.emplace(std::piecewise_construct,
261 std::forward_as_tuple(0),
262 std::forward_as_tuple(local_map.begin(), local_map.end()));
265 std::map<RayID, std::vector<std::pair<processor_id_type, char>>> global_map;
268 auto receive_functor = [&global_map](processor_id_type pid,
269 const std::vector<std::pair<RayID, char>> & id_claimed_pairs)
271 for (
const auto & id_claimed_pair : id_claimed_pairs)
272 global_map[id_claimed_pair.first].emplace_back(pid, id_claimed_pair.second);
276 Parallel::push_parallel_vector_data(
comm(), send_info, receive_functor);
280 for (
const auto & id_pairs_pair : global_map)
282 const RayID id = id_pairs_pair.first;
283 const std::vector<std::pair<processor_id_type, char>> & pid_claimed_pairs =
284 id_pairs_pair.second;
286 std::vector<processor_id_type> claimed_pids;
287 for (
const auto & pid_claimed_pair : pid_claimed_pairs)
288 if (pid_claimed_pair.second)
289 claimed_pids.push_back(pid_claimed_pair.first);
291 if (claimed_pids.size() == 0)
293 mooseAssert(claimed_pids.size() == 1,
"Ray was claimed on multiple processors");
unsigned long int RayID
Type for a Ray's ID.
virtual void postClaimRay(std::shared_ptr< Ray > &ray, const Elem *elem)
Entry point for acting on a Ray after it is claimed.
void possiblyClaim(const std::shared_ptr< Ray > &obj)
Possibly claim a Ray.
const libMesh::BoundingBox & inflatedBoundingBox(const processor_id_type pid) const
Get the inflated bounding box for rank \pid.
const std::vector< std::shared_ptr< Ray > > & _rays
The Rays that need to be searched to possibly claimed.
bool _needs_init
Whether or not an init is needed (bounding boxes, neighbors)
MooseMesh & _mesh
The mesh.
virtual void meshChanged() override
Call on mesh changes to reinit the necessary data structures.
RayTracingStudy & _study
The RayTracingStudy.
virtual void init()
Initialize the object.
ClaimRays(RayTracingStudy &study, const std::vector< std::shared_ptr< Ray > > &rays, std::vector< std::shared_ptr< Ray > > &local_rays, const bool do_exchange)
Constructor.
ParallelStudy< std::shared_ptr< Ray >, Ray > & _parallel_study
The ParallelStudy, used as the context for communicating rays.
std::unordered_map< dof_id_type, std::vector< const Elem * > > _elem_point_neighbors
Map of point neighbors for each element.
virtual RayID getID(const std::shared_ptr< Ray > &ray) const
Gets an ID associated with the Ray for claiming purposes.
virtual void postClaim()
Entry point after claim()
const processor_id_type _pid
This processor ID.
virtual void prePossiblyClaimRay(const std::shared_ptr< Ray > &)
Entry point before possibly claiming a Ray.
std::vector< libMesh::BoundingBox > _inflated_bboxes
The inflated bounding boxes for all processors.
void claim()
Claim the Rays.
std::vector< std::shared_ptr< Ray > > & _local_rays
The local Rays that are claimed.
std::unique_ptr< libMesh::PointLocatorBase > _point_locator
The point locator.
void buildPointNeighbors()
Build the map of elements to all of their point neighbors.
const Elem * claimPoint(const Point &point, const RayID id, const Elem *elem)
Try to claim a spatial point.
virtual void preClaim()
Entry point before claim()
void buildBoundingBoxes()
Builds the bounding boxes (_inflated_bboxes).
void verifyClaiming()
Verifies that the claiming process succeeded.
const bool _do_exchange
Whether or not the Rays need to be initially exchanged.
void mooseError(Args &&... args) const
virtual Elem * elemPtr(const dof_id_type i)
const std::unordered_map< dof_id_type, std::vector< dof_id_type > > & nodeToElemMap()
virtual Elem * queryElemPtr(const dof_id_type i)
Base class for Ray tracing studies that will generate Rays and then propagate all of them to terminat...
bool sideIsIncoming(const Elem *const elem, const unsigned short side, const Point &direction, const THREAD_ID tid)
Whether or not side is incoming on element elem in direction direction.
const libMesh::Elem & elemSide(const libMesh::Elem &elem, const unsigned int s, const THREAD_ID tid=0)
Get an element's side pointer without excessive memory allocation.
bool verifyRays() const
Whether or not to verify if Rays have valid information before being traced.
processor_id_type size() const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
const Parallel::Communicator & comm() const
static const unsigned short invalid_side
Identifier for an invalid side index.