13 #include "libmesh/ignore_warnings.h" 15 #include "libmesh/restore_warnings.h" 22 #include "libmesh/mesh_tools.h" 23 #include "libmesh/parallel_algebra.h" 24 #include "libmesh/parallel_sync.h" 25 #include "libmesh/remote_elem.h" 34 params.
addRequiredParam<UserObjectName>(
"study",
"The RayTracingStudy to get the segments from");
36 params.
addParam<
bool>(
"output_data",
false,
"Whether or not to also output the Ray's data");
37 params.
addParam<std::vector<std::string>>(
"output_data_names",
38 "The names of specific data to output");
39 params.
addParam<
bool>(
"output_data_nodal",
41 "Whether or not to output the Ray's data in a nodal sense, in which the " 42 "data is interpolated linearly across segments");
45 "output_aux_data",
false,
"Whether or not to also output the Ray's aux data");
46 params.
addParam<std::vector<std::string>>(
"output_aux_data_names",
47 "The names of specific aux data to output");
49 MultiMooseEnum props(
"ray_id intersections pid processor_crossings trajectory_changes",
50 "ray_id intersections");
60 _output_data(getParam<bool>(
"output_data")),
61 _output_data_names(isParamValid(
"output_data_names")
62 ? &getParam<
std::vector<
std::string>>(
"output_data_names")
64 _output_data_nodal(getParam<bool>(
"output_data_nodal")),
65 _output_aux_data(getParam<bool>(
"output_aux_data")),
66 _output_aux_data_names(isParamValid(
"output_aux_data_names")
67 ? &getParam<
std::vector<
std::string>>(
"output_aux_data_names")
74 _segmented_rays(false)
77 mooseError(
"In order to output Ray data in output '",
79 "', the RayTracingStudy '",
81 "' must set data_on_cache_traces = true");
83 mooseError(
"In order to output Ray aux data in output '",
85 "', the RayTracingStudy '",
87 "' must set aux_data_on_cache_traces = true");
90 "Cannot be used unless there is data to output; in addition set either " 91 "'output_data' or 'output_data_names");
93 paramError(
"output_data_nodal",
"Not supported when study segments_on_cache_traces = false");
95 paramError(
"output_data",
"Cannot be used in addition to 'output_data_names'; choose one");
98 "Cannot be used in addition to 'output_aux_data_names'; choose one");
105 std::ostringstream
output;
110 output <<
"-s" << std::setw(
_padding) << std::setprecision(0) << std::setfill(
'0') << std::right
152 TIME_SECTION(
"buildIDMap", 3,
"Building RayTracing ID Map");
155 std::map<RayID, dof_id_type> local_ray_needed_nodes;
158 const auto find = local_ray_needed_nodes.find(trace_data._ray_id);
159 if (find == local_ray_needed_nodes.end())
160 local_ray_needed_nodes[trace_data._ray_id] =
neededNodes(trace_data);
163 auto &
value = find->second;
169 std::map<processor_id_type, std::vector<std::pair<RayID, dof_id_type>>> send_needed_nodes;
170 if (local_ray_needed_nodes.size())
172 auto & root_entry = send_needed_nodes[0];
173 for (
const auto & id_nodes_pair : local_ray_needed_nodes)
174 root_entry.emplace_back(id_nodes_pair);
178 std::map<RayID, dof_id_type> global_needed_nodes;
180 std::unordered_map<processor_id_type, std::set<RayID>> pid_received_ids;
183 const auto append_global_max =
184 [&global_needed_nodes, &pid_received_ids](
187 auto & pid_received_entry = pid_received_ids[pid];
188 for (
const auto & id_max_pair : pairs)
190 const RayID ray_id = id_max_pair.first;
193 const auto find = global_needed_nodes.find(ray_id);
194 if (find == global_needed_nodes.end())
195 global_needed_nodes.emplace(ray_id,
max);
198 auto & current_max = find->second;
199 current_max = std::max(current_max,
max);
202 pid_received_entry.insert(ray_id);
205 Parallel::push_parallel_vector_data(
comm(), send_needed_nodes, append_global_max);
208 std::map<RayID, std::pair<dof_id_type, dof_id_type>> global_ids;
211 for (
auto & pair : global_needed_nodes)
213 const RayID ray_id = pair.first;
216 global_ids.emplace(ray_id, std::make_pair(current_node_id, current_elem_id));
218 current_node_id += max_nodes;
220 current_elem_id += max_nodes - 1;
222 current_elem_id += 1;
230 std::unordered_map<processor_id_type, std::vector<std::tuple<RayID, dof_id_type, dof_id_type>>>
232 for (
auto & pid_ids_pair : pid_received_ids)
235 const std::set<RayID> & ray_ids = pid_ids_pair.second;
237 auto & pid_send = send_ids[pid];
238 for (
const RayID ray_id : ray_ids)
240 const auto & global_entry = global_ids.at(ray_id);
243 pid_send.emplace_back(ray_id, node_id, elem_id);
248 const auto append_ids =
250 const std::vector<std::tuple<RayID, dof_id_type, dof_id_type>> & tuples)
252 for (
const auto & tuple : tuples)
254 const RayID ray_id = std::get<0>(tuple);
262 Parallel::push_parallel_vector_data(
comm(), send_ids, append_ids);
268 TIME_SECTION(
"buildSegmentMesh", 3,
"Building RayTracing Mesh Output");
278 const auto num_segments = entry.numSegments();
279 num_nodes += num_segments + 1;
280 if (num_segments >= 1)
283 num_elems += num_segments;
285 else if (entry.stationary())
319 if (trace_data.numSegments() == 0 && !trace_data.stationary())
326 mooseAssert(!
_segment_mesh->query_node_ptr(node_id),
"Node already exists");
329 last_node->set_unique_id(node_id++);
332 if (trace_data.stationary())
334 mooseAssert(!
_segment_mesh->query_elem_ptr(elem_id),
"Elem already exists");
338 elem->set_node(0, last_node);
343 Elem * last_elem =
nullptr;
345 for (std::size_t i = 1; i < trace_data._point_data.size(); ++i)
347 const auto & point = trace_data._point_data[i]._point;
350 mooseAssert(!
_segment_mesh->query_node_ptr(node_id),
"Node already exists");
352 node->set_unique_id(node_id++);
355 mooseAssert(!
_segment_mesh->query_elem_ptr(elem_id),
"Elem already exists");
359 elem->set_node(0, last_node);
360 elem->set_node(1, node);
365 elem->set_neighbor(0, last_elem);
386 std::vector<Node *> need_node_owners;
389 const auto num_segments = trace_data.numSegments();
391 if (num_segments == 0)
395 startingIDs(trace_data, start_node_id, start_elem_id);
399 : (
unsigned long int)(trace_data._processor_crossings +
400 trace_data._trajectory_changes)) != 0)
413 need_node_owners.push_back(start_elem->
node_ptr(0));
421 if (!trace_data._last)
432 need_node_owners.push_back(end_elem->
node_ptr(1));
439 std::unordered_map<processor_id_type, std::vector<dof_id_type>> need_node_owners_sends;
440 for (
const Node * node : need_node_owners)
443 const auto neighbor_pid = neighbor_pid_bbox_pair.first;
444 const auto & neighbor_bbox = neighbor_pid_bbox_pair.second;
445 if (neighbor_bbox.contains_point(*node))
446 need_node_owners_sends[neighbor_pid].push_back(node->id());
454 std::unordered_map<processor_id_type, std::vector<dof_id_type>> confirm_node_owners_sends;
455 auto decide_node_owners_functor =
457 const std::vector<dof_id_type> & incoming_node_ids)
459 auto & confirm_pid = confirm_node_owners_sends[pid];
460 for (
const auto & node_id : incoming_node_ids)
467 confirm_pid.push_back(node_id);
473 Parallel::push_parallel_vector_data(
474 _communicator, need_node_owners_sends, decide_node_owners_functor);
479 for (
Node * node : need_node_owners)
480 if (!node->valid_processor_id())
490 TIME_SECTION(
"setupEquationSystem", 3,
"Setting Up Ray Tracing MeshOutput Equation System");
492 _es = std::make_unique<EquationSystems>(*_segment_mesh);
528 const auto get_data_vars = [
this](
const bool aux)
531 std::vector<std::pair<RayDataIndex, unsigned int>>
vars;
533 const auto from_names =
543 for (
const auto &
name : *from_names)
545 const auto data_index =
549 const std::string names_param = aux ?
"output_aux_data_names" :
"output_data_names";
550 const std::string data_prefix = aux ?
"aux " :
"";
551 paramError(names_param,
"The ray ", data_prefix,
"data '",
name,
"' is not registered");
554 const std::string var_prefix = aux ?
"aux_" :
"";
555 if (output_data_nodal)
560 vars.emplace_back(data_index, var_num);
576 TIME_SECTION(
"fillFields", 3,
"Filling RayTracing MeshOutput Fields");
579 const auto set_solution =
582 mooseAssert(dof,
"Nullptr dof");
592 [&set_solution](
const DofObject *
const dof,
const auto &
vars,
const auto & data)
594 mooseAssert(dof,
"Nullptr dof");
595 for (
const auto & [data_index, var_num] :
vars)
596 set_solution(dof, var_num, data[data_index]);
601 auto intersection = trace_data._intersections;
605 if (!trace_data.numSegments() && !trace_data.stationary())
618 const std::size_t start = trace_data.stationary() ? 0 : 1;
619 for (
const auto i :
make_range(start, trace_data._point_data.size()))
621 mooseAssert(elem,
"Nullptr elem");
624 set_solution(elem,
_ray_id_var, trace_data._ray_id);
627 if (!trace_data.stationary())
633 const auto & point_data = trace_data._point_data[i];
643 if (!trace_data.stationary())
655 TIME_SECTION(
"buildBoundingBoxes", 3,
"Building Bounding Boxes for RayTracing Mesh Output");
665 std::vector<std::pair<Point, Point>> bb_points = {
static_cast<std::pair<Point, Point>
>(
_bbox)};
671 pid_bbox.
scale(0.01);
701 start_node_id = begin_node_id + offset;
702 start_elem_id = begin_elem_id + offset;
void buildSegmentMesh()
Build the mesh that contains the ray tracing segments.
void fillFields()
Fill the Ray field data.
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
bool hasRayData() const
Whether or not any Ray data are registered.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
bool segmentsOnCacheTraces() const
Whether or not to cache individual element segments when _cache_traces = true.
void fill_data(std::map< processor_id_type, std::vector< std::set< unsigned int >>> &data, int M)
static const RayDataIndex INVALID_RAY_DATA_INDEX
Invalid index into a Ray's data.
const bool _output_data
Whether or not to output all of the Ray's data.
unsigned long int RayID
Type for a Ray's ID.
const unsigned int invalid_uint
const bool _output_data_nodal
Whether or not to output the Ray's data in a nodal, linear sense.
Data structure that stores information for output of a partial trace of a Ray on a processor...
void startingIDs(const TraceData &trace_data, dof_id_type &start_node_id, dof_id_type &start_elem_id) const
Gets the starting node and element IDs in the EDGE2 mesh for a given trace.
bool intersects(const BoundingBox &) const
const std::vector< TraceData > & getCachedTraces() const
Get the cached trace data structure.
const std::vector< std::string > & rayDataNames() const
The Ray data names.
const Parallel::Communicator & comm() const
std::vector< std::pair< RayDataIndex, unsigned int > > _data_vars
The ray data index -> variable index map.
const Parallel::Communicator & _communicator
std::unordered_map< RayID, std::pair< dof_id_type, dof_id_type > > _ray_starting_id_map
The map from RayID to the starting element and node ID of the mesh element for said Ray...
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
dof_id_type _max_node_id
The max node ID for the ray tracing mesh for creating unique elem IDs.
const RayTracingStudy & _study
The RayTracingStudy.
const unsigned long int _intersections
The number of intersections thus far.
bool _segmented_rays
Whether or not we have segmented rays.
virtual const std::string & name() const
auto max(const L &left, const R &right)
void buildIDMap()
Builds a map for each Ray to starting element and node ID for the EDGE2 mesh that will represent said...
RayDataIndex getRayAuxDataIndex(const std::string &name, const bool graceful=false) const
Gets the index associated with a registered value in the Ray aux data.
unsigned int variable_number(std::string_view var) const
processor_id_type size() const
uint8_t processor_id_type
unsigned int number() const
const bool _output_aux_data
Whether or not to output the Ray's aux data.
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
bool auxDataOnCacheTraces() const
Whether or not to store the Ray aux data on the cached Ray traces.
virtual unsigned int dimension() const
std::vector< std::pair< RayDataIndex, unsigned int > > _aux_data_vars
The ray aux data index -> variable index map.
bool valid_processor_id() const
const std::vector< std::string > *const _output_data_names
Specific Ray data to output.
std::unique_ptr< NumericVector< Number > > solution
static InputParameters validParams()
static InputParameters validParams()
void setupEquationSystem()
Setup the equation system that stores the segment-wise field data.
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
const std::vector< std::string > *const _output_aux_data_names
Specific Ray Aux data to output.
std::unique_ptr< libMesh::EquationSystems > _es
The EquationSystems.
dof_id_type neededNodes(const TraceData &trace_data) const
Gets the number of nodes needed to represent a given trace.
void paramError(const std::string ¶m, Args... args) const
const unsigned int _processor_crossings
Number of processor crossings thus far.
void set_neighbor(const unsigned int i, Elem *n)
unsigned int _intersections_var
The variable index in _sys for the intersection ID (if any)
void invalidate_processor_id()
const std::vector< std::string > & rayAuxDataNames() const
The Ray aux data names.
RayTracingMeshOutput(const InputParameters ¶meters)
virtual void outputMesh()=0
Output the mesh - to be overridden.
unsigned int _ray_id_var
The variable index in _sys for the Ray's ID (if any)
const Elem * neighbor_ptr(unsigned int i) const
libMesh::ExplicitSystem * _sys
The system that stores the field data.
std::vector< std::pair< processor_id_type, BoundingBox > > _inflated_neighbor_bboxes
Inflated bounding boxes that are neighboring to this processor (pid : bbox for each entry) ...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::unique_ptr< MeshBase > _segment_mesh
The mesh that contains the segments.
void max(const T &r, T &o, Request &req) const
const unsigned int _trajectory_changes
Number of trajectory changes thus far.
const Node * node_ptr(const unsigned int i) const
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
const RayID _ray_id
The Ray ID.
const InputParameters & _pars
std::vector< BoundingBox > _inflated_bboxes
The inflated bounding boxes for all processors.
BoundingBox _bbox
The bounding box for this processor.
std::vector< TracePointData > _point_data
The data for each point along the track.
void scale(const Real factor)
processor_id_type processor_id() const
unsigned int _processor_crossings_var
The variable index in _sys for the Ray's processor crossings (if any)
processor_id_type processor_id() const
bool dataOnCacheTraces() const
Whether or not to store the Ray data on the cached Ray traces.
RayDataIndex getRayDataIndex(const std::string &name, const bool graceful=false) const
Gets the index associated with a registered value in the Ray data.
unsigned int _pid_var
The variable index in _sys for the Ray's processor id (if any)
void ErrorVector unsigned int
void buildBoundingBoxes()
Build the inflated neighbor bounding boxes stored in _inflated_neighbor_bboxes for the purposes of id...
virtual std::string filename() override
unsigned int _trajectory_changes_var
The variable index in _sys for the Ray's trajectory changes (if any)
Base class for Ray tracing studies that will generate Rays and then propagate all of them to terminat...
const RemoteElem * remote_elem