https://mooseframework.inl.gov
NestedMonteCarloSampler.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 "Distribution.h"
12 
13 registerMooseObjectAliased("StochasticToolsApp", NestedMonteCarloSampler, "NestedMonteCarlo");
14 
17 {
19  params.addClassDescription("Monte Carlo sampler for nested loops of parameters.");
20  params.addRequiredParam<std::vector<dof_id_type>>(
21  "num_rows",
22  "The number of rows for each loop of parameters. The first number represents the outermost "
23  "loop.");
24  params.addRequiredParam<std::vector<std::vector<DistributionName>>>(
25  "distributions",
26  "Sets of distribution names to be sampled. Each set defines the parameters for the nested "
27  "loop, with the first set being the outermost loop.");
28  return params;
29 }
30 
32  : Sampler(parameters)
33 {
34  // Grab inputs and make sure size is consistent
35  const auto & dnames = getParam<std::vector<std::vector<DistributionName>>>("distributions");
36  const auto & nrows = getParam<std::vector<dof_id_type>>("num_rows");
37  if (dnames.size() != nrows.size())
38  paramError("distributions",
39  "There must be a set of distributions for each loop defined by 'num_rows'.");
40 
41  // Gather distribution pointers and fill in loop index
42  const std::size_t nloop = dnames.size();
43  std::vector<std::size_t> loop_index;
44  for (const auto & n : make_range(nloop))
45  for (const auto & name : dnames[n])
46  {
48  loop_index.push_back(n);
49  }
50 
51  // Compute what row indices need to recompute which columns
52  std::vector<dof_id_type> loop_mod(nloop);
53  std::partial_sum(nrows.rbegin(), nrows.rend(), loop_mod.rbegin(), std::multiplies<dof_id_type>());
54  loop_mod.erase(loop_mod.begin());
55  loop_mod.push_back(1);
56 
57  // Fill in the mod for each column
58  _col_mod.resize(_distributions.size());
59  for (const auto j : index_range(_distributions))
60  _col_mod[j] = loop_mod[loop_index[j]];
61 
62  setNumberOfRows(std::accumulate(nrows.begin(), nrows.end(), 1, std::multiplies<dof_id_type>()));
64 }
65 
66 Real
68 {
69  const auto mod = _col_mod[col_index];
70  const dof_id_type target_row = std::floor(row_index / mod) * mod;
71  const Real rn = getRand(target_row * getNumberOfCols() + col_index);
72  return _distributions[col_index]->quantile(rn);
73 }
void setNumberOfRows(dof_id_type n_rows)
static InputParameters validParams()
static InputParameters validParams()
void paramError(const std::string &param, Args... args) const
NestedMonteCarloSampler(const InputParameters &parameters)
std::vector< const Distribution * > _distributions
Storage for distribution objects to be utilized.
std::vector< dof_id_type > _col_mod
Helper for determining the target row for the given column index: target_row = std::floor(row_index /...
registerMooseObjectAliased("StochasticToolsApp", NestedMonteCarloSampler, "NestedMonteCarlo")
void addRequiredParam(const std::string &name, const std::string &doc_string)
const std::string & name() const
Real getRand(std::size_t n, unsigned int index=0) const
virtual Real computeSample(dof_id_type row_index, dof_id_type col_index) override
Return the sample for the given row and column.
const Distribution & getDistributionByName(const DistributionName &name) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void setNumberOfCols(dof_id_type n_cols)
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")
auto index_range(const T &sizable)
dof_id_type getNumberOfCols() const
A class used to perform nested Monte Carlo Sampling.
uint8_t dof_id_type