https://mooseframework.inl.gov
ParallelSubsetSimulation.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 
12 #include "Normal.h"
13 #include "Uniform.h"
14 
15 registerMooseObject("StochasticToolsApp", ParallelSubsetSimulation);
16 
19 {
21  params.addClassDescription("Parallel Subset Simulation sampler.");
22  params.addRequiredParam<std::vector<DistributionName>>(
23  "distributions",
24  "The distribution names to be sampled, the number of distributions provided defines the "
25  "number of columns per matrix.");
26  params.addRequiredParam<ReporterName>("output_reporter",
27  "Reporter with results of samples created by the SubApp.");
28  params.addRequiredParam<ReporterName>("inputs_reporter", "Reporter with input parameters.");
29  params.addRangeCheckedParam<Real>("subset_probability",
30  0.1,
31  "subset_probability>0 & subset_probability<=1",
32  "Conditional probability of each subset");
33  params.addRequiredParam<unsigned int>("num_samplessub", "Number of samples per subset");
34  params.addRequiredParam<unsigned int>("num_subsets", "Number of desired subsets");
35  params.addParam<unsigned int>("num_parallel_chains",
36  "Number of Markov chains to run in parallel, default is based on "
37  "the number of processors used.");
38  params.addParam<bool>("use_absolute_value", false, "Use absolute value of the sub app output");
39  params.addParam<unsigned int>(
40  "num_random_seeds",
41  100000,
42  "Initialize a certain number of random seeds. Change from the default only if you have to.");
43  return params;
44 }
45 
47  : Sampler(parameters),
48  _num_samplessub(getParam<unsigned int>("num_samplessub")),
49  _num_subsets(getParam<unsigned int>("num_subsets")),
50  _use_absolute_value(getParam<bool>("use_absolute_value")),
51  _subset_probability(getParam<Real>("subset_probability")),
52  _num_random_seeds(getParam<unsigned int>("num_random_seeds")),
53  _outputs(getReporterValue<std::vector<Real>>("output_reporter")),
54  _inputs(getReporterValue<std::vector<std::vector<Real>>>("inputs_reporter")),
55  _step(getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")->timeStep()),
56  _count_max(std::floor(1 / _subset_probability)),
57  _subset(0),
58  _is_sampling_completed(false)
59 {
60  // Fixing the number of rows to the number of processors
61  const dof_id_type nchains = isParamValid("num_parallel_chains")
62  ? getParam<unsigned int>("num_parallel_chains")
64  setNumberOfRows(nchains);
65  if ((_num_samplessub / nchains) % _count_max > 0)
66  mooseError("Number of model evaluations per chain per subset (",
67  _num_samplessub / nchains,
68  ") should be a multiple of requested chain length (",
69  _count_max,
70  ").");
71 
72  // Filling the `distributions` vector with the user-provided distributions.
73  for (const DistributionName & name : getParam<std::vector<DistributionName>>("distributions"))
75 
76  // Setting the number of columns in the sampler matrix (equal to the number of distributions).
78 
79  /* `inputs_sto` is a member variable that aids in deciding the next set of samples
80  in the Subset Simulation algorithm by storing the input parameter values*/
81  _inputs_sto.resize(_distributions.size(), std::vector<Real>(_num_samplessub, 0.0));
82  _outputs_sto.resize(_num_samplessub, 0.0);
83 
84  /* `inputs_sorted` is a member variable which also aids in deciding the next set of samples
85  in the Subset Simulation algorithm by storing the sorted input parameter values
86  by their corresponding output values*/
87  _inputs_sorted.resize(_distributions.size());
88 
89  /* `markov_seed` is a member variable to store the seed input values for proposing
90  the next set of Markov chain samples.*/
91  _markov_seed.resize(_distributions.size());
92 
95 }
96 
97 const unsigned int &
99 {
100  return _num_samplessub;
101 }
102 
103 const bool &
105 {
106  return _use_absolute_value;
107 }
108 
109 const Real &
111 {
112  return _subset_probability;
113 }
114 
115 void
117 {
119  mooseError("Internal bug: the adaptive sampling is supposed to be completed but another sample "
120  "has been requested.");
121 
123  const unsigned int sub_ind = _step - (_num_samplessub / getNumberOfRows()) * _subset;
124  const unsigned int offset = sub_ind * getNumberOfRows();
125 
126  // check if we have completed the last sample
127  if (_subset >= _num_subsets)
128  {
129  _is_sampling_completed = true;
130  return;
131  }
132 
133  // Get and store the accepted samples input across all the procs from the previous step
134  for (dof_id_type j = 0; j < _distributions.size(); ++j)
135  for (dof_id_type ss = 0; ss < getNumberOfRows(); ++ss)
136  _inputs_sto[j][ss + offset] = Normal::quantile(_distributions[j]->cdf(_inputs[j][ss]), 0, 1);
137 
138  // Get the accepted sample outputs across all the procs from the previous step
139  std::vector<Real> tmp =
142  if (tmp.empty())
143  tmp.resize(getNumberOfRows(), 0.0);
144  for (dof_id_type ss = 0; ss < getNumberOfRows(); ++ss)
145  _outputs_sto[ss + offset] = tmp[ss];
146 
147  // These are the subsequent subsets which use Markov Chain Monte Carlo sampling scheme
148  if (_subset > 0)
149  {
150  // Check whether the subset index has changed
151  if (sub_ind == 0)
152  {
153  // _inputs_sorted contains the input values corresponding to the largest po percentile
154  // output values
157  }
158 
159  // Reinitialize the starting inputs values for the next set of Markov chains
160  if (sub_ind % _count_max == 0)
161  {
162  const unsigned int soffset = (sub_ind / _count_max) * getNumberOfRows();
163  for (dof_id_type j = 0; j < _distributions.size(); ++j)
164  _markov_seed[j].assign(_inputs_sorted[j].begin() + soffset,
165  _inputs_sorted[j].begin() + soffset + getNumberOfRows());
166  }
167  // Otherwise, use the previously accepted input values to propose the next set of input
168  // values
169  else
170  {
171  for (dof_id_type j = 0; j < _distributions.size(); ++j)
172  _markov_seed[j].assign(_inputs_sto[j].begin() + offset,
173  _inputs_sto[j].begin() + offset + getNumberOfRows());
174  }
175  }
176 }
177 
178 Real
180 {
181  unsigned int seed_value = _step > 0 ? (_step - 1) * 2 : 0;
182  const dof_id_type n = row_index * getNumberOfCols() + col_index;
183  Real val;
184 
185  if (_subset == 0)
186  val = getRand(n, seed_value);
187  else
188  {
189  const Real rv =
190  Normal::quantile(getRand(n, seed_value), _markov_seed[col_index][row_index], 1.0);
191  const Real acceptance_ratio = std::log(Normal::pdf(rv, 0, 1)) -
192  std::log(Normal::pdf(_markov_seed[col_index][row_index], 0, 1));
193  const Real new_sample = acceptance_ratio > std::log(getRand(n, seed_value + 1))
194  ? rv
195  : _markov_seed[col_index][row_index];
196  val = Normal::cdf(new_sample, 0, 1);
197  }
198 
199  return _distributions[col_index]->quantile(val);
200 }
void setNumberOfRows(dof_id_type n_rows)
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
const std::vector< std::vector< Real > > & _inputs
Reporter value containing input values from decision reporter.
virtual Real cdf(const Real &x) const override
Definition: Normal.C:74
const std::vector< Real > & _outputs
Reporter value containing calculated outputs.
static InputParameters validParams()
const T & getParam(const std::string &name) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
A class used to perform Parallel Subset Simulation Sampling.
std::vector< Distribution const * > _distributions
Storage for distribution objects to be utilized.
std::vector< Real > computeVectorABS(const std::vector< Real > &data)
return the absolute values in a vector.
registerMooseObject("StochasticToolsApp", ParallelSubsetSimulation)
unsigned int _subset
Track the current subset index.
const bool & getUseAbsoluteValue() const
Access use absolute value bool.
virtual Real computeSample(dof_id_type row_index, dof_id_type col_index) override
std::vector< Real > _outputs_sto
Storage for previously accepted sample outputs across all the subsets.
virtual void executeSetUp() override
const Parallel::Communicator & _communicator
const unsigned int & _num_random_seeds
Initialize a certain number of random seeds. Change from the default only if you have to...
std::vector< std::vector< Real > > _markov_seed
Mean input vector for the next proposed sample inputs across several processors.
void addRequiredParam(const std::string &name, const std::string &doc_string)
virtual Real pdf(const Real &x) const override
Definition: Normal.C:68
std::vector< std::vector< Real > > _inputs_sorted
Store the sorted input samples according to their corresponding outputs.
const unsigned int & _num_subsets
Number of subsets.
bool _is_sampling_completed
True if the sampling is completed.
processor_id_type n_processors() const
const std::string & name() const
Real getRand(std::size_t n, unsigned int index=0) const
const int & _step
Track the current step of the main App.
const unsigned int & getNumSamplesSub() const
Access the number samples per subset.
const bool & _use_absolute_value
Absolute value of the model result. Use this when failure is defined as a non-exceedance rather than ...
ParallelSubsetSimulation(const InputParameters &parameters)
const Real & getSubsetProbability() const
Access the subset probability.
const dof_id_type _min_procs_per_row
const unsigned int _count_max
Maximum length of markov chains based on subset probability.
std::vector< std::vector< Real > > _inputs_sto
Storage for the previously accepted sample inputs across all the subsets.
dof_id_type getNumberOfRows() const
const Distribution & getDistributionByName(const DistributionName &name) const
void setAutoAdvanceGenerators(const bool state)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void setNumberOfCols(dof_id_type n_cols)
std::vector< std::vector< Real > > sortInput(const std::vector< std::vector< Real >> &inputs, const std::vector< Real > &outputs, const unsigned int samplessub, const Real subset_prob)
return input values corresponding to the largest po percentile output values.
void mooseError(Args &&... args) const
const Real & _subset_probability
The subset conditional failure probability.
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
bool isParamValid(const std::string &name) const
static InputParameters validParams()
const unsigned int & _num_samplessub
Number of samples per subset.
virtual Real quantile(const Real &p) const override
Definition: Normal.C:80
void ErrorVector unsigned int
dof_id_type getNumberOfCols() const
uint8_t dof_id_type
void setNumberOfRandomSeeds(std::size_t number)