https://mooseframework.inl.gov
AdaptiveMonteCarloDecision.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 "Sampler.h"
12 #include "DenseMatrix.h"
14 #include "StochasticToolsUtils.h"
15 
16 registerMooseObject("StochasticToolsApp", AdaptiveMonteCarloDecision);
17 
20 {
22  params.addClassDescription("Generic reporter which decides whether or not to accept a proposed "
23  "sample in Adaptive Monte Carlo type of algorithms.");
24  params.addRequiredParam<ReporterName>("output_value",
25  "Value of the model output from the SubApp.");
26  params.addParam<ReporterValueName>(
27  "output_required",
28  "output_required",
29  "Modified value of the model output from this reporter class.");
30  params.addParam<ReporterValueName>("inputs", "inputs", "Uncertain inputs to the model.");
31  params.addRequiredParam<SamplerName>("sampler", "The sampler object.");
32  params.addParam<UserObjectName>("gp_decision", "The Gaussian Process decision reporter.");
33  return params;
34 }
35 
37  : GeneralReporter(parameters),
38  _output_value(isParamValid("gp_decision") ? getReporterValue<std::vector<Real>>("output_value")
39  : getReporterValue<std::vector<Real>>(
40  "output_value", REPORTER_MODE_DISTRIBUTED)),
41  _output_required(declareValue<std::vector<Real>>("output_required")),
42  _inputs(declareValue<std::vector<std::vector<Real>>>("inputs")),
43  _sampler(getSampler("sampler")),
44  _ais(dynamic_cast<const AdaptiveImportanceSampler *>(&_sampler)),
45  _pss(dynamic_cast<const ParallelSubsetSimulation *>(&_sampler)),
46  _check_step(std::numeric_limits<int>::max()),
47  _local_comm(_sampler.getLocalComm()),
48  _gp_used(isParamValid("gp_decision")),
49  _gp_training_samples(
50  _gp_used ? &getUserObject<ActiveLearningGPDecision>("gp_decision").getTrainingSamples()
51  : nullptr)
52 {
53 
54  // Check whether the selected sampler is an adaptive sampler or not
55  if (!_ais && !_pss)
56  paramError("sampler", "The selected sampler is not an adaptive sampler.");
57 
58  const auto rows = _sampler.getNumberOfRows();
59  const auto cols = _sampler.getNumberOfCols();
60 
61  // Initialize the required variables depending upon the type of adaptive Monte Carlo algorithm
62  _inputs.resize(cols, std::vector<Real>(rows));
63  _prev_val.resize(cols, std::vector<Real>(rows));
64  _output_required.resize(rows);
65  _prev_val_out.resize(rows);
66 
67  if (_ais)
68  {
69  for (dof_id_type j = 0; j < _sampler.getNumberOfCols(); ++j)
70  _prev_val[j][0] = _ais->getInitialValues()[j];
72  }
73  else if (_pss)
74  {
75  _inputs_sto.resize(cols, std::vector<Real>(_pss->getNumSamplesSub()));
76  _inputs_sorted.resize(cols);
78  _output_limit = -std::numeric_limits<Real>::max();
79  }
80 }
81 
82 void
84 {
85  const std::vector<Real> & tmp1 = _ais->getInitialValues();
86  for (dof_id_type j = 0; j < tmp1.size(); ++j)
87  _inputs[j][0] = tmp1[j];
89  _prev_val_out[0] = 1.0;
90 }
91 
92 void
94 {
96  {
98  return;
99  }
100 
101  /* Decision step to whether or not to accept the proposed sample by the sampler.
102  This decision step changes with the type of adaptive Monte Carlo sampling algorithm. */
103  if (_ais)
104  {
105  const Real tmp = _ais->getUseAbsoluteValue() ? std::abs(_output_value[0]) : _output_value[0];
106 
107  /* Checking whether a GP surrogate is used. If it is used, importance sampling is not performed
108  during the training phase of the GP and all proposed samples are accepted until the training
109  phase is completed. Once the training is completed, the importance sampling starts.
110  If a GP surrogate is not used, the standard proposal and acceptance/rejection is performed as
111  part of the importance sampling. */
112  const bool restart_gp = _gp_used && _t_step == *_gp_training_samples;
113  const bool output_limit_reached = _gp_used || tmp >= _output_limit;
114  if (restart_gp)
115  reinitChain();
116 
117  _output_required[0] = output_limit_reached ? 1.0 : 0.0;
118 
119  if (_t_step <= _ais->getNumSamplesTrain() && !restart_gp)
120  {
121  /* This is the training phase of the Adaptive Importance Sampling algorithm.
122  Here, it is decided whether or not to accept a proposed sample by the
123  AdaptiveImportanceSampler.C sampler depending upon the model output_value. */
124  _inputs = output_limit_reached
126  : _prev_val;
127  if (output_limit_reached)
128  _prev_val = _inputs;
130  }
131  else if (_t_step > _ais->getNumSamplesTrain() && !restart_gp)
132  {
133  /* This is the sampling phase of the Adaptive Importance Sampling algorithm.
134  Here, all proposed samples by the AdaptiveImportanceSampler.C sampler are accepted since
135  the importance distribution traning phase is finished. */
137  _prev_val_out[0] = tmp;
138  }
139  }
140  else if (_pss)
141  {
142  // Track the current subset
143  const unsigned int subset =
145  const unsigned int sub_ind =
146  (_t_step - 1) - (_pss->getNumSamplesSub() / _sampler.getNumberOfRows()) * subset;
147  const unsigned int offset = sub_ind * _sampler.getNumberOfRows();
148  const unsigned int count_max = 1 / _pss->getSubsetProbability();
149 
151  for (dof_id_type ss = _sampler.getLocalRowBegin(); ss < _sampler.getLocalRowEnd(); ++ss)
152  {
153  const auto data = _sampler.getNextLocalRow();
154  for (unsigned int j = 0; j < _sampler.getNumberOfCols(); ++j)
155  data_in(ss, j) = data[j];
156  }
157  _local_comm.sum(data_in.get_values());
158 
159  // Get the accepted samples outputs across all the procs from the previous step
162  : _output_value;
164 
165  // These are the subsequent subsets which use Markov Chain Monte Carlo sampling scheme
166  if (subset > 0)
167  {
168  if (sub_ind == 0)
169  {
170  // _output_sorted contains largest po percentile output values
173  // _inputs_sorted contains the input values corresponding to the largest po percentile
174  // output values
177  // Get the subset's intermediate failure threshold values
179  }
180  // Check whether the number of samples in a Markov chain exceeded the limit
181  if (sub_ind % count_max == 0)
182  {
183  const unsigned int soffset = (sub_ind / count_max) * _sampler.getNumberOfRows();
184  // Reinitialize the starting input values for the next set of Markov chains
185  for (dof_id_type j = 0; j < _sampler.getNumberOfCols(); ++j)
186  _prev_val[j].assign(_inputs_sorted[j].begin() + soffset,
187  _inputs_sorted[j].begin() + soffset + _sampler.getNumberOfRows());
188  _prev_val_out.assign(_output_sorted.begin() + soffset,
189  _output_sorted.begin() + soffset + _sampler.getNumberOfRows());
190  }
191  else
192  {
193  // Otherwise, use the previously accepted input values to propose the next set of input
194  // values
195  for (dof_id_type j = 0; j < _sampler.getNumberOfCols(); ++j)
196  _prev_val[j].assign(_inputs_sto[j].begin() + offset - _sampler.getNumberOfRows(),
197  _inputs_sto[j].begin() + offset);
198  _prev_val_out.assign(_outputs_sto.begin() + offset - _sampler.getNumberOfRows(),
199  _outputs_sto.begin() + offset);
200  }
201  }
202 
203  // Check whether the outputs exceed the subset's intermediate failure threshold value
204  for (dof_id_type ss = 0; ss < _sampler.getNumberOfRows(); ++ss)
205  {
206  // Check whether the outputs exceed the subset's intermediate failure threshold value
207  // If so, accept the proposed input values by the Sampler object
208  // Otherwise, use the previously accepted input values
209  const bool output_limit_reached = _output_required[ss] >= _output_limit;
210  for (dof_id_type i = 0; i < _sampler.getNumberOfCols(); ++i)
211  {
212  _inputs[i][ss] = output_limit_reached ? data_in(ss, i) : _prev_val[i][ss];
213  _inputs_sto[i][ss + offset] = _inputs[i][ss];
214  }
215  if (!output_limit_reached)
217  _outputs_sto[ss + offset] = _output_required[ss];
218  }
219  }
220  // Track the current step
222 }
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
std::vector< std::vector< T > > reshapeVector(const std::vector< T > &vec, std::size_t n, bool row_major)
Reshape a vector into matrix-like vector of vectors.
Sampler & _sampler
The adaptive Monte Carlo sampler.
std::vector< Real > _prev_val_out
Storage for previously accepted output value.
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.
const bool _gp_used
Check if a GP is used.
A class used to perform Adaptive Importance Sampling using a Markov Chain Monte Carlo algorithm...
std::vector< Real > computeVectorABS(const std::vector< Real > &data)
return the absolute values in a vector.
AdaptiveMonteCarloDecision(const InputParameters &parameters)
void reinitChain()
This reinitializes the Markov chain to the starting value until the Gaussian process training is comp...
const bool & getUseAbsoluteValue() const
Access use absolute value bool.
std::vector< Real > getNextLocalRow()
std::vector< std::vector< Real > > _inputs_sto
Storage for the previously accepted sample inputs across all the subsets.
dof_id_type getLocalRowBegin() const
std::vector< std::vector< Real > > _inputs_sorted
Store the sorted input samples according to their corresponding outputs.
std::vector< std::vector< Real > > _prev_val
Storage for previously accepted input values. This helps in making decision on the next proposed inpu...
static InputParameters validParams()
dof_id_type getNumberOfLocalRows() const
void addRequiredParam(const std::string &name, const std::string &doc_string)
auto max(const L &left, const R &right)
const int *const _gp_training_samples
Store the GP training samples.
Real computeMin(const std::vector< Real > &data)
return the minimum value in a vector.
libMesh::Parallel::Communicator & _local_comm
Communicator that was split based on samples that have rows.
const std::vector< Real > & _output_value
Model output value from SubApp.
const unsigned int & getNumSamplesSub() const
Access the number samples per subset.
const ParallelSubsetSimulation *const _pss
Parallel Subset Simulation sampler.
std::vector< Real > _output_sorted
Store the sorted output sample values.
AdaptiveMonteCarloDecision will help make sample accept/reject decisions in adaptive Monte Carlo sche...
int _check_step
Ensure that the MCMC algorithm proceeds in a sequential fashion.
static InputParameters validParams()
void paramError(const std::string &param, Args... args) const
const ReporterMode REPORTER_MODE_DISTRIBUTED
const Real & getSubsetProbability() const
Access the subset probability.
dof_id_type getLocalRowEnd() const
std::vector< Real > _outputs_sto
Storage for previously accepted sample outputs across all the subsets.
dof_id_type getNumberOfRows() const
const int & getNumSamplesTrain() const
const bool & getUseAbsoluteValue() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< Real > & _output_required
Modified value of model output by this reporter class.
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.
const AdaptiveImportanceSampler *const _ais
Adaptive Importance Sampler.
std::vector< std::vector< Real > > & _inputs
Model input data that is uncertain.
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
registerMooseObject("StochasticToolsApp", AdaptiveMonteCarloDecision)
Real _output_limit
Store the intermediate ouput failure thresholds.
const std::vector< Real > & getInitialValues() const
void ErrorVector unsigned int
dof_id_type getNumberOfCols() const
uint8_t dof_id_type
std::vector< Real > sortOutput(const std::vector< Real > &outputs, const unsigned int samplessub, const Real subset_prob)
return the largest po percentile output values.