Line data Source code
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 "NestedMonteCarloSampler.h" 11 : #include "Distribution.h" 12 : 13 : registerMooseObjectAliased("StochasticToolsApp", NestedMonteCarloSampler, "NestedMonteCarlo"); 14 : 15 : InputParameters 16 44 : NestedMonteCarloSampler::validParams() 17 : { 18 44 : InputParameters params = Sampler::validParams(); 19 44 : params.addClassDescription("Monte Carlo sampler for nested loops of parameters."); 20 88 : params.addRequiredParam<std::vector<dof_id_type>>( 21 : "num_rows", 22 : "The number of rows for each loop of parameters. The first number represents the outermost " 23 : "loop."); 24 88 : params.addRequiredParam<std::vector<std::vector<DistributionName>>>( 25 : "distributions", 26 : "Sets of distribution names to be sampled. Each set defines the parameters for the nested " 27 : "loop, with the first set being the outermost loop."); 28 44 : return params; 29 0 : } 30 : 31 25 : NestedMonteCarloSampler::NestedMonteCarloSampler(const InputParameters & parameters) 32 25 : : Sampler(parameters) 33 : { 34 : // Grab inputs and make sure size is consistent 35 25 : const auto & dnames = getParam<std::vector<std::vector<DistributionName>>>("distributions"); 36 50 : const auto & nrows = getParam<std::vector<dof_id_type>>("num_rows"); 37 25 : if (dnames.size() != nrows.size()) 38 2 : paramError("distributions", 39 : "There must be a set of distributions for each loop defined by 'num_rows'."); 40 : 41 : // Gather distribution pointers and fill in loop index 42 : const std::size_t nloop = dnames.size(); 43 : std::vector<std::size_t> loop_index; 44 92 : for (const auto & n : make_range(nloop)) 45 207 : for (const auto & name : dnames[n]) 46 : { 47 138 : _distributions.push_back(&getDistributionByName(name)); 48 138 : loop_index.push_back(n); 49 : } 50 : 51 : // Compute what row indices need to recompute which columns 52 23 : std::vector<dof_id_type> loop_mod(nloop); 53 23 : std::partial_sum(nrows.rbegin(), nrows.rend(), loop_mod.rbegin(), std::multiplies<dof_id_type>()); 54 : loop_mod.erase(loop_mod.begin()); 55 23 : loop_mod.push_back(1); 56 : 57 : // Fill in the mod for each column 58 23 : _col_mod.resize(_distributions.size()); 59 161 : for (const auto j : index_range(_distributions)) 60 138 : _col_mod[j] = loop_mod[loop_index[j]]; 61 : 62 23 : setNumberOfRows(std::accumulate(nrows.begin(), nrows.end(), 1, std::multiplies<dof_id_type>())); 63 23 : setNumberOfCols(_distributions.size()); 64 23 : } 65 : 66 : Real 67 5400 : NestedMonteCarloSampler::computeSample(dof_id_type row_index, dof_id_type col_index) 68 : { 69 5400 : const auto mod = _col_mod[col_index]; 70 5400 : const dof_id_type target_row = std::floor(row_index / mod) * mod; 71 5400 : const Real rn = getRand(target_row * getNumberOfCols() + col_index); 72 5400 : return _distributions[col_index]->quantile(rn); 73 : }