https://mooseframework.inl.gov
Classes | Functions
PolynomialQuadrature Namespace Reference

Polynomials and quadratures based on defined distributions for Polynomial Chaos. More...

Classes

class  ClenshawCurtisGrid
 Clenshaw-Curtis sparse grid. More...
 
class  Hermite
 Normal distributions use Hermite polynomials. More...
 
class  Legendre
 Uniform distributions use Legendre polynomials. More...
 
class  Polynomial
 General polynomial class with function for evaluating a polynomial of a given order at a given point. More...
 
class  Quadrature
 General multidimensional quadrature class. More...
 
class  SmolyakGrid
 Smolyak sparse grid. More...
 
class  TensorGrid
 Full tensor product of 1D quadratures. More...
 

Functions

std::unique_ptr< const PolynomialmakePolynomial (const Distribution *dist)
 
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. More...
 
Real hermite (const unsigned int order, const Real x, const Real mu=0.0, const Real sig=1.0)
 Hermite polynomial of specified order. More...
 
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. More...
 
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. More...
 
void clenshaw_curtis (const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights)
 

Detailed Description

Polynomials and quadratures based on defined distributions for Polynomial Chaos.

Function Documentation

◆ clenshaw_curtis()

void PolynomialQuadrature::clenshaw_curtis ( const unsigned int  order,
std::vector< Real > &  points,
std::vector< Real > &  weights 
)

Definition at line 395 of file PolynomialQuadrature.C.

Referenced by PolynomialQuadrature::Legendre::clenshawQuadrature(), and TEST().

396 {
397  // Number of points needed
398  unsigned int N = order + (order % 2);
399  points.resize(N + 1);
400  weights.resize(N + 1);
401 
402  if (N == 0)
403  {
404  points[0] = 0;
405  weights[0] = 1;
406  return;
407  }
408 
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);
412 
413  for (unsigned int n = 0; n <= (N / 2); ++n)
414  {
415  Real theta = (Real)n * M_PI / ((Real)N);
416  points[n] = -std::cos(theta);
417  for (unsigned int k = 0; k <= (N / 2); ++k)
418  {
419  Real Dnk =
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];
422  }
423  }
424 
425  for (unsigned int n = 0; n < (N / 2); ++n)
426  {
427  points[N - n] = -points[n];
428  weights[N - n] = weights[n];
429  }
430  weights[N / 2] *= 2.0;
431 }
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
int N
static const std::string k
Definition: NS.h:130

◆ gauss_hermite()

void PolynomialQuadrature::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.

Resulting number of points is then: N = order + 1 The sum of weights is sqrt(2*) Uses the Golub-Welsch algorithm:

Definition at line 365 of file PolynomialQuadrature.C.

Referenced by PolynomialQuadrature::Hermite::gaussQuadrature(), and TEST().

370 {
371  // Number of points needed
372  unsigned int n = order + 1;
373  points.resize(n);
374  weights.resize(n);
375 
376  DenseMatrix<Real> mat(n, n);
377  DenseVector<Real> lambda(n);
378  DenseVector<Real> lambdai(n);
379  DenseMatrix<Real> vec(n, n);
380  for (unsigned int i = 1; i < n; ++i)
381  {
382  mat(i, i - 1) = std::sqrt(static_cast<Real>(i));
383  mat(i - 1, i) = mat(i, i - 1);
384  }
385  mat.evd_right(lambda, lambdai, vec);
386 
387  for (unsigned int i = 0; i < n; ++i)
388  {
389  points[i] = mu + lambda(i) * sig;
390  weights[i] = vec(0, i) * vec(0, i);
391  }
392 }
static const std::string mu
Definition: NS.h:123

◆ gauss_legendre()

void PolynomialQuadrature::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.

Resulting number of points is then: N = order + 1 The sum of weights is 2 Uses the Golub-Welsch algorithm:

Definition at line 333 of file PolynomialQuadrature.C.

Referenced by PolynomialQuadrature::Legendre::gaussQuadrature(), and TEST().

338 {
339  unsigned int n = order + 1;
340  points.resize(n);
341  weights.resize(n);
342 
343  DenseMatrix<Real> mat(n, n);
344  DenseVector<Real> lambda(n);
345  DenseVector<Real> lambdai(n);
346  DenseMatrix<Real> vec(n, n);
347  for (unsigned int i = 1; i < n; ++i)
348  {
349  Real ri = i;
350  mat(i, i - 1) = ri / std::sqrt(((2. * ri - 1.) * (2. * ri + 1.)));
351  mat(i - 1, i) = mat(i, i - 1);
352  }
353  mat.evd_right(lambda, lambdai, vec);
354 
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)
358  {
359  points[i] = lambda(i) * dx + xav;
360  weights[i] = vec(0, i) * vec(0, i);
361  }
362 }
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ hermite()

Real PolynomialQuadrature::hermite ( const unsigned int  order,
const Real  x,
const Real  mu = 0.0,
const Real  sig = 1.0 
)

Hermite polynomial of specified order.

Uses boost if available.

Definition at line 297 of file PolynomialQuadrature.C.

Referenced by PolynomialQuadrature::Hermite::compute(), PolynomialQuadrature::Hermite::computeDerivative(), and TEST().

298 {
299  Real xref = (x - mu) / sig;
300 #ifdef LIBMESH_HAVE_EXTERNAL_BOOST
301  // Using Hermite polynomials from boost library (if available)
302  // https://www.boost.org/doc/libs/1_46_1/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_poly/hermite.html
303  // Need to do some modification since boost does physicists hermite polynomials:
304  // H_n^prob(x) = 2^(-n/2)H_n^phys(x / sqrt(2))
305  xref /= M_SQRT2; // 1 / sqrt(2)
306  Real val = boost::math::hermite(order, xref);
307  val /= pow(M_SQRT2, order); // 2^(-order / 2)
308  return val;
309 #else
310  // Using explicit expression of polynomial coefficients:
311  // H_n(x) = n!\sum_{m=1}^{floor(n/2)} (-1)^m / (m!(n-2m)!) * x^(n-2m) / 2^m
312  // https://en.wikipedia.org/wiki/Hermite_polynomials
313  if (order < 13)
314  {
315  Real val = 0;
316  for (unsigned int m = 0; m <= (order % 2 == 0 ? order / 2 : (order - 1) / 2); ++m)
317  {
318  Real sgn = (m % 2 == 0 ? 1.0 : -1.0);
319  Real coeff =
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);
323  }
324  return val * Utility::factorial(order);
325  }
326  else
327  return xref * hermite(order - 1, xref) -
328  (static_cast<Real>(order) - 1.0) * hermite(order - 2, xref);
329 #endif
330 }
int sgn(T val)
The sign function.
Definition: Numerics.h:41
const std::vector< double > x
static const std::string mu
Definition: NS.h:123
Real hermite(const unsigned int order, const Real x, const Real mu=0.0, const Real sig=1.0)
Hermite polynomial of specified order.
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ legendre()

Real PolynomialQuadrature::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.

Uses boost if available

Definition at line 206 of file PolynomialQuadrature.C.

Referenced by PolynomialQuadrature::Legendre::compute(), PolynomialQuadrature::Legendre::computeDerivativeRef(), and TEST().

207 {
208  Real xref = 2 / (upper_bound - lower_bound) * (x - (upper_bound + lower_bound) / 2);
209 #ifdef LIBMESH_HAVE_EXTERNAL_BOOST
210  // Using Legendre polynomials from boost library (if available)
211  // https://www.boost.org/doc/libs/1_46_1/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_poly/legendre.html
212  return boost::math::legendre_p(order, xref);
213 #else
214  // Using explicit expression of polynomial coefficients:
215  // P_n(x) = 1/2^n\sum_{k=1}^{floor(n/2)} (-1)^k * nchoosek(n, k) * nchoosek(2n-2k, n) * x^(n-2k)
216  // https://en.wikipedia.org/wiki/Legendre_polynomials
217  if (order < 16)
218  {
219  Real val = 0;
220  for (unsigned int k = 0; k <= (order % 2 == 0 ? order / 2 : (order - 1) / 2); ++k)
221  {
222  Real coeff =
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);
227  }
228  return val / pow(2.0, order);
229  }
230  else
231  {
232  Real ord = order;
233  return ((2.0 * ord - 1.0) * xref * legendre(order - 1, xref) -
234  (ord - 1.0) * legendre(order - 2, xref)) /
235  ord;
236  }
237 #endif
238 }
int sgn(T val)
The sign function.
Definition: Numerics.h:41
const std::vector< double > x
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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.
static const std::string k
Definition: NS.h:130

◆ makePolynomial()

std::unique_ptr< const Polynomial > PolynomialQuadrature::makePolynomial ( const Distribution dist)

Definition at line 34 of file PolynomialQuadrature.C.

Referenced by PolynomialChaosTrainer::PolynomialChaosTrainer(), and QuadratureSampler::QuadratureSampler().

35 {
36  const Uniform * u_dist = dynamic_cast<const Uniform *>(dist);
37  if (u_dist)
38  return std::make_unique<const Legendre>(dist->getParam<Real>("lower_bound"),
39  dist->getParam<Real>("upper_bound"));
40 
41  const Normal * n_dist = dynamic_cast<const Normal *>(dist);
42  if (n_dist)
43  return std::make_unique<const Hermite>(dist->getParam<Real>("mean"),
44  dist->getParam<Real>("standard_deviation"));
45 
46  ::mooseError("Polynomials for '", dist->type(), "' distributions have not been implemented.");
47  return nullptr;
48 }
A class used to generate uniform distribution.
Definition: Uniform.h:17
A class used to generate a normal distribution.
Definition: Normal.h:17
const std::string & type() const
const T & getParam(const std::string &name) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real