PSCF v1.1
AutoCorrStage.tpp
1#ifndef UTIL_AUTOCORR_STAGE_TPP
2#define UTIL_AUTOCORR_STAGE_TPP
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 "AutoCorrStage.h"
12
13#include <util/accumulators/setToZero.h>
14#include <util/accumulators/product.h>
15#include <util/format/Int.h>
16#include <util/format/write.h>
17
18#include <complex>
19#include <math.h>
20
21using std::complex;
22
23namespace Util
24{
25
26 /*
27 * Constructor for rootPtr AutoCorrStage, with stageId = 0.
28 */
29 template <typename Data, typename Product>
31 : bufferCapacity_(64),
32 maxStageId_(10),
33 blockFactor_(2),
34 buffer_(),
35 corr_(),
36 nCorr_(),
37 nSample_(0),
38 blockSum_(),
39 nBlockSample_(0),
40 stageInterval_(1),
41 childPtr_(0),
42 rootPtr_(0),
43 stageId_(0)
44 {
45 rootPtr_ = this;
46 setToZero(blockSum_);
47 }
48
49 /*
50 * Private constructor for stages with stageId > 0.
51 */
52 template <typename Data, typename Product>
54 int stageId, int maxStageId,
56 int blockFactor)
57 : bufferCapacity_(rootPtr->bufferCapacity()),
58 maxStageId_(maxStageId),
59 blockFactor_(blockFactor),
60 buffer_(),
61 corr_(),
62 nCorr_(),
63 nSample_(0),
64 blockSum_(),
65 nBlockSample_(0),
66 stageInterval_(stageInterval),
67 childPtr_(0),
68 rootPtr_(rootPtr),
69 stageId_(stageId)
70 {
71 allocate();
72 setToZero(blockSum_);
73 }
74
75 /*
76 * Destructor.
77 */
78 template <typename Data, typename Product>
80 {
81 if (childPtr_) {
82 delete childPtr_;
83 }
84 }
85
86 /*
87 * Set buffer capacity and initialize.
88 */
89 template <typename Data, typename Product>
91 int maxStageId, int blockFactor)
92 {
93 bufferCapacity_ = bufferCapacity;
94 maxStageId_ = maxStageId;
95 blockFactor_ = blockFactor;
96 allocate();
97 }
98
99 /*
100 * Set previously allocated to initial empty state.
101 */
102 template <typename Data, typename Product>
104 {
105 setToZero(blockSum_);
106 nSample_ = 0;
107 nBlockSample_ = 0;
108 if (bufferCapacity_ > 0) {
109 for (int i=0; i < bufferCapacity_; ++i) {
110 setToZero(corr_[i]);
111 nCorr_[i] = 0;
112 }
113 buffer_.clear();
114 }
115 }
116
117 /*
118 * Add a sampled value to the ensemble.
119 */
120 template <typename Data, typename Product>
122 {
123 if (bufferCapacity_ <= 0) {
124 bufferCapacity_ = 64;
125 blockFactor_ = 2;
126 maxStageId_ = 10;
127 allocate();
128 }
129
130 // Increment global accumulators
131 buffer_.append(value);
132 for (int i=0; i < buffer_.size(); ++i) {
133 corr_[i] += product(buffer_[i], value);
134 ++nCorr_[i];
135 };
136 ++nSample_;
137
138 // Increment block accumulators
139 blockSum_ += value;
140 ++nBlockSample_;
141
142 if (nBlockSample_ == blockFactor_) {
143 if (stageId_ < maxStageId_) {
144 if (!childPtr_) {
145 long nextStageInterval = stageInterval_*blockFactor_;
146 int nextStageId = stageId_ + 1;
147 childPtr_ = new AutoCorrStage(nextStageInterval, nextStageId,
148 maxStageId_, rootPtr_, blockFactor_);
149 rootPtr_->registerDescendant(childPtr_);
150 }
151 // Add block average as first value in child sequence
152 blockSum_ /= double(blockFactor_);
153 childPtr_->sample(blockSum_);
154 }
155 // Reset block accumulators
156 setToZero(blockSum_);
157 nBlockSample_ = 0;
158 }
159
160 }
161
162 /*
163 * Serialize this AutoCorr.
164 */
165 template <typename Data, typename Product>
166 template <class Archive>
167 void
169 const unsigned int version)
170 {
171 // Parameters (required for initialization)
172 ar & bufferCapacity_;
173 ar & maxStageId_;
174 ar & blockFactor_;
175
176 // Serialize private state info.
177 serializePrivate(ar, version);
178 }
179
180 /*
181 * Serialize private info for this AutoCorrStage.
182 */
183 template <typename Data, typename Product>
184 template <class Archive>
185 void
187 const unsigned int version)
188 {
189 // State of simple nonblock correlator
190 ar & buffer_;
191 ar & corr_;
192 ar & nCorr_;
193 ar & nSample_;
194 isValid();
195
196 ar & blockSum_;
197 ar & nBlockSample_;
198
199 // Constructor sets rootPtr_, stageInterval_ and stageId_
200
201 // Does this stage have a child?
202 int hasChild;
203 if (Archive::is_saving()) {
204 hasChild = (childPtr_ == 0) ? 0 : 1;
205 }
206 ar & hasChild;
207
208 // Serialize child (if any)
209 if (hasChild) {
210 if (Archive::is_loading()) {
211 long nextStageInterval = stageInterval_*blockFactor_;
212 int nextStageId = stageId_ + 1;
213 childPtr_ = new AutoCorrStage(nextStageInterval,
214 nextStageId, maxStageId_,
215 rootPtr_, blockFactor_);
216 rootPtr_->registerDescendant(childPtr_);
217 }
218 ar & (*childPtr_);
219 } else {
220 if (Archive::is_loading()) {
221 childPtr_ = 0;
222 }
223 }
224
225 }
226
227 /*
228 * Return capacity of history buffer.
229 */
230 template <typename Data, typename Product>
232 { return bufferCapacity_; }
233
234 /*
235 * Return current size of the history buffer.
236 */
237 template <typename Data, typename Product>
239 { return buffer_.size(); }
240
241 /*
242 * Return the number of sampled values.
243 */
244 template <typename Data, typename Product>
246 { return nSample_; }
247
248 /*
249 * Return the number of measured values per sample at this stage.
250 */
251 template <typename Data, typename Product>
253 { return stageInterval_; }
254
255 /*
256 * Calculate and output autocorrelation function, assuming zero average.
257 */
258 template <typename Data, typename Product>
259 void AutoCorrStage<Data, Product>::output(std::ostream& outFile)
260 {
261 Product aveSq;
262 setToZero(aveSq);
263 output(outFile, aveSq);
264 }
265
266 /*
267 * Calculate and output autocorrelation function.
268 */
269 template <typename Data, typename Product>
270 void AutoCorrStage<Data, Product>::output(std::ostream& outFile, Product aveSq)
271 {
272 int min;
273 if (stageId_ == 0) {
274 min = 0;
275 } else {
276 min = bufferCapacity_ / blockFactor_;
277 }
278
279 Product autocorr;
280 for (int i = min; i < buffer_.size(); ++i) {
281 autocorr = corr_[i]/double(nCorr_[i]);
282 autocorr -= aveSq;
283 outFile << Int(i*stageInterval_) << " ";
284 write<Product>(outFile, autocorr);
285 outFile << std::endl;
286 }
287 if (childPtr_) {
288 childPtr_->output(outFile, aveSq);
289 }
290 }
291
292 /*
293 * Return autocorrelation at a given lag time, assuming zero average.
294 */
295 template <typename Data, typename Product>
297 {
298 Product aveSq;
299 setToZero(aveSq);
300 return autoCorrelation(t, aveSq);
301 }
302
303 /*
304 * Return autocorrelation at a given lag time.
305 */
306 template <typename Data, typename Product>
307 Product AutoCorrStage<Data, Product>::autoCorrelation(int t, Product aveSq) const
308 {
309 assert(t < buffer_.size());
310 Product autocorr = corr_[t]/double(nCorr_[t]);
311 autocorr -= aveSq;
312 return autocorr;
313 }
314
315 /*
316 * Return correlation time, in Data samples, assuming zero average.
317 */
318 template <typename Data, typename Product>
320 {
321 Product aveSq;
322 setToZero(aveSq);
323 return corrTime(aveSq);
324 }
325
326 /*
327 * Return correlation time in unit of sampling interval.
328 */
329 template <typename Data, typename Product>
330 double AutoCorrStage<Data, Product>::corrTime(Product aveSq) const
331 {
332 // Compute variance from value C(t=0)
333 Product variance = corr_[0];
334 variance /= double(nCorr_[0]);
335 variance -= aveSq;
336
337 // Compute integral of C(t)/C(0)
338 Product autocorr, sum;
339 setToZero(sum);
340 int size = buffer_.size();
341 for (int i = 1; i < size/2; ++i) {
342 autocorr = corr_[i];
343 autocorr /= double(nCorr_[i]);
344 autocorr -= aveSq;
345 sum += autocorr;
346 }
347 sum /= variance;
348 return sum;
349 }
350
351 // Private member functions
352
353 /*
354 * Allocate arrays and CyclicBuffer, and initialize.
355 */
356 template <typename Data, typename Product>
358 {
359 if (bufferCapacity_ > 0) {
360 corr_.allocate(bufferCapacity_);
361 nCorr_.allocate(bufferCapacity_);
362 buffer_.allocate(bufferCapacity_);
363 }
365 }
366
367 /*
368 * Are capacities consistent?
369 */
370 template <typename Data, typename Product>
372 {
373 bool valid = true;
374 if (bufferCapacity_ != corr_.capacity()) valid = false;
375 if (bufferCapacity_ != nCorr_.capacity()) valid = false;
376 if (bufferCapacity_ != buffer_.capacity()) valid = false;
377 if (!valid) {
378 UTIL_THROW("Invalid AutoCorrStage");
379 }
380 return valid;
381 }
382
383 template <typename Data, typename Product>
384 void
386 {}
387
388}
389#endif
Hierarchical auto-correlation function algorithm.
Definition: AutoCorrStage.h:54
long stageInterval() const
Return the number of primary values per block at this stage.
int bufferCapacity() const
Return capacity of history buffer.
void output(std::ostream &out)
Output the autocorrelation function, assuming zero mean.
AutoCorrStage()
Constructor.
int bufferSize() const
Return current size of history buffer.
void serialize(Archive &ar, const unsigned int version)
Serialize to/from an archive.
void clear()
Clear accumulators and destroy descendants.
void serializePrivate(Archive &ar, const unsigned int version)
Serialize private data members, and descendants.
virtual void sample(Data value)
Sample a value.
Product autoCorrelation(int t) const
Return autocorrelation at a given time, assuming zero average.
virtual ~AutoCorrStage()
Destructor.
double corrTime() const
Estimate of autocorrelation time, in samples.
long nSample() const
Return the number of sampled values.
virtual void registerDescendant(AutoCorrStage< Data, Product > *ptr)
Register the creation of a descendant stage.
void allocate()
Allocate memory and initialize to empty state.
void setParam(int bufferCapacity=64, int maxStageId=0, int blockFactor=2)
Set all parameters and allocate to initialize state.
Wrapper for an int, for formatted ostream output.
Definition: Int.h:37
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
Utility classes for scientific computation.
Definition: accumulators.mod:1
void setToZero(int &value)
Set an int variable to zero.
Definition: setToZero.h:25
float product(float a, float b)
Product for float Data.
Definition: product.h:22