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