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
10 #include "Sampler.h"
11 #include "DenseMatrix.h"
13 #include "StochasticToolsUtils.h"
14 
15 #ifdef MOOSE_LIBTORCH_ENABLED
17 #endif
18 
19 registerMooseObject("StochasticToolsApp", AdaptiveMonteCarloDecision);
20 
23 {
25  params.addClassDescription("Generic reporter which decides whether or not to accept a proposed "
26  "sample in Adaptive Monte Carlo type of algorithms.");
27  params.addRequiredParam<ReporterName>("output_value",
28  "Value of the model output from the SubApp.");
29  params.addParam<ReporterValueName>(
30  "output_required",
31  "output_required",
32  "Modified value of the model output from this reporter class.");
33  params.addParam<ReporterValueName>("inputs", "inputs", "Uncertain inputs to the model.");
34  params.addRequiredParam<SamplerName>("sampler", "The sampler object.");
35  params.addParam<UserObjectName>("gp_decision", "The Gaussian Process decision reporter.");
36  return params;
37 }
38 
40  : GeneralReporter(parameters),
41  _output_value(isParamValid("gp_decision") ? getReporterValue<std::vector<Real>>("output_value")
42  : getReporterValue<std::vector<Real>>(
43  "output_value", REPORTER_MODE_DISTRIBUTED)),
44  _output_required(declareValue<std::vector<Real>>("output_required")),
45  _inputs(declareValue<std::vector<std::vector<Real>>>("inputs")),
46  _sampler(getSampler("sampler")),
47  _ais(dynamic_cast<const AdaptiveImportanceSampler *>(&_sampler)),
48  _pss(dynamic_cast<const ParallelSubsetSimulation *>(&_sampler)),
49  _check_step(std::numeric_limits<int>::max()),
50  _local_comm(_sampler.getLocalComm()),
51  _gp_used(isParamValid("gp_decision")),
52 #ifdef MOOSE_LIBTORCH_ENABLED
53  _gp_training_samples(
54  _gp_used ? &getUserObject<ActiveLearningGPDecision>("gp_decision").getTrainingSamples()
55  : nullptr)
56 #else
57  _gp_training_samples(nullptr)
58 #endif
59 {
60 #ifndef MOOSE_LIBTORCH_ENABLED
61  if (_gp_used)
62  paramError("gp_decision", "The 'gp_decision' parameter requires libtorch.");
63 #endif
64 
65  // Check whether the selected sampler is an adaptive sampler or not
66  if (!_ais && !_pss)
67  paramError("sampler", "The selected sampler is not an adaptive sampler.");
68 
69  const auto rows = _sampler.getNumberOfRows();
70  const auto cols = _sampler.getNumberOfCols();
71 
72  // Initialize the required variables depending upon the type of adaptive Monte Carlo algorithm
73  _inputs.resize(cols, std::vector<Real>(rows));
74  _prev_val.resize(cols, std::vector<Real>(rows));
75  _output_required.resize(rows);
76  _prev_val_out.resize(rows);
77 
78  if (_ais)
79  {
80  for (dof_id_type j = 0; j < _sampler.getNumberOfCols(); ++j)
81  _prev_val[j][0] = _ais->getInitialValues()[j];
83  }
84  else if (_pss)
85  {
86  _inputs_sto.resize(cols, std::vector<Real>(_pss->getNumSamplesSub()));
87  _inputs_sorted.resize(cols);
89  _output_limit = -std::numeric_limits<Real>::max();
90  }
91 }
92 
93 void
95 {
96  const std::vector<Real> & tmp1 = _ais->getInitialValues();
97  for (dof_id_type j = 0; j < tmp1.size(); ++j)
98  _inputs[j][0] = tmp1[j];
100  _prev_val_out[0] = 1.0;
101 }
102 
103 void
105 {
107  {
109  return;
110  }
111 
112  /* Decision step to whether or not to accept the proposed sample by the sampler.
113  This decision step changes with the type of adaptive Monte Carlo sampling algorithm. */
114  if (_ais)
115  {
116  const Real tmp = _ais->getUseAbsoluteValue() ? std::abs(_output_value[0]) : _output_value[0];
117 
118  /* Checking whether a GP surrogate is used. If it is used, importance sampling is not performed
119  during the training phase of the GP and all proposed samples are accepted until the training
120  phase is completed. Once the training is completed, the importance sampling starts.
121  If a GP surrogate is not used, the standard proposal and acceptance/rejection is performed as
122  part of the importance sampling. */
123  const bool restart_gp = _gp_used && _t_step == *_gp_training_samples;
124  const bool output_limit_reached = _gp_used || tmp >= _output_limit;
125  if (restart_gp)
126  reinitChain();
127 
128  _output_required[0] = output_limit_reached ? 1.0 : 0.0;
129 
130  if (_t_step <= _ais->getNumSamplesTrain() && !restart_gp)
131  {
132  /* This is the training phase of the Adaptive Importance Sampling algorithm.
133  Here, it is decided whether or not to accept a proposed sample by the
134  AdaptiveImportanceSampler.C sampler depending upon the model output_value. */
135  _inputs = output_limit_reached
137  : _prev_val;
138  if (output_limit_reached)
139  _prev_val = _inputs;
141  }
142  else if (_t_step > _ais->getNumSamplesTrain() && !restart_gp)
143  {
144  /* This is the sampling phase of the Adaptive Importance Sampling algorithm.
145  Here, all proposed samples by the AdaptiveImportanceSampler.C sampler are accepted since
146  the importance distribution traning phase is finished. */
148  _prev_val_out[0] = tmp;
149  }
150  }
151  else if (_pss)
152  {
153  // Track the current subset
154  const unsigned int subset =
156  const unsigned int sub_ind =
157  (_t_step - 1) - (_pss->getNumSamplesSub() / _sampler.getNumberOfRows()) * subset;
158  const unsigned int offset = sub_ind * _sampler.getNumberOfRows();
159  const unsigned int count_max = 1 / _pss->getSubsetProbability();
160 
162  for (dof_id_type ss = _sampler.getLocalRowBegin(); ss < _sampler.getLocalRowEnd(); ++ss)
163  {
164  const auto data = _sampler.getNextLocalRow();
165  for (unsigned int j = 0; j < _sampler.getNumberOfCols(); ++j)
166  data_in(ss, j) = data[j];
167  }
168  _local_comm.sum(data_in.get_values());
169 
170  // Get the accepted samples outputs across all the procs from the previous step
173  : _output_value;
175 
176  // These are the subsequent subsets which use Markov Chain Monte Carlo sampling scheme
177  if (subset > 0)
178  {
179  if (sub_ind == 0)
180  {
181  // _output_sorted contains largest po percentile output values
184  // _inputs_sorted contains the input values corresponding to the largest po percentile
185  // output values
188  // Get the subset's intermediate failure threshold values
190  }
191  // Check whether the number of samples in a Markov chain exceeded the limit
192  if (sub_ind % count_max == 0)
193  {
194  const unsigned int soffset = (sub_ind / count_max) * _sampler.getNumberOfRows();
195  // Reinitialize the starting input values for the next set of Markov chains
196  for (dof_id_type j = 0; j < _sampler.getNumberOfCols(); ++j)
197  _prev_val[j].assign(_inputs_sorted[j].begin() + soffset,
198  _inputs_sorted[j].begin() + soffset + _sampler.getNumberOfRows());
199  _prev_val_out.assign(_output_sorted.begin() + soffset,
200  _output_sorted.begin() + soffset + _sampler.getNumberOfRows());
201  }
202  else
203  {
204  // Otherwise, use the previously accepted input values to propose the next set of input
205  // values
206  for (dof_id_type j = 0; j < _sampler.getNumberOfCols(); ++j)
207  _prev_val[j].assign(_inputs_sto[j].begin() + offset - _sampler.getNumberOfRows(),
208  _inputs_sto[j].begin() + offset);
209  _prev_val_out.assign(_outputs_sto.begin() + offset - _sampler.getNumberOfRows(),
210  _outputs_sto.begin() + offset);
211  }
212  }
213 
214  // Check whether the outputs exceed the subset's intermediate failure threshold value
215  for (dof_id_type ss = 0; ss < _sampler.getNumberOfRows(); ++ss)
216  {
217  // Check whether the outputs exceed the subset's intermediate failure threshold value
218  // If so, accept the proposed input values by the Sampler object
219  // Otherwise, use the previously accepted input values
220  const bool output_limit_reached = _output_required[ss] >= _output_limit;
221  for (dof_id_type i = 0; i < _sampler.getNumberOfCols(); ++i)
222  {
223  _inputs[i][ss] = output_limit_reached ? data_in(ss, i) : _prev_val[i][ss];
224  _inputs_sto[i][ss + offset] = _inputs[i][ss];
225  }
226  if (!output_limit_reached)
228  _outputs_sto[ss + offset] = _output_required[ss];
229  }
230  }
231  // Track the current step
233 }
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.
void paramError(const std::string &param, Args... args) const
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()
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.