16 #include "libmesh/dense_matrix_impl.h" 19 #ifdef LIBMESH_HAVE_EXTERNAL_BOOST 20 #pragma GCC diagnostic push 21 #pragma GCC diagnostic ignored "-Wparentheses" 22 #include <boost/math/special_functions/legendre.hpp> 23 #include <boost/math/special_functions/hermite.hpp> 24 #pragma GCC diagnostic pop 33 std::unique_ptr<const Polynomial>
38 return std::make_unique<const Legendre>(dist->
getParam<
Real>(
"lower_bound"),
41 const Normal * n_dist =
dynamic_cast<const Normal *
>(dist);
43 return std::make_unique<const Hermite>(dist->
getParam<
Real>(
"mean"),
46 ::mooseError(
"Polynomials for '", dist->
type(),
"' distributions have not been implemented.");
54 ::mooseError(
"Polynomial child class must override this method.");
61 ::mooseError(
"Polynomial child class must override this method.");
67 ::mooseError(
"Polynomial type has not been implemented.");
74 const unsigned int )
const 76 ::mooseError(
"Polynomial type has not been implemented.");
83 std::vector<Real> & )
const 85 ::mooseError(
"Clenshaw quadrature has not been implemented for this polynomial type.");
91 const unsigned int nprod = order.size();
94 return (order[0] == 0 ? 1.0 : 0.0);
96 return (order[0] == order[1] ?
innerProduct(order[0]) : 0.0);
98 unsigned int poly_order = std::accumulate(order.begin(), order.end(), 0);
99 unsigned int quad_order = (poly_order % 2 == 0 ? poly_order : poly_order - 1) / 2;
101 std::vector<Real> xq;
102 std::vector<Real> wq;
106 for (
unsigned int q = 0; q < xq.size(); ++q)
109 for (
unsigned int i = 0; i < nprod; ++i)
110 prod *=
compute(order[i], xq[q],
false);
114 return val / std::accumulate(wq.begin(), wq.end(), 0.0);
118 :
Polynomial(), _lower_bound(lower_bound), _upper_bound(upper_bound)
125 std::string type =
"Legendre";
134 json[
"type"] =
"Legendre";
143 ::mooseError(
"The requested polynomial point is outside of distribution bounds.");
156 ::mooseError(
"The requested polynomial point is outside of distribution bounds.");
166 const unsigned int m)
const 181 std::vector<Real> & points,
182 std::vector<Real> & weights)
const 189 std::vector<Real> & points,
190 std::vector<Real> & weights)
const 195 for (
unsigned int i = 0; i < points.size(); ++i)
196 points[i] = points[i] * dx + xav;
202 return 1. / (2. *
static_cast<Real>(order) + 1.);
206 legendre(
const unsigned int order,
const Real
x,
const Real lower_bound,
const Real upper_bound)
208 Real xref = 2 / (upper_bound - lower_bound) * (
x - (upper_bound + lower_bound) / 2);
209 #ifdef LIBMESH_HAVE_EXTERNAL_BOOST 212 return boost::math::legendre_p(order, xref);
220 for (
unsigned int k = 0;
k <= (order % 2 == 0 ? order / 2 : (order - 1) / 2); ++
k)
223 Real(Utility::binomial(order,
k)) *
Real(Utility::binomial(2 * order - 2 *
k, order));
224 Real sgn = (
k % 2 == 0 ? 1.0 : -1.0);
225 unsigned int ord = order - 2 *
k;
226 val +=
sgn * coeff *
pow(xref, ord);
228 return val /
pow(2.0, order);
233 return ((2.0 * ord - 1.0) * xref *
legendre(order - 1, xref) -
234 (ord - 1.0) *
legendre(order - 2, xref)) /
245 return (
Real)Utility::factorial(order);
251 std::string type =
"Hermite";
260 json[
"type"] =
"Hermite";
282 for (
unsigned int i = 0; i < m; ++i)
283 val *= static_cast<Real>(order - i) /
_sig;
290 std::vector<Real> & points,
291 std::vector<Real> & weights)
const 297 hermite(
const unsigned int order,
const Real
x,
const Real
mu,
const Real sig)
300 #ifdef LIBMESH_HAVE_EXTERNAL_BOOST 307 val /=
pow(M_SQRT2, order);
316 for (
unsigned int m = 0; m <= (order % 2 == 0 ? order / 2 : (order - 1) / 2); ++m)
318 Real sgn = (m % 2 == 0 ? 1.0 : -1.0);
320 1.0 /
Real(Utility::factorial(m) * Utility::factorial(order - 2 * m)) /
pow(2.0, m);
321 unsigned int ord = order - 2 * m;
322 val +=
sgn * coeff *
pow(xref, ord);
324 return val * Utility::factorial(order);
327 return xref *
hermite(order - 1, xref) -
328 (
static_cast<Real>(order) - 1.0) *
hermite(order - 2, xref);
334 std::vector<Real> & points,
335 std::vector<Real> & weights,
336 const Real lower_bound,
337 const Real upper_bound)
339 unsigned int n = order + 1;
344 DenseVector<Real> lambda(n);
345 DenseVector<Real> lambdai(n);
347 for (
unsigned int i = 1; i < n; ++i)
350 mat(i, i - 1) = ri / std::sqrt(((2. * ri - 1.) * (2. * ri + 1.)));
351 mat(i - 1, i) = mat(i, i - 1);
355 Real dx = (upper_bound - lower_bound) / 2.0;
356 Real xav = (upper_bound + lower_bound) / 2.0;
357 for (
unsigned int i = 0; i < n; ++i)
359 points[i] = lambda(i) * dx + xav;
360 weights[i] = vec(0, i) * vec(0, i);
366 std::vector<Real> & points,
367 std::vector<Real> & weights,
372 unsigned int n = order + 1;
377 DenseVector<Real> lambda(n);
378 DenseVector<Real> lambdai(n);
380 for (
unsigned int i = 1; i < n; ++i)
382 mat(i, i - 1) = std::sqrt(static_cast<Real>(i));
383 mat(i - 1, i) = mat(i, i - 1);
387 for (
unsigned int i = 0; i < n; ++i)
389 points[i] =
mu + lambda(i) * sig;
390 weights[i] = vec(0, i) * vec(0, i);
395 clenshaw_curtis(
const unsigned int order, std::vector<Real> & points, std::vector<Real> & weights)
398 unsigned int N = order + (order % 2);
399 points.resize(
N + 1);
400 weights.resize(
N + 1);
409 std::vector<Real> dk(
N / 2 + 1);
410 for (
unsigned int k = 0;
k <= (
N / 2); ++
k)
411 dk[
k] = ((
k == 0 ||
k == (
N / 2)) ? 1.0 : 2.0) / (1.0 - 4.0 * (
Real)
k * (
Real)
k);
413 for (
unsigned int n = 0; n <= (
N / 2); ++n)
416 points[n] = -std::cos(theta);
417 for (
unsigned int k = 0;
k <= (
N / 2); ++
k)
420 ((n == 0 || n == (
N / 2)) ? 0.5 : 1.0) * std::cos((
Real)
k * theta * 2.0) / ((
Real)
N);
421 weights[n] += Dnk * dk[
k];
425 for (
unsigned int n = 0; n < (
N / 2); ++n)
427 points[
N - n] = -points[n];
428 weights[
N - n] = weights[n];
430 weights[
N / 2] *= 2.0;
434 std::vector<std::unique_ptr<const Polynomial>> & poly)
436 if (npoints.size() !=
poly.size())
437 ::
mooseError(
"List of number of 1D quadrature points must be same size as number of Polynomial " 440 std::vector<std::vector<Real>> qpoints_1D(
poly.size());
441 std::vector<std::vector<Real>> qweights_1D(
poly.size());
442 for (
unsigned int d = 0;
d <
poly.size(); ++
d)
443 poly[
d]->gaussQuadrature(npoints[
d] - 1, qpoints_1D[
d], qweights_1D[
d]);
445 _quad = std::make_unique<const StochasticTools::WeightedCartesianProduct<Real, Real>>(
446 qpoints_1D, qweights_1D);
450 std::vector<std::unique_ptr<const Polynomial>> & poly)
455 std::vector<std::vector<unsigned int>> tuple_1d(
_ndim);
456 for (
unsigned int d = 0;
d <
_ndim; ++
d)
458 tuple_1d[
d].resize(max_order);
459 for (
unsigned int i = 0; i < max_order; ++i)
465 unsigned int maxq = max_order - 1;
466 unsigned int minq = (max_order >
_ndim ? max_order -
_ndim : 0);
467 for (std::size_t p = 0; p < tensor_tuple.
numRows(); ++p)
469 std::vector<unsigned int> dorder = tensor_tuple.
computeRow(p);
470 unsigned int q = std::accumulate(dorder.begin(), dorder.end(), 0);
471 if (q <= maxq && q >= minq)
473 int sgn = ((max_order - q - 1) % 2 == 0 ? 1 : -1);
476 std::vector<std::vector<Real>> qpoints_1D(
_ndim);
477 std::vector<std::vector<Real>> qweights_1D(
_ndim);
478 for (
unsigned int d = 0;
d <
poly.size(); ++
d)
479 poly[
d]->gaussQuadrature(dorder[
d], qpoints_1D[
d], qweights_1D[
d]);
482 qpoints_1D, qweights_1D));
512 for (
unsigned int i = 0; i <
_npoints.size() - 1; ++i)
516 ::mooseError(
"Point index requested is greater than number of points.");
522 std::vector<std::unique_ptr<const Polynomial>> & poly)
526 std::vector<std::vector<unsigned int>> tuple_1d(
_ndim);
527 for (
unsigned int d = 0;
d <
_ndim; ++
d)
529 tuple_1d[
d].resize(max_order);
530 for (
unsigned int i = 0; i < max_order; ++i)
537 std::map<std::vector<Real>,
Real> quad_map;
538 unsigned int maxq = max_order - 1;
539 unsigned int minq = (max_order >
_ndim ? max_order -
_ndim : 0);
540 for (std::size_t p = 0; p < tensor_tuple.
numRows(); ++p)
542 std::vector<unsigned int> dorder = tensor_tuple.
computeRow(p);
543 unsigned int q = std::accumulate(dorder.begin(), dorder.end(), 0);
544 if (q <= maxq && q >= minq)
546 int sgn = ((max_order - q - 1) % 2 == 0 ? 1 : -1);
549 std::vector<std::vector<Real>> qpoints_1D(
_ndim);
550 std::vector<std::vector<Real>> qweights_1D(
_ndim);
551 for (
unsigned int d = 0;
d <
poly.size(); ++
d)
552 poly[
d]->clenshawQuadrature(dorder[
d], qpoints_1D[
d], qweights_1D[
d]);
556 for (
unsigned int i = 0; i < quad.
numRows(); ++i)
562 for (
const auto & it : quad_map)
570 std::unique_ptr<const PolynomialQuadrature::Polynomial> & ptr,
573 ptr->store(stream, context);
579 std::unique_ptr<const PolynomialQuadrature::Polynomial> & ptr,
582 std::string poly_type;
583 dataLoad(stream, poly_type, context);
584 if (poly_type ==
"Legendre")
586 Real lower_bound, upper_bound;
587 dataLoad(stream, lower_bound, context);
588 dataLoad(stream, upper_bound, context);
589 ptr = std::make_unique<const PolynomialQuadrature::Legendre>(lower_bound, upper_bound);
591 else if (poly_type ==
"Hermite")
596 ptr = std::make_unique<const PolynomialQuadrature::Hermite>(mean, stddev);
599 ::mooseError(
"Unknown Polynomaial type: ", poly_type);
virtual void gaussQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const =0
void gauss_hermite(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights, const Real mu, const Real sig)
Generalized formula for any polynomial order.
R poly(const C &c, const T x, const bool derivative=false)
A class used to generate a normal distribution.
std::unique_ptr< const Polynomial > makePolynomial(const Distribution *dist)
virtual Real computeDerivative(const unsigned int order, const Real x, const unsigned int m=1) const override
Compute derivative of Hermite polynomial P'n = nP{n-1}.
SmolyakGrid(const unsigned int max_order, std::vector< std::unique_ptr< const Polynomial >> &poly)
virtual Real computeDerivative(const unsigned int order, const Real x, const unsigned int m=1) const override
Compute derivative of Legendre polynomial Recursive algorithm: d^m/dx^m P_n = (n + m - 1)d^(m-1)/dx^(...
void mooseError(Args &&... args)
virtual Real compute(const unsigned int order, const Real x, const bool normalize=true) const override
Hermite polynomial using static function then scales by <P_n^2> = n!
TensorGrid(const std::vector< unsigned int > &npoints, std::vector< std::unique_ptr< const Polynomial >> &poly)
virtual Real quadratureWeight(const unsigned int n) const override
Weight for quadrature point n.
Real computeDerivativeRef(const unsigned int order, const Real x, const unsigned int m=1) const
Real productIntegral(const std::vector< unsigned int > order) const
std::vector< std::pair< std::vector< Real >, Real > > _quadrature
int sgn(T val)
The sign function.
virtual Real innerProduct(const unsigned int order) const override
Legendre(const Real lower_bound, const Real upper_bound)
virtual void gaussQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const override
Gauss-Hermite quadrature: sum(weights) = sqrt(2)
ClenshawCurtisGrid(const unsigned int max_order, std::vector< std::unique_ptr< const Polynomial >> &poly)
const std::vector< double > x
virtual void store(std::ostream &stream, void *context) const override
virtual void gaussQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const override
Gauss-Legendre quadrature: sum(weights) = 2.
static const std::string mu
void dataLoad(std::istream &stream, std::unique_ptr< const PolynomialQuadrature::Polynomial > &ptr, void *context)
virtual Real compute(const unsigned int order, const Real x, const bool normalize=true) const
unsigned int gridIndex(const unsigned int n) const
Helper function to find which quadrature product to use.
std::vector< std::size_t > _npoints
Cumulative number of points for each quadrature product.
void evd_right(DenseVector< Real > &lambda_real, DenseVector< Real > &lambda_imag, DenseMatrix< Real > &VR)
virtual void store(std::ostream &stream, void *context) const
const std::string & type() const
const T & getParam(const std::string &name) const
void clenshaw_curtis(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights)
Real hermite(const unsigned int order, const Real x, const Real mu=0.0, const Real sig=1.0)
Hermite polynomial of specified order.
virtual void store(std::ostream &stream, void *context) const override
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
Hermite(const Real mu, const Real sig)
General polynomial class with function for evaluating a polynomial of a given order at a given point...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual Real computeDerivative(const unsigned int order, const Real x, const unsigned int m=1) const
Computes the mth derivative of polynomial: d^mP_n/dx^m.
Polynomials and quadratures based on defined distributions for Polynomial Chaos.
virtual std::vector< Real > quadraturePoint(const unsigned int n) const override
Quadrature point n.
Real legendre(const unsigned int order, const Real x, const Real lower_bound=-1.0, const Real upper_bound=1.0)
Legendre polynomial of specified order.
virtual void clenshawQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const override
Just normal Clenshaw Curtis with shifted points.
std::unique_ptr< const StochasticTools::WeightedCartesianProduct< Real, Real > > _quad
virtual Real compute(const unsigned int order, const Real x, const bool normalize=true) const override
Legendre polynomial using static function then scales by <P_n^2> = 1 / (2n+1)
void dataStore(std::ostream &stream, std::unique_ptr< const PolynomialQuadrature::Polynomial > &ptr, void *context)
virtual Real innerProduct(const unsigned int order) const =0
std::vector< std::unique_ptr< const StochasticTools::WeightedCartesianProduct< Real, Real > > > _quad
Container for all the combinations of quadrature products.
static const std::string k
virtual Real innerProduct(const unsigned int order) const override
virtual void clenshawQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const
std::vector< int > _coeff
Modification of quadrature weight based on polynomial order.
void gauss_legendre(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights, const Real lower_bound, const Real upper_bound)
Generalized formula for any polynomial order.