https://mooseframework.inl.gov
VectorCalculators.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 "VectorCalculators.h"
11 
12 namespace StochasticTools
13 {
14 
15 template <typename InType, typename OutType>
16 std::vector<std::vector<OutType>>
17 Percentile<std::vector<InType>, std::vector<OutType>>::compute(const std::vector<InType> & data,
18  const bool is_distributed)
19 {
20  // Bootstrap estimates
21  const auto values = this->computeBootstrapEstimates(data, is_distributed);
22 
23  // Extract percentiles
24  std::vector<std::vector<OutType>> output;
25  if (this->processor_id() == 0)
26  for (const Real & level : this->_levels)
27  {
28  long unsigned int index = std::lrint(level * (this->_replicates - 1));
29  output.push_back(values[index]);
30  }
31 
32  return output;
33 }
34 
35 template <typename InType, typename OutType>
36 std::vector<std::vector<OutType>>
37 BiasCorrectedAccelerated<std::vector<InType>, std::vector<OutType>>::compute(
38  const std::vector<InType> & data, bool is_distributed)
39 {
40  // Bootstrap estimates
41  const std::vector<std::vector<OutType>> values =
42  this->computeBootstrapEstimates(data, is_distributed);
43 
44  // Compute bias-correction, Efron and Tibshirani (2003), Eq. 14.14, p. 186
45  const std::vector<OutType> value = this->_calc.compute(data, is_distributed);
46  std::vector<Real> bias(value.size());
47  for (const auto & i : index_range(value))
48  {
49  Real count = 0.;
50  for (const auto & val : values)
51  {
52  if (val[i] < value[i])
53  count++;
54  else
55  break;
56  }
57  bias[i] = NormalDistribution::quantile(count / this->_replicates, 0, 1);
58  }
59 
60  // Compute Acceleration, Efron and Tibshirani (2003), Eq. 14.15, p. 186
61  const std::vector<OutType> acc =
62  data.empty() ? std::vector<OutType>(value.size()) : acceleration(data, is_distributed);
63 
64  // Compute intervals, Efron and Tibshirani (2003), Eq. 14.10, p. 185
65  std::vector<std::vector<OutType>> output(this->_levels.size(),
66  std::vector<OutType>(value.size()));
67  for (const auto & l : index_range(this->_levels))
68  {
69  const Real z = NormalDistribution::quantile(this->_levels[l], 0, 1);
70  for (const auto & i : index_range(value))
71  {
72  const OutType x = bias[i] + (bias[i] + (bias[i] + z) / (1 - acc[i] * (bias[i] + z)));
73  const Real alpha = NormalDistribution::cdf(x, 0, 1);
74 
75  long unsigned int index = std::lrint(alpha * (this->_replicates - 1));
76  output[l][i] = values[index][i];
77  }
78  }
79  return output;
80 }
81 
82 template <typename InType, typename OutType>
83 std::vector<OutType>
85  const std::vector<InType> & data, const bool is_distributed)
86 {
87  const std::size_t local_size = data.size();
88  std::vector<std::size_t> local_sizes = {local_size};
89  if (is_distributed)
90  this->_communicator.allgather(local_sizes);
91  const std::size_t count = std::accumulate(local_sizes.begin(), local_sizes.end(), 0);
92  const processor_id_type rank = is_distributed ? this->processor_id() : 0;
93 
94  // Jackknife statistics
95  std::vector<std::vector<OutType>> theta_i(local_size);
96 
97  // Compute jackknife estimates, Ch. 11, Eq. 11.2, p. 141
98  for (processor_id_type r = 0; r < local_sizes.size(); ++r)
99  for (std::size_t i = 0; i < local_sizes[r]; ++i)
100  {
101  this->_calc.initializeCalculator();
102  for (std::size_t il = 0; il < local_size; ++il)
103  if (i != il || r != rank)
104  this->_calc.updateCalculator(data[il]);
105  this->_calc.finalizeCalculator(is_distributed);
106  if (r == rank)
107  theta_i[i] = this->_calc.getValue();
108  }
109 
110  // Compute jackknife sum, Ch. 11, Eq. 11.4, p. 141
111  const std::size_t nval = theta_i.size() > 0 ? theta_i[0].size() : 0;
112  std::vector<OutType> theta_dot(nval, 0.);
113  for (const auto & ti : theta_i)
114  for (const auto & i : make_range(nval))
115  theta_dot[i] += ti[i] / count;
116  if (is_distributed)
117  this->_communicator.sum(theta_dot);
118 
119  // Acceleration, Ch. 14, Eq. 14.15, p. 185
120  std::vector<OutType> num_den(2 * nval);
121  for (const auto & jk : theta_i)
122  for (const auto & i : make_range(nval))
123  {
124  num_den[i] += MathUtils::pow(theta_dot[i] - jk[i], 3);
125  num_den[nval + i] += MathUtils::pow(theta_dot[i] - jk[i], 2);
126  }
127  if (is_distributed)
128  this->_communicator.sum(num_den);
129 
130  mooseAssert(std::find(num_den.begin() + nval, num_den.end(), OutType()) == num_den.end(),
131  "The acceleration denomenator must not be zero.");
132  std::vector<OutType> acc(nval);
133  for (const auto & i : make_range(nval))
134  acc[i] = num_den[i] / (6 * std::pow(num_den[nval + i], 3. / 2.));
135  return acc;
136 }
137 
138 template <typename InType, typename OutType>
139 std::unique_ptr<Calculator<std::vector<InType>, std::vector<OutType>>>
140 CalculatorBuilder<std::vector<InType>, std::vector<OutType>>::build(
141  const MooseEnumItem & item, const libMesh::ParallelObject & other)
142 {
143  if (item == "min")
144  return std::make_unique<VectorCalculator<InType, OutType, Min>>(other, item);
145 
146  else if (item == "max")
147  return std::make_unique<VectorCalculator<InType, OutType, Max>>(other, item);
148 
149  else if (item == "sum")
150  return std::make_unique<VectorCalculator<InType, OutType, Sum>>(other, item);
151 
152  else if (item == "mean" || item == "average") // average is deprecated
153  return std::make_unique<VectorCalculator<InType, OutType, Mean>>(other, item);
154 
155  else if (item == "stddev")
156  return std::make_unique<VectorCalculator<InType, OutType, StdDev>>(other, item);
157 
158  else if (item == "stderr")
159  return std::make_unique<VectorCalculator<InType, OutType, StdErr>>(other, item);
160 
161  else if (item == "norm2")
162  return std::make_unique<VectorCalculator<InType, OutType, L2Norm>>(other, item);
163 
164  else if (item == "ratio")
165  return std::make_unique<VectorCalculator<InType, OutType, Ratio>>(other, item);
166 
167  else if (item == "median")
168  return std::make_unique<VectorCalculator<InType, OutType, Median>>(other, item);
169 
170  else if (item == "meanabs")
171  return std::make_unique<VectorCalculator<InType, OutType, MeanAbsoluteValue>>(other, item);
172 
173  ::mooseError("Failed to create Statistics::Calculator object for ", item);
174  return nullptr;
175 }
176 
177 template <typename InType, typename OutType>
178 std::unique_ptr<BootstrapCalculator<std::vector<InType>, std::vector<OutType>>>
180  const MooseEnum & item,
181  const libMesh::ParallelObject & other,
182  const std::vector<Real> & levels,
183  unsigned int replicates,
184  unsigned int seed,
185  StochasticTools::Calculator<std::vector<InType>, std::vector<OutType>> & calc)
186 {
187  std::unique_ptr<BootstrapCalculator<std::vector<InType>, std::vector<OutType>>> ptr = nullptr;
188  if (item == "percentile")
189  ptr = std::make_unique<Percentile<std::vector<InType>, std::vector<OutType>>>(
190  other, item, levels, replicates, seed, calc);
191  else if (item == "bca")
192  ptr = std::make_unique<BiasCorrectedAccelerated<std::vector<InType>, std::vector<OutType>>>(
193  other, item, levels, replicates, seed, calc);
194  else
195  ::mooseError("Failed to create Statistics::BootstrapCalculator object for ", item);
196 
197  return ptr;
198 }
199 
200 #define createVectorCalculators(InType, OutType) \
201  template class Percentile<std::vector<InType>, std::vector<OutType>>; \
202  template class BiasCorrectedAccelerated<std::vector<InType>, std::vector<OutType>>; \
203  template struct CalculatorBuilder<std::vector<InType>, std::vector<OutType>>; \
204  template struct BootstrapCalculatorBuilder<std::vector<InType>, std::vector<OutType>>
205 
206 createVectorCalculators(std::vector<Real>, Real);
207 
208 } // StocasticTools namespace
static const std::string acceleration
Definition: NS.h:85
virtual Real cdf(const Real &x) const override
Definition: Normal.C:74
uint8_t processor_id_type
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
Enum for batch type in stochastic tools MultiApp.
const std::vector< double > x
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string alpha
Definition: NS.h:134
IntRange< T > make_range(T beg, T end)
T pow(T x, int e)
virtual Real quantile(const Real &p) const override
Definition: Normal.C:80
MooseUnits pow(const MooseUnits &, int)
createVectorCalculators(std::vector< Real >, Real)
auto index_range(const T &sizable)