deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
histogram.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 1999 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#include <deal.II/base/config.h>
14
18
19#include <deal.II/lac/vector.h>
20
22
23#include <Kokkos_Macros.hpp>
24
25#include <algorithm>
26#include <cmath>
27#include <cstddef>
28#include <ostream>
29#include <string>
30#include <vector>
31
33
34
35template <typename number>
36bool
37Histogram::logarithmic_less(const number n1, const number n2)
38{
39 return (((n1 < n2) && (n1 > 0)) || ((n1 < n2) && (n2 <= 0)) ||
40 ((n2 < n1) && (n1 > 0) && (n2 <= 0)));
41}
42
43
44
45Histogram::Interval::Interval(const double left_point, const double right_point)
46 : left_point(left_point)
47 , right_point(right_point)
48 , content(0)
49{}
50
51
52
53std::size_t
55{
56 return sizeof(*this);
57}
58
59
60
61template <typename number>
62void
63Histogram::evaluate(const std::vector<Vector<number>> &values,
64 const std::vector<double> &y_values_,
65 const unsigned int n_intervals,
66 const IntervalSpacing interval_spacing)
67{
68 Assert(values.size() > 0,
70 "Your input data needs to contain at least one input vector."));
71 Assert(n_intervals > 0,
72 ExcMessage("The number of intervals needs to be at least one."));
73 for (unsigned int i = 0; i < values.size(); ++i)
74 Assert(values[i].size() > 0, ExcEmptyData());
75 Assert(values.size() == y_values_.size(),
76 ExcIncompatibleArraySize(values.size(), y_values_.size()));
77
78 // store y_values
79 y_values = y_values_;
80
81 // first find minimum and maximum value
82 // in the indicators
83 number min_value = 0, max_value = 0;
84 switch (interval_spacing)
85 {
86 case linear:
87 {
88 min_value = *std::min_element(values[0].begin(), values[0].end());
89 max_value = *std::max_element(values[0].begin(), values[0].end());
90
91 for (unsigned int i = 1; i < values.size(); ++i)
92 {
93 min_value =
94 std::min(min_value,
95 *std::min_element(values[i].begin(), values[i].end()));
96 max_value =
97 std::max(max_value,
98 *std::max_element(values[i].begin(), values[i].end()));
99 }
100
101 break;
102 }
103
104 case logarithmic:
105 {
106 const auto logarithmic_less_function =
107 &Histogram::template logarithmic_less<number>;
108
109 min_value = *std::min_element(values[0].begin(),
110 values[0].end(),
111 logarithmic_less_function);
112
113 max_value = *std::max_element(values[0].begin(),
114 values[0].end(),
115 logarithmic_less_function);
116
117 for (unsigned int i = 1; i < values.size(); ++i)
118 {
119 min_value = std::min(min_value,
120 *std::min_element(values[i].begin(),
121 values[i].end(),
122 logarithmic_less_function),
123 logarithmic_less_function);
124
125 max_value = std::max(max_value,
126 *std::max_element(values[i].begin(),
127 values[i].end(),
128 logarithmic_less_function),
129 logarithmic_less_function);
130 }
131
132 break;
133 }
134
135 default:
137 }
138
139 // move right bound arbitrarily if
140 // necessary. sometimes in logarithmic
141 // mode, max_value may be larger than
142 // min_value, but only up to rounding
143 // precision.
144 if (max_value <= min_value)
145 max_value = min_value + 1;
146
147
148 // now set up the intervals based on
149 // the min and max values
150 intervals.clear();
151 // set up one list of intervals
152 // for the first data vector. we will
153 // then produce all the other lists
154 // for the other data vectors by
155 // copying
156 intervals.emplace_back();
157
158 switch (interval_spacing)
159 {
160 case linear:
161 {
162 const float delta = (max_value - min_value) / n_intervals;
163
164 for (unsigned int n = 0; n < n_intervals; ++n)
165 intervals[0].emplace_back(min_value + n * delta,
166 min_value + (n + 1) * delta);
167
168 break;
169 }
170
171 case logarithmic:
172 {
173 const float delta =
174 (std::log(max_value) - std::log(min_value)) / n_intervals;
175
176 for (unsigned int n = 0; n < n_intervals; ++n)
177 intervals[0].emplace_back(std::exp(std::log(min_value) + n * delta),
178 std::exp(std::log(min_value) +
179 (n + 1) * delta));
180
181 break;
182 }
183
184 default:
186 }
187
188 // fill the other lists of intervals
189 for (unsigned int i = 1; i < values.size(); ++i)
190 intervals.push_back(intervals[0]);
191
192
193 // finally fill the intervals
194 for (unsigned int i = 0; i < values.size(); ++i)
195 for (typename Vector<number>::const_iterator p = values[i].begin();
196 p < values[i].end();
197 ++p)
198 {
199 // find the right place for *p in
200 // intervals[i]. use regular
201 // operator< here instead of
202 // the logarithmic one to
203 // map negative or zero value
204 // to the leftmost interval always
205 for (unsigned int n = 0; n < n_intervals; ++n)
206 if (*p <= intervals[i][n].right_point)
207 {
208 ++intervals[i][n].content;
209 break;
210 }
211 }
212}
213
214
215
216template <typename number>
217void
219 const unsigned int n_intervals,
220 const IntervalSpacing interval_spacing)
221{
222 std::vector<Vector<number>> values_list(1, values);
223 evaluate(values_list,
224 std::vector<double>(1, 0.),
225 n_intervals,
226 interval_spacing);
227}
228
229
230
231void
232Histogram::write_gnuplot(std::ostream &out) const
233{
234 AssertThrow(out.fail() == false, ExcIO());
235 Assert(!intervals.empty(),
236 ExcMessage("There is nothing to write into the output file. "
237 "Did you forget to call the evaluate() function?"));
238
239 // do a simple 2d plot, if only
240 // one data set is available
241 if (intervals.size() == 1)
242 {
243 for (const auto &interval : intervals[0])
244 out << interval.left_point << ' ' << interval.content << std::endl
245 << interval.right_point << ' ' << interval.content << std::endl;
246 }
247 else
248 // otherwise create a whole 3d plot
249 // for the data. use th patch method
250 // of gnuplot for this
251 //
252 // run this loop backwards since otherwise
253 // gnuplot thinks the upper side is the
254 // lower side and draws the diagram in
255 // strange colors
256 for (int i = intervals.size() - 1; i >= 0; --i)
257 {
258 for (unsigned int n = 0; n < intervals[i].size(); ++n)
259 out << intervals[i][n].left_point << ' '
260 << (i < static_cast<int>(intervals.size()) - 1 ?
261 y_values[i + 1] :
262 y_values[i] + (y_values[i] - y_values[i - 1]))
263 << ' ' << intervals[i][n].content << std::endl
264 << intervals[i][n].right_point << ' '
265 << (i < static_cast<int>(intervals.size()) - 1 ?
266 y_values[i + 1] :
267 y_values[i] + (y_values[i] - y_values[i - 1]))
268 << ' ' << intervals[i][n].content << std::endl;
269
270 out << std::endl;
271 for (unsigned int n = 0; n < intervals[i].size(); ++n)
272 out << intervals[i][n].left_point << ' ' << y_values[i] << ' '
273 << intervals[i][n].content << std::endl
274 << intervals[i][n].right_point << ' ' << y_values[i] << ' '
275 << intervals[i][n].content << std::endl;
276
277 out << std::endl;
278 }
279
280 AssertThrow(out.fail() == false, ExcIO());
281}
282
283
284
285std::string
287{
288 return "linear|logarithmic";
289}
290
291
292
294Histogram::parse_interval_spacing(const std::string &name)
295{
296 if (name == "linear")
297 return linear;
298 else if (name == "logarithmic")
299 return logarithmic;
300 else
301 {
302 AssertThrow(false, ExcInvalidName(name));
303
304 return linear;
305 }
306}
307
308
309
310std::size_t
316
317
318#ifndef DOXYGEN
319// explicit instantiations for float
320template void
321Histogram::evaluate<float>(const std::vector<Vector<float>> &values,
322 const std::vector<double> &y_values,
323 const unsigned int n_intervals,
324 const IntervalSpacing interval_spacing);
325template void
326Histogram::evaluate<float>(const Vector<float> &values,
327 const unsigned int n_intervals,
328 const IntervalSpacing interval_spacing);
329
330
331// explicit instantiations for double
332template void
333Histogram::evaluate<double>(const std::vector<Vector<double>> &values,
334 const std::vector<double> &y_values,
335 const unsigned int n_intervals,
336 const IntervalSpacing interval_spacing);
337template void
338Histogram::evaluate<double>(const Vector<double> &values,
339 const unsigned int n_intervals,
340 const IntervalSpacing interval_spacing);
341#endif
342
*  iterator end()
*  *  iterator begin()
void write_gnuplot(std::ostream &out) const
Definition histogram.cc:232
@ logarithmic
Definition histogram.h:83
static std::string get_interval_spacing_names()
Definition histogram.cc:286
std::vector< double > y_values
Definition histogram.h:238
static IntervalSpacing parse_interval_spacing(const std::string &name)
Definition histogram.cc:294
static bool logarithmic_less(const number n1, const number n2)
Definition histogram.cc:37
std::vector< std::vector< Interval > > intervals
Definition histogram.h:232
std::size_t memory_consumption() const
Definition histogram.cc:311
void evaluate(const std::vector< Vector< number > > &values, const std::vector< double > &y_values, const unsigned int n_intervals, const IntervalSpacing interval_spacing=linear)
Definition histogram.cc:63
const value_type * const_iterator
Definition vector.h:119
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
static ::ExceptionBase & ExcInvalidName(std::string arg1)
static ::ExceptionBase & ExcIO()
#define Assert(cond, exc)
static ::ExceptionBase & ExcIncompatibleArraySize(int arg1, int arg2)
static ::ExceptionBase & ExcEmptyData()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::size_t size
Definition mpi.cc:733
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
::VectorizedArray< Number, width > log(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > exp(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
Interval(const double left_point, const double right_point)
Definition histogram.cc:45
std::size_t memory_consumption() const
Definition histogram.cc:54