https://mooseframework.inl.gov
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"
25 #include "RayTracingPackingUtils.h"
26 
27 using namespace libMesh;
28 
29 registerMooseObject("HeatTransferApp", ViewFactorRayStudy);
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>(
139  _mesh.dimension(),
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 
149 void
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 
207 void
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 
222 void
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 
244 void
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 
390 void
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 
405 Real
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 
418 void
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)
447  mooseError(
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 
504 namespace libMesh
505 {
506 namespace Parallel
507 {
508 
509 unsigned 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 
522 unsigned int
523 Packing<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 
529 unsigned 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 
537 template <>
539 Packing<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 
577 template <>
578 void
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
bool hasRayKernels(const THREAD_ID tid)
Whether or not there are currently any active RayKernel objects.
static void gaussLegendre(const unsigned int order, std::vector< Real > &x, std::vector< Real > &w)
Builds Gauss-Legendre quadrature on 0, 1, with weights that sum to 1.
Order
unsigned int n_threads()
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
virtual void initialSetup() override
const Elem * _start_elem
The element the trace will start from.
const std::set< BoundaryID > _bnd_ids
The user supplied boundary IDs we need view factors on.
MooseMesh & _mesh
The Mesh.
void initialSetup() override
std::vector< StartElem > _start_elems
The StartElem objects that this proc needs to spawn Rays from.
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.
void mooseInfo(Args &&... args) const
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.
T stringToEnum(const std::string &s)
Converts a string to an enum.
QuadratureType
std::vector< Real > _2d_aq_weights
const Parallel::Communicator & _communicator
void postExecuteStudy() override
Entry point after study execution.
std::unique_ptr< RayTracingAngularQuadrature > _3d_aq
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
ViewFactorRayStudy(const InputParameters &parameters)
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.
void preExecuteStudy() override
Entry point before study execution.
static T unpack(BufferIter in, Context *ctx)
const std::unique_ptr< libMesh::QBase > _q_face
Face quadrature used for _fe_face.
static unsigned int packable_size(const T &object, const Context *context)
std::vector< Real > _weights
The weights associated with each point.
RayBC that reflects a Ray.
Definition: ReflectRayBC.h:17
std::vector< Point > _points
The points on start_elem to spawn Rays from.
RayTracingStudy used to generate Rays for view factor computation using the angular quadrature method...
std::map< BoundaryID, std::map< BoundaryID, Real > > _vf_info
Cumulative view factor information; [from_bid][to_bid] = val.
RayBC used in the computation of view factors using the angular quadrature ray tracing method...
uint8_t processor_id_type
TypeVector< Real > unit() const
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.
static InputParameters validParams()
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
TET4
const std::unique_ptr< libMesh::FEBase > _fe_face
Face FE used for creating face quadrature points and weights.
const Elem * _elem
The element the points originate from.
const std::vector< double > x
virtual unsigned int dimension() const
unsigned int which_neighbor_am_i(const Elem *e) const
boundary_id_type BoundaryID
static unsigned int packed_size(BufferIter iter)
const RayDataIndex _ray_index_start_total_weight
Index in the Ray aux data for the starting total weight (dot * qp weight)
void reserveRayBuffer(const std::size_t size)
Reserve size entires in the Ray buffer.
const std::string & type() const
static InputParameters validParams()
libMesh::Real distanceFromLine(const libMesh::Point &pt, const libMesh::Point &line0, const libMesh::Point &line1)
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
const std::string _name
static void pack(const T &object, OutputIter data_out, const Context *context)
const RayDataIndex _ray_index_start_bnd_id
Index in the Ray aux data for the starting boundary ID.
bool sideIsNonPlanar(const Elem *elem, const unsigned short s) const
Whether or not the side on elem elem is non-planar.
registerMooseObject("HeatTransferApp", ViewFactorRayStudy)
Data structure used for storing all of the information needed to spawn Rays from a single element...
const Elem * neighbor_ptr(unsigned int i) const
virtual const Point & getSideNormal(const Elem *elem, const unsigned short side, const THREAD_ID tid)
Get the outward normal for a given element side.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool currentlyPropagating() const
Whether or not the study is propagating (tracing Rays)
const MooseEnum _internal_convention
The convention for spawning rays from internal sidesets.
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 mooseError(Args &&... args) const
MeshBase & meshBase() const
Access to the libMesh MeshBase.
const processor_id_type _pid
The rank of this processor (this actually takes time to lookup - so just do it once) ...
BoundaryID _bnd_id
The boundary ID associated with this start elem.
void moveRayToBuffer(std::shared_ptr< Ray > &ray)
Moves a ray to the buffer to be traced during generateRays().
Real viewFactorInfo(const BoundaryID from_id, const BoundaryID to_id) const
Accessor for the finalized view factor info.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< Real > _2d_aq_angles
angular quadrature info
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement *> * getBoundaryElementRange()
const ConsoleStream _console
unsigned short int _incoming_side
The incoming side on start_elem that the trace will start from.
Base class for the RayBC syntax.
void generateRays() override
Subclasses should override this to determine how to generate Rays.
bool active() const
processor_id_type processor_id() const
virtual ElemType type() const=0
unsigned int THREAD_ID
Base class for Ray tracing studies that will generate Rays and then propagate all of them to terminat...