https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PolynomialChaosTrainer.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#include "Sampler.h"
12#include "CartesianProduct.h"
13
15
18{
20 params.addClassDescription("Computes and evaluates polynomial chaos surrogate model.");
21 params.addRequiredParam<unsigned int>("order", "Maximum polynomial order.");
22 params.addRequiredParam<std::vector<DistributionName>>(
23 "distributions", "Names of the distributions samples were taken from.");
24 MooseEnum rtype("integration ols auto", "auto");
25 params.addParam<MooseEnum>(
26 "regression_type",
27 rtype,
28 "The type of regression to perform for finding polynomial coefficents.");
29 params.addParam<Real>("penalty", 0.0, "Ridge regularization penalty factor for OLS regression.");
30
31 params.suppressParameter<MooseEnum>("response_type");
32 return params;
33}
34
36 : SurrogateTrainer(parameters),
37 _predictor_row(getPredictorData()),
38 _order(declareModelData<unsigned int>("_order", getParam<unsigned int>("order"))),
39 _ndim(declareModelData<unsigned int>("_ndim", _sampler.getNumberOfCols())),
40 _tuple(declareModelData<std::vector<std::vector<unsigned int>>>(
41 "_tuple", StochasticTools::MultiDimPolynomialGenerator::generateTuple(_ndim, _order))),
42 _ncoeff(declareModelData<std::size_t>("_ncoeff", _tuple.size())),
43 _coeff(declareModelData<std::vector<Real>>("_coeff")),
44 _poly(declareModelData<std::vector<std::unique_ptr<const PolynomialQuadrature::Polynomial>>>(
45 "_poly")),
46 _ridge_penalty(getParam<Real>("penalty")),
47 _quad_sampler(dynamic_cast<QuadratureSampler *>(&_sampler))
48{
49 // Check if number of distributions is correct
51 paramError("distributions",
52 "Sampler number of columns does not match number of inputted distributions.");
53
54 auto rtype_enum = getParam<MooseEnum>("regression_type");
55 if (rtype_enum == "auto")
56 _rtype = _quad_sampler ? 0 : 1;
57 else
58 _rtype = rtype_enum == "integration" ? 0 : 1;
59
60 if (_rtype == 0 && _quad_sampler &&
61 (!_pvals.empty() || _pcols.size() != _sampler.getNumberOfCols()))
62 paramError("sampler",
63 "QuadratureSampler must use all Sampler columns for training, and cannot be"
64 " used with other Reporters - otherwise, quadrature integration does not work.");
65 if (_rtype == 0 && _ridge_penalty != 0.0)
66 paramError("penalty",
67 "Ridge regularization penalty is only relevant if 'regression_type = ols'.");
68
69 // Make polynomials
70 for (const auto & nm : getParam<std::vector<DistributionName>>("distributions"))
72
73 // Create calculators for standardization
74 if (_rtype == 1)
75 {
76 _calculators.resize(_ncoeff * 3);
77 for (const auto & term : make_range(_ncoeff))
78 {
80 _calculators[3 * term + 1] = StochasticTools::makeCalculator(MooseEnumItem("stddev"), *this);
81 _calculators[3 * term + 2] = StochasticTools::makeCalculator(MooseEnumItem("sum"), *this);
82 }
83 }
84}
85
86void
88{
89 _coeff.assign(_ncoeff, 0.0);
90
91 if (_rtype == 1)
92 {
94 paramError("order",
95 "Number of data points (",
97 ") must be greater than the number of terms in the polynomial (",
98 _ncoeff,
99 ").");
101 _rhs.resize(_ncoeff);
102 for (auto & calc : _calculators)
103 calc->initializeCalculator();
104 _r_sum = 0.0;
105 }
106}
107
108void
110{
111 // Evaluate polynomials to avoid duplication
112 DenseMatrix<Real> poly_val(_ndim, _order);
113 for (unsigned int d = 0; d < _ndim; ++d)
114 for (unsigned int i = 0; i < _order; ++i)
115 poly_val(d, i) = _poly[d]->compute(i, _predictor_row[d], /*normalize=*/_rtype == 0);
116
117 // Evaluate multi-dimensional polynomials
118 std::vector<Real> basis(_ncoeff, 1.0);
119 for (const auto i : make_range(_ncoeff))
120 for (const auto d : make_range(_ndim))
121 basis[i] *= poly_val(d, _tuple[i][d]);
122
123 // For integration
124 if (_rtype == 0)
125 {
126 const Real fact = (*_rval) * (_quad_sampler ? _quad_sampler->getQuadratureWeight(_row) : 1.0);
127 for (const auto i : make_range(_ncoeff))
128 _coeff[i] += fact * basis[i];
129 }
130 // For least-squares
131 else
132 {
133 // Loop over coefficients
134 for (const auto i : make_range(_ncoeff))
135 {
136 // Matrix is symmetric, so we'll add the upper diagonal later
137 for (const auto j : make_range(i + 1))
138 _matrix(i, j) += basis[i] * basis[j];
139 _rhs(i) += basis[i] * (*_rval);
140
141 for (unsigned int c = i * 3; c < (i + 1) * 3; ++c)
142 _calculators[c]->updateCalculator(basis[i]);
143 }
144 _r_sum += (*_rval);
145
146 if (_ridge_penalty != 0.0)
147 for (const auto i : make_range(_ncoeff))
148 _matrix(i, i) += _ridge_penalty;
149 }
150}
151
152void
154{
155 if (_rtype == 0)
156 {
158 if (!_quad_sampler)
159 for (std::size_t i = 0; i < _ncoeff; ++i)
161 }
162 else
163 {
165 gatherSum(_rhs.get_values());
166 for (auto & calc : _calculators)
167 calc->finalizeCalculator(true);
169
170 std::vector<Real> mu(_ncoeff);
171 std::vector<Real> sig(_ncoeff);
172 std::vector<Real> sum_pf(_ncoeff);
173 for (const auto i : make_range(_ncoeff))
174 {
175 mu[i] = i > 0 ? _calculators[3 * i]->getValue() : 0.0;
176 sig[i] = i > 0 ? _calculators[3 * i + 1]->getValue() : 1.0;
177 sum_pf[i] = _calculators[3 * i + 2]->getValue();
178 }
179
180 const Real n = getCurrentSampleSize();
181 for (const auto i : make_range(_ncoeff))
182 {
183 for (const auto j : make_range(i + 1))
184 {
185 _matrix(i, j) -= (mu[j] * sum_pf[i] + mu[i] * sum_pf[j]);
186 _matrix(i, j) += n * mu[i] * mu[j];
187 _matrix(i, j) /= (sig[i] * sig[j]);
188 _matrix(j, i) = _matrix(i, j);
189 }
190 _rhs(i) = (_rhs(i) - mu[i] * _r_sum) / sig[i];
191 }
192
193 DenseVector<Real> sol;
194 _matrix.lu_solve(_rhs, sol);
195 _coeff = sol.get_values();
196
197 for (unsigned int i = 1; i < _ncoeff; ++i)
198 {
199 _coeff[i] /= sig[i];
200 _coeff[0] -= _coeff[i] * mu[i];
201 }
202 }
203}
const double mu
registerMooseObject("StochasticToolsApp", PolynomialChaosTrainer)
void ErrorVector unsigned int
const Distribution & getDistributionByName(const DistributionName &name) const
void suppressParameter(const std::string &name)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
unsigned int & _ndim
Total number of parameters/dimensions.
const unsigned int & _order
Maximum polynomial order. The sum of 1D polynomial orders does not go above this value.
unsigned int _rtype
The method in which to perform the regression (0=integration, 1=OLS)
const Real & _ridge_penalty
The penalty parameter for Ridge regularization.
virtual void preTrain() override
QuadratureSampler * _quad_sampler
QuadratureSampler pointer, necessary for applying quadrature weights.
std::vector< std::unique_ptr< RealCalculator > > _calculators
Calculators used for standardization in linear regression.
std::vector< std::unique_ptr< const PolynomialQuadrature::Polynomial > > & _poly
The distributions used for sampling.
virtual void postTrain() override
std::vector< Real > & _coeff
These are the coefficients we are after in the PC expansion.
std::vector< std::vector< unsigned int > > & _tuple
A _ndim-by-_ncoeff matrix containing the appropriate one-dimensional polynomial order.
virtual void train() override
const std::vector< Real > & _predictor_row
Predictor values.
std::size_t & _ncoeff
Total number of coefficient (defined by size of _tuple)
static InputParameters validParams()
PolynomialChaosTrainer(const InputParameters &parameters)
A class used to produce samples based on quadrature for Polynomial Chaos.
Real getQuadratureWeight(dof_id_type row_index) const
dof_id_type getNumberOfCols() const
This is the main trainer base class.
unsigned int getCurrentSampleSize() const
dof_id_type _row
During training loop, this is the row index of the data.
std::vector< const Real * > _pvals
Predictor values from reporters.
static InputParameters validParams()
std::vector< unsigned int > _pcols
Columns from sampler for predictors.
void gatherSum(T &value)
std::vector< T > & get_values()
void resize(const unsigned int new_m, const unsigned int new_n)
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Polynomials and quadratures based on defined distributions for Polynomial Chaos.
std::unique_ptr< const Polynomial > makePolynomial(const Distribution *dist)
Enum for batch type in stochastic tools MultiApp.
std::unique_ptr< Calculator< InType, OutType > > makeCalculator(const MooseEnumItem &item, const libMesh::ParallelObject &other)