https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ViewFactorRayStudy.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "ViewFactorRayStudy.h"
11
12// Local includes
13#include "ViewFactorRayBC.h"
14#include "GeometryUtils.h"
15
16// libMesh includes
17#include "libmesh/parallel_algebra.h"
18#include "libmesh/parallel_sync.h"
19#include "libmesh/enum_quadrature_type.h"
20#include "libmesh/fe_base.h"
21#include "libmesh/quadrature.h"
22
23// Ray tracing includes
24#include "ReflectRayBC.h"
26
27using namespace libMesh;
28
30
33{
34 auto params = RayTracingStudy::validParams();
35
36 params.addRequiredParam<std::vector<BoundaryName>>(
37 "boundary", "The list of boundaries where view factors are desired");
38
39 MooseEnum qorders("CONSTANT FIRST SECOND THIRD FOURTH FIFTH SIXTH SEVENTH EIGHTH NINTH TENTH "
40 "ELEVENTH TWELFTH THIRTEENTH FOURTEENTH FIFTEENTH SIXTEENTH SEVENTEENTH "
41 "EIGHTTEENTH NINTEENTH TWENTIETH",
42 "CONSTANT");
43 params.addParam<MooseEnum>("face_order", qorders, "The face quadrature rule order");
44
45 MooseEnum qtypes("GAUSS GRID", "GRID");
46 params.addParam<MooseEnum>("face_type", qtypes, "The face quadrature type");
47
48 MooseEnum convention("positive=0 negative=1", "positive");
49 params.addParam<MooseEnum>(
50 "internal_convention",
51 convention,
52 "The convention for spawning rays from internal sidesets; denotes the sign of the dot "
53 "product between a ray and the internal sideset side normal");
54
55 params.addParam<unsigned int>(
56 "polar_quad_order",
57 16,
58 "Order of the polar quadrature [polar angle is between ray and normal]. Must be even.");
59 params.addParam<unsigned int>(
60 "azimuthal_quad_order",
61 8,
62 "Order of the azimuthal quadrature per quadrant [azimuthal angle is measured in "
63 "a plane perpendicular to the normal].");
64
65 // Shouldn't ever need RayKernels for view factors
66 params.set<bool>("ray_kernel_coverage_check") = false;
67 params.suppressParameter<bool>("ray_kernel_coverage_check");
68
69 // So that the study executes before the RayTracingViewFactor
70 params.set<bool>("force_preaux") = true;
71 params.suppressParameter<bool>("force_preaux");
72
73 // Need to use internal sidesets
74 params.set<bool>("use_internal_sidesets") = true;
75 params.suppressParameter<bool>("use_internal_sidesets");
76
77 // Don't verify Rays in opt mode by default - it's expensive
78 params.set<bool>("verify_rays") = false;
79
80 // No need to use Ray registration
81 params.set<bool>("_use_ray_registration") = false;
82 // Do not need to bank Rays on completion
83 params.set<bool>("_bank_rays_on_completion") = false;
84
85 params.addClassDescription(
86 "This ray study is used to compute view factors in cavities with obstruction. It sends out "
87 "rays from surfaces bounding the radiation cavity into a set of directions determined by an "
88 "angular quadrature. The rays are tracked and view factors are computed by determining the "
89 "surface where the ray dies.");
90 return params;
91}
92
94 : RayTracingStudy(parameters),
95 _bnd_ids_vec(_mesh.getBoundaryIDs(getParam<std::vector<BoundaryName>>("boundary"))),
96 _bnd_ids(_bnd_ids_vec.begin(), _bnd_ids_vec.end()),
97 _internal_convention(getParam<MooseEnum>("internal_convention")),
98 _ray_index_start_bnd_id(registerRayAuxData("start_bnd_id")),
99 _ray_index_start_total_weight(registerRayAuxData("start_total_weight")),
100 _fe_face(FEBase::build(_mesh.dimension(), FEType(CONSTANT, MONOMIAL))),
101 _q_face(QBase::build(Moose::stringToEnum<QuadratureType>(getParam<MooseEnum>("face_type")),
102 _mesh.dimension() - 1,
103 Moose::stringToEnum<Order>(getParam<MooseEnum>("face_order")))),
104 _is_3d(_mesh.dimension() == 3),
105 _threaded_vf_info(libMesh::n_threads())
106{
107 _fe_face->attach_quadrature_rule(_q_face.get());
108 _fe_face->get_xyz();
109
110 // create angular quadrature
111 if (!_is_3d)
112 {
113 // In 2D, we integrate over angle theta instead of mu = cos(theta)
114 // The integral over theta is approximated using a Gauss Legendre
115 // quadrature. The integral we need to approximate is given by:
116 //
117 // int_{-pi/2}^{pi/2} cos(theta) d theta
118 //
119 // We get abscissae x and weight w for range of integration
120 // from 0 to 1 and then rescale it to the integration range
121 //
122 std::vector<Real> x;
123 std::vector<Real> w;
125 2 * getParam<unsigned int>("polar_quad_order"), x, w);
126
127 _2d_aq_angles.resize(x.size());
128 _2d_aq_weights.resize(x.size());
129 for (unsigned int j = 0; j < x.size(); ++j)
130 {
131 _2d_aq_angles[j] = (2 * x[j] - 1) * M_PI / 2;
132 _2d_aq_weights[j] = w[j] * M_PI;
133 }
134 _num_dir = _2d_aq_angles.size();
135 }
136 else
137 {
138 _3d_aq = std::make_unique<RayTracingAngularQuadrature>(
140 getParam<unsigned int>("polar_quad_order"),
141 4 * getParam<unsigned int>("azimuthal_quad_order"),
142 /* mu_min = */ 0,
143 /* mu_max = */ 1);
144
145 _num_dir = _3d_aq->numDirections();
146 }
147}
148
149void
151{
153
154 // We optimized away RayKernels, so don't allow them
155 if (hasRayKernels(/* tid = */ 0))
156 mooseError("Not compatible with RayKernels.");
157
158 // RayBC coverage checks (at least one ViewFactorRayBC and optionally a ReflectRayBC
159 // on ONLY external boundaries).
160 std::vector<RayBoundaryConditionBase *> ray_bcs;
161 RayTracingStudy::getRayBCs(ray_bcs, 0);
162 unsigned int vf_bc_count = 0;
163 for (RayBoundaryConditionBase * rbc : ray_bcs)
164 {
165 auto view_factor_bc = dynamic_cast<ViewFactorRayBC *>(rbc);
166 if (view_factor_bc)
167 {
168 ++vf_bc_count;
169
170 if (!view_factor_bc->hasBoundary(_bnd_ids))
171 mooseError("The boundary restriction of ",
172 rbc->type(),
173 " '",
174 rbc->name(),
175 "' does not match 'boundary'");
176 }
177 else
178 {
179 auto reflect_bc = dynamic_cast<ReflectRayBC *>(rbc);
180 if (reflect_bc)
181 {
182 if (reflect_bc->hasBoundary(_bnd_ids))
183 mooseError("The boundaries applied in ReflectRayBC '",
184 rbc->name(),
185 "' cannot include any of the boundaries in ",
186 type());
187
188 for (const BoundaryID internal_bnd_id : getInternalSidesets())
189 if (reflect_bc->hasBoundary(internal_bnd_id))
190 mooseError("The ReflectRayBC '",
191 rbc->name(),
192 "' is defined on an internal boundary (",
193 internal_bnd_id,
194 ").\n\n",
195 "This is not allowed for view factor computation.");
196 }
197 else
198 mooseError("Does not support the ",
199 rbc->type(),
200 " ray boundary condition.\nSupported RayBCs: ReflectRayBC and ViewFactorRayBC.");
201 }
202 if (vf_bc_count != 1)
203 mooseError("Requires one and only one ViewFactorRayBC.");
204 }
205}
206
207void
209{
210 // Clear and zero the view factor maps we're about to accumulate into for each thread
211 for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
212 {
213 _threaded_vf_info[tid].clear();
214 for (const BoundaryID from_id : _bnd_ids)
215 for (const BoundaryID to_id : _bnd_ids)
216 _threaded_vf_info[tid][from_id][to_id] = 0;
217 }
218
220}
221
222void
224{
225 // Finalize the cumulative _vf_info;
226 _vf_info.clear();
227 for (const BoundaryID from_id : _bnd_ids)
228 for (const BoundaryID to_id : _bnd_ids)
229 {
230 Real & entry = _vf_info[from_id][to_id];
231
232 // Zero before summing
233 entry = 0;
234
235 // Sum over threads
236 for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
237 entry += _threaded_vf_info[tid][from_id][to_id];
238
239 // Sum over processors
240 _communicator.sum(entry);
241 }
242}
243
244void
246{
247 TIME_SECTION("generateRays", 3, "ViewFactorRayStudy Generating Rays");
248
249 // Determine number of Rays and points to allocate space before generation and for output
250 std::size_t num_local_rays = 0;
251 std::size_t num_local_start_points = 0;
252 for (const auto & start_elem : _start_elems)
253 {
254 num_local_start_points += start_elem._points.size();
255 num_local_rays += start_elem._points.size() * _num_dir;
256 }
257
258 // Print out totals while we're here
259 std::size_t num_total_points = num_local_start_points;
260 std::size_t num_total_rays = num_local_rays;
261 _communicator.sum(num_total_points);
262 _communicator.sum(num_total_rays);
263 _console << "ViewFactorRayStudy generated " << num_total_points
264 << " points with an angular quadrature of " << _num_dir
265 << " directions per point requiring " << num_total_rays << " rays" << std::endl;
266
267 // Reserve space in the buffer ahead of time before we fill it
268 reserveRayBuffer(num_local_rays);
269
270 Point direction;
271 unsigned int num_rays_skipped = 0;
272
273 // loop through all starting points and spawn rays from each for each point and angle
274 for (const auto & start_elem : _start_elems)
275 {
276 // Get normal for the element we're starting on
277 auto inward_normal =
278 getSideNormal(start_elem._start_elem, start_elem._incoming_side, /* tid = */ 0);
279 // We actually want the normal of the original element (remember that we may swap starting
280 // elements to the element on the other face per requirements of the ray tracer)
281 if (start_elem._start_elem != start_elem._elem)
282 inward_normal *= -1;
283 // Lastly, if the boundary is external and the internal convention is positive, we must
284 // switch the normal because our AQ uses the inward normal
285 if (_internal_convention == 0 &&
286 !start_elem._start_elem->neighbor_ptr(start_elem._incoming_side))
287 inward_normal *= -1;
288
289 // Rotation for the quadrature to align with the normal; in 3D we can do all of this
290 // once up front using the 3D aq object. For 2D, we will do it within the direction loop
291 if (_is_3d)
292 _3d_aq->rotate(inward_normal);
293
294 // Loop through all points and then all directions
295 for (std::size_t start_i = 0; start_i < start_elem._points.size(); ++start_i)
296 for (std::size_t l = 0; l < _num_dir; ++l)
297 {
298 // Get direction of the ray; in 3D we already rotated, in 2D we rotate here
299 if (_is_3d)
300 direction = _3d_aq->getDirection(l);
301 else
302 {
303 const Real sin_theta = std::sin(_2d_aq_angles[l]);
304 const Real cos_theta = std::cos(_2d_aq_angles[l]);
305 direction(0) = cos_theta * inward_normal(0) - sin_theta * inward_normal(1);
306 direction(1) = sin_theta * inward_normal(0) + cos_theta * inward_normal(1);
307 direction(2) = 0;
308 }
309
310 // Angular weight function differs in 2D/3D
311 // 2D: the quadrature abscissae are the angles between direction & normal.
312 // The integrand is the cosine of that angle
313 // 3D: the quadrature abscissae are the azimuthal angle phi and the cosine of the angle
314 // between normal and direction (= mu). The integrand is mu in that case.
315 const auto awf = _is_3d ? inward_normal * direction * _3d_aq->getTotalWeight(l)
316 : std::cos(_2d_aq_angles[l]) * _2d_aq_weights[l];
317 const auto start_weight = start_elem._weights[start_i] * awf;
318
319 // Skip the ray if it exists the domain through the non-planar side it is starting from.
320 // We do not expect there are any neighbor elements to track it on if it exits the
321 // non-planar side.
322 bool intersection_found = false;
323 if (_is_3d && start_elem._start_elem &&
324 !start_elem._start_elem->neighbor_ptr(start_elem._incoming_side) &&
325 sideIsNonPlanar(start_elem._start_elem, start_elem._incoming_side))
326 {
327 // Find edge on side that is 'in front' of the future ray
328 Point intersection_point(std::numeric_limits<Real>::max(), -1, -1);
329 const auto side_elem = start_elem._start_elem->side_ptr(start_elem._incoming_side);
330 Point proj_dir;
331 for (const auto edge_i : side_elem->side_index_range())
332 {
333 const auto edge_1 = side_elem->side_ptr(edge_i);
334 // Project direction onto (start_point, node 1, node 2)
335 const auto d1 = *edge_1->node_ptr(0) - start_elem._points[start_i];
336 const auto d2 = *edge_1->node_ptr(1) - start_elem._points[start_i];
337 const auto d1_unit = d1.unit();
338 const auto d2_unit = d2.unit();
339 // If the starting point is aligned with the edge, it wont cross it
340 if (MooseUtils::absoluteFuzzyEqual(std::abs(d1_unit * d2_unit), 1))
341 continue;
342 const auto normal = (d1_unit.cross(d2_unit)).unit();
343
344 // One of the nodes must be in front of the start point following the direction
345 if (d1 * direction < 0 && d2 * direction < 0)
346 continue;
347
348 proj_dir = (direction - (direction * normal) * normal).unit();
349
350 // Only the side of interest will have the projected direction in between d1 and d2
351 if ((proj_dir * d2_unit > d1_unit * d2_unit) &&
352 (proj_dir * d1_unit > d1_unit * d2_unit))
353 {
354 const auto dist = geom_utils::distanceFromLine(
355 start_elem._points[start_i], *edge_1->node_ptr(0), *edge_1->node_ptr(1));
356 // Ortho-normalize the base on the plane
357 intersection_point = start_elem._points[start_i] + dist * proj_dir;
358 intersection_found = true;
359 break;
360 }
361 }
362
363 // Skip the ray if it goes out of the element
364 const auto grazing_dir = (intersection_point - start_elem._points[start_i]).unit();
365 if (intersection_found && inward_normal * direction < inward_normal * grazing_dir)
366 {
367 num_rays_skipped++;
368 continue;
369 }
370 }
371
372 // Acquire a Ray and fill with the starting information
373 std::shared_ptr<Ray> ray = acquireRay();
374 ray->setStart(
375 start_elem._points[start_i], start_elem._start_elem, start_elem._incoming_side);
376 ray->setStartingDirection(direction);
377 ray->auxData(_ray_index_start_bnd_id) = start_elem._bnd_id;
378 ray->auxData(_ray_index_start_total_weight) = start_weight;
379
380 // Move the Ray into the buffer to be traced
381 moveRayToBuffer(ray);
382 }
383 }
384 if (num_rays_skipped)
385 mooseInfo(num_rays_skipped,
386 " rays were skipped as they exited the mesh at their starting point through "
387 "non-planar sides.");
388}
389
390void
392 const BoundaryID from_id,
393 const BoundaryID to_id,
394 const THREAD_ID tid)
395{
396 mooseAssert(currentlyPropagating(), "Can only be called during Ray tracing");
397 mooseAssert(_threaded_vf_info[tid].count(from_id),
398 "Threaded view factor info does not have from boundary");
399 mooseAssert(_threaded_vf_info[tid][from_id].count(to_id),
400 "Threaded view factor info does not have from -> to boundary");
401
402 _threaded_vf_info[tid][from_id][to_id] += value;
403}
404
405Real
407{
408 auto it = _vf_info.find(from_id);
409 if (it == _vf_info.end())
410 mooseError("From boundary id ", from_id, " not in view factor map.");
411
412 auto itt = it->second.find(to_id);
413 if (itt == it->second.end())
414 mooseError("From boundary id ", from_id, " to boundary_id ", to_id, " not in view factor map.");
415 return itt->second;
416}
417
418void
420{
421 const auto & points = _fe_face->get_xyz();
422 const auto & weights = _fe_face->get_JxW();
423
424 // Clear before filling
425 _start_elems.clear();
426
427 // Starting elements we have that are on the wrong side of an internal boundary
428 std::unordered_map<processor_id_type, std::vector<StartElem>> send_start_map;
429
430 // Get all possible points on the user defined boundaries on this proc
431 for (const BndElement * belem : *_mesh.getBoundaryElementRange())
432 {
433 const Elem * elem = belem->_elem;
434 const auto side = belem->_side;
435 const auto bnd_id = belem->_bnd_id;
436
437 // Skip if we don't own you
438 if (elem->processor_id() != _pid)
439 continue;
440
441 // Skip if the boundary id isn't one we're looking for
442 if (!_bnd_ids.count(bnd_id))
443 continue;
444
445 // Sanity check on QGRID not working on some types
446 if (_q_face->type() == libMesh::QGRID && elem->type() == TET4)
448 "Cannot use GRID quadrature type with tetrahedral elements in ViewFactorRayStudy '",
449 _name,
450 "'");
451
452 // The elem/side that we will actually start the trace from
453 // (this may change on internal sidesets)
454 const Elem * start_elem = elem;
455 auto start_side = side;
456
457 // Reinit this face for points
458 _fe_face->reinit(elem, side);
459
460 // See if this boundary is internal
461 const Elem * neighbor = elem->neighbor_ptr(side);
462 if (neighbor)
463 {
464 if (!neighbor->active())
465 mooseError(type(), " does not work with adaptivity");
466
467 // With the positive convention, the Rays that we want to spawn from internal boundaries
468 // have positive dot products with the outward normal on the side. The ray-tracer requires
469 // that we provide an element incoming side that is actually incoming (the dot product with
470 // the direction and the normal is negative). Therefore, switch the physical trace to start
471 // from the other element and the corresponding side
472 if (_internal_convention == 0)
473 {
474 start_elem = neighbor;
475 start_side = neighbor->which_neighbor_am_i(elem);
476 }
477 }
478
479 // If we own the true starting elem, add to our start info. Otherwise, package the
480 // start info to be sent to the processor that will actually start this trace
481 const auto start_pid = start_elem->processor_id();
482 auto & add_to = _pid ? _start_elems : send_start_map[start_pid];
483 add_to.emplace_back(elem, start_elem, start_side, bnd_id, points, weights);
484 }
485
486 // If the internal convention is positive, we may have points that we switched to another
487 // element for the actual trace, so communicate those to the processors that will
488 // actually be starting them
489 if (_internal_convention == 0)
490 {
491 // Functor that takes in StartElems and appends them to our local list
492 auto append_start_elems = [this](processor_id_type, const std::vector<StartElem> & start_elems)
493 {
494 _start_elems.reserve(_start_elems.size() + start_elems.size());
495 for (const StartElem & start_elem : start_elems)
496 _start_elems.emplace_back(start_elem);
497 };
498
499 // Communicate and act on data
500 Parallel::push_parallel_packed_range(_communicator, send_start_map, this, append_start_elems);
501 }
502}
503
504namespace libMesh
505{
506namespace Parallel
507{
508
509unsigned int
511{
512 // Number of points, elem_id, start_elem_id, incoming_side, bnd_id
513 unsigned int total_size = 5;
514 // Points
515 total_size += num_points * 3;
516 // Weights
517 total_size += num_points;
518
519 return total_size;
520}
521
522unsigned int
523Packing<ViewFactorRayStudy::StartElem>::packed_size(typename std::vector<Real>::const_iterator in)
524{
525 const std::size_t num_points = *in++;
526 return packing_size(num_points);
527}
528
529unsigned int
531 const ViewFactorRayStudy::StartElem & start_elem, const void *)
532{
533 mooseAssert(start_elem._points.size() == start_elem._weights.size(), "Size mismatch");
534 return packing_size(start_elem._points.size());
535}
536
537template <>
539Packing<ViewFactorRayStudy::StartElem>::unpack(std::vector<Real>::const_iterator in,
540 ViewFactorRayStudy * study)
541{
542 // StartElem to fill into
544
545 // Number of points
546 const std::size_t num_points = static_cast<std::size_t>(*in++);
547
548 // Elem id
549 RayTracingPackingUtils::unpack(start_elem._elem, *in++, &study->meshBase());
550
551 // Start elem id
552 RayTracingPackingUtils::unpack(start_elem._start_elem, *in++, &study->meshBase());
553
554 // Incoming side
555 start_elem._incoming_side = static_cast<unsigned short>(*in++);
556
557 // Boundary ID
558 start_elem._bnd_id = static_cast<BoundaryID>(*in++);
559
560 // Points
561 start_elem._points.resize(num_points);
562 for (std::size_t i = 0; i < num_points; ++i)
563 {
564 start_elem._points[i](0) = *in++;
565 start_elem._points[i](1) = *in++;
566 start_elem._points[i](2) = *in++;
567 }
568
569 // Weights
570 start_elem._weights.resize(num_points);
571 for (std::size_t i = 0; i < num_points; ++i)
572 start_elem._weights[i] = *in++;
573
574 return start_elem;
575}
576
577template <>
578void
580 std::back_insert_iterator<std::vector<Real>> data_out,
581 const ViewFactorRayStudy * study)
582{
583 // Number of points
584 data_out = static_cast<buffer_type>(start_elem._points.size());
585
586 // Elem id
587 data_out = RayTracingPackingUtils::pack<buffer_type>(start_elem._elem, &study->meshBase());
588
589 // Start elem id
590 data_out = RayTracingPackingUtils::pack<buffer_type>(start_elem._start_elem, &study->meshBase());
591
592 // Incoming side
593 data_out = static_cast<buffer_type>(start_elem._incoming_side);
594
595 // Boundary id
596 data_out = static_cast<buffer_type>(start_elem._bnd_id);
597
598 // Points
599 for (const auto & point : start_elem._points)
600 {
601 data_out = point(0);
602 data_out = point(1);
603 data_out = point(2);
604 }
605
606 // Weights
607 std::copy(start_elem._weights.begin(), start_elem._weights.end(), data_out);
608}
609
610} // namespace Parallel
611
612} // namespace libMesh
boundary_id_type BoundaryID
const std::vector< double > x
unsigned int THREAD_ID
unsigned int count
registerMooseObject("HeatTransferApp", ViewFactorRayStudy)
const ConsoleStream _console
const std::string & type() const
void mooseError(Args &&... args) const
const std::string & _name
void mooseInfo(Args &&... args) const
virtual unsigned int dimension() const
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
Base class for the RayBC syntax.
static void gaussLegendre(const unsigned int order, std::vector< Real > &x, std::vector< Real > &w)
Builds Gauss-Legendre quadrature on [0, 1] (symmetric about 0.5), with weights that sum to 1.
Base class for Ray tracing studies that will generate Rays and then propagate all of them to terminat...
MeshBase & meshBase() const
Access to the libMesh MeshBase.
bool sideIsNonPlanar(const Elem *elem, const unsigned short s) const
Whether or not the side \s on elem elem is non-planar.
virtual void initialSetup() override
static InputParameters validParams()
MooseMesh & _mesh
The Mesh.
void moveRayToBuffer(std::shared_ptr< Ray > &ray)
Moves a ray to the buffer to be traced during generateRays().
void reserveRayBuffer(const std::size_t size)
Reserve size entires in the Ray buffer.
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::shared_ptr< Ray > acquireRay()
User APIs for constructing Rays within the RayTracingStudy.
const std::set< BoundaryID > & getInternalSidesets() const
Gets the internal sidesets (that have RayBCs) within the local domain.
void getRayBCs(std::vector< RayBoundaryConditionBase * > &result, BoundaryID id, THREAD_ID tid)
Fills the active RayBCs associated with this study and a boundary into result.
const processor_id_type _pid
The rank of this processor (this actually takes time to lookup - so just do it once)
bool hasRayKernels(const THREAD_ID tid)
Whether or not there are currently any active RayKernel objects.
bool currentlyPropagating() const
Whether or not the study is propagating (tracing Rays)
RayBC that reflects a Ray.
RayBC used in the computation of view factors using the angular quadrature ray tracing method.
RayTracingStudy used to generate Rays for view factor computation using the angular quadrature method...
void addToViewFactorInfo(Real value, const BoundaryID from_id, const BoundaryID to_id, const THREAD_ID tid)
Adds into the view factor info; to be used in ViewFactorRayBC.
std::map< BoundaryID, std::map< BoundaryID, Real > > _vf_info
Cumulative view factor information; [from_bid][to_bid] = val.
const std::set< BoundaryID > _bnd_ids
The user supplied boundary IDs we need view factors on.
void initialSetup() override
const RayDataIndex _ray_index_start_bnd_id
Index in the Ray aux data for the starting boundary ID.
std::vector< StartElem > _start_elems
The StartElem objects that this proc needs to spawn Rays from.
static InputParameters validParams()
Real viewFactorInfo(const BoundaryID from_id, const BoundaryID to_id) const
Accessor for the finalized view factor info.
ViewFactorRayStudy(const InputParameters &parameters)
std::unique_ptr< RayTracingAngularQuadrature > _3d_aq
const std::unique_ptr< libMesh::FEBase > _fe_face
Face FE used for creating face quadrature points and weights.
void generateRays() override
Subclasses should override this to determine how to generate Rays.
const std::unique_ptr< libMesh::QBase > _q_face
Face quadrature used for _fe_face.
void postExecuteStudy() override
Entry point after study execution.
void preExecuteStudy() override
Entry point before study execution.
std::vector< Real > _2d_aq_angles
angular quadrature info
const MooseEnum _internal_convention
The convention for spawning rays from internal sidesets.
std::vector< Real > _2d_aq_weights
const RayDataIndex _ray_index_start_total_weight
Index in the Ray aux data for the starting total weight (dot * qp weight)
std::vector< std::unordered_map< BoundaryID, std::unordered_map< BoundaryID, Real > > > _threaded_vf_info
View factor information by tid and then from/to pair; [tid][from_bid][to_bid] = val.
processor_id_type processor_id() const
bool active() const
unsigned int which_neighbor_am_i(const Elem *e) const
virtual ElemType type() const=0
const Elem * neighbor_ptr(unsigned int i) const
const Parallel::Communicator & _communicator
std::pair< T1, T2 > unpack(BufferIter in, Context *ctx)
static unsigned int packed_size(BufferIter iter)
unsigned int packable_size(const std::pair< T1, T2 > &pr, const Context *ctx)
void pack(const std::pair< T1, T2 > &pr, OutputIter data_out, const Context *ctx)
TypeVector< Real > unit() const
void unpack(const BufferType value_as_buffer_type, ValueType &value)
Unpacks value_as_buffer_type (which is packed with pack()) into value at a byte level.
libMesh::Real distanceFromLine(const libMesh::Point &pt, const libMesh::Point &line0, const libMesh::Point &line1)
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
unsigned int n_threads()
Data structure used for storing all of the information needed to spawn Rays from a single element.
const Elem * _start_elem
The element the trace will start from.
std::vector< Point > _points
The points on start_elem to spawn Rays from.
const Elem * _elem
The element the points originate from.
unsigned short int _incoming_side
The incoming side on start_elem that the trace will start from.
std::vector< Real > _weights
The weights associated with each point.
BoundaryID _bnd_id
The boundary ID associated with this start elem.