https://mooseframework.inl.gov
PMCMCBase.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 "PMCMCBase.h"
12 #include "Uniform.h"
13 #include "DelimitedFileReader.h"
14 
15 registerMooseObject("StochasticToolsApp", PMCMCBase);
16 
19 {
21  params.addClassDescription("Parallel Markov chain Monte Carlo base.");
22  params.addRequiredParam<std::vector<DistributionName>>(
23  "prior_distributions", "The prior distributions of the parameters to be calibrated.");
24  params.addParam<DistributionName>(
25  "prior_variance", "The prior distribution of the variance parameter to be calibrated.");
26  params.addRequiredParam<unsigned int>(
27  "num_parallel_proposals",
28  "Number of proposals to make and corresponding subApps executed in "
29  "parallel.");
30  params.addRequiredParam<FileName>("file_name", "Name of the CSV file with configuration values.");
31  params.addParam<std::string>(
32  "file_column_name", "Name of column in CSV file to use, by default first column is used.");
33  params.addParam<unsigned int>(
34  "num_columns", "Number of columns to be used in the CSV file with the configuration values.");
35  params.addParam<std::vector<Real>>("lower_bound", "Lower bounds for making the next proposal.");
36  params.addParam<std::vector<Real>>("upper_bound", "Upper bounds for making the next proposal.");
37  params.addParam<Real>("variance_bound",
38  std::numeric_limits<Real>::max(),
39  "Upper bound for variance for making the next proposal.");
40  params.addRequiredParam<std::vector<Real>>("initial_values",
41  "The starting values of the inputs to be calibrated.");
42  params.addParam<unsigned int>(
43  "num_random_seeds",
44  100000,
45  "Initialize a certain number of random seeds. Change from the default only if you have to.");
46  return params;
47 }
48 
50  : Sampler(parameters),
51  TransientInterface(this),
52  _num_parallel_proposals(getParam<unsigned int>("num_parallel_proposals")),
53  _lower_bound(isParamValid("lower_bound") ? &getParam<std::vector<Real>>("lower_bound")
54  : nullptr),
55  _upper_bound(isParamValid("upper_bound") ? &getParam<std::vector<Real>>("upper_bound")
56  : nullptr),
57  _variance_bound(getParam<Real>("variance_bound")),
58  _initial_values(getParam<std::vector<Real>>("initial_values")),
59  _num_random_seeds(getParam<unsigned int>("num_random_seeds")),
60  _seed_index(0),
61  _rand_index(0)
62 {
63  // Filling the `priors` vector with the user-provided distributions.
64  for (const DistributionName & name :
65  getParam<std::vector<DistributionName>>("prior_distributions"))
66  _priors.push_back(&getDistributionByName(name));
67 
68  // Filling the `var_prior` object with the user-provided distribution for the variance.
69  if (isParamValid("prior_variance"))
70  _var_prior = &getDistributionByName(getParam<DistributionName>("prior_variance"));
71  else
72  _var_prior = nullptr;
73 
74  // Read the experimental configurations from a csv file
75  MooseUtils::DelimitedFileReader reader(getParam<FileName>("file_name"));
76  reader.read();
77  _confg_values.resize(1);
78  if (isParamValid("file_column_name"))
79  _confg_values[0] = reader.getData(getParam<std::string>("file_column_name"));
80  else if (isParamValid("num_columns"))
81  {
82  _confg_values.resize(getParam<unsigned int>("num_columns"));
83  for (unsigned int i = 0; i < _confg_values.size(); ++i)
84  _confg_values[i] = reader.getData(i);
85  }
86  else
87  _confg_values[0] = reader.getData(0);
88 
89  // Setting the number of sampler rows to be equal to the number of parallel proposals
91 
92  // Setting the number of columns in the sampler matrix (equal to the number of distributions).
93  setNumberOfCols(_priors.size() + _confg_values.size());
94 
95  // Resizing the vectors and vector of vectors
98  std::vector<Real>(_priors.size() + _confg_values.size(), 0.0));
101 
104 
105  // Check whether both the lower and the upper bounds are specified and of same size
106  bool bound_check1 = _lower_bound && !_upper_bound;
107  bool bound_check2 = !_lower_bound && _upper_bound;
108  if (bound_check1 || bound_check2)
109  mooseError("Both lower and upper bounds should be specified.");
110  bool size_check = _lower_bound ? ((*_lower_bound).size() != (*_upper_bound).size()) : 0;
111  if (size_check)
112  mooseError("Lower and upper bounds should be of the same size.");
113 
114  // Check whether the priors, bounds, and initial values are all of the same size
115  if (_priors.size() != _initial_values.size())
116  mooseError("The priors and initial values should be of the same size.");
117 }
118 
119 void
121 {
122  for (unsigned int j = 0; j < _num_parallel_proposals; ++j)
123  for (unsigned int i = 0; i < _priors.size(); ++i)
124  _new_samples[j][i] = _priors[i]->quantile(random());
125 }
126 
127 void
129 {
131  _rand_index = 0;
132 
133  // Filling the new_samples vector of vectors with new proposal samples
134  proposeSamples();
135 
136  // Draw random numbers to facilitate decision making later on
137  for (unsigned int j = 0; j < _num_parallel_proposals; ++j)
138  _rnd_vec[j] = random();
139 }
140 
141 Real
143 {
144  return getRand(_rand_index++, _seed_index);
145 }
146 
147 unsigned int
148 PMCMCBase::randomIndex(const unsigned int & upper_bound, const unsigned int & exclude)
149 {
150  auto req_index = exclude;
151  while (req_index == exclude)
152  req_index = getRandl(_rand_index++, 0, upper_bound, _seed_index);
153  return req_index;
154 }
155 
156 std::pair<unsigned int, unsigned int>
157 PMCMCBase::randomIndexPair(const unsigned int & upper_bound, const unsigned int & exclude)
158 {
159  auto req_index1 = randomIndex(upper_bound, exclude);
160  auto req_index2 = req_index1;
161  while (req_index1 == req_index2)
162  req_index2 = randomIndex(upper_bound, exclude);
163  return {req_index1, req_index2};
164 }
165 
166 void
168 {
169  unsigned int index1;
170  int index2 = -1;
171  std::vector<Real> tmp;
172  for (unsigned int i = 0; i < _num_parallel_proposals * _confg_values[0].size(); ++i)
173  {
174  index1 = i % _num_parallel_proposals;
175  if (index1 == 0)
176  ++index2;
177  tmp = _new_samples[index1];
178  for (unsigned int j = 0; j < _confg_values.size(); ++j)
179  tmp.push_back(_confg_values[j][index2]);
180  _new_samples_confg[i] = tmp;
181  }
182 }
183 
184 const std::vector<Real> &
186 {
187  return _rnd_vec;
188 }
189 
190 const std::vector<Real> &
192 {
193  return _new_var_samples;
194 }
195 
196 const std::vector<std::vector<Real>> &
198 {
199  return _new_samples;
200 }
201 
202 const std::vector<const Distribution *>
204 {
205  return _priors;
206 }
207 
208 const Distribution *
210 {
211  return _var_prior;
212 }
213 
214 Real
216 {
217  if (_t_step < 1)
218  for (unsigned int i = 0; i < _num_parallel_proposals; ++i)
220 
221  // Combine the proposed samples with experimental configurations
223 
224  return _new_samples_confg[row_index][col_index];
225 }
void setNumberOfRows(dof_id_type n_rows)
Real random()
Sample a random number between 0 and 1.
Definition: PMCMCBase.C:142
const unsigned int _num_random_seeds
Initialize a certain number of random seeds. Change from the default only if you have to...
Definition: PMCMCBase.h:148
const unsigned int _num_parallel_proposals
Number of parallel proposals to be made and subApps to be executed.
Definition: PMCMCBase.h:112
const std::vector< std::vector< Real > > & getSamples() const
Return the proposed samples to facilitate decision making in reporters.
Definition: PMCMCBase.C:197
const std::vector< Real > & _initial_values
Initial values of the input params to get the MCMC scheme started.
Definition: PMCMCBase.h:130
std::size_t _rand_index
Running index for the random number generators.
Definition: PMCMCBase.h:154
static InputParameters validParams()
const T & getParam(const std::string &name) const
std::vector< std::vector< Real > > _new_samples_confg
Vectors of new proposed samples combined with the experimental configuration values.
Definition: PMCMCBase.h:160
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const std::vector< Real > * _lower_bound
Lower bounds for making the next proposal.
Definition: PMCMCBase.h:121
void combineWithExperimentalConfig()
Generates combinations of the new samples with the experimental configurations.
Definition: PMCMCBase.C:167
PMCMCBase(const InputParameters &parameters)
Definition: PMCMCBase.C:49
unsigned int getRandl(std::size_t n, unsigned int lower, unsigned int upper, unsigned int index=0) const
std::vector< const Distribution * > _priors
Storage for prior distribution objects to be utilized.
Definition: PMCMCBase.h:115
registerMooseObject("StochasticToolsApp", PMCMCBase)
const std::vector< const Distribution * > getPriors() const
Return the priors to facilitate decision making in reporters.
Definition: PMCMCBase.C:203
void addRequiredParam(const std::string &name, const std::string &doc_string)
const Distribution * getVarPrior() const
Return the prior over variance to facilitate decision making in reporters.
Definition: PMCMCBase.C:209
virtual void proposeSamples()
Fill in the _new_samples vector of vectors (happens within sampleSetUp)
Definition: PMCMCBase.C:120
const std::string & name() const
std::vector< Real > _new_var_samples
Vector of new proposed variance samples.
Definition: PMCMCBase.h:136
Real getRand(std::size_t n, unsigned int index=0) const
std::pair< unsigned int, unsigned int > randomIndexPair(const unsigned int &upper_bound, const unsigned int &exclude)
Sample two random indices without repitition excluding a specified index.
Definition: PMCMCBase.C:157
unsigned int _seed_index
Generator index when requesting random numbers.
Definition: PMCMCBase.h:151
std::vector< Real > _rnd_vec
Vector of random numbers for decision making.
Definition: PMCMCBase.h:139
const std::vector< std::vector< T > > & getData() const
const std::vector< Real > * _upper_bound
Upper bounds for making the next proposal.
Definition: PMCMCBase.h:124
const std::vector< Real > & getVarSamples() const
Return the proposed variance samples to facilitate decision making in reporters.
Definition: PMCMCBase.C:191
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 > > _new_samples
Vectors of new proposed samples.
Definition: PMCMCBase.h:133
const Distribution * _var_prior
Storage for prior distribution object of the variance to be utilized.
Definition: PMCMCBase.h:118
const std::vector< Real > & getRandomNumbers() const
Return the random numbers to facilitate decision making in reporters.
Definition: PMCMCBase.C:185
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
bool isParamValid(const std::string &name) const
unsigned int randomIndex(const unsigned int &upper_bound, const unsigned int &exclude)
Sample a random index excluding a specified index.
Definition: PMCMCBase.C:148
std::vector< std::vector< Real > > _confg_values
Configuration values.
Definition: PMCMCBase.h:157
virtual void executeSetUp() override
Definition: PMCMCBase.C:128
virtual Real computeSample(dof_id_type row_index, dof_id_type col_index) override
Definition: PMCMCBase.C:215
void ErrorVector unsigned int
static InputParameters validParams()
Definition: PMCMCBase.C:18
uint8_t dof_id_type
void setNumberOfRandomSeeds(std::size_t number)
A base class used to perform Parallel Markov Chain Monte Carlo (MCMC) sampling.
Definition: PMCMCBase.h:19