https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PolynomialChaos.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
10#include "PolynomialChaos.h"
11#include "Sampler.h"
12#include "CartesianProduct.h"
13
14registerMooseObject("StochasticToolsApp", PolynomialChaos);
15
18{
20 params.addClassDescription("Computes and evaluates polynomial chaos surrogate model.");
21 return params;
22}
23
25 : SurrogateModel(parameters),
26 _order(getModelData<unsigned int>("_order")),
27 _ndim(getModelData<unsigned int>("_ndim")),
28 _ncoeff(getModelData<std::size_t>("_ncoeff")),
29 _tuple(getModelData<std::vector<std::vector<unsigned int>>>("_tuple")),
30 _coeff(getModelData<std::vector<Real>>("_coeff")),
31 _poly(
32 getModelData<std::vector<std::unique_ptr<const PolynomialQuadrature::Polynomial>>>("_poly"))
33{
34}
35
36Real
37PolynomialChaos::evaluate(const std::vector<Real> & x) const
38{
39 mooseAssert(x.size() == _ndim, "Number of inputted parameters does not match PC model.");
40
41 DenseMatrix<Real> poly_val(_ndim, _order);
42
43 // Evaluate polynomials to avoid duplication
44 for (unsigned int d = 0; d < _ndim; ++d)
45 for (unsigned int i = 0; i < _order; ++i)
46 poly_val(d, i) = _poly[d]->compute(i, x[d], /*normalize =*/false);
47
48 Real val = 0;
49 for (std::size_t i = 0; i < _ncoeff; ++i)
50 {
51 Real tmp = _coeff[i];
52 for (unsigned int d = 0; d < _ndim; ++d)
53 tmp *= poly_val(d, _tuple[i][d]);
54 val += tmp;
55 }
56
57 return val;
58}
59
60const std::vector<std::vector<unsigned int>> &
65
66unsigned
67PolynomialChaos::getPolynomialOrder(const unsigned int dim, const unsigned int i) const
68{
69 return _tuple[i][dim];
70}
71
72const std::vector<Real> &
74{
75 return _coeff;
76}
77
78Real
80{
81 mooseAssert(_coeff.size() > 0, "The coefficient matrix is empty.");
82 return _coeff[0];
83}
84
85Real
87{
88 Real var = 0;
89 for (std::size_t i = 1; i < _ncoeff; ++i)
90 {
91 Real norm = 1.0;
92 for (std::size_t d = 0; d < _ndim; ++d)
93 norm *= _poly[d]->innerProduct(_tuple[i][d]);
94 var += _coeff[i] * _coeff[i] * norm;
95 }
96
97 return std::sqrt(var);
98}
99
100Real
101PolynomialChaos::powerExpectation(const unsigned int n) const
102{
103 std::vector<StochasticTools::WeightedCartesianProduct<unsigned int, Real>> order;
104 order.reserve(_ndim);
105 std::vector<std::vector<Real>> c_1d(n, std::vector<Real>(_coeff.begin() + 1, _coeff.end()));
106 for (unsigned int d = 0; d < _ndim; ++d)
107 {
108 std::vector<std::vector<unsigned int>> order_1d(n, std::vector<unsigned int>(_ncoeff - 1));
109 for (std::size_t i = 1; i < _ncoeff; ++i)
110 for (unsigned int m = 0; m < n; ++m)
111 order_1d[m][i - 1] = _tuple[i][d];
113 }
114
115 dof_id_type n_local, st_local, end_local;
117 order[0].numRows(), n_processors(), processor_id(), n_local, st_local, end_local);
118
119 Real val = 0;
120 for (dof_id_type i = st_local; i < end_local; ++i)
121 {
122 Real tmp = order[0].computeWeight(i);
123 for (unsigned int d = 0; d < _ndim; ++d)
124 {
125 if (MooseUtils::absoluteFuzzyEqual(tmp, 0.0))
126 break;
127 std::vector<unsigned int> comb(n);
128 for (unsigned int m = 0; m < n; ++m)
129 comb[m] = order[d].computeValue(i, m);
130 tmp *= _poly[d]->productIntegral(comb);
131 }
132 val += tmp;
133 }
134
135 return val;
136}
137
138Real
139PolynomialChaos::computeDerivative(const unsigned int dim, const std::vector<Real> & x) const
140{
141 return computePartialDerivative({dim}, x);
142}
143
144Real
145PolynomialChaos::computePartialDerivative(const std::vector<unsigned int> & dim,
146 const std::vector<Real> & x) const
147{
148 mooseAssert(x.size() == _ndim, "Number of inputted parameters does not match PC model.");
149
150 std::vector<unsigned int> grad(_ndim);
151 for (const auto & d : dim)
152 {
153 mooseAssert(d < _ndim, "Specified dimension is greater than total number of parameters.");
154 grad[d]++;
155 }
156
157 DenseMatrix<Real> poly_val(_ndim, _order);
158
159 // Evaluate polynomials to avoid duplication
160 for (unsigned int d = 0; d < _ndim; ++d)
161 for (unsigned int i = 0; i < _order; ++i)
162 poly_val(d, i) = _poly[d]->computeDerivative(i, x[d], grad[d]);
163
164 Real val = 0;
165 for (std::size_t i = 0; i < _ncoeff; ++i)
166 {
167 Real tmp = _coeff[i];
168 for (unsigned int d = 0; d < _ndim; ++d)
169 tmp *= poly_val(d, _tuple[i][d]);
170 val += tmp;
171 }
172
173 return val;
174}
175
176Real
177PolynomialChaos::computeSobolIndex(const std::set<unsigned int> & ind) const
178{
180
181 // If set is empty, compute mean
182 if (ind.empty())
183 return computeMean();
184
185 // Do some sanity checks in debug
186 mooseAssert(ind.size() <= _ndim, "Number of indices is greater than number of parameters.");
187 mooseAssert(*ind.rbegin() < _ndim, "Maximum index provided exceeds number of parameters.");
188
189 Real val = 0.0;
190 for (dof_id_type i = _local_coeff_begin; i < _local_coeff_end; ++i)
191 {
192 Real tmp = _coeff[i] * _coeff[i];
193 for (unsigned int d = 0; d < _ndim; ++d)
194 {
195 if ((ind.find(d) != ind.end() && _tuple[i][d] > 0) ||
196 (ind.find(d) == ind.end() && _tuple[i][d] == 0))
197 {
198 tmp *= _poly[d]->innerProduct(_tuple[i][d]);
199 }
200 else
201 {
202 tmp = 0.0;
203 break;
204 }
205 }
206 val += tmp;
207 }
208
209 return val;
210}
211
212Real
213PolynomialChaos::computeSobolTotal(const unsigned int dim) const
214{
216
217 // Do some sanity checks in debug
218 mooseAssert(dim < _ndim, "Requested dimension is greater than number of parameters.");
219
220 Real val = 0.0;
221 for (dof_id_type i = _local_coeff_begin; i < _local_coeff_end; ++i)
222 if (_tuple[i][dim] > 0)
223 val += _coeff[i] * _coeff[i] * _poly[dim]->innerProduct(_tuple[i][dim]);
224
225 return val;
226}
227
228void
239
240void
241PolynomialChaos::store(nlohmann::json & json) const
242{
243 json["order"] = _order;
244 json["ndim"] = getNumberOfParameters();
245 json["ncoeff"] = getNumberofCoefficients();
246 json["tuple"] = getPolynomialOrders();
247 json["coeff"] = getCoefficients();
248 for (const auto & p : _poly)
249 {
250 nlohmann::json jsonp;
251 p->store(jsonp);
252 json["poly"].push_back(jsonp);
253 }
254}
const std::vector< double > x
const Real p
registerMooseObject("StochasticToolsApp", PolynomialChaos)
unsigned int dim
void ErrorVector unsigned int
void addClassDescription(const std::string &doc_string)
const std::vector< std::vector< unsigned int > > & _tuple
A _ndim-by-_ncoeff matrix containing the appropriate one-dimensional polynomial order.
Real powerExpectation(const unsigned int n) const
Compute expectation of a certain power of the QoI: E[(u-\mu)^n].
std::size_t getNumberOfParameters() const
Access number of dimensions/parameters.
Real computeSobolTotal(const unsigned int dim) const
const std::vector< std::unique_ptr< const PolynomialQuadrature::Polynomial > > & _poly
The distributions used for sampling.
Real computeDerivative(const unsigned int dim, const std::vector< Real > &x) const
Evaluates partial derivative of expansion: du(x)/dx_dim.
dof_id_type _local_coeff_begin
const unsigned int & _order
Maximum polynomial order. The sum of 1D polynomial orders does not go above this value.
static InputParameters validParams()
void linearPartitionCoefficients() const
Real computeSobolIndex(const std::set< unsigned int > &ind) const
Computes Sobol sensitivities S_{i_1,i_2,...,i_s}, where ind = i_1,i_2,...,i_s.
virtual Real evaluate(const std::vector< Real > &x) const override
Evaluate surrogate model given a row of parameters.
virtual Real computeStandardDeviation() const
Evaluate standard deviation: \sigma = sqrt(E[(u-\mu)^2])
const std::vector< std::vector< unsigned int > > & getPolynomialOrders() const
Access polynomial orders from tuple /.
void store(nlohmann::json &json) const
dof_id_type _local_coeff_end
dof_id_type _n_local_coeff
Variables calculation and for looping over the computed coefficients in parallel.
const std::vector< Real > & getCoefficients() const
Access computed expansion coefficients.
const std::vector< Real > & _coeff
These are the coefficients we are after in the PC expansion.
const unsigned int & _ndim
Total number of parameters/dimensions.
virtual Real computeMean() const
Evaluate mean: \mu = E[u].
PolynomialChaos(const InputParameters &parameters)
std::size_t getNumberofCoefficients() const
Number of terms in expansion.
Real computePartialDerivative(const std::vector< unsigned int > &dim, const std::vector< Real > &x) const
Evaluates sum of partial derivative of expansion.
const std::size_t & _ncoeff
Total number of coefficient (defined by size of _tuple)
unsigned int getPolynomialOrder(const unsigned int dim, const unsigned int i) const
static InputParameters validParams()
processor_id_type processor_id() const
processor_id_type n_processors() const
void linearPartitionItems(dof_id_type num_items, dof_id_type num_chunks, dof_id_type chunk_id, dof_id_type &num_local_items, dof_id_type &local_items_begin, dof_id_type &local_items_end)
Polynomials and quadratures based on defined distributions for Polynomial Chaos.