CMP++: Uncertainty Quantification & Bayesian Calibration
Loading...
Searching...
No Matches
poly.h
Go to the documentation of this file.
1#ifndef POLY_H
2#define POLY_H
3
4#include <vector>
5#include <iostream>
6#include <memory>
7#include <stdexcept>
8#include <cmath>
9#include <Eigen/Dense>
10
11#include <fstream>
12#include <string>
13#include <integrator.h>
14
19namespace cmp {
20
21// Basis for polynomial chaos expansion
37 static inline double evaluate(size_t deg, double xi) {
38 if(deg == 0) return 1.0;
39 if(deg == 1) return xi;
40 double Hn_2 = 1.0, Hn_1 = xi, Hn = 0.0;
41 for(size_t n = 2; n <= deg; ++n) {
42 Hn = xi * Hn_1 - (n - 1) * Hn_2;
43 Hn_2 = Hn_1;
44 Hn_1 = Hn;
45 }
46 return Hn;
47 }
48
49 static inline double normSquared(size_t deg) {
50 double norm = 1.0;
51 for(size_t i = 2; i <= deg; ++i) norm *= i;
52 return norm;
53 }
54
55 static inline Eigen::MatrixXd getJacobiMatrix(int numPoints) {
56 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
57 for(int i = 0; i < numPoints - 1; ++i) {
58 double beta = std::sqrt(i + 1.0);
59 J(i, i + 1) = beta;
60 J(i + 1, i) = beta;
61 }
62 return J;
63 }
64
65 static inline double getPDFWeight() {
66 return 1.0;
67 }
68
69 // Maps canonical N(0,1) root to physical N(mean, stdDev)
70 static inline double mapToPhysical(double xi, double mean, double stdDev) {
71 return mean + stdDev * xi;
72 }
73
74 // Maps physical x to canonical N(0,1) root
75 static inline double mapToCanonical(double x, double mean, double stdDev) {
76 return (x - mean) / stdDev;
77 }
78};
79
95 static inline double evaluate(size_t deg, double xi) {
96 if(deg == 0) return 1.0;
97 if(deg == 1) return xi;
98 double Pn_2 = 1.0, Pn_1 = xi, Pn = 0.0;
99 for(size_t n = 2; n <= deg; ++n) {
100 Pn = ((2 * n - 1) * xi * Pn_1 - (n - 1) * Pn_2) / n;
101 Pn_2 = Pn_1;
102 Pn_1 = Pn;
103 }
104 return Pn;
105 }
106
107 static inline double normSquared(size_t deg) {
108 return 1.0 / (2.0 * deg + 1.0);
109 }
110
111 static inline Eigen::MatrixXd getJacobiMatrix(int numPoints) {
112 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
113 for(int i = 0; i < numPoints - 1; ++i) {
114 double beta = std::sqrt((i + 1.0) * (i + 1.0) / ((2 * i + 1.0) * (2 * i + 3.0)));
115 J(i, i + 1) = beta;
116 J(i + 1, i) = beta;
117 }
118 return J;
119 }
120
121 static inline double getPDFWeight() {
122 return 1.0;
123 }
124
125 // Maps canonical [-1, 1] root to physical [lowerBound, upperBound]
126 static inline double mapToPhysical(double xi, double lowerBound, double upperBound) {
127 return lowerBound + (upperBound - lowerBound) * (xi + 1.0) / 2.0;
128 }
129
130 // Maps physical x to canonical [-1, 1] root
131 static inline double mapToCanonical(double x, double lowerBound, double upperBound) {
132 return 2.0 * (x - lowerBound) / (upperBound - lowerBound) - 1.0;
133 }
134};
135
150 static inline double evaluate(size_t deg, double xi) {
151 if(deg == 0) return 1.0;
152 if(deg == 1) return xi;
153 double Tn_2 = 1.0, Tn_1 = xi, Tn = 0.0;
154 for(size_t n = 2; n <= deg; ++n) {
155 Tn = 2.0 * xi * Tn_1 - Tn_2;
156 Tn_2 = Tn_1;
157 Tn_1 = Tn;
158 }
159 return Tn;
160 }
161
162 static inline double normSquared(size_t deg) {
163 constexpr double pi = 3.14159265358979323846;
164 if(deg == 0) return pi;
165 return pi / 2.0;
166 }
167
168 static inline Eigen::MatrixXd getJacobiMatrix(int numPoints) {
169 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
170 if(numPoints > 1) {
171 J(0, 1) = 1.0 / std::sqrt(2.0);
172 J(1, 0) = 1.0 / std::sqrt(2.0);
173 for(int i = 1; i < numPoints - 1; ++i) {
174 J(i, i + 1) = 0.5;
175 J(i + 1, i) = 0.5;
176 }
177 }
178 return J;
179 }
180
181 static inline double mapToPhysical(double xi, double lowerBound, double upperBound) {
182 return lowerBound + (upperBound - lowerBound) * (xi + 1.0) / 2.0;
183 }
184
185 static inline double mapToCanonical(double x, double lowerBound, double upperBound) {
186 return 2.0 * (x - lowerBound) / (upperBound - lowerBound) - 1.0;
187 }
188};
189
204 static inline double evaluate(size_t deg, double xi) {
205 if(deg == 0) return 1.0;
206 if(deg == 1) return 1.0 - xi;
207 double Ln_2 = 1.0, Ln_1 = 1.0 - xi, Ln = 0.0;
208 for(size_t n = 1; n < deg; ++n) {
209 Ln = ((2.0 * n + 1.0 - xi) * Ln_1 - n * Ln_2) / (n + 1.0);
210 Ln_2 = Ln_1;
211 Ln_1 = Ln;
212 }
213 return Ln;
214 }
215
216 static inline double normSquared(size_t deg) {
217 return 1.0;
218 }
219
220 static inline Eigen::MatrixXd getJacobiMatrix(int numPoints) {
221 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
222 for(int i = 0; i < numPoints; ++i) {
223 J(i, i) = 2.0 * i + 1.0;
224 if(i < numPoints - 1) {
225 double off_diag = static_cast<double>(i + 1);
226 J(i, i + 1) = off_diag;
227 J(i + 1, i) = off_diag;
228 }
229 }
230 return J;
231 }
232
233 // Maps canonical root [0, inf) to physical
234 static inline double mapToPhysical(double xi, double location, double scale) {
235 return location + scale * xi;
236 }
237
238 // Maps physical x to canonical root [0, inf)
239 static inline double mapToCanonical(double x, double location, double scale) {
240 return (x - location) / scale;
241 }
242};
243
245 public:
246 using Index = std::vector<size_t>;
247 std::vector<Index> indices;
248
249 MultiIndex() = default;
250 void set(size_t dimension, size_t totalDegree, double q = 1.0);
251
252 std::size_t size() const {
253 return indices.size();
254 }
255 const Index& operator[](std::size_t i) const {
256 return indices[i];
257 }
258 void print() const;
259
260 private:
261 void generateRecursive(Index& current, int pos, size_t remaining, double currentQSum, double maxQSum, double q);
262};
263
300template <typename Basis>
302 private:
304 Eigen::VectorXd coefficients_;
305 Eigen::MatrixXd normalMatrixInverse_;
306 Eigen::MatrixXd xObs_;
307 Eigen::VectorXd yObs_;
308 double residualVariance_ = 0.0;
309
310 // Distribution parameters for each dimension
311 Eigen::VectorXd p1_;
312 Eigen::VectorXd p2_;
313
314 // Vectorized evaluation of a block of data
315 Eigen::MatrixXd computeDesignMatrix(const Eigen::Ref<const Eigen::MatrixXd>& X) const {
316 const int numSamples = X.rows();
317 const int numBasis = multiIndex_.size();
318 const int dim = X.cols();
319
320 Eigen::MatrixXd A(numSamples, numBasis);
321
322 #pragma omp parallel for schedule(static)
323 for(int i = 0; i < numSamples; ++i) {
324 for(int b = 0; b < numBasis; ++b) {
325 double term = 1.0;
326 for(int d = 0; d < dim; ++d) {
327 // Map the physical observation X to canonical space
328 double xi = Basis::mapToCanonical(X(i, d), p1_(d), p2_(d));
329 term *= Basis::evaluate(multiIndex_.indices[b][d], xi);
330 }
331 A(i, b) = term;
332 }
333 }
334 return A;
335 }
336
337 template <typename MatrixType>
338 void writeEigenMatrix(std::ofstream& out, const MatrixType& mat) const {
339 typename MatrixType::Index rows = mat.rows();
340 typename MatrixType::Index cols = mat.cols();
341 out.write(reinterpret_cast<const char*>(&rows), sizeof(rows));
342 out.write(reinterpret_cast<const char*>(&cols), sizeof(cols));
343 out.write(reinterpret_cast<const char*>(mat.data()), rows * cols * sizeof(typename MatrixType::Scalar));
344 }
345
346 template <typename MatrixType>
347 void readEigenMatrix(std::ifstream& in, MatrixType& mat) {
348 typename MatrixType::Index rows = 0, cols = 0;
349 in.read(reinterpret_cast<char*>(&rows), sizeof(rows));
350 in.read(reinterpret_cast<char*>(&cols), sizeof(cols));
351 mat.resize(rows, cols);
352 in.read(reinterpret_cast<char*>(mat.data()), rows * cols * sizeof(typename MatrixType::Scalar));
353 }
354
355 public:
357
358 // Updated init method to capture bounding/distribution parameters
359 void set(size_t dimension, size_t totalDegree, const Eigen::VectorXd& p1, const Eigen::VectorXd& p2, double q = 1.0) {
360 if(p1.size() != dimension || p2.size() != dimension) {
361 throw std::invalid_argument("Parameter vectors must match dimension.");
362 }
363 p1_ = p1;
364 p2_ = p2;
365 multiIndex_.set(dimension, totalDegree, q);
366 coefficients_ = Eigen::VectorXd::Zero(multiIndex_.size());
367 }
368
369 void fit(const Eigen::Ref<const Eigen::MatrixXd>& samples, const Eigen::Ref<const Eigen::VectorXd>& values) {
370 if(samples.rows() != values.size()) throw std::invalid_argument("Dimension mismatch.");
371
372 xObs_ = samples;
373 yObs_ = values;
374
375 Eigen::MatrixXd A = computeDesignMatrix(samples);
376
377 Eigen::ColPivHouseholderQR<Eigen::MatrixXd> qr(A);
378 coefficients_ = qr.solve(values);
379
380 normalMatrixInverse_ = (A.transpose() * A).completeOrthogonalDecomposition().pseudoInverse();
381 Eigen::VectorXd residuals = values - A * coefficients_;
382
383 if(samples.rows() > coefficients_.size()) {
384 residualVariance_ = residuals.squaredNorm() / (samples.rows() - coefficients_.size());
385 }
386 }
387
388 double getAnalyticalMean() const {
389 if(coefficients_.size() == 0) return 0.0;
390 return coefficients_(0);
391 }
392
393 double getAnalyticalVariance() const {
394 double totalVar = 0.0;
395 for(size_t i = 1; i < multiIndex_.size(); ++i) {
396 double basisNormSq = 1.0;
397 for(size_t d = 0; d < multiIndex_.indices[i].size(); ++d) {
398 basisNormSq *= Basis::normSquared(multiIndex_.indices[i][d]);
399 }
401 }
402 return totalVar;
403 }
404
405 Eigen::VectorXd getSobolMainIndices() const {
407 size_t dim = multiIndex_.indices[0].size();
408 Eigen::VectorXd sobolIndices = Eigen::VectorXd::Zero(dim);
409
410 if(totalVar < 1e-12) return sobolIndices;
411
412 for(size_t i = 1; i < multiIndex_.size(); ++i) {
413 int activeDim = -1;
414 bool isMainEffect = true;
415
416 for(size_t d = 0; d < dim; ++d) {
417 if(multiIndex_.indices[i][d] > 0) {
418 if(activeDim == -1) activeDim = d;
419 else isMainEffect = false;
420 }
421 }
422
423 if(isMainEffect && activeDim != -1) {
424 double basisNormSq = 1.0;
425 for(size_t d = 0; d < dim; ++d) {
426 basisNormSq *= Basis::normSquared(multiIndex_.indices[i][d]);
427 }
429 }
430 }
431 return sobolIndices / totalVar;
432 }
433
434 Eigen::VectorXd predictBatch(const Eigen::Ref<const Eigen::MatrixXd>& X) const {
435 Eigen::MatrixXd A = computeDesignMatrix(X);
436 return A * coefficients_;
437 }
438
439 std::pair<double, double> predict(const Eigen::Ref<const Eigen::VectorXd> &x) const {
440 Eigen::VectorXd phi = computeBasisRow(x);
441 double mean = coefficients_.dot(phi);
442
443 double variance = 0.0;
444 if(residualVariance_ > 0.0 && normalMatrixInverse_.size() > 0) {
446 }
447 return {mean, variance};
448 }
449
450 std::pair<double, double> predictWithObs(const Eigen::Ref<const Eigen::VectorXd> &x, const double &yObs) const {
451 if(normalMatrixInverse_.size() == 0 || yObs_.size() == 0) {
452 throw std::runtime_error("predictWithObs requires a fitted model.");
453 }
454 Eigen::VectorXd phi = computeBasisRow(x);
455 Eigen::VectorXd influence = normalMatrixInverse_ * phi;
456 const double denom = 1.0 + phi.dot(influence);
457
458 if(std::abs(denom) <= std::numeric_limits<double>::epsilon()) {
459 throw std::runtime_error("Rank-one update is singular.");
460 }
461
462 const double innovation = yObs - phi.dot(coefficients_);
463 Eigen::VectorXd gain = influence / denom;
464 Eigen::VectorXd coeffsUpdated = coefficients_ + gain * innovation;
465 Eigen::MatrixXd normalInvUpdated = normalMatrixInverse_ - (influence * influence.transpose()) / denom;
466
467 const double mean = phi.dot(coeffsUpdated);
468 double variance = 0.0;
469 if(residualVariance_ > 0.0) {
471 }
472
473 return {mean, variance};
474 }
475
476 std::pair<double, double> predictLOO(const size_t& i) const {
477 if(i >= (size_t)xObs_.rows()) {
478 throw std::out_of_range("LOO index out of range.");
479 }
480 if(normalMatrixInverse_.size() == 0) {
481 throw std::runtime_error("LOO prediction requires a fitted normal matrix inverse.");
482 }
483
484 Eigen::VectorXd x = xObs_.row(i).transpose();
485 Eigen::VectorXd phi = computeBasisRow(x);
486
487 const double y_i = yObs_(i);
488 const double residual_i = y_i - phi.dot(coefficients_);
489 Eigen::VectorXd influence = normalMatrixInverse_ * phi;
490 const double leverage_i = phi.dot(influence);
491 const double denom = 1.0 - leverage_i;
492
493 if(std::abs(denom) <= std::numeric_limits<double>::epsilon()) {
494 throw std::runtime_error("LOO rank-one update is singular.");
495 }
496
497 Eigen::VectorXd coeffsLOO = coefficients_ - influence * (residual_i / denom);
498 const double mean = phi.dot(coeffsLOO);
499
500 double variance = 0.0;
501 if(residualVariance_ > 0.0) {
502 Eigen::MatrixXd normalInvLOO = normalMatrixInverse_ + (influence * influence.transpose()) / denom;
504 }
505
506 return {mean, variance};
507 }
508
509 Eigen::VectorXd computeBasisRow(const Eigen::Ref<const Eigen::VectorXd> &x) const {
510 if(multiIndex_.size() == 0) {
511 throw std::runtime_error("Polynomial basis is not initialized.");
512 }
513 if(x.size() != (int)multiIndex_.indices[0].size()) {
514 throw std::invalid_argument("Input vector size does not match the polynomial dimension.");
515 }
516
517 Eigen::VectorXd phi(multiIndex_.size());
518 for(size_t i = 0; i < multiIndex_.size(); ++i) {
519 double term = 1.0;
520 for(size_t d = 0; d < (size_t)x.size(); ++d) {
521 // Map the physical input vector to the canonical space
522 double xi = Basis::mapToCanonical(x(d), p1_[d], p2_[d]);
523 term *= Basis::evaluate(multiIndex_.indices[i][d], xi);
524 }
525 phi(i) = term;
526 }
527 return phi;
528 }
529
530 void save(const std::string& filename) const {
531 std::ofstream out(filename, std::ios::binary);
532 if(!out.is_open()) {
533 throw std::runtime_error("Failed to open file for writing: " + filename);
534 }
535
536 // 1. Serialize domain parameters
537 size_t p_size = p1_.size();
538 out.write(reinterpret_cast<const char*>(&p_size), sizeof(p_size));
539 if(p_size > 0) {
540 out.write(reinterpret_cast<const char*>(p1_.data()), p_size * sizeof(double));
541 out.write(reinterpret_cast<const char*>(p2_.data()), p_size * sizeof(double));
542 }
543
544 // 2. Serialize residual variance
545 out.write(reinterpret_cast<const char*>(&residualVariance_), sizeof(residualVariance_));
546
547 // 3. Serialize MultiIndex
548 size_t numIndices = multiIndex_.indices.size();
549 out.write(reinterpret_cast<const char*>(&numIndices), sizeof(numIndices));
550 for(const auto& idx : multiIndex_.indices) {
551 size_t dim = idx.size();
552 out.write(reinterpret_cast<const char*>(&dim), sizeof(dim));
553 out.write(reinterpret_cast<const char*>(idx.data()), dim * sizeof(size_t));
554 }
555
556 // 4. Serialize Eigen Objects
561
562 out.close();
563 }
564
565 void load(const std::string& filename) {
566 std::ifstream in(filename, std::ios::binary);
567 if(!in.is_open()) {
568 throw std::runtime_error("Failed to open file for reading: " + filename);
569 }
570
571 // 1. Deserialize domain parameters
572 size_t p_size = 0;
573 in.read(reinterpret_cast<char*>(&p_size), sizeof(p_size));
574 p1_.resize(p_size);
575 p2_.resize(p_size);
576 if(p_size > 0) {
577 in.read(reinterpret_cast<char*>(p1_.data()), p_size * sizeof(double));
578 in.read(reinterpret_cast<char*>(p2_.data()), p_size * sizeof(double));
579 }
580
581 // 2. Deserialize residual variance
582 in.read(reinterpret_cast<char*>(&residualVariance_), sizeof(residualVariance_));
583
584 // 3. Deserialize MultiIndex
585 size_t numIndices = 0;
586 in.read(reinterpret_cast<char*>(&numIndices), sizeof(numIndices));
587 multiIndex_.indices.clear();
589
590 for(size_t i = 0; i < numIndices; ++i) {
591 size_t dim = 0;
592 in.read(reinterpret_cast<char*>(&dim), sizeof(dim));
593 multiIndex_.indices[i].resize(dim);
594 in.read(reinterpret_cast<char*>(multiIndex_.indices[i].data()), dim * sizeof(size_t));
595 }
596
597 // 4. Deserialize Eigen Objects
602
603 in.close();
604 }
605
606 size_t getNumBasisFunctions() const {
607 return multiIndex_.size();
608 }
609
610 void project(const std::function<double(const Eigen::VectorXd&)>& model, int pointsPerDim) {
611 if(multiIndex_.size() == 0) throw std::runtime_error("Basis not set.");
612 int dim = multiIndex_.indices[0].size();
613
615 int numEvals = integrator.gridNodes.rows();
616
617 Eigen::VectorXd yVals(numEvals);
618 for(int i = 0; i < numEvals; ++i) {
619 // Evaluate the model using the mapped PHYSICAL nodes
620 Eigen::VectorXd physicalPoint(dim);
621 for(size_t d = 0; d < dim; ++d) {
622 physicalPoint(d) = Basis::mapToPhysical(integrator.gridNodes(i, d), p1_[d], p2_[d]);
623 }
625 }
626
627 // Compute coefficients via Galerkin projection
628 for(size_t k = 0; k < multiIndex_.size(); ++k) {
629 double integral_sum = 0.0;
630 double basis_norm_squared = 1.0;
631
632 for(size_t d = 0; d < dim; ++d) {
633 basis_norm_squared *= Basis::normSquared(multiIndex_.indices[k][d]);
634 }
635
636 for(int i = 0; i < numEvals; ++i) {
637 double psi_k = 1.0;
638 for(size_t d = 0; d < dim; ++d) {
639 // Polynomials MUST be evaluated on the CANONICAL nodes
640 psi_k *= Basis::evaluate(multiIndex_.indices[k][d], integrator.gridNodes(i, d));
641 }
642 integral_sum += yVals(i) * psi_k * integrator.gridWeights(i);
643 }
645 }
646 residualVariance_ = 0.0;
647 }
648};
649
650} // namespace cmp
653#endif // POLY_H
Definition poly.h:244
std::size_t size() const
Definition poly.h:252
void print() const
Definition poly.cpp:20
const Index & operator[](std::size_t i) const
Definition poly.h:255
std::vector< size_t > Index
Definition poly.h:246
MultiIndex()=default
std::vector< Index > indices
Multi-index set matrix (each row corresponds to degree exponents vector).
Definition poly.h:247
void set(size_t dimension, size_t totalDegree, double q=1.0)
Definition poly.cpp:3
void generateRecursive(Index &current, int pos, size_t remaining, double currentQSum, double maxQSum, double q)
Definition poly.cpp:32
Implements multi-dimensional Polynomial Chaos Expansion (PCE) for spectral surrogate modeling.
Definition poly.h:301
void readEigenMatrix(std::ifstream &in, MatrixType &mat)
Definition poly.h:347
Eigen::VectorXd predictBatch(const Eigen::Ref< const Eigen::MatrixXd > &X) const
Definition poly.h:434
double residualVariance_
Running residual variance.
Definition poly.h:308
void fit(const Eigen::Ref< const Eigen::MatrixXd > &samples, const Eigen::Ref< const Eigen::VectorXd > &values)
Definition poly.h:369
Eigen::VectorXd yObs_
Training target response values.
Definition poly.h:307
size_t getNumBasisFunctions() const
Definition poly.h:606
void project(const std::function< double(const Eigen::VectorXd &)> &model, int pointsPerDim)
Definition poly.h:610
std::pair< double, double > predictLOO(const size_t &i) const
Definition poly.h:476
Eigen::MatrixXd normalMatrixInverse_
Precomputed inverse normal matrix (A^T A)^-1.
Definition poly.h:305
Eigen::VectorXd p1_
Mapping boundary lower limits/means.
Definition poly.h:311
void save(const std::string &filename) const
Definition poly.h:530
MultiIndex multiIndex_
Multi-index set defining the active polynomial terms.
Definition poly.h:303
double getAnalyticalVariance() const
Definition poly.h:393
Eigen::VectorXd computeBasisRow(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition poly.h:509
Eigen::VectorXd p2_
Mapping boundary upper limits/std devs.
Definition poly.h:312
Eigen::MatrixXd xObs_
Training input data in canonical space.
Definition poly.h:306
void load(const std::string &filename)
Definition poly.h:565
Eigen::MatrixXd computeDesignMatrix(const Eigen::Ref< const Eigen::MatrixXd > &X) const
Definition poly.h:315
Eigen::VectorXd getSobolMainIndices() const
Definition poly.h:405
void set(size_t dimension, size_t totalDegree, const Eigen::VectorXd &p1, const Eigen::VectorXd &p2, double q=1.0)
Definition poly.h:359
double getAnalyticalMean() const
Definition poly.h:388
Eigen::VectorXd coefficients_
Estimated expansion coefficients vector.
Definition poly.h:304
std::pair< double, double > predictWithObs(const Eigen::Ref< const Eigen::VectorXd > &x, const double &yObs) const
Definition poly.h:450
void writeEigenMatrix(std::ofstream &out, const MatrixType &mat) const
Definition poly.h:338
std::pair< double, double > predict(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition poly.h:439
Multi-dimensional tensor product quadrature integrator.
Definition integrator.h:108
Definition classifier.h:17
Chebyshev orthogonal polynomial basis.
Definition poly.h:149
static double mapToPhysical(double xi, double lowerBound, double upperBound)
Definition poly.h:181
static double evaluate(size_t deg, double xi)
Definition poly.h:150
static double normSquared(size_t deg)
Definition poly.h:162
static double mapToCanonical(double x, double lowerBound, double upperBound)
Definition poly.h:185
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:168
Hermite orthogonal polynomial basis.
Definition poly.h:36
static double mapToCanonical(double x, double mean, double stdDev)
Definition poly.h:75
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:55
static double normSquared(size_t deg)
Definition poly.h:49
static double evaluate(size_t deg, double xi)
Definition poly.h:37
static double mapToPhysical(double xi, double mean, double stdDev)
Definition poly.h:70
static double getPDFWeight()
Definition poly.h:65
Laguerre orthogonal polynomial basis.
Definition poly.h:203
static double mapToCanonical(double x, double location, double scale)
Definition poly.h:239
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:220
static double normSquared(size_t deg)
Definition poly.h:216
static double mapToPhysical(double xi, double location, double scale)
Definition poly.h:234
static double evaluate(size_t deg, double xi)
Definition poly.h:204
Legendre orthogonal polynomial basis.
Definition poly.h:94
static double getPDFWeight()
Definition poly.h:121
static double evaluate(size_t deg, double xi)
Definition poly.h:95
static double normSquared(size_t deg)
Definition poly.h:107
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:111
static double mapToCanonical(double x, double lowerBound, double upperBound)
Definition poly.h:131
static double mapToPhysical(double xi, double lowerBound, double upperBound)
Definition poly.h:126