https://mooseframework.inl.gov
PolynomialChaosReporter.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 "SobolReporter.h"
13 #include "StochasticReporter.h"
14 
15 registerMooseObject("StochasticToolsApp", PolynomialChaosReporter);
16 
19 {
21  params.addClassDescription(
22  "Tool for extracting data from PolynomialChaos surrogates and computing statistics.");
23  params.addRequiredParam<std::vector<UserObjectName>>(
24  "pc_name", "Name(s) of PolynomialChaos surrogate object(s).");
25  params.addParam<bool>("include_data",
26  false,
27  "True to output information on the polynomial chaos model, including "
28  "polynomial types, orders, and coefficients.");
29  MultiMooseEnum stats("mean=1 stddev=2 skewness=3 kurtosis=4", "");
30  params.addParam<MultiMooseEnum>("statistics", stats, "Statistics to compute.");
31  params.addParam<bool>("include_sobol", false, "True to compute Sobol indices.");
32  params.addParam<std::vector<std::vector<Real>>>(
33  "local_sensitivity_points",
34  std::vector<std::vector<Real>>(0),
35  "Points for each polynomial chaos surrogate specifying desired location of sensitivity "
36  "measurement.");
37  params.addParam<std::vector<SamplerName>>(
38  "local_sensitivity_sampler",
39  std::vector<SamplerName>(0),
40  "Sampler for each polynomial chaos surrogate specifying desired location of sensitivity "
41  "measurement.");
42  return params;
43 }
44 
46  : GeneralReporter(parameters),
48  _loc_point(getParam<std::vector<std::vector<Real>>>("local_sensitivity_points"))
49 {
50  for (const auto & sn : getParam<std::vector<SamplerName>>("local_sensitivity_sampler"))
51  _loc_sampler.push_back(&getSamplerByName(sn));
52 
53  for (const auto & nm : getParam<std::vector<UserObjectName>>("pc_name"))
54  {
55  // Gather polynomial chaos surrogates
56  _pc.push_back(&getSurrogateModelByName<PolynomialChaos>(nm));
57  // PolynomialChaos data reporter
58  if (getParam<bool>("include_data"))
59  {
60  auto & pc_ptr = declareValueByName<const PolynomialChaos *>(nm, REPORTER_MODE_ROOT);
61  pc_ptr = _pc.back();
62  }
63  // Statistics reporter
64  for (const auto & stat : getParam<MultiMooseEnum>("statistics"))
65  declareValueByName<std::pair<Real, std::vector<Real>>, PCStatisticsContext<Real>>(
66  nm + "_" + stat.name(), REPORTER_MODE_ROOT, *_pc.back(), stat);
67  // Sobol reporter
68  if (getParam<bool>("include_sobol"))
69  declareValueByName<std::pair<std::vector<Real>, std::vector<std::vector<Real>>>,
70  PCSobolContext<Real>>(nm + "_SOBOL", REPORTER_MODE_ROOT, *_pc.back());
71  // Local sensitivity points reporter
72  if (_loc_point.size() > 0)
73  {
74  if (_loc_point.size() < _pc.size())
75  paramError("local_sensitivity_points",
76  "There must be a set of points for each inputted polynomial chaos model.");
77  _loc_point_sense.push_back(&declareValueByName<std::vector<std::vector<Real>>>(
78  nm + "_POINT_SENSITIVITY", REPORTER_MODE_ROOT));
79  }
80  // Local sensitivity sampler reporter
81  if (_loc_sampler.size() > 0)
82  {
83  if (_loc_sampler.size() < _pc.size())
84  paramError("local_sensitivity_sampler",
85  "There must be a sampler for each inputted polynomial chaos model.");
86  _loc_sampler_sense.push_back(
87  &declareValueByName<std::vector<std::vector<Real>>,
88  StochasticReporterContext<std::vector<Real>>>(
89  nm + "_SAMPLE_SENSITIVITY", REPORTER_MODE_ROOT, *_loc_sampler[_pc.size() - 1]));
90  }
91  }
92 }
93 
94 void
96 {
97  if ((_loc_point.size() + _loc_sampler.size()) == 0)
98  return;
99 
100  for (const auto & i : index_range(_pc))
101  {
102  const auto & pc = *_pc[i];
103  const auto nparam = pc.getNumberOfParameters();
104  if (_loc_point.size() > 0)
105  {
106  if (_loc_point[i].size() % pc.getNumberOfParameters() != 0)
107  paramError("local_sensitivity_points",
108  "Number of values must be divisible by number of parameters in "
109  "Polynomial Chaos model.");
110 
111  const auto npoint = _loc_point[i].size() / nparam;
112  _loc_point_sense[i]->resize(npoint);
113  for (const auto & p : make_range(npoint))
114  {
115  const std::vector<Real> data(_loc_point[i].begin() + p * nparam,
116  _loc_point[i].begin() + (p + 1) * nparam);
117  (*_loc_point_sense[i])[p] = computeLocalSensitivity(pc, data);
118  }
119 
120  if (_loc_sampler.size() > 0)
121  {
122  if (_loc_sampler[i]->getNumberOfCols() != nparam)
123  paramError(
124  "local_sensitivity_sampler",
125  "Sampler ",
126  _loc_sampler[i]->name(),
127  " does not have the same number of columns as the number of dimensions in model ",
128  pc.name(),
129  ".");
130  for (const auto & p : make_range(_loc_sampler[i]->getNumberOfLocalRows()))
131  (*_loc_sampler_sense[i])[p] =
132  computeLocalSensitivity(pc, _loc_sampler[i]->getNextLocalRow());
133  }
134  }
135  }
136 }
137 
138 std::vector<Real>
140  const std::vector<Real> & data)
141 {
142  std::vector<Real> sense(data.size());
143  const auto val = pc.evaluate(data);
144  for (const auto & d : index_range(data))
145  sense[d] = data[d] / val * pc.computeDerivative(d, data);
146  return sense;
147 }
148 
149 void
150 to_json(nlohmann::json & json, const PolynomialChaos * const & pc)
151 {
152  pc->store(json);
153 }
154 
155 template <typename OutType>
157  const libMesh::ParallelObject & other,
158  const MooseObject & producer,
159  ReporterState<std::pair<OutType, std::vector<OutType>>> & state,
160  const PolynomialChaos & pc,
161  const MooseEnumItem & stat)
162  : ReporterGeneralContext<std::pair<OutType, std::vector<OutType>>>(other, producer, state),
163  _pc(pc),
164  _stat(stat)
165 {
166 }
167 
168 template <typename OutType>
169 void
171 {
172  // Compute standard deviation
173  OutType sig = OutType();
174  if (_stat == "stddev" || _stat == "skewness" || _stat == "kurtosis")
175  sig = _pc.computeStandardDeviation();
176 
177  OutType & val = this->_state.value().first;
178  val = OutType();
179  // Mean
180  if (_stat == "mean" && this->processor_id() == 0)
181  val = _pc.computeMean();
182  // Standard Deviation
183  else if (_stat == "stddev" && this->processor_id() == 0)
184  val = sig;
185  // Skewness
186  else if (_stat == "skewness")
187  val = _pc.powerExpectation(3) / (sig * sig * sig);
188  // Kurtosis
189  else if (_stat == "kurtosis")
190  val = _pc.powerExpectation(4) / (sig * sig * sig * sig);
191  this->_communicator.sum(val);
192 
194 }
195 
196 template <typename OutType>
197 void
198 PCStatisticsContext<OutType>::storeInfo(nlohmann::json & json) const
199 {
201  json["stat"] = _stat.name();
202 }
203 
204 template <typename OutType>
206  const libMesh::ParallelObject & other,
207  const MooseObject & producer,
208  ReporterState<std::pair<std::vector<OutType>, std::vector<std::vector<OutType>>>> & state,
209  const PolynomialChaos & pc)
210  : ReporterGeneralContext<std::pair<std::vector<OutType>, std::vector<std::vector<OutType>>>>(
211  other, producer, state),
212  _pc(pc)
213 {
214 }
215 
216 template <typename OutType>
217 void
219 {
220  const unsigned int nparam = _pc.getNumberOfParameters();
221  std::vector<OutType> & val = this->_state.value().first;
222  val.clear();
223 
224  // Compute variance
225  auto var = _pc.computeStandardDeviation();
226  var *= var;
227 
228  // First order
229  for (const auto & i : make_range(nparam))
230  val.push_back(_pc.computeSobolIndex({i}) / var);
231  // Total
232  for (const auto & i : make_range(nparam))
233  val.push_back(_pc.computeSobolTotal(i) / var);
234  // Second order
235  for (const auto & i : make_range(nparam))
236  for (const auto & j : make_range(i + 1, nparam))
237  val.push_back(_pc.computeSobolIndex({i, j}) / var);
238 }
239 
240 template <typename OutType>
241 void
242 PCSobolContext<OutType>::store(nlohmann::json & json) const
243 {
244  SobolReporterContext<std::vector<OutType>, OutType>::storeSobol(
245  json, this->_state.value(), _pc.getNumberOfParameters());
246 }
247 
248 template class PCStatisticsContext<Real>;
249 template class PCSobolContext<Real>;
PCSobolContext is almost identical to SobolReporterContext with InType == Outype. ...
T & declareValueByName(const ReporterValueName &value_name, Args &&... args)
T & getSamplerByName(const SamplerName &name)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
PCSobolContext(const libMesh::ParallelObject &other, const MooseObject &producer, ReporterState< std::pair< std::vector< OutType >, std::vector< std::vector< OutType >>>> &state, const PolynomialChaos &pc)
virtual void store(nlohmann::json &json) const override
const ReporterMode REPORTER_MODE_ROOT
virtual void finalize() override
virtual void execute() override
static InputParameters validParams()
PCStatisticsContext(const libMesh::ParallelObject &other, const MooseObject &producer, ReporterState< std::pair< OutType, std::vector< OutType >>> &state, const PolynomialChaos &pc, const MooseEnumItem &stat)
std::vector< std::vector< std::vector< Real > > * > _loc_sampler_sense
Local sensitivity from sampled points.
void store(nlohmann::json &json) const
static InputParameters validParams()
virtual const std::string & name() const
std::vector< std::vector< std::vector< Real > > * > _loc_point_sense
Local sensitivity from specified points.
void addRequiredParam(const std::string &name, const std::string &doc_string)
PCStatisticsContext is almost identical to ReporterStatisticsContext with InType == Outype...
const std::vector< std::vector< Real > > & _loc_point
Points for local sensitivity calculation.
virtual void finalize() override
std::vector< const PolynomialChaos * > _pc
Polynomial chaos models.
const T & getParam(const std::string &name) const
static std::vector< Real > computeLocalSensitivity(const PolynomialChaos &pc, const std::vector< Real > &data)
Helper function for computing local sensitivity from a polynomial chaos model.
void paramError(const std::string &param, Args... args) const
Real computeDerivative(const unsigned int dim, const std::vector< Real > &x) const
Evaluates partial derivative of expansion: du(x)/dx_dim.
PolynomialChaosReporter(const InputParameters &parameters)
virtual Real evaluate(const std::vector< Real > &x) const override
Evaluate surrogate model given a row of parameters.
std::vector< Sampler * > _loc_sampler
Samplers for local sensitivity calculation.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Interface for objects that need to use samplers.
IntRange< T > make_range(T beg, T end)
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual void storeInfo(nlohmann::json &json) const override
auto index_range(const T &sizable)
void to_json(nlohmann::json &json, const PolynomialChaos *const &pc)
registerMooseObject("StochasticToolsApp", PolynomialChaosReporter)