https://mooseframework.inl.gov
Calculators.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 "Calculators.h"
11 
12 namespace StochasticTools
13 {
14 
17 {
18  return MultiMooseEnum(
19  "min=0 max=1 sum=2 mean=3 stddev=4 norm2=5 ratio=6 stderr=7 median=8 meanabs=9");
20 }
21 
22 // MEAN ////////////////////////////////////////////////////////////////////////////////////////////
23 template <typename InType, typename OutType>
24 void
26 {
27  _count = 0;
28  _sum = OutType();
29 }
30 
31 template <typename InType, typename OutType>
32 void
33 Mean<InType, OutType>::update(const typename InType::value_type & val)
34 {
35  _count++;
36  _sum += static_cast<OutType>(val);
37 }
38 
39 template <typename InType, typename OutType>
40 void
41 Mean<InType, OutType>::finalize(bool is_distributed)
42 {
43  if (is_distributed)
44  {
45  this->_communicator.sum(_count);
46  this->_communicator.sum(_sum);
47  }
48  if (_count > 0)
49  _sum /= static_cast<OutType>(_count);
50 }
51 
52 // MEAN ABS ////////////////////////////////////////////////////////////////////////////////////////
53 template <typename InType, typename OutType>
54 void
55 MeanAbsoluteValue<InType, OutType>::update(const typename InType::value_type & val)
56 {
57  Mean<InType, OutType>::update(std::abs(val));
58 }
59 
60 // SUM /////////////////////////////////////////////////////////////////////////////////////////////
61 template <typename InType, typename OutType>
62 void
63 Sum<InType, OutType>::finalize(bool is_distributed)
64 {
65  if (is_distributed)
66  this->_communicator.sum(this->_sum);
67 }
68 
69 // STDDEV //////////////////////////////////////////////////////////////////////////////////////////
70 template <typename InType, typename OutType>
71 void
73 {
74  _count = 0;
75  _sum = OutType();
76  _sum_of_square = OutType();
77 }
78 
79 template <typename InType, typename OutType>
80 void
81 StdDev<InType, OutType>::update(const typename InType::value_type & val)
82 {
83  _count++;
84  _sum += static_cast<OutType>(val);
85  _sum_of_square += MathUtils::pow(static_cast<OutType>(val), 2);
86 }
87 
88 template <typename InType, typename OutType>
89 void
91 {
92  if (is_distributed)
93  {
94  this->_communicator.sum(_count);
95  this->_communicator.sum(_sum);
96  this->_communicator.sum(_sum_of_square);
97  }
98 
99  if (_count <= 1)
100  _sum_of_square = 0;
101  else
102  _sum_of_square = std::sqrt(std::abs(_sum_of_square - _sum * _sum / _count) / (_count - 1));
103 }
104 
105 // STDERR //////////////////////////////////////////////////////////////////////////////////////////
106 template <typename InType, typename OutType>
107 void
109 {
110  StdDev<InType, OutType>::finalize(is_distributed);
111  this->_sum_of_square /= std::sqrt(this->_count);
112 }
113 
114 // RATIO ///////////////////////////////////////////////////////////////////////////////////////////
115 template <typename InType, typename OutType>
116 void
118 {
119  _min = std::numeric_limits<OutType>::max();
120  _max = std::numeric_limits<OutType>::min();
121 }
122 
123 template <typename InType, typename OutType>
124 void
125 Ratio<InType, OutType>::update(const typename InType::value_type & val)
126 {
127  if (_min > val)
128  _min = static_cast<OutType>(val);
129  if (_max < val)
130  _max = static_cast<OutType>(val);
131 }
132 
133 template <typename InType, typename OutType>
134 void
136 {
137  if (is_distributed)
138  {
139  this->_communicator.min(_min);
140  this->_communicator.max(_max);
141  }
142 }
143 
144 // L2NORM //////////////////////////////////////////////////////////////////////////////////////////
145 template <typename InType, typename OutType>
146 void
148 {
149  _l2_norm = OutType();
150 }
151 
152 template <typename InType, typename OutType>
153 void
154 L2Norm<InType, OutType>::update(const typename InType::value_type & val)
155 {
156  _l2_norm += MathUtils::pow(static_cast<OutType>(val), 2);
157 }
158 
159 template <typename InType, typename OutType>
160 void
162 {
163  if (is_distributed)
164  this->_communicator.sum(_l2_norm);
165  _l2_norm = std::sqrt(_l2_norm);
166 }
167 
168 // MEDIAN //////////////////////////////////////////////////////////////////////////////////////////
169 template <typename InType, typename OutType>
170 void
172 {
173  _storage.clear();
174 }
175 
176 template <typename InType, typename OutType>
177 void
178 Median<InType, OutType>::update(const typename InType::value_type & val)
179 {
180  _storage.push_back(static_cast<OutType>(val));
181 }
182 
183 template <typename InType, typename OutType>
184 void
186 {
187  // Make sure we aren't doing anything silly like taking the median of an empty vector
188  _median = OutType();
189  auto count = _storage.size();
190  if (is_distributed)
191  this->_communicator.sum(count);
192  if (count == 0)
193  return;
194 
195  if (!is_distributed || this->n_processors() == 1)
196  {
197  std::sort(_storage.begin(), _storage.end());
198  if (count % 2)
199  _median = _storage[count / 2];
200  else
201  _median += (_storage[count / 2] + _storage[count / 2 - 1]) / 2;
202  return;
203  }
204 
205  dof_id_type kgt = count % 2 ? (count / 2) : (count / 2 - 1);
206  dof_id_type klt = kgt;
207  while (true)
208  {
209  // Gather all sizes and figure out current number of values
210  std::vector<std::size_t> sz = {_storage.size()};
211  this->_communicator.allgather(sz);
212  dof_id_type n = std::accumulate(sz.begin(), sz.end(), 0);
213 
214  // Choose the first value for the first processor with values
215  for (const auto & i : index_range(sz))
216  if (sz[i])
217  {
218  if (this->processor_id() == i)
219  _median = _storage[0];
220  this->_communicator.broadcast(_median, i);
221  break;
222  }
223 
224  // Count number of values greater than, less than, and equal to _median
225  std::vector<dof_id_type> m(3, 0);
226  for (const auto & val : _storage)
227  {
228  if (_median < val)
229  m[0]++;
230  else if (val < _median)
231  m[1]++;
232  }
233  this->_communicator.sum(m);
234  m[2] = n - m[0] - m[1];
235 
236  // Remove greater than equal to
237  if ((m[0] + m[2]) <= kgt)
238  {
239  _storage.erase(std::remove_if(_storage.begin(),
240  _storage.end(),
241  [this](const OutType & val) { return val >= _median; }),
242  _storage.end());
243  kgt -= m[0] + m[2];
244  }
245  // Remove less than equal to
246  else if ((m[1] + m[2]) <= klt)
247  {
248  _storage.erase(std::remove_if(_storage.begin(),
249  _storage.end(),
250  [this](const OutType & val) { return val <= _median; }),
251  _storage.end());
252  klt -= m[1] + m[2];
253  }
254  // If the number of points is odd, then we've found it
255  else if (count % 2)
256  break;
257  // Get average of the two middle numbers
258  else
259  {
260  OutType num2;
261  // Find the next greater than
262  if (m[0] > kgt)
263  {
264  num2 = std::numeric_limits<OutType>::max();
265  for (const auto & val : _storage)
266  if (_median < val && val < num2)
267  num2 = val;
268  this->_communicator.min(num2);
269  }
270  // Find the next less than
271  else if (m[1] > klt)
272  {
273  num2 = std::numeric_limits<OutType>::min();
274  for (const auto & val : _storage)
275  if (val < _median && num2 < val)
276  num2 += val;
277  this->_communicator.max(num2);
278  }
279  // Otherwise we know the other number is equal
280  else
281  num2 = _median;
282 
283  _median = (_median + num2) / 2;
284  break;
285  }
286  }
287 }
288 
289 // CalculatorBuilder
290 // //////////////////////////////////////////////////////////////////////////////////
291 template <typename InType, typename OutType>
292 std::unique_ptr<Calculator<InType, OutType>>
294  const libMesh::ParallelObject & other)
295 {
296  if (item == "min")
297  return std::make_unique<Min<InType, OutType>>(other, item);
298 
299  else if (item == "max")
300  return std::make_unique<Max<InType, OutType>>(other, item);
301 
302  else if (item == "sum")
303  return std::make_unique<Sum<InType, OutType>>(other, item);
304 
305  else if (item == "mean" || item == "average") // average is deprecated
306  return std::make_unique<Mean<InType, OutType>>(other, item);
307 
308  else if (item == "stddev")
309  return std::make_unique<StdDev<InType, OutType>>(other, item);
310 
311  else if (item == "stderr")
312  return std::make_unique<StdErr<InType, OutType>>(other, item);
313 
314  else if (item == "norm2")
315  return std::make_unique<L2Norm<InType, OutType>>(other, item);
316 
317  else if (item == "ratio")
318  return std::make_unique<Ratio<InType, OutType>>(other, item);
319 
320  else if (item == "median")
321  return std::make_unique<Median<InType, OutType>>(other, item);
322 
323  else if (item == "meanabs")
324  return std::make_unique<MeanAbsoluteValue<InType, OutType>>(other, item);
325 
326  ::mooseError("Failed to create Statistics::Calculator object for ", item);
327  return nullptr;
328 }
329 
330 #define createCalculators(InType, OutType) \
331  template class Mean<InType, OutType>; \
332  template class Max<InType, OutType>; \
333  template class Min<InType, OutType>; \
334  template class Sum<InType, OutType>; \
335  template class StdDev<InType, OutType>; \
336  template class StdErr<InType, OutType>; \
337  template class Ratio<InType, OutType>; \
338  template class L2Norm<InType, OutType>; \
339  template class Median<InType, OutType>; \
340  template struct CalculatorBuilder<InType, OutType>
341 
342 createCalculators(std::vector<Real>, Real);
343 createCalculators(std::vector<int>, Real);
344 
345 } // StocasticTools namespace
static std::unique_ptr< Calculator< InType, OutType > > build(const MooseEnumItem &item, const libMesh::ParallelObject &other)
Definition: Calculators.C:293
virtual void finalize(bool is_distributed) override
This is used to compute the resulting calculator value by performing necessary arithmetic and paralle...
Definition: Calculators.C:108
virtual void initialize() override
This function is used to reset the calculator to its initial state and prepare it for another evaluat...
Definition: Calculators.C:72
createCalculators(std::vector< Real >, Real)
virtual void finalize(bool is_distributed) override
This is used to compute the resulting calculator value by performing necessary arithmetic and paralle...
Definition: Calculators.C:135
virtual void finalize(bool is_distributed) override
This is used to compute the resulting calculator value by performing necessary arithmetic and paralle...
Definition: Calculators.C:63
virtual void finalize(bool is_distributed) override
This is used to compute the resulting calculator value by performing necessary arithmetic and paralle...
Definition: Calculators.C:185
MultiMooseEnum makeCalculatorEnum()
Definition: Calculators.C:16
virtual void update(const typename InType::value_type &val) override
Updating the calculator with a piece of data.
Definition: Calculators.C:55
Enum for batch type in stochastic tools MultiApp.
virtual void finalize(bool is_distributed) override
This is used to compute the resulting calculator value by performing necessary arithmetic and paralle...
Definition: Calculators.C:161
virtual void update(const typename InType::value_type &val) override
Updating the calculator with a piece of data.
Definition: Calculators.C:33
virtual void update(const typename InType::value_type &val) override
Updating the calculator with a piece of data.
Definition: Calculators.C:154
virtual void initialize() override
This function is used to reset the calculator to its initial state and prepare it for another evaluat...
Definition: Calculators.C:25
virtual void update(const typename InType::value_type &val) override
Updating the calculator with a piece of data.
Definition: Calculators.C:178
virtual void initialize() override
This function is used to reset the calculator to its initial state and prepare it for another evaluat...
Definition: Calculators.C:117
virtual void initialize() override
This function is used to reset the calculator to its initial state and prepare it for another evaluat...
Definition: Calculators.C:147
T pow(T x, int e)
virtual void update(const typename InType::value_type &val) override
Updating the calculator with a piece of data.
Definition: Calculators.C:81
virtual void finalize(bool is_distributed) override
This is used to compute the resulting calculator value by performing necessary arithmetic and paralle...
Definition: Calculators.C:41
virtual void initialize() override
This function is used to reset the calculator to its initial state and prepare it for another evaluat...
Definition: Calculators.C:171
virtual void finalize(bool is_distributed) override
This is used to compute the resulting calculator value by performing necessary arithmetic and paralle...
Definition: Calculators.C:90
virtual void update(const typename InType::value_type &val) override
Updating the calculator with a piece of data.
Definition: Calculators.C:125
auto index_range(const T &sizable)
uint8_t dof_id_type