https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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 (",
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
97const unsigned int &
102
103const bool &
108
109const Real &
114
115void
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 {
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
178Real
179ParallelSubsetSimulation::computeSample(dof_id_type row_index, dof_id_type col_index)
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}
registerMooseObject("StochasticToolsApp", ParallelSubsetSimulation)
void ErrorVector unsigned int
const Distribution & getDistributionByName(const DistributionName &name) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
const std::string & name() const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
virtual Real cdf(const Real &x) const override
Definition Normal.C:74
virtual Real pdf(const Real &x) const override
Definition Normal.C:68
virtual Real quantile(const Real &p) const override
Definition Normal.C:80
A class used to perform Parallel Subset Simulation Sampling.
const bool & _use_absolute_value
Absolute value of the model result. Use this when failure is defined as a non-exceedance rather than ...
const Real & getSubsetProbability() const
Access the subset probability.
const std::vector< Real > & _outputs
Reporter value containing calculated outputs.
const unsigned int & _num_random_seeds
Initialize a certain number of random seeds. Change from the default only if you have to.
const unsigned int & getNumSamplesSub() const
Access the number samples per subset.
bool _is_sampling_completed
True if the sampling is completed.
const int & _step
Track the current step of the main App.
ParallelSubsetSimulation(const InputParameters &parameters)
virtual void executeSetUp() override
const bool & getUseAbsoluteValue() const
Access use absolute value bool.
const std::vector< std::vector< Real > > & _inputs
Reporter value containing input values from decision reporter.
const unsigned int & _num_samplessub
Number of samples per subset.
const unsigned int _count_max
Maximum length of markov chains based on subset probability.
const Real & _subset_probability
The subset conditional failure probability.
virtual Real computeSample(dof_id_type row_index, dof_id_type col_index) override
std::vector< Distribution const * > _distributions
Storage for distribution objects to be utilized.
std::vector< std::vector< Real > > _markov_seed
Mean input vector for the next proposed sample inputs across several processors.
std::vector< Real > _outputs_sto
Storage for previously accepted sample outputs across all the subsets.
const unsigned int & _num_subsets
Number of subsets.
std::vector< std::vector< Real > > _inputs_sto
Storage for the previously accepted sample inputs across all the subsets.
std::vector< std::vector< Real > > _inputs_sorted
Store the sorted input samples according to their corresponding outputs.
static InputParameters validParams()
unsigned int _subset
Track the current subset index.
void setNumberOfCols(dof_id_type n_cols)
Real getRand(std::size_t n, unsigned int index=0) const
dof_id_type getNumberOfRows() const
void setAutoAdvanceGenerators(const bool state)
static InputParameters validParams()
dof_id_type getNumberOfCols() const
void setNumberOfRows(dof_id_type n_rows)
const dof_id_type _min_procs_per_row
void setNumberOfRandomSeeds(std::size_t number)
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
const Parallel::Communicator & _communicator
processor_id_type n_processors() const
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.
std::vector< Real > computeVectorABS(const std::vector< Real > &data)
return the absolute values in a vector.