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(declareRecoverableData<unsigned int>("subset", 0)),
58 _is_sampling_completed(declareRecoverableData<bool>("is_sampling_completed", false)),
59 _inputs_sto(declareRecoverableData<std::vector<std::vector<Real>>>("inputs_sto")),
60 _outputs_sto(declareRecoverableData<std::vector<Real>>("outputs_sto")),
61 _inputs_sorted(declareRecoverableData<std::vector<std::vector<Real>>>("inputs_sorted")),
62 _markov_seed(declareRecoverableData<std::vector<std::vector<Real>>>("markov_seed"))
63{
64 // Fixing the number of rows to the number of processors
65 const dof_id_type nchains = isParamValid("num_parallel_chains")
66 ? getParam<unsigned int>("num_parallel_chains")
68 setNumberOfRows(nchains);
69 if ((_num_samplessub / nchains) % _count_max > 0)
70 mooseError("Number of model evaluations per chain per subset (",
71 _num_samplessub / nchains,
72 ") should be a multiple of requested chain length (",
74 ").");
75
76 // Filling the `distributions` vector with the user-provided distributions.
77 for (const DistributionName & name : getParam<std::vector<DistributionName>>("distributions"))
79
80 // Setting the number of columns in the sampler matrix (equal to the number of distributions).
82
83 /* `inputs_sto` is a member variable that aids in deciding the next set of samples
84 in the Subset Simulation algorithm by storing the input parameter values*/
85 _inputs_sto.resize(_distributions.size(), std::vector<Real>(_num_samplessub, 0.0));
86 _outputs_sto.resize(_num_samplessub, 0.0);
87
88 /* `inputs_sorted` is a member variable which also aids in deciding the next set of samples
89 in the Subset Simulation algorithm by storing the sorted input parameter values
90 by their corresponding output values*/
91 _inputs_sorted.resize(_distributions.size());
92
93 /* `markov_seed` is a member variable to store the seed input values for proposing
94 the next set of Markov chain samples.*/
95 _markov_seed.resize(_distributions.size());
96
99}
100
101const unsigned int &
106
107const bool &
112
113const Real &
118
119void
121{
123 mooseError("Internal bug: the adaptive sampling is supposed to be completed but another sample "
124 "has been requested.");
125
127 const unsigned int sub_ind = _step - (_num_samplessub / getNumberOfRows()) * _subset;
128 const unsigned int offset = sub_ind * getNumberOfRows();
129
130 // check if we have completed the last sample
131 if (_subset >= _num_subsets)
132 {
134 return;
135 }
136
137 // Get and store the accepted samples input across all the procs from the previous step
138 for (dof_id_type j = 0; j < _distributions.size(); ++j)
139 for (dof_id_type ss = 0; ss < getNumberOfRows(); ++ss)
140 _inputs_sto[j][ss + offset] = Normal::quantile(_distributions[j]->cdf(_inputs[j][ss]), 0, 1);
141
142 // Get the accepted sample outputs across all the procs from the previous step
143 std::vector<Real> tmp =
146 if (tmp.empty())
147 tmp.resize(getNumberOfRows(), 0.0);
148 for (dof_id_type ss = 0; ss < getNumberOfRows(); ++ss)
149 _outputs_sto[ss + offset] = tmp[ss];
150
151 // These are the subsequent subsets which use Markov Chain Monte Carlo sampling scheme
152 if (_subset > 0)
153 {
154 // Check whether the subset index has changed
155 if (sub_ind == 0)
156 {
157 // _inputs_sorted contains the input values corresponding to the largest po percentile
158 // output values
161 }
162
163 // Reinitialize the starting inputs values for the next set of Markov chains
164 if (sub_ind % _count_max == 0)
165 {
166 const unsigned int soffset = (sub_ind / _count_max) * getNumberOfRows();
167 for (dof_id_type j = 0; j < _distributions.size(); ++j)
168 _markov_seed[j].assign(_inputs_sorted[j].begin() + soffset,
169 _inputs_sorted[j].begin() + soffset + getNumberOfRows());
170 }
171 // Otherwise, use the previously accepted input values to propose the next set of input
172 // values
173 else
174 {
175 for (dof_id_type j = 0; j < _distributions.size(); ++j)
176 _markov_seed[j].assign(_inputs_sto[j].begin() + offset,
177 _inputs_sto[j].begin() + offset + getNumberOfRows());
178 }
179 }
180}
181
182Real
183ParallelSubsetSimulation::computeSample(dof_id_type row_index, dof_id_type col_index) const
184{
185 unsigned int seed_value = _step > 0 ? (_step - 1) * 2 : 0;
186 const dof_id_type n = row_index * getNumberOfCols() + col_index;
187 Real val;
188
189 if (_subset == 0)
190 val = getRand(n, seed_value);
191 else
192 {
193 const Real rv =
194 Normal::quantile(getRand(n, seed_value), _markov_seed[col_index][row_index], 1.0);
195 const Real acceptance_ratio = std::log(Normal::pdf(rv, 0, 1)) -
196 std::log(Normal::pdf(_markov_seed[col_index][row_index], 0, 1));
197 const Real new_sample = acceptance_ratio > std::log(getRand(n, seed_value + 1))
198 ? rv
199 : _markov_seed[col_index][row_index];
200 val = Normal::cdf(new_sample, 0, 1);
201 }
202
203 return _distributions[col_index]->quantile(val);
204}
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.
std::vector< Real > & _outputs_sto
Storage for previously accepted sample outputs across all the subsets.
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.
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.
std::vector< std::vector< Real > > & _inputs_sorted
Store the sorted input samples according to their corresponding outputs.
std::vector< std::vector< Real > > & _markov_seed
Mean input vector for the next proposed sample inputs across several processors.
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.
std::vector< Distribution const * > _distributions
Storage for distribution objects to be utilized.
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.
static InputParameters validParams()
unsigned int & _subset
Track the current subset index.
bool & _is_sampling_completed
True if the sampling is completed.
virtual Real computeSample(dof_id_type row_index, dof_id_type col_index) const override
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.