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