Simpatico  v1.10
AutoCorr.h
1 #ifndef UTIL_AUTO_CORR_H
2 #define UTIL_AUTO_CORR_H
3 
4 /*
5 * Util Package - C++ Utilities for Scientific Computation
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include <util/param/ParamComposite.h> // Base class
12 #include <util/containers/RingBuffer.h> // member
13 #include <util/containers/DArray.h> // member
14 
15 // Needed for implementation
16 #include <util/accumulators/setToZero.h>
17 #include <util/accumulators/product.h>
18 #include <util/space/Vector.h>
19 #include <util/format/Int.h>
20 #include <util/format/Dbl.h>
21 #include <util/format/write.h>
22 
23 #include <complex>
24 
25 using std::complex;
26 
27 namespace Util
28 {
29 
48  template <typename Data, typename Product>
49  class AutoCorr : public ParamComposite
50  {
51 
52  public:
53 
57  AutoCorr();
58 
62  ~AutoCorr();
63 
67  void clear();
68 
74  void readParameters(std::istream& in);
75 
81  void setParam(int bufferCapacity);
82 
88  virtual void loadParameters(Serializable::IArchive& ar);
89 
95  virtual void save(Serializable::OArchive& ar);
96 
103  template <class Archive>
104  void serialize(Archive& ar, const unsigned int version);
105 
111  void sample(Data value);
112 
118  void output(std::ostream& out);
119 
123  int bufferCapacity() const;
124 
128  int nSample() const;
129 
133  Data average() const;
134 
138  double corrTime() const;
139 
145  Product autoCorrelation(int t) const;
146 
147  private:
148 
149  // Ring buffer containing a sequence of stored Data values.
150  RingBuffer<Data> buffer_;
151 
152  // Array in which corr[j] = sum of values of <x(i-j), x(i)>
153  DArray<Product> corr_;
154 
155  // Array in which nCorr[i] = number of values added to corr[i]
156  DArray<int> nCorr_;
157 
158  // Sum of all previous values of x(t)
159  Data sum_;
160 
161  // Physical capacity (# of elements) of buffer, corr, and nCorr
162  int bufferCapacity_;
163 
164  // Total number of previous values of x(t)
165  int nSample_;
166 
170  void allocate();
171 
175  bool isValid();
176 
177  };
178 
179  /*
180  * Default constructor.
181  */
182  template <typename Data, typename Product>
184  : buffer_(),
185  corr_(),
186  nCorr_(),
187  bufferCapacity_(0),
188  nSample_(0)
189  {
190  setClassName("AutoCorr");
191  setToZero(sum_);
192  }
193 
194  /*
195  * Destructor
196  */
197  template <typename Data, typename Product>
199  {}
200 
201  /*
202  * Read buffer capacity and allocate all required memory.
203  */
204  template <typename Data, typename Product>
206  {
207  read<int>(in, "capacity", bufferCapacity_);
208  allocate();
209  }
210 
211  /*
212  * Set buffer capacity and initialize.
213  */
214  template <typename Data, typename Product>
216  {
217  bufferCapacity_ = bufferCapacity;
218  allocate();
219  }
220 
221  /*
222  * Load state from an archive.
223  */
224  template <typename Data, typename Product>
226  {
227  loadParameter<int>(ar, "capacity", bufferCapacity_);
228  ar & buffer_;
229  ar & corr_;
230  ar & nCorr_;
231  ar & sum_;
232  ar & nSample_;
233  isValid();
234  }
235 
236  /*
237  * Save state to an archive.
238  */
239  template <typename Data, typename Product>
241  { ar & *this; }
242 
243  /*
244  * Set previously allocated to initial empty state.
245  */
246  template <typename Data, typename Product>
248  {
249  setToZero(sum_);
250  nSample_ = 0;
251 
252  if (bufferCapacity_ > 0) {
253  for (int i=0; i < bufferCapacity_; ++i) {
254  setToZero(corr_[i]);
255  nCorr_[i] = 0;
256  }
257  buffer_.clear();
258  }
259  }
260 
261  /*
262  * Allocate arrays and CyclicBuffer, and initialize.
263  */
264  template <typename Data, typename Product>
266  {
267  if (bufferCapacity_ > 0) {
268  corr_.allocate(bufferCapacity_);
269  nCorr_.allocate(bufferCapacity_);
270  buffer_.allocate(bufferCapacity_);
271  }
272  clear();
273  }
274 
275  /*
276  * Are capacities consistent?
277  */
278  template <typename Data, typename Product>
280  {
281  bool valid = true;
282  if (bufferCapacity_ != corr_.capacity()) valid = false;
283  if (bufferCapacity_ != nCorr_.capacity()) valid = false;
284  if (bufferCapacity_ != buffer_.capacity()) valid = false;
285  if (!valid) {
286  UTIL_THROW("Invalid AutoCorr");
287  }
288  return valid;
289  }
290 
291  /*
292  * Sample a single value from a time sequence.
293  */
294  template <typename Data, typename Product>
296  {
297  ++nSample_;
298  sum_ += value;
299  buffer_.append(value);
300  for (int i=0; i < buffer_.size(); ++i) {
301  corr_[i] += product(buffer_[i], value);
302  ++nCorr_[i];
303  };
304  }
305 
306  /*
307  * Return capacity of history buffer.
308  */
309  template <typename Data, typename Product>
311  { return bufferCapacity_; }
312 
313  /*
314  * Return number of values sampled thus far.
315  */
316  template <typename Data, typename Product>
318  { return nSample_; }
319 
320  /*
321  * Return average of sampled values.
322  */
323  template <typename Data, typename Product>
325  {
326  Data ave = sum_;
327  ave /= double(nSample_);
328  return ave;
329  }
330 
331  /*
332  * Final output
333  */
334  template <typename Data, typename Product>
335  void AutoCorr<Data, Product>::output(std::ostream& outFile)
336  {
337  Data ave;
338  Product autocorr;
339  Product aveSq;
340 
341  // Calculate and output average of sampled values
342  ave = sum_;
343  ave /= double(nSample_);
344  aveSq = product(ave, ave);
345 
346  // Calculate and output autocorrelation
347  for (int i = 0; i < buffer_.size(); ++i) {
348  autocorr = corr_[i]/double(nCorr_[i]);
349  autocorr = autocorr - aveSq;
350  outFile << Int(i);
351  write<Product>(outFile, autocorr);
352  outFile << std::endl;
353  }
354 
355  }
356 
357  /*
358  * Return correlation time in unit of sampling interval
359  */
360  template <typename Data, typename Product>
362  {
363  Data ave;
364  Product aveSq, variance, autocorr, sum;
365  int size;
366 
367  size = buffer_.size();
368 
369  // Calculate average sampled values
370  ave = sum_/double(nSample_);
371  ave /= double(nSample_);
372  aveSq = product(ave, ave);
373 
374  // Calculate variance sampled values
375  variance = corr_[0]/double(nCorr_[0]);
376  variance = variance - aveSq;
377 
378  setToZero(sum);
379  for (int i = 1; i < size/2; ++i) {
380  autocorr = corr_[i]/double(nCorr_[i]);
381  autocorr = autocorr - aveSq;
382  sum += autocorr;
383  }
384  sum = sum/variance;
385 
386  return sum;
387  }
388 
389  /*
390  * Return autocorrelation at a given lag time index
391  *
392  * \param t the lag time index
393  */
394  template <typename Data, typename Product>
396  {
397  Data ave;
398  Product autocorr;
399  Product aveSq;
400 
401  // Calculate average of sampled values
402  ave = sum_;
403  ave /= double(nSample_);
404  aveSq = product(ave, ave);
405 
406  // Calculate and return autocorrelation
407  assert(t < buffer_.size());
408  autocorr = corr_[t]/double(nCorr_[t]);
409  autocorr = autocorr - aveSq;
410 
411  return autocorr;
412  }
413 
414  /*
415  * Serialize this AutoCorr.
416  */
417  template <typename Data, typename Product>
418  template <class Archive>
420  const unsigned int version)
421  {
422  ar & bufferCapacity_;
423  ar & buffer_;
424  ar & corr_;
425  ar & nCorr_;
426  ar & sum_;
427  ar & nSample_;
428  isValid();
429  }
430 
431 }
432 #endif
void output(std::ostream &out)
Output the autocorrelation function.
Definition: AutoCorr.h:335
float product(float a, float b)
Product for float Data.
Definition: product.h:22
AutoCorr()
Constructor.
Definition: AutoCorr.h:183
Data average() const
Return average of all sampled values.
Definition: AutoCorr.h:324
Class for storing history of previous values in an array.
Definition: RingBuffer.h:26
void readParameters(std::istream &in)
Read buffer capacity, allocate memory and initialize.
Definition: AutoCorr.h:205
~AutoCorr()
Destructor.
Definition: AutoCorr.h:198
double corrTime() const
Numerical integration of autocorrelation function.
Definition: AutoCorr.h:361
void clear()
Reset to empty state.
Definition: AutoCorr.h:247
Saving / output archive for binary ostream.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
virtual void save(Serializable::OArchive &ar)
Save state to an archive.
Definition: AutoCorr.h:240
void setToZero(int &value)
Set an int variable to zero.
Definition: setToZero.h:25
void setParam(int bufferCapacity)
Set buffer capacity, allocate memory and initialize.
Definition: AutoCorr.h:215
void serialize(Archive &ar, const unsigned int version)
Serialize to/from an archive.
Definition: AutoCorr.h:419
Utility classes for scientific computation.
Definition: accumulators.mod:1
Auto-correlation function for one sequence of Data values.
Definition: AutoCorr.h:49
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
int nSample() const
Return number of values sampled thus far.
Definition: AutoCorr.h:317
int bufferCapacity() const
Return capacity of history buffer.
Definition: AutoCorr.h:310
Saving archive for binary istream.
virtual void loadParameters(Serializable::IArchive &ar)
Load state from an archive.
Definition: AutoCorr.h:225
void setClassName(const char *className)
Set class name string.
int capacity() const
Return allocated size.
Definition: Array.h:153
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:191
void sample(Data value)
Sample a value.
Definition: AutoCorr.h:295
An object that can read multiple parameters from file.
Product autoCorrelation(int t) const
Return autocorrelation at a given lag time.
Definition: AutoCorr.h:395