libMesh
Loading...
Searching...
No Matches
statistics.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19// C++ includes
20#include <algorithm> // for std::min_element, std::max_element
21#include <fstream> // std::ofstream
22#include <numeric> // std::accumulate
23
24// Local includes
25#include "libmesh/statistics.h"
26#include "libmesh/int_range.h"
27#include "libmesh/libmesh_logging.h"
28
29namespace libMesh
30{
31
32
33
34// ------------------------------------------------------------
35// StatisticsVector class member functions
36template <typename T>
38{
39 Real normsq = 0.;
40 const dof_id_type n = cast_int<dof_id_type>(this->size());
41 for (dof_id_type i = 0; i != n; ++i)
42 normsq += ((*this)[i] * (*this)[i]);
43
44 return std::sqrt(normsq);
45}
46
47
48template <typename T>
50{
51 LOG_SCOPE ("minimum()", "StatisticsVector");
52
53 const T min = *(std::min_element(this->begin(), this->end()));
54
55 return min;
56}
57
58
59
60
61template <typename T>
63{
64 LOG_SCOPE ("maximum()", "StatisticsVector");
65
66 const T max = *(std::max_element(this->begin(), this->end()));
67
68 return max;
69}
70
71
72
73
74template <typename T>
76{
77 LOG_SCOPE ("mean()", "StatisticsVector");
78
79 const dof_id_type n = cast_int<dof_id_type>(this->size());
80
81 Real the_mean = 0;
82
83 for (dof_id_type i=0; i<n; i++)
84 {
85 the_mean += ( static_cast<Real>((*this)[i]) - the_mean ) /
86 static_cast<Real>(i + 1);
87 }
88
89 return the_mean;
90}
92
93
94
95template <typename T>
97{
98 const dof_id_type n = cast_int<dof_id_type>(this->size());
99
100 if (n == 0)
101 return 0.;
102
103 LOG_SCOPE ("median()", "StatisticsVector");
104
105 std::sort(this->begin(), this->end());
106
107 const dof_id_type lhs = (n-1) / 2;
108 const dof_id_type rhs = n / 2;
110 Real the_median = 0;
111
112
113 if (lhs == rhs)
114 {
115 the_median = static_cast<Real>((*this)[lhs]);
116 }
118 else
119 {
120 the_median = ( static_cast<Real>((*this)[lhs]) +
121 static_cast<Real>((*this)[rhs]) ) / 2.0;
122 }
124 return the_median;
125}
126
127
128
129
130template <typename T>
132{
133 StatisticsVector<T> sv = (*this);
134
135 return sv.median();
136}
137
138
139
140
141template <typename T>
143{
144 const dof_id_type n = cast_int<dof_id_type>(this->size());
145
146 LOG_SCOPE ("variance()", "StatisticsVector");
147
148 Real the_variance = 0;
149
150 for (dof_id_type i=0; i<n; i++)
151 {
152 const Real delta = ( static_cast<Real>((*this)[i]) - mean_in );
153 the_variance += (delta * delta - the_variance) /
154 static_cast<Real>(i + 1);
155 }
156
157 if (n > 1)
158 the_variance *= static_cast<Real>(n) / static_cast<Real>(n - 1);
159
160 return the_variance;
161}
162
163
164template <typename T>
166{
167 const dof_id_type n = cast_int<dof_id_type>(this->size());
168 const Real max = this->maximum();
169
170 for (dof_id_type i=0; i<n; i++)
171 (*this)[i] = static_cast<T>((*this)[i] / max);
172}
173
174
175
176
177
178template <typename T>
179void StatisticsVector<T>::histogram(std::vector<dof_id_type> & bin_members,
180 unsigned int n_bins)
182 // Must have at least 1 bin
183 libmesh_assert (n_bins>0);
184
185 const dof_id_type n = cast_int<dof_id_type>(this->size());
186
187 std::sort(this->begin(), this->end());
188
189 // The StatisticsVector can hold both integer and float types.
190 // We will define all the bins, etc. using Reals.
191 Real min = static_cast<Real>(this->minimum());
192 Real max = static_cast<Real>(this->maximum());
193 Real bin_size = (max - min) / static_cast<Real>(n_bins);
194
195 LOG_SCOPE ("histogram()", "StatisticsVector");
196
197 std::vector<Real> bin_bounds(n_bins+1);
198 for (auto i : index_range(bin_bounds))
199 bin_bounds[i] = min + Real(i) * bin_size;
200
201 // Give the last bin boundary a little wiggle room: we don't want
202 // it to be just barely less than the max, otherwise our bin test below
203 // may fail.
204 bin_bounds.back() += 1.e-6 * bin_size;
205
206 // This vector will store the number of members each bin has.
207 bin_members.resize(n_bins);
208
209#ifdef DEBUG
210 // we may not bin all values.
211 // Those we skip on purpose (e.g. inactive elements in an ErrorVector)
212 // should also not appear in the consistency-check below.
213 unsigned int unbinned=0;
214#endif
215
216 dof_id_type data_index = 0;
217 for (auto j : index_range(bin_members)) // bin vector indexing
218 {
219 // libMesh::out << "(debug) Filling bin " << j << std::endl;
220
221 for (dof_id_type i=data_index; i<n; i++) // data vector indexing
222 {
223 //libMesh::out << "(debug) Processing index=" << i << std::endl;
224 Real current_val = static_cast<Real>( (*this)[i] );
225
226 // There may be entries in the vector smaller than the value
227 // reported by this->minimum(). (e.g. inactive elements in an
228 // ErrorVector.) We just skip entries like that.
229 if (current_val < min)
230 {
231#ifdef DEBUG
232 unbinned++;
233#endif
234 // libMesh::out << "(debug) Skipping entry v[" << i << "]="
235 // << (*this)[i]
236 // << " which is less than the min value: min="
237 // << min << std::endl;
238 continue;
239 }
240
241 if (current_val > bin_bounds[j+1]) // if outside the current bin (bin[j] is bounded
242 // by bin_bounds[j] and bin_bounds[j+1])
243 {
244 // libMesh::out.precision(16);
245 // libMesh::out.setf(std::ios_base::fixed);
246 // libMesh::out << "(debug) (*this)[i]= " << (*this)[i]
247 // << " is greater than bin_bounds[j+1]="
248 // << bin_bounds[j+1] << std::endl;
249 data_index = i; // start searching here for next bin
250 break; // go to next bin
251 }
252
253 // Otherwise, increment current bin's count
254 bin_members[j]++;
255 // libMesh::out << "(debug) Binned index=" << i << std::endl;
256#ifdef DEBUG
257 if (i== n-1) // we read the last 'i' only in the last bin.
258 libmesh_assert_equal_to(j, bin_members.size()-1);
259#endif
260 }
261 }
262
263#ifdef DEBUG
264 // Check the number of binned entries
265 const dof_id_type n_binned = std::accumulate(bin_members.begin(),
266 bin_members.end(),
267 static_cast<dof_id_type>(0),
268 std::plus<dof_id_type>());
269
270 if (n-unbinned != n_binned)
271 {
272 libMesh::out << "Warning: The number of binned entries, n_binned="
273 << n_binned
274 << ", did not match the total number of binnable entries, n="
275 << n-unbinned << "." << std::endl;
276 }
277#endif
278}
279
280
281
282
283
284template <typename T>
286 const std::string & filename,
287 unsigned int n_bins)
288{
289 // First generate the histogram with the desired number of bins
290 std::vector<dof_id_type> bin_members;
291 this->histogram(bin_members, n_bins);
292
293 // The max, min and bin size are used to generate x-axis values.
294 T min = this->minimum();
295 T max = this->maximum();
296 T bin_size = (max - min) / static_cast<T>(n_bins);
297
298 // On processor 0: Write histogram to file
299 if (my_procid==0)
300 {
301 std::ofstream out_stream (filename.c_str());
302
303 out_stream << "clear all\n";
304 out_stream << "clf\n";
305 //out_stream << "x=linspace(" << min << "," << max << "," << n_bins+1 << ");\n";
306
307 // abscissa values are located at the center of each bin.
308 out_stream << "x=[";
309 for (auto i : index_range(bin_members))
310 {
311 out_stream << min + (Real(i)+0.5)*bin_size << " ";
312 }
313 out_stream << "];\n";
314
315 out_stream << "y=[";
316 for (auto bmi : bin_members)
317 {
318 out_stream << bmi << " ";
319 }
320 out_stream << "];\n";
321 out_stream << "bar(x,y);\n";
322 }
323}
324
325
326
327template <typename T>
328void StatisticsVector<T>::histogram(std::vector<dof_id_type> & bin_members,
329 unsigned int n_bins) const
330{
331 StatisticsVector<T> sv = (*this);
332
333 return sv.histogram(bin_members, n_bins);
334}
335
336
337
338
339template <typename T>
340std::vector<dof_id_type> StatisticsVector<T>::cut_below(Real cut) const
341{
342 LOG_SCOPE ("cut_below()", "StatisticsVector");
343
344 const dof_id_type n = cast_int<dof_id_type>(this->size());
345
346 std::vector<dof_id_type> cut_indices;
347 cut_indices.reserve(n/2); // Arbitrary
348
349 for (dof_id_type i=0; i<n; i++)
350 {
351 if ((*this)[i] < cut)
352 {
353 cut_indices.push_back(i);
354 }
355 }
356
357 return cut_indices;
358}
359
360
361
362
363template <typename T>
364std::vector<dof_id_type> StatisticsVector<T>::cut_above(Real cut) const
365{
366 LOG_SCOPE ("cut_above()", "StatisticsVector");
367
368 const dof_id_type n = cast_int<dof_id_type>(this->size());
369
370 std::vector<dof_id_type> cut_indices;
371 cut_indices.reserve(n/2); // Arbitrary
372
373 for (dof_id_type i=0; i<n; i++)
374 if ((*this)[i] > cut)
375 cut_indices.push_back(i);
376
377 return cut_indices;
378}
379
380
381
382
383//------------------------------------------------------------
384// Explicit Instantiations
385template class LIBMESH_EXPORT StatisticsVector<float>;
386template class LIBMESH_EXPORT StatisticsVector<double>;
387#ifdef LIBMESH_DEFAULT_TRIPLE_PRECISION
388template class LIBMESH_EXPORT StatisticsVector<long double>;
389#endif
390#ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
391template class LIBMESH_EXPORT StatisticsVector<Real>;
392#endif
393template class LIBMESH_EXPORT StatisticsVector<int>;
394template class LIBMESH_EXPORT StatisticsVector<unsigned int>;
395
396} // namespace libMesh
The StatisticsVector class is derived from the std::vector<> and therefore has all of its useful feat...
Definition statistics.h:68
virtual Real mean() const
Definition statistics.C:75
virtual std::vector< dof_id_type > cut_below(Real cut) const
Definition statistics.C:340
void normalize()
Divides all entries by the largest entry and stores the result.
Definition statistics.C:165
virtual Real median()
Definition statistics.C:96
virtual std::vector< dof_id_type > cut_above(Real cut) const
Definition statistics.C:364
virtual void histogram(std::vector< dof_id_type > &bin_members, unsigned int n_bins=10)
Definition statistics.C:179
virtual T maximum() const
Definition statistics.C:62
virtual Real variance() const
Definition statistics.h:134
virtual Real l2_norm() const
Definition statistics.C:37
void plot_histogram(const processor_id_type my_procid, const std::string &filename, unsigned int n_bins)
Generates a Matlab/Octave style file which can be used to make a plot of the histogram having the des...
Definition statistics.C:285
virtual T minimum() const
Definition statistics.C:49
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
libmesh_assert(ctx)
OStreamProxy out
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
Definition id_types.h:104