https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PolynomialQuadrature.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
11
12#include "MooseError.h"
13#include "DataIO.h"
14
15// For computing legendre quadrature
16#include "libmesh/dense_matrix_impl.h"
17
18// For quickly computing polynomials
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
25#endif
26
27#include <cmath>
28#include <memory>
29
31{
32
33std::unique_ptr<const Polynomial>
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}
49
50void
51Polynomial::store(std::ostream & /*stream*/, void * /*context*/) const
52{
53 // Cannot be pure virtual because for dataLoad operations the base class must be constructed
54 ::mooseError("Polynomial child class must override this method.");
55}
56
57void
58Polynomial::store(nlohmann::json & /*json*/) const
59{
60 // Cannot be pure virtual because for dataLoad operations the base class must be constructed
61 ::mooseError("Polynomial child class must override this method.");
62}
63
64Real
65Polynomial::compute(const unsigned int /*order*/, const Real /*x*/, const bool /*normalize*/) const
66{
67 ::mooseError("Polynomial type has not been implemented.");
68 return 0;
69}
70
71Real
72Polynomial::computeDerivative(const unsigned int /*order*/,
73 const Real /*x*/,
74 const unsigned int /*n*/) const
75{
76 ::mooseError("Polynomial type has not been implemented.");
77 return 0;
78}
79
80void
81Polynomial::clenshawQuadrature(const unsigned int /*order*/,
82 std::vector<Real> & /*points*/,
83 std::vector<Real> & /*weights*/) const
84{
85 ::mooseError("Clenshaw quadrature has not been implemented for this polynomial type.");
86}
87
88Real
89Polynomial::productIntegral(const std::vector<unsigned int> order) const
90{
91 const unsigned int nprod = order.size();
92
93 if (nprod == 1)
94 return (order[0] == 0 ? 1.0 : 0.0);
95 else if (nprod == 2)
96 return (order[0] == order[1] ? innerProduct(order[0]) : 0.0);
97
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;
100
101 std::vector<Real> xq;
102 std::vector<Real> wq;
103 gaussQuadrature(quad_order, xq, wq);
104
105 Real val = 0.0;
106 for (unsigned int q = 0; q < xq.size(); ++q)
107 {
108 Real prod = wq[q];
109 for (unsigned int i = 0; i < nprod; ++i)
110 prod *= compute(order[i], xq[q], false);
111 val += prod;
112 }
113
114 return val / std::accumulate(wq.begin(), wq.end(), 0.0);
115}
116
117Legendre::Legendre(const Real lower_bound, const Real upper_bound)
118 : Polynomial(), _lower_bound(lower_bound), _upper_bound(upper_bound)
119{
120}
121
122void
123Legendre::store(std::ostream & stream, void * context) const
124{
125 std::string type = "Legendre";
126 dataStore(stream, type, context);
127 dataStore(stream, _lower_bound, context);
128 dataStore(stream, _upper_bound, context);
129}
130
131void
132Legendre::store(nlohmann::json & json) const
133{
134 json["type"] = "Legendre";
135 json["lower_bound"] = _lower_bound;
136 json["upper_bound"] = _upper_bound;
137}
138
139Real
140Legendre::compute(const unsigned int order, const Real x, const bool normalize) const
141{
142 if ((x < _lower_bound) || (x > _upper_bound))
143 ::mooseError("The requested polynomial point is outside of distribution bounds.");
144
145 Real val = legendre(order, x, _lower_bound, _upper_bound);
146 if (normalize)
147 val /= innerProduct(order);
148
149 return val;
150}
151
152Real
153Legendre::computeDerivative(const unsigned int order, const Real x, const unsigned int m) const
154{
155 if ((x < _lower_bound) || (x > _upper_bound))
156 ::mooseError("The requested polynomial point is outside of distribution bounds.");
157
158 Real xref = 2.0 / (_upper_bound - _lower_bound) * (x - (_upper_bound + _lower_bound) / 2.0);
159 Real Jac = pow(2.0 / (_upper_bound - _lower_bound), m);
160 return Jac * computeDerivativeRef(order, xref, m);
161}
162
163Real
164Legendre::computeDerivativeRef(const unsigned int order,
165 const Real xref,
166 const unsigned int m) const
167{
168 if (m == 0)
169 return legendre(order, xref);
170 else if (m > order)
171 return 0.0;
172 else if (order == 1)
173 return 1.0;
174 else
175 return static_cast<Real>(order + m - 1) * computeDerivativeRef(order - 1, xref, m - 1) +
176 xref * computeDerivativeRef(order - 1, xref, m);
177}
178
179void
180Legendre::gaussQuadrature(const unsigned int order,
181 std::vector<Real> & points,
182 std::vector<Real> & weights) const
183{
184 gauss_legendre(order, points, weights, _lower_bound, _upper_bound);
185}
186
187void
188Legendre::clenshawQuadrature(const unsigned int order,
189 std::vector<Real> & points,
190 std::vector<Real> & weights) const
191{
192 clenshaw_curtis(order, points, weights);
193 Real dx = (_upper_bound - _lower_bound) / 2.0;
194 Real xav = (_upper_bound + _lower_bound) / 2.0;
195 for (unsigned int i = 0; i < points.size(); ++i)
196 points[i] = points[i] * dx + xav;
197}
198
199Real
200Legendre::innerProduct(const unsigned int order) const
201{
202 return 1. / (2. * static_cast<Real>(order) + 1.);
203}
204
205Real
206legendre(const unsigned int order, const Real x, const Real lower_bound, const Real upper_bound)
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}
239
240Hermite::Hermite(const Real mu, const Real sig) : Polynomial(), _mu(mu), _sig(sig) {}
241
242Real
243Hermite::innerProduct(const unsigned int order) const
244{
245 return (Real)Utility::factorial(order);
246}
247
248void
249Hermite::store(std::ostream & stream, void * context) const
250{
251 std::string type = "Hermite";
252 dataStore(stream, type, context);
253 dataStore(stream, _mu, context);
254 dataStore(stream, _sig, context);
255}
256
257void
258Hermite::store(nlohmann::json & json) const
259{
260 json["type"] = "Hermite";
261 json["mu"] = _mu;
262 json["sig"] = _sig;
263}
264
265Real
266Hermite::compute(const unsigned int order, const Real x, const bool normalize) const
267{
268 Real val = hermite(order, x, _mu, _sig);
269 if (normalize)
270 val /= innerProduct(order);
271 return val;
272}
273
274Real
275Hermite::computeDerivative(const unsigned int order, const Real x, const unsigned int m) const
276{
277 if (m > order)
278 return 0.0;
279
280 Real xref = (x - _mu) / _sig;
281 Real val = hermite(order - m, xref);
282 for (unsigned int i = 0; i < m; ++i)
283 val *= static_cast<Real>(order - i) / _sig;
284
285 return val;
286}
287
288void
289Hermite::gaussQuadrature(const unsigned int order,
290 std::vector<Real> & points,
291 std::vector<Real> & weights) const
292{
293 gauss_hermite(order, points, weights, _mu, _sig);
294}
295
296Real
297hermite(const unsigned int order, const Real x, const Real mu, const Real sig)
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}
331
332void
333gauss_legendre(const unsigned int order,
334 std::vector<Real> & points,
335 std::vector<Real> & weights,
336 const Real lower_bound,
337 const Real upper_bound)
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}
363
364void
365gauss_hermite(const unsigned int order,
366 std::vector<Real> & points,
367 std::vector<Real> & weights,
368 const Real mu,
369 const Real sig)
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}
393
394void
395clenshaw_curtis(const unsigned int order, std::vector<Real> & points, std::vector<Real> & weights)
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}
432
433TensorGrid::TensorGrid(const std::vector<unsigned int> & npoints,
434 std::vector<std::unique_ptr<const Polynomial>> & poly)
435{
436 if (npoints.size() != poly.size())
437 ::mooseError("List of number of 1D quadrature points must be same size as number of Polynomial "
438 "objects.");
439
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]);
444
445 _quad = std::make_unique<const StochasticTools::WeightedCartesianProduct<Real, Real>>(
446 qpoints_1D, qweights_1D);
447}
448
449SmolyakGrid::SmolyakGrid(const unsigned int max_order,
450 std::vector<std::unique_ptr<const Polynomial>> & poly)
451 : _ndim(poly.size())
452{
453
454 // Compute full tensor tuple
455 std::vector<std::vector<unsigned int>> tuple_1d(_ndim);
456 for (unsigned int d = 0; d < _ndim; ++d)
457 {
458 tuple_1d[d].resize(max_order);
459 for (unsigned int i = 0; i < max_order; ++i)
460 tuple_1d[d][i] = i;
461 }
463
464 _npoints.push_back(0);
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)
468 {
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)
472 {
473 int sgn = ((max_order - q - 1) % 2 == 0 ? 1 : -1);
474 _coeff.push_back(sgn * Utility::binomial(_ndim - 1, _ndim + q - max_order));
475
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]);
480
481 _quad.push_back(std::make_unique<const StochasticTools::WeightedCartesianProduct<Real, Real>>(
482 qpoints_1D, qweights_1D));
483 _npoints.push_back(_npoints.back() + _quad.back()->numRows());
484 }
485 }
486}
487
488std::vector<Real>
489SmolyakGrid::quadraturePoint(const unsigned int n) const
490{
491 unsigned int ind = gridIndex(n);
492 return _quad[ind]->computeRow(n - _npoints[ind]);
493}
494
495Real
496SmolyakGrid::quadraturePoint(const unsigned int n, const unsigned int dim) const
497{
498 unsigned int ind = gridIndex(n);
499 return _quad[ind]->computeValue(n - _npoints[ind], dim);
500}
501
502Real
503SmolyakGrid::quadratureWeight(const unsigned int n) const
504{
505 unsigned int ind = gridIndex(n);
506 return static_cast<Real>(_coeff[ind]) * _quad[ind]->computeWeight(n - _npoints[ind]);
507}
508
509unsigned int
510SmolyakGrid::gridIndex(const unsigned int n) const
511{
512 for (unsigned int i = 0; i < _npoints.size() - 1; ++i)
513 if (_npoints[i + 1] > n)
514 return i;
515
516 ::mooseError("Point index requested is greater than number of points.");
517
518 return 0;
519}
520
521ClenshawCurtisGrid::ClenshawCurtisGrid(const unsigned int max_order,
522 std::vector<std::unique_ptr<const Polynomial>> & poly)
523 : _ndim(poly.size())
524{
525 // Compute full tensor tuple
526 std::vector<std::vector<unsigned int>> tuple_1d(_ndim);
527 for (unsigned int d = 0; d < _ndim; ++d)
528 {
529 tuple_1d[d].resize(max_order);
530 for (unsigned int i = 0; i < max_order; ++i)
531 tuple_1d[d][i] = i;
532 }
534
535 // Curtis clenshaw has a lot of nested points,
536 // so it behooves us to avoid duplicate points
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)
541 {
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)
545 {
546 int sgn = ((max_order - q - 1) % 2 == 0 ? 1 : -1);
547 Real coeff = static_cast<Real>(sgn * Utility::binomial(_ndim - 1, _ndim + q - max_order));
548
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]);
553
554 StochasticTools::WeightedCartesianProduct<Real, Real> quad(qpoints_1D, qweights_1D);
555
556 for (unsigned int i = 0; i < quad.numRows(); ++i)
557 quad_map[quad.computeRow(i)] += coeff * quad.computeWeight(i);
558 }
559 }
560
561 _quadrature.reserve(quad_map.size());
562 for (const auto & it : quad_map)
563 _quadrature.push_back(it);
564}
565} // namespace PolynomialQuadrature
566
567template <>
568void
569dataStore(std::ostream & stream,
570 std::unique_ptr<const PolynomialQuadrature::Polynomial> & ptr,
571 void * context)
572{
573 ptr->store(stream, context);
574}
575
576template <>
577void
578dataLoad(std::istream & stream,
579 std::unique_ptr<const PolynomialQuadrature::Polynomial> & ptr,
580 void * context)
581{
582 std::string poly_type;
583 dataLoad(stream, poly_type, context);
584 if (poly_type == "Legendre")
585 {
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);
590 }
591 else if (poly_type == "Hermite")
592 {
593 Real mean, stddev;
594 dataLoad(stream, mean, context);
595 dataLoad(stream, stddev, context);
596 ptr = std::make_unique<const PolynomialQuadrature::Hermite>(mean, stddev);
597 }
598 else
599 ::mooseError("Unknown Polynomaial type: ", poly_type);
600}
const std::vector< double > x
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const double mu
const Real p
void dataStore(std::ostream &stream, LineSegment &l, void *context)
void dataLoad(std::istream &stream, std::unique_ptr< const PolynomialQuadrature::Polynomial > &ptr, void *context)
void dataStore(std::ostream &stream, std::unique_ptr< const PolynomialQuadrature::Polynomial > &ptr, void *context)
unsigned int dim
Legendre()
Definition Legendre.C:19
const std::string & type() const
const T & getParam(const std::string &name) const
A class used to generate a normal distribution.
Definition Normal.h:18
std::vector< std::pair< std::vector< Real >, Real > > _quadrature
ClenshawCurtisGrid(const unsigned int max_order, std::vector< std::unique_ptr< const Polynomial > > &poly)
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-Hermite quadrature: sum(weights) = sqrt(2\pi)
virtual Real innerProduct(const unsigned int order) const override
Hermite(const Real mu, const Real sig)
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}.
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!
Real computeDerivativeRef(const unsigned int order, const Real x, const unsigned int m=1) const
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 override
Just normal Clenshaw Curtis with shifted points.
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^(...
virtual void gaussQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const override
Gauss-Legendre quadrature: sum(weights) = 2.
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)
virtual void store(std::ostream &stream, void *context) const override
General polynomial class with function for evaluating a polynomial of a given order at a given point.
virtual void store(std::ostream &stream, void *context) const
Real productIntegral(const std::vector< unsigned int > order) const
virtual Real innerProduct(const unsigned int order) const =0
virtual void gaussQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const =0
virtual void clenshawQuadrature(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights) const
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.
virtual Real compute(const unsigned int order, const Real x, const bool normalize=true) const
std::vector< int > _coeff
Modification of quadrature weight based on polynomial order.
virtual std::vector< Real > quadraturePoint(const unsigned int n) const override
Quadrature point n.
virtual Real quadratureWeight(const unsigned int n) const override
Weight for quadrature point n.
std::vector< std::unique_ptr< const StochasticTools::WeightedCartesianProduct< Real, Real > > > _quad
Container for all the combinations of quadrature products.
std::vector< std::size_t > _npoints
Cumulative number of points for each quadrature product.
unsigned int gridIndex(const unsigned int n) const
Helper function to find which quadrature product to use.
SmolyakGrid(const unsigned int max_order, std::vector< std::unique_ptr< const Polynomial > > &poly)
std::unique_ptr< const StochasticTools::WeightedCartesianProduct< Real, Real > > _quad
TensorGrid(const std::vector< unsigned int > &npoints, std::vector< std::unique_ptr< const Polynomial > > &poly)
std::size_t numRows() const
Total number of rows in the complete matrix.
std::vector< T > computeRow(std::size_t row) const
Compute specified row of Cartesian product matrix.
W computeWeight(std::size_t row) const
Compute specific weight value, given row.
A class used to generate uniform distribution.
Definition Uniform.h:18
Polynomials and quadratures based on defined distributions for Polynomial Chaos.
std::unique_ptr< const Polynomial > makePolynomial(const Distribution *dist)
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.
void clenshaw_curtis(const unsigned int order, std::vector< Real > &points, std::vector< Real > &weights)
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.
Real hermite(const unsigned int order, const Real x, const Real mu=0.0, const Real sig=1.0)
Hermite polynomial of specified order.
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.