Metis 2.0.0
High-performance C++20 dual-mode numerical framework
Loading...
Searching...
No Matches
Polynomial Chaos

Metis includes a PCE (Polynomial Chaos Expansion) layer in PolynomialChaos.hpp for spectral uncertainty quantification. It provides Askey-scheme basis polynomials, multidimensional basis construction, structured stochastic quadrature rules and sparse grids, coefficient recovery from projection or regression samples, and symbolic mean and variance propagation. The key benefit is that fitted PCE coefficients can remain symbolic casadi::MX expressions, so statistical moments can be differentiated with respect to design variables without nesting Monte Carlo inside an optimizer. This works in both numeric and symbolic modes.

Quick Start

#include <metis/metis.hpp>
// Build a 1D Legendre basis of degree <= 2
// Get quadrature rule for projection
// Evaluate your model at quadrature nodes
metis::NumericVector values(rule.nodes.size());
for (Eigen::Index i = 0; i < rule.nodes.size(); ++i) {
values(i) = std::sin(rule.nodes(i)); // Example: sin(xi)
}
// Recover PCE coefficients via projection
// Extract mean and variance
double mean = metis::pce_mean(coeffs);
double variance = metis::pce_variance(basis, coeffs);
Multidimensional polynomial chaos basis with fixed truncation/order.
Definition PolynomialChaos.hpp:456
Umbrella header that includes the entire Metis public API.
UnivariateQuadratureRule stochastic_quadrature_rule(const PolynomialChaosDimension &dimension, int order, StochasticQuadratureRule rule=StochasticQuadratureRule::Gauss)
Build a one-dimensional stochastic quadrature rule with a fixed order.
Definition Quadrature.hpp:426
Scalar pce_variance(const PolynomialChaosBasis &basis, const MetisVector< Scalar > &coefficients)
Compute PCE variance from coefficients.
Definition PolynomialChaos.hpp:680
MetisVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition MetisTypes.hpp:67
MetisVector< Scalar > pce_projection_coefficients(const PolynomialChaosBasis &basis, const NumericMatrix &samples, const NumericVector &weights, const MetisVector< Scalar > &sample_values)
Compute PCE projection coefficients from weighted samples (vector).
Definition PolynomialChaos.hpp:554
PolynomialChaosDimension legendre_dimension()
Create a uniform (Legendre) dimension on [-1, 1].
Definition PolynomialChaos.hpp:65
Scalar pce_mean(const MetisVector< Scalar > &coefficients)
Extract PCE mean (zeroth coefficient).
Definition PolynomialChaos.hpp:665

Core API

  • metis::hermite_dimension(): Hermite basis for standard normal variables.
  • metis::legendre_dimension(): Legendre basis for uniform variables on [-1, 1].
  • metis::jacobi_dimension(alpha, beta): Jacobi basis for beta-family variables on [-1, 1].
  • metis::laguerre_dimension(): Laguerre basis for exponential/gamma-family variables on [0, inf).
  • metis::pce_polynomial(dim, order, x): Evaluate a univariate basis function (normalized by default).
  • metis::pce_squared_norm(dim, order, normalized): Get the squared norm of a basis function.
  • metis::PolynomialChaosBasis(dims, degree, opts): Build a multidimensional basis with total-order or tensor-product truncation.
  • metis::pce_projection_coefficients(basis, rule, values): Recover coefficients via weighted projection.
  • metis::pce_regression_coefficients(basis, samples, values, ridge): Recover coefficients via regression.
  • metis::pce_mean(coeffs): Extract the mean from PCE coefficients.
  • metis::pce_variance(basis, coeffs): Extract the variance from PCE coefficients.

Usage Patterns

Supported Families

Use one PolynomialChaosDimension per uncertain input:

auto gaussian = metis::hermite_dimension();
auto uniform = metis::legendre_dimension();
auto beta_like = metis::jacobi_dimension(1.0, 2.0);
auto exponential = metis::laguerre_dimension(); // alpha = 0
PolynomialChaosDimension laguerre_dimension(double alpha=0.0)
Create a Gamma-family (Laguerre) dimension on [0, inf).
Definition PolynomialChaos.hpp:84
PolynomialChaosDimension jacobi_dimension(double alpha, double beta)
Create a Beta-family (Jacobi) dimension on [-1, 1].
Definition PolynomialChaos.hpp:75
PolynomialChaosDimension hermite_dimension()
Create a standard normal (Hermite) dimension.
Definition PolynomialChaos.hpp:57

The canonical variable domains are:

  • Hermite: standard normal variable
  • Legendre: uniform variable on [-1, 1]
  • Jacobi: mapped beta-family variable on [-1, 1]
  • Laguerre: exponential / gamma-family variable on [0, inf)

Evaluate one univariate basis function with:

double psi2 = metis::pce_polynomial(uniform, 2, 0.25);
double raw_norm = metis::pce_squared_norm(uniform, 2, false);
Scalar pce_polynomial(const PolynomialChaosDimension &dimension, int degree, const Scalar &x, bool normalized=true)
Evaluate a univariate chaos basis polynomial.
Definition PolynomialChaos.hpp:413
double pce_squared_norm(const PolynomialChaosDimension &dimension, int degree, bool normalized=true)
Return the probability-measure squared norm of a univariate basis term.
Definition PolynomialChaos.hpp:445

By default pce_polynomial(...) returns the normalized basis function. Pass normalized = false if you want the classical raw polynomial instead.

Building a Multidimensional Basis

PolynomialChaosBasis builds the multi-index set and caches each term's squared norm:

This constructs a total-order basis of degree <= 2. To switch to tensor-product truncation:

2,
.normalized = true
});
@ TensorProduct
Definition PolynomialChaos.hpp:37
Basis construction controls for multidimensional PCE.
Definition PolynomialChaos.hpp:91

Inspect the generated terms and evaluate:

for (const auto &term : basis.terms()) {
// term.multi_index, term.squared_norm
}
xi << 0.25, -0.4;
metis::NumericVector psi = basis.evaluate(xi);

Sample Matrix Layout

For projection and regression, Metis expects the sample matrix as:

  • rows: sample points
  • columns: stochastic dimensions
// For one uncertain variable:
metis::NumericMatrix samples(nodes.size(), 1);
samples.col(0) = nodes;
// For d uncertain variables and N sample points, samples should be N x d.
NumericVector lgl_nodes(int N)
Compute Legendre-Gauss-Lobatto nodes on [-1, 1].
Definition OrthogonalPolynomials.hpp:138
MetisMatrix< NumericScalar > NumericMatrix
Eigen::MatrixXd equivalent.
Definition MetisTypes.hpp:66

Structured Quadrature Rules

For probability-measure quadrature, prefer Quadrature.hpp over manually assembling nodes and weights:

The returned weights already integrate against the probability measure, so for Legendre/uniform variables they sum to 1 directly. You do not need the extra 0.5 scaling that raw lgl_weights(...) require.

For bounded-support families, nested refinement is available:

auto coarse =
2,
UnivariateQuadratureRule stochastic_quadrature_level(const PolynomialChaosDimension &dimension, int level, StochasticQuadratureRule rule=StochasticQuadratureRule::AutoNested)
Build a one-dimensional stochastic quadrature rule from a refinement level.
Definition Quadrature.hpp:456
@ ClenshawCurtis
Nested Clenshaw-Curtis-like rule on bounded support.
Definition Quadrature.hpp:56

For higher-dimensional problems:

auto sparse_grid = metis::smolyak_sparse_grid(
3);
StochasticQuadratureGrid smolyak_sparse_grid(const std::vector< PolynomialChaosDimension > &dimensions, int level, SmolyakQuadratureOptions options={})
Build a Smolyak sparse grid on probability measures.
Definition Quadrature.hpp:554

See Stochastic Quadrature Guide for the full rule set and sparse-grid details.

Projection Coefficients

Use weighted projection when you already have quadrature-like nodes and weights:

auto rule =
metis::NumericVector values(rule.nodes.size());
for (Eigen::Index i = 0; i < rule.nodes.size(); ++i) {
values(i) = 1.2 * metis::pce_polynomial(metis::legendre_dimension(), 0, rule.nodes(i))
+ 0.5 * metis::pce_polynomial(metis::legendre_dimension(), 1, rule.nodes(i))
- 0.7 * metis::pce_polynomial(metis::legendre_dimension(), 2, rule.nodes(i));
}
metis::pce_projection_coefficients(basis, rule, values);

If you already have your own samples matrix and weights vector, the original overloads still work:

metis::pce_projection_coefficients(basis, samples, weights, values);

Regression Coefficients

Use regression when you have collocation samples without matching quadrature weights:

// continued from "Projection Coefficients" above (reuses basis, values)
nodes << -1.0, -0.6, -0.2, 0.2, 0.6, 1.0;
metis::NumericMatrix samples(nodes.size(), 1);
samples.col(0) = nodes;
metis::pce_regression_coefficients(basis, samples, values, 0.0);
MetisVector< Scalar > pce_regression_coefficients(const PolynomialChaosBasis &basis, const NumericMatrix &samples, const MetisVector< Scalar > &sample_values, double ridge=1e-12)
Compute PCE coefficients via least-squares regression (vector).
Definition PolynomialChaos.hpp:630

The final ridge argument is an optional Tikhonov regularization parameter. When ridge = 0, Metis rejects rank-deficient design matrices instead of silently returning a bad fit.

Symbolic Moments

The main Metis-specific payoff is that the sampled response can stay symbolic:

// continued from "Regression Coefficients" above (reuses basis, nodes, samples)
auto a = metis::sym("a");
metis::SymbolicVector sample_values(nodes.size());
for (Eigen::Index i = 0; i < nodes.size(); ++i) {
sample_values(i) = (1.0 + a) * metis::pce_polynomial(metis::legendre_dimension(), 0, nodes(i))
+ (0.25 * a) * metis::pce_polynomial(metis::legendre_dimension(), 2, nodes(i));
}
auto coeffs = metis::pce_regression_coefficients(basis, samples, sample_values, 0.0);
auto mean = metis::pce_mean(coeffs);
auto variance = metis::pce_variance(basis, coeffs);
MetisVector< SymbolicScalar > SymbolicVector
Eigen vector of MX elements.
Definition MetisTypes.hpp:72
SymbolicScalar sym(const std::string &name)
Create a named symbolic scalar variable.
Definition MetisTypes.hpp:107

Because coeffs, mean, and variance are symbolic expressions, you can differentiate them directly:

auto dmean_da = metis::jacobian(mean, a);
auto dvariance_da = metis::jacobian(variance, a);
auto jacobian(const Expr &expression, const Vars &...variables)
Computes Jacobian of an expression with respect to variables.
Definition AutoDiff.hpp:109

With the default normalized basis:

  • pce_mean(coeffs) returns the constant coefficient
  • pce_variance(basis, coeffs) returns the sum of squared non-constant coefficients

If you build the basis with .normalized = false, Metis uses each term's stored squared norm instead.

See Also