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 : #pragma once
11 :
12 : #include "MooseTypes.h"
13 : #include "MultiMooseEnum.h"
14 : #include "MathUtils.h"
15 :
16 : #include "libmesh/parallel.h"
17 :
18 : #include <vector>
19 : #include <memory>
20 : #include <numeric>
21 :
22 : class MooseEnumItem;
23 :
24 : namespace StochasticTools
25 : {
26 :
27 : /*
28 : * Free function that returns the available statistics available to the Statistics object(s)
29 : */
30 : MultiMooseEnum makeCalculatorEnum();
31 :
32 : /* Base class for computing statistics (e.g., mean, min) for use with Statistics object
33 : *
34 : * The purpose of these objects are to provide an API for computing statistics in serial or parallel
35 : * without any state. This allows future statistics to be quickly added and for each statistic
36 : * to be used with the BootstrapCalculator for computing bootstrap statistics such as confidence
37 : * level intervals.
38 : *
39 : * The calculators are evaluating using the following sequence:
40 : * \code
41 : * auto calculator = makeCalculator<InType, OutType>(*this, type);
42 : * calculator->initializeCalculator();
43 : * for (const typename InType::value_type & val : data)
44 : * calculator->updateCalculator(data);
45 : * calculator->finalizeCalculator(is_distributed);
46 : * OutType stat = calculator->getValue();
47 : * \endcode
48 : * The base Calculator class does this automatically with an input vector of data:
49 : * \code
50 : * auto calculator = makeCalculator<InType, OutType>(*this, type);
51 : * OutType stat = calculator->compute(data, is_distributed);
52 : * \endcode
53 : * The base class has state checks to make sure these functions are called
54 : * in the correct order.
55 : *
56 : * To create new Calculator objects first create the Calculator class and then update the
57 : * the initialize, update, finalize, and get virtual functions.
58 : *
59 : * Explicit instantiations are generated in the C file.
60 : */
61 : template <typename InType, typename OutType>
62 : class Calculator : public libMesh::ParallelObject
63 : {
64 : public:
65 32182 : Calculator(const libMesh::ParallelObject & other, const std::string & name)
66 16307826 : : libMesh::ParallelObject(other), _name(name), _state(CalculatorState::NONE)
67 : {
68 : }
69 :
70 0 : virtual ~Calculator() = default;
71 : /**
72 : * Evaluate the calculator on the full vector of data. This is basically a convenient
73 : * wrapper around initializeCalculator, updateCalculator, finalizeCalculator, and getvalue.
74 : */
75 : OutType compute(const InType &, bool);
76 :
77 : /**
78 : * Public function that must be called before updateCalculator and finalizeCalculator.
79 : * Sets _state to INITIALIZED
80 : */
81 : void initializeCalculator();
82 : /**
83 : * Public function to update calculator with a piece of data.
84 : * _state mush be INITIALIZED
85 : */
86 : void updateCalculator(const typename InType::value_type &);
87 : /**
88 : * Public function to finalize the resulting calculator value.
89 : * _state must be INITLIALIZED
90 : * Sets _state to FINALIZED
91 : */
92 : void finalizeCalculator(bool);
93 : /**
94 : * Public function to return the calculated value
95 : * _state must be FINALIZED
96 : */
97 : OutType getValue() const;
98 :
99 16266012 : const std::string & name() const { return _name; }
100 :
101 : protected:
102 : /**
103 : * This function is used to reset the calculator to its initial state and prepare it
104 : * for another evaluation. This usually involves clearing class members.
105 : */
106 : virtual void initialize() = 0;
107 : /**
108 : * Updating the calculator with a piece of data. Sometimes some clever arithmetic
109 : * is required to avoid storing data.
110 : */
111 : virtual void update(const typename InType::value_type &) = 0;
112 : /**
113 : * This is used to compute the resulting calculator value by performing necessary
114 : * arithmetic and parallel communication. This only called once after all the input
115 : * data is entered through update.
116 : */
117 : virtual void finalize(bool) = 0;
118 : /**
119 : * Returns the resulting calculator value. It is important to not modify member
120 : * data here so the calculator can retain its state.
121 : */
122 : virtual OutType get() const = 0;
123 :
124 : private:
125 : enum CalculatorState
126 : {
127 : NONE,
128 : INITIALIZED,
129 : FINALIZED
130 : };
131 :
132 : const std::string _name;
133 : CalculatorState _state;
134 : };
135 :
136 : template <typename InType, typename OutType>
137 : class Mean : public Calculator<InType, OutType>
138 : {
139 : public:
140 8330810 : using Calculator<InType, OutType>::Calculator;
141 :
142 : protected:
143 : virtual void initialize() override;
144 : virtual void update(const typename InType::value_type & val) override;
145 : virtual void finalize(bool is_distributed) override;
146 13059411 : virtual OutType get() const override { return _sum; }
147 :
148 : dof_id_type _count;
149 : OutType _sum;
150 : };
151 :
152 : template <typename InType, typename OutType>
153 32 : class MeanAbsoluteValue : public Mean<InType, OutType>
154 : {
155 : public:
156 384480 : using Mean<InType, OutType>::Mean;
157 :
158 : protected:
159 : virtual void update(const typename InType::value_type & val) override;
160 : };
161 :
162 : template <typename InType, typename OutType>
163 : class Ratio : public Calculator<InType, OutType>
164 : {
165 : public:
166 952 : using Calculator<InType, OutType>::Calculator;
167 :
168 : protected:
169 : virtual void initialize() override;
170 : virtual void update(const typename InType::value_type & val) override;
171 : virtual void finalize(bool is_distributed) override;
172 200272 : virtual OutType get() const override { return _max / _min; }
173 :
174 : OutType _min;
175 : OutType _max;
176 : };
177 :
178 : template <typename InType, typename OutType>
179 119 : class Min : public Ratio<InType, OutType>
180 : {
181 : public:
182 326 : using Ratio<InType, OutType>::Ratio;
183 :
184 : protected:
185 200292 : virtual OutType get() const override { return this->_min; }
186 : };
187 :
188 : template <typename InType, typename OutType>
189 119 : class Max : public Ratio<InType, OutType>
190 : {
191 : public:
192 326 : using Ratio<InType, OutType>::Ratio;
193 :
194 : protected:
195 200292 : virtual OutType get() const override { return this->_max; }
196 : };
197 :
198 : template <typename InType, typename OutType>
199 119 : class Sum : public Mean<InType, OutType>
200 : {
201 : public:
202 2854 : using Mean<InType, OutType>::Mean;
203 :
204 : protected:
205 : virtual void finalize(bool is_distributed) override;
206 : };
207 :
208 : template <typename InType, typename OutType>
209 : class StdDev : public Calculator<InType, OutType>
210 : {
211 : public:
212 7943364 : using Calculator<InType, OutType>::Calculator;
213 :
214 : protected:
215 : virtual void initialize() override;
216 : virtual void update(const typename InType::value_type & val) override;
217 : virtual void finalize(bool is_distributed) override;
218 11131009 : virtual OutType get() const override { return _sum_of_square; }
219 :
220 : dof_id_type _count;
221 : OutType _sum;
222 : OutType _sum_of_square;
223 : };
224 :
225 : template <typename InType, typename OutType>
226 119 : class StdErr : public StdDev<InType, OutType>
227 : {
228 : public:
229 322 : using StdDev<InType, OutType>::StdDev;
230 :
231 : protected:
232 : virtual void finalize(bool is_distributed) override;
233 : };
234 :
235 : template <typename InType, typename OutType>
236 : class L2Norm : public Calculator<InType, OutType>
237 : {
238 : public:
239 326 : using Calculator<InType, OutType>::Calculator;
240 :
241 : protected:
242 : virtual void initialize() override;
243 : virtual void update(const typename InType::value_type & val) override;
244 : virtual void finalize(bool is_distributed) override;
245 200292 : virtual OutType get() const override { return _l2_norm; }
246 :
247 : OutType _l2_norm;
248 : };
249 :
250 : template <typename InType, typename OutType>
251 : class Median : public Calculator<InType, OutType>
252 : {
253 : public:
254 192 : using Calculator<InType, OutType>::Calculator;
255 :
256 : protected:
257 : virtual void initialize() override;
258 : virtual void update(const typename InType::value_type & val) override;
259 : virtual void finalize(bool is_distributed) override;
260 200182 : virtual OutType get() const override { return _median; }
261 :
262 : std::vector<OutType> _storage;
263 : OutType _median;
264 : };
265 :
266 : /*
267 : * Free function for building a const Calculator object for use by Statistics object.
268 : *
269 : * Explicit instantiations in C file.
270 : */
271 : template <typename InType = std::vector<Real>, typename OutType = Real>
272 : std::unique_ptr<Calculator<InType, OutType>> makeCalculator(const MooseEnumItem & item,
273 : const libMesh::ParallelObject & other);
274 :
275 : /*
276 : * Simple struct that makeCalculator wraps around, this is so building calculators
277 : * can be partially specialized.
278 : */
279 : template <typename InType, typename OutType>
280 : struct CalculatorBuilder
281 : {
282 : static std::unique_ptr<Calculator<InType, OutType>> build(const MooseEnumItem & item,
283 : const libMesh::ParallelObject & other);
284 : };
285 :
286 : template <typename InType, typename OutType>
287 : OutType
288 5807 : Calculator<InType, OutType>::compute(const InType & data, bool is_distributed)
289 : {
290 : initializeCalculator();
291 4568560 : for (const auto & val : data)
292 : updateCalculator(val);
293 5807 : finalizeCalculator(is_distributed);
294 5807 : return getValue();
295 : }
296 :
297 : template <typename InType, typename OutType>
298 : void
299 : Calculator<InType, OutType>::initializeCalculator()
300 : {
301 28098276 : initialize();
302 11802242 : _state = CalculatorState::INITIALIZED;
303 16296034 : }
304 :
305 : template <typename InType, typename OutType>
306 : void
307 : Calculator<InType, OutType>::updateCalculator(const typename InType::value_type & val)
308 : {
309 : mooseAssert(_state == CalculatorState::INITIALIZED, "Calculator is in wrong state.");
310 2039413844 : update(val);
311 5322429 : }
312 :
313 : template <typename InType, typename OutType>
314 : void
315 28098276 : Calculator<InType, OutType>::finalizeCalculator(bool is_distributed)
316 : {
317 28098276 : if (_state != CalculatorState::INITIALIZED)
318 0 : ::mooseError("Calculator is in wrong state.");
319 28098276 : finalize(is_distributed);
320 28098276 : _state = CalculatorState::FINALIZED;
321 28098276 : }
322 :
323 : template <typename InType, typename OutType>
324 : OutType
325 28095052 : Calculator<InType, OutType>::getValue() const
326 : {
327 28095052 : if (_state != CalculatorState::FINALIZED)
328 0 : ::mooseError("Calculator is in wrong state.");
329 28095052 : return get();
330 : }
331 :
332 : // makeCalculator //////////////////////////////////////////////////////////////////////////////////
333 : template <typename InType, typename OutType>
334 : std::unique_ptr<Calculator<InType, OutType>>
335 : makeCalculator(const MooseEnumItem & item, const libMesh::ParallelObject & other)
336 : {
337 12055 : return CalculatorBuilder<InType, OutType>::build(item, other);
338 : }
339 :
340 : } // namespace
|