16#include "libmesh/dense_vector.h"
19 const unsigned int polar_order,
20 const unsigned int azimuthal_order,
24 _polar_order(polar_order),
25 _azimuthal_order(azimuthal_order),
30 mooseError(
"polar_order must be positive in RayTracingAngularQuadrature");
32 mooseError(
"azimuthal_order must be positive in RayTracingAngularQuadrature");
34 mooseError(
"mu_min must be < mu_max in RayTracingAngularQuadrature");
36 mooseError(
"mu_min must be >= -1 in RayTracingAngularQuadrature");
38 mooseError(
"mu_max must be <= 1 in RayTracingAngularQuadrature");
40 mooseError(
"RayTracingAngularQuadrature only supports dimensions 2 and 3");
58 std::vector<Real> gauss_legendre_x;
59 std::vector<Real> gauss_legendre_w;
67 for (std::size_t i = 0; i < chebyshev_x.size(); ++i)
68 for (std::size_t j = 0; j < gauss_legendre_x.size(); ++j)
71 if (
_dim == 2 && gauss_legendre_x[j] < 0.5 - TOLERANCE * TOLERANCE)
74 _phi.push_back(chebyshev_x[i]);
78 const Real weight_factor =
79 (
_dim == 2 && !MooseUtils::absoluteFuzzyEqual(gauss_legendre_x[j], 0.5)) ? 2.0 : 1.0;
80 _w.push_back(weight_factor * chebyshev_w[i] * gauss_legendre_w[j]);
86 std::vector<Real> &
x,
87 std::vector<Real> & w)
90 mooseError(
"Order must be positive in gaussLegendre()");
99 for (
unsigned int i = 1; i < order; ++i)
102 mat(i, i - 1) = ri / std::sqrt(((2. * ri - 1.) * (2. * ri + 1.)));
103 mat(i - 1, i) = mat(i, i - 1);
107 for (
unsigned int i = 0; i < order; ++i)
109 x[i] = 0.5 * (lambda(i) + 1.0);
110 w[i] = vec(0, i) * vec(0, i);
114 std::vector<std::size_t> sorted_indices(
x.size());
115 std::iota(sorted_indices.begin(), sorted_indices.end(), 0);
116 std::stable_sort(sorted_indices.begin(),
117 sorted_indices.end(),
118 [&
x](
size_t i1,
size_t i2) { return x[i1] < x[i2]; });
119 const auto x_copy =
x;
120 const auto w_copy = w;
121 for (std::size_t i = 0; i <
x.size(); ++i)
123 x[i] = x_copy[sorted_indices[i]];
124 w[i] = w_copy[sorted_indices[i]];
149 for (std::size_t q = 0; q <
_phi.size(); ++q)
152 omega(0) = sqrt(1 -
_mu[q] *
_mu[q]) * cos(
_phi[q]);
153 omega(1) = sqrt(1 -
_mu[q] *
_mu[q]) * sin(
_phi[q]);
158 direction(0) = omega_p(0);
159 direction(1) = omega_p(1);
160 direction(2) = omega_p(2);
175 direction /= direction.norm();
194 mooseAssert(
_dim == 2,
"Should only have duplicates in 2D");
209const std::vector<Real> &
223const std::vector<Real> &
243 mooseError(
"RayTracingAngularQuadrature does not have direction ", l);
248 std::vector<Real> &
x,
249 std::vector<Real> & w)
254 for (std::size_t i = 0; i < order; ++i)
256 x[i] = 2 * (Real)i * M_PI / (Real)order;
257 w[i] = 2 * M_PI / (Real)order;
273 for (
unsigned int j = 0; j < 3; ++j)
275 matrix(j, 0) = tx(j);
276 matrix(j, 1) = ty(j);
277 matrix(j, 2) = direction(j);
284 if (MooseUtils::absoluteFuzzyLessEqual(
v.norm(), 0))
285 ::mooseError(
"Vector v has norm close to 0 in orthonormalVector()");
287 if (MooseUtils::absoluteFuzzyEqual(
v(0), 0))
289 if (MooseUtils::absoluteFuzzyEqual(
v(1), 0))
291 if (MooseUtils::absoluteFuzzyEqual(
v(2), 0))
const std::vector< double > x
void mooseError(Args &&... args)
std::vector< Real > _mu
Quadrature mu.
void checkDirection(const unsigned int l) const
Throws a MooseError if the angular quadrature does not have direction l.
std::vector< libMesh::Point > _current_directions
The current quadrature information.
const std::vector< Real > & getWeights(const unsigned int l) const
Get the weights associated with the direction l.
const Real _mu_max
The maximum mu.
std::vector< Real > _w
Quadrature combined weights.
std::size_t numPolar(const unsigned int l) const
The number of polar directions associated with the given direction.
libMesh::Point _current_rotation_direction
The current rotation direction.
static void chebyshev(const unsigned int order, std::vector< Real > &x, std::vector< Real > &w)
Builds Chebyshev quadrature on [0, 2\pi] with weights that sum to 2\pi.
const Real _mu_min
The minimum mu.
const unsigned int _azimuthal_order
The azimuthal order.
RayTracingAngularQuadrature(const unsigned int dim, const unsigned int polar_order, const unsigned int azimuthal_order, const Real mu_min, const Real mu_max)
Constructor.
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.
Real getTotalWeight(const unsigned int l) const
Gets the total of the weights associated with the direction l.
bool hasDirection(const unsigned int l) const
Whether or not the angular quadrature has direction l.
std::vector< std::vector< Real > > _current_polar_sins
const libMesh::Point & getDirection(const unsigned int l) const
Get the direction associated with direction l.
void rotate(const libMesh::Point &rotation_direction)
Rotates the quadrature to a given direction.
const std::vector< Real > & getPolarSins(const unsigned int l) const
Gets the polar sins for the direction l.
unsigned int dim() const
Get the quadrature dimension.
const unsigned int _dim
The dimension.
void build()
Build the quadrature.
static libMesh::Point orthonormalVector(const libMesh::Point &v)
Gets the vector that is orthonormal to v.
std::vector< Real > _phi
Quadrature phi.
std::vector< Real > _polar_sin
Quadrature polar sin.
std::vector< std::vector< Real > > _current_weights
const unsigned int _polar_order
The polar order.
static void rotationMatrix(const libMesh::Point &direction, libMesh::DenseMatrix< Real > &matrix)
Builds the rotation matrix for direction direction into matrix.
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
void resize(const unsigned int new_m, const unsigned int new_n)
void evd_right(DenseVector< T > &lambda_real, DenseVector< T > &lambda_imag, DenseMatrix< T > &VR)
virtual void zero() override final
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const
TypeVector< Real > unit() const