https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PMCMCDecision.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 "PMCMCDecision.h"
11#include "Sampler.h"
12#include "DenseMatrix.h"
13
14registerMooseObject("StochasticToolsApp", PMCMCDecision);
15
18{
21 params.addClassDescription("Generic reporter which decides whether or not to accept a proposed "
22 "sample in parallel Markov chain Monte Carlo type of algorithms.");
23 params.addParam<ReporterName>("output_value", "Value of the model output from the SubApp.");
24 params.addParam<ReporterValueName>(
25 "outputs_required",
26 "outputs_required",
27 "Modified value of the model output from this reporter class.");
28 params.addParam<ReporterValueName>("inputs", "inputs", "Uncertain inputs to the model.");
29 params.addParam<ReporterValueName>("tpm", "tpm", "The transition probability matrix.");
30 params.addParam<ReporterValueName>("variance", "variance", "Model variance term.");
31 params.addParam<ReporterValueName>(
32 "noise", "noise", "Model noise term to pass to Likelihoods object.");
33 params.addRequiredParam<SamplerName>("sampler", "The sampler object.");
34 params.addRequiredParam<std::vector<UserObjectName>>("likelihoods", "Names of likelihoods.");
35 return params;
36}
37
39 : GeneralReporter(parameters),
40 LikelihoodInterface(parameters),
41 _inputs(declareValue<std::vector<std::vector<Real>>>("inputs")),
42 _tpm(declareValue<std::vector<Real>>("tpm")),
43 _variance(declareValue<std::vector<Real>>("variance")),
44 _noise(declareValue<Real>("noise")),
45 _sampler(getSampler("sampler")),
46 _pmcmc(dynamic_cast<const PMCMCBase *>(&_sampler)),
47 _rnd_vec(_pmcmc->getRandomNumbers()),
48 _new_var_samples(_pmcmc->getVarSamples()),
49 _priors(_pmcmc->getPriors()),
50 _var_prior(_pmcmc->getVarPrior()),
51 _outputs_required(
52 isParamValid("output_value")
53 ? &declareValue<std::vector<Real>>("outputs_required", REPORTER_MODE_DISTRIBUTED)
54 : nullptr),
55 _output_value(isParamValid("output_value") ? &getReporterValue<std::vector<Real>>(
56 "output_value", REPORTER_MODE_DISTRIBUTED)
57 : nullptr),
58 _local_comm(_sampler.getLocalComm()),
59 _check_step(std::numeric_limits<int>::max())
60{
61 // Filling the `likelihoods` vector with the user-provided distributions.
62 for (const UserObjectName & name : getParam<std::vector<UserObjectName>>("likelihoods"))
64
65 // Check whether the selected sampler is an MCMC sampler or not
66 if (!_pmcmc)
67 paramError("sampler", "The selected sampler is not of type MCMC.");
68
69 // Fetching the sampler characteristics
73
74 // Resizing the data arrays to transmit to the output file
75 _inputs.resize(_props);
76 for (unsigned int i = 0; i < _props; ++i)
80 _tpm.resize(_props);
81 _variance.resize(_props);
82}
83
84void
86{
87 if (!isParamValid("output_value") && !usingGP())
88 paramError("output_value", "Value of the model output from the SubApp should be specified.");
89}
90
91void
92PMCMCDecision::computeEvidence(std::vector<Real> & evidence, const DenseMatrix<Real> & input_matrix)
93{
94 std::vector<Real> out1(_num_confg_values);
95 std::vector<Real> out2(_num_confg_values);
96 for (unsigned int i = 0; i < evidence.size(); ++i)
97 {
98 evidence[i] = 0.0;
99 for (unsigned int j = 0; j < _priors.size(); ++j)
100 evidence[i] += (std::log(_priors[j]->pdf(input_matrix(i, j))) -
101 std::log(_priors[j]->pdf(_data_prev(i, j))));
102 for (unsigned int j = 0; j < _num_confg_values; ++j)
103 {
104 out1[j] = (*_outputs_required)[j * _props + i];
105 out2[j] = _outputs_prev[j * _props + i];
106 }
107 if (_var_prior)
108 {
109 evidence[i] += (std::log(_var_prior->pdf(_new_var_samples[i])) -
110 std::log(_var_prior->pdf(_var_prev[i])));
111 _noise = std::sqrt(_new_var_samples[i]);
112 for (unsigned int j = 0; j < _likelihoods.size(); ++j)
113 evidence[i] += _likelihoods[j]->function(out1);
114 _noise = std::sqrt(_var_prev[i]);
115 for (unsigned int j = 0; j < _likelihoods.size(); ++j)
116 evidence[i] -= _likelihoods[j]->function(out2);
117 }
118 else
119 for (unsigned int j = 0; j < _likelihoods.size(); ++j)
120 evidence[i] += (_likelihoods[j]->function(out1) - _likelihoods[j]->function(out2));
121 }
122}
123
124void
126 const std::vector<Real> & /*evidence*/)
127{
128 tv.assign(_props, 1.0);
129}
130
131void
132PMCMCDecision::nextSamples(std::vector<Real> & req_inputs,
133 DenseMatrix<Real> & input_matrix,
134 const std::vector<Real> & tv,
135 const unsigned int & parallel_index)
136{
137 if (tv[parallel_index] >= _rnd_vec[parallel_index])
138 {
139 for (unsigned int k = 0; k < _sampler.getNumberOfCols() - _num_confg_params; ++k)
140 req_inputs[k] = input_matrix(parallel_index, k);
141 _variance[parallel_index] = _new_var_samples[parallel_index];
142 }
143 else
144 {
145 for (unsigned int k = 0; k < _sampler.getNumberOfCols() - _num_confg_params; ++k)
146 {
147 req_inputs[k] = _data_prev(parallel_index, k);
148 input_matrix(parallel_index, k) = _data_prev(parallel_index, k);
149 }
150 if (_var_prior)
151 _variance[parallel_index] = _var_prev[parallel_index];
152 for (unsigned int k = 0; k < _num_confg_values; ++k)
153 (*_outputs_required)[k * _props + parallel_index] =
154 _outputs_prev[k * _props + parallel_index];
155 }
156}
157
158void
160{
162 {
164 return;
165 }
166
167 // Gather inputs and outputs from the sampler and subApps
168 DenseMatrix<Real> data_in(_sampler.getNumberOfRows(), _sampler.getNumberOfCols());
169 for (dof_id_type ss = _sampler.getLocalRowBegin(); ss < _sampler.getLocalRowEnd(); ++ss)
170 {
171 const auto data = _sampler.getNextLocalRow();
172 for (unsigned int j = 0; j < _sampler.getNumberOfCols(); ++j)
173 data_in(ss, j) = data[j];
174 }
175 _local_comm.sum(data_in.get_values());
176 if (!usingGP())
177 {
178 (*_outputs_required) = *_output_value;
180 }
181
182 // Compute the evidence and transitimkon vectors
183 std::vector<Real> evidence(_props);
184 if (_t_step > _pmcmc->decisionStep())
185 {
186 computeEvidence(evidence, data_in);
187 computeTransitionVector(_tpm, evidence);
188 }
189 else
190 _tpm.assign(_props, 1.0);
191
192 // Accept/reject the proposed samples and assign the correct outputs
193 std::vector<Real> req_inputs(_sampler.getNumberOfCols() - _num_confg_params);
194 for (unsigned int i = 0; i < _props; ++i)
195 {
196 nextSamples(req_inputs, data_in, _tpm, i);
197 _inputs[i] = req_inputs;
198 }
199
200 // Compute the next seeds to facilitate proposals (not always required)
201 nextSeeds();
202
203 // Store data from previous step
204 _data_prev = data_in;
206 if (!usingGP())
207 _outputs_prev = (*_outputs_required);
208
209 // Track the current step
211}
registerMooseObject("StochasticToolsApp", PMCMCDecision)
const ReporterMode REPORTER_MODE_DISTRIBUTED
void ErrorVector unsigned int
virtual Real pdf(const Real &x) const=0
static InputParameters validParams()
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)
static InputParameters validParams()
LikelihoodFunctionBase * getLikelihoodFunctionByName(const UserObjectName &name) const
Lookup a LikelihoodFunction object by name and return pointer.
const std::string & name() const
void paramError(const std::string &param, Args... args) const
bool isParamValid(const std::string &name) const
A base class used to perform Parallel Markov Chain Monte Carlo (MCMC) sampling.
Definition PMCMCBase.h:20
dof_id_type getNumberOfConfigParams() const
Return the number of configuration parameters.
Definition PMCMCBase.h:34
virtual int decisionStep() const
Return the step after which decision making can begin.
Definition PMCMCBase.h:73
dof_id_type getNumberOfConfigValues() const
Return the number of configuration parameters.
Definition PMCMCBase.h:29
dof_id_type getNumParallelProposals() const
Return the number of parallel proposals.
Definition PMCMCBase.h:39
PMCMCDecision will help making sample accept/reject decisions in MCMC schemes (for e....
const std::vector< Real > & _rnd_vec
Storage for the random numbers for decision making.
std::vector< Real > & _tpm
Transition probability matrix.
int _check_step
Ensure that the MCMC algorithm proceeds in a sequential fashion.
dof_id_type _num_confg_values
Storage for the number of experimental configuration values.
libMesh::Parallel::Communicator & _local_comm
Communicator that was split based on samples that have rows.
std::vector< const LikelihoodFunctionBase * > _likelihoods
Storage for the likelihood objects to be utilized.
std::vector< Real > & _variance
Model variance term.
virtual void execute() override
virtual void nextSeeds()
Compute the next set of seeds to facilitate proposals.
std::vector< std::vector< Real > > & _inputs
Model input data that is uncertain.
const std::vector< const Distribution * > _priors
Storage for the priors.
virtual void initialize() override
dof_id_type _num_confg_params
Storage for the number of experimental configuration parameters.
Sampler & _sampler
The MCMC sampler.
virtual bool usingGP() const
Flag to specify if a pre-trained Gaussian process model is used.
static InputParameters validParams()
virtual void nextSamples(std::vector< Real > &req_inputs, DenseMatrix< Real > &input_matrix, const std::vector< Real > &tv, const unsigned int &parallel_index)
Resample inputs given the transition vector (after transition vector computed)
const std::vector< Real > * _output_value
Current output values.
std::vector< Real > _var_prev
Storage for previous variances.
DenseMatrix< Real > _data_prev
Storage for previous inputs.
const PMCMCBase *const _pmcmc
MCMC sampler base.
const Distribution * _var_prior
Storage for the prior over the variance.
PMCMCDecision(const InputParameters &parameters)
Real & _noise
Model noise term to pass to Likelihoods object.
const std::vector< Real > & _new_var_samples
Storage for new proposed variance samples.
std::vector< Real > _outputs_prev
Storage for previous outputs.
virtual void computeTransitionVector(std::vector< Real > &tv, const std::vector< Real > &evidence)
Compute the transition probability vector (after the computation of evidence)
dof_id_type _props
Storage for the number of parallel proposals.
virtual void computeEvidence(std::vector< Real > &evidence, const DenseMatrix< Real > &input_matrix)
Compute the evidence (aka, betterness of the proposed sample vs the previous)
std::vector< Real > * _outputs_required
Transfer the right outputs to the file.
std::vector< Real > getNextLocalRow()
dof_id_type getNumberOfLocalRows() const
dof_id_type getLocalRowEnd() const
dof_id_type getLocalRowBegin() const
dof_id_type getNumberOfRows() const
dof_id_type getNumberOfCols() const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const