OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
Accumulator.hpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#ifndef OPENMD_UTILS_ACCUMULATOR_HPP
46#define OPENMD_UTILS_ACCUMULATOR_HPP
47
48#include <cassert>
49#include <cmath>
50#include <cstddef>
51#include <limits>
52#include <type_traits>
53#include <vector>
54
55#include "math/SquareMatrix.hpp"
57#include "math/Vector.hpp"
58#include "math/Vector3.hpp"
59#include "nonbonded/NonBondedInteraction.hpp"
60#include "utils/simError.h"
61
62namespace OpenMD::Utils {
63
64 template<typename T>
66 static_assert(std::is_default_constructible_v<T>,
67 "Accumulator type parameters must be default constructible.");
68
69 public:
70 void add(const T& val) {
71 Count_++;
72
73 Val_ = val;
74 Total_ += val;
75 Avg_ += (val - Avg_) / static_cast<RealType>(Count_);
76 Avg2_ += (val * val - Avg2_) / static_cast<RealType>(Count_);
77
78 if (Count_ <= 1) {
79 Max_ = val;
80 Min_ = val;
81 } else {
82 Max_ = val > Max_ ? val : Max_;
83 Min_ = val < Min_ ? val : Min_;
84 }
85 }
86
87 std::size_t getCount() const { return Count_; }
88
89 T getLastValue() const { return Val_; }
90
91 T getTotal() const {
92 assert(Count_ != 0);
93 return Total_;
94 }
95
96 RealType getMax() const {
97 static_assert(std::is_arithmetic<T>::value,
98 "getMax() requires a RealType Accumulator.");
99 assert(Count_ != 0);
100 return Max_;
101 }
102
103 RealType getMin() const {
104 static_assert(std::is_arithmetic<T>::value,
105 "getMin() requires a RealType Accumulator.");
106 assert(Count_ != 0);
107 return Min_;
108 }
109
110 RealType getAverage() const {
111 assert(Count_ != 0);
112 return Avg_;
113 }
114
115 RealType getVariance() const {
116 assert(Count_ != 0);
117 T var = (Avg2_ - Avg_ * Avg_);
118 if (var < 0) var = 0;
119
120 return var;
121 }
122
123 RealType getStdDev() const {
124 assert(Count_ != 0);
125 T sd = std::sqrt(this->getVariance());
126
127 return sd;
128 }
129
130 RealType get95percentConfidenceInterval() const {
131 assert(Count_ != 0);
132 T ci =
133 1.960 * this->getStdDev() / std::sqrt(static_cast<RealType>(Count_));
134
135 return ci;
136 }
137
138 private:
139 std::size_t Count_ {};
140 T Val_ {}, Total_ {};
141 RealType Max_ {}, Min_ {}, Avg_ {}, Avg2_ {};
142 };
143
144 // Specializations for commonly used Accumulator types
145 template<>
146 class Accumulator<std::vector<RealType>> {
147 public:
148 /* A flag specifying that a given bin is empty and should be ignored
149 during calls to add() */
150 constexpr static RealType BinEmptyFlag =
151 std::numeric_limits<RealType>::max();
152
153 void add(const std::vector<RealType>& val) {
154 if (val.empty() || (val.size() != Avg_.size() && !Avg_.empty())) {
155 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
156 "Size of vector passed to add() did not "
157 "match the size of the StaticAccumulator.");
158 painCave.isFatal = 1;
159 simError();
160 }
161
162 Count_++;
163
164 if (Avg_.empty()) {
165 Val_.resize(val.size());
166 Total_.resize(val.size());
167 Avg_.resize(val.size());
168 Avg2_.resize(val.size());
169 }
170
171 for (std::size_t i = 0; i < val.size(); i++) {
172 /* If our placeholder, BinEmptyFlag, is passed to add(), we should
173 not record data at the current index */
174 if (val[i] == BinEmptyFlag) continue;
175 Val_[i] = val[i];
176 Total_[i] += val[i];
177 Avg_[i] += (val[i] - Avg_[i]) / static_cast<RealType>(Count_);
178 Avg2_[i] +=
179 (val[i] * val[i] - Avg2_[i]) / static_cast<RealType>(Count_);
180 }
181 }
182
183 std::size_t getCount() const { return Count_; }
184
185 std::vector<RealType> getLastValue() const { return Val_; }
186
187 std::vector<RealType> getTotal() const { return Total_; }
188
189 std::vector<RealType> getAverage() const { return Avg_; }
190
191 std::vector<RealType> getVariance() const {
192 std::vector<RealType> var(Avg_.size());
193
194 for (std::size_t i = 0; i < Avg_.size(); i++) {
195 var[i] = (Avg2_[i] - Avg_[i] * Avg_[i]);
196 if (var[i] < 0) var[i] = 0;
197 }
198
199 return var;
200 }
201
202 std::vector<RealType> getStdDev() const {
203 std::vector<RealType> sd(Avg_.size());
204 std::vector<RealType> variance = this->getVariance();
205
206 for (std::size_t i = 0; i < variance.size(); i++) {
207 sd[i] = std::sqrt(variance[i]);
208 }
209
210 return sd;
211 }
212
213 std::vector<RealType> get95percentConfidenceInterval() const {
214 std::vector<RealType> ci(Avg_.size());
215 std::vector<RealType> stdDev = this->getStdDev();
216
217 for (std::size_t i = 0; i < stdDev.size(); i++) {
218 ci[i] = 1.960 * stdDev[i] / std::sqrt(static_cast<RealType>(Count_));
219 }
220
221 return ci;
222 }
223
224 private:
225 std::size_t Count_ {};
226 std::vector<RealType> Val_ {}, Total_ {}, Avg_ {}, Avg2_ {};
227 };
228
229 template<unsigned int Dim>
230 class Accumulator<Vector<RealType, Dim>> {
231 public:
232 void add(const Vector<RealType, Dim>& val) {
233 Count_++;
234
235 for (std::size_t i = 0; i < Dim; i++) {
236 Val_[i] = val[i];
237 Total_[i] += val[i];
238 Avg_[i] += (val[i] - Avg_[i]) / static_cast<RealType>(Count_);
239 Avg2_[i] +=
240 (val[i] * val[i] - Avg2_[i]) / static_cast<RealType>(Count_);
241 }
242 }
243
244 std::size_t getCount() const { return Count_; }
245
246 Vector<RealType, Dim> getLastValue() const { return Val_; }
247
248 Vector<RealType, Dim> getTotal() const {
249 assert(Count_ != 0);
250
251 return Total_;
252 }
253
254 Vector<RealType, Dim> getAverage() const {
255 assert(Count_ != 0);
256
257 return Avg_;
258 }
259
260 Vector<RealType, Dim> getVariance() const {
261 assert(Count_ != 0);
262
263 Vector<RealType, Dim> var {};
264
265 for (std::size_t i = 0; i < Dim; i++) {
266 var[i] = (Avg2_[i] - Avg_[i] * Avg_[i]);
267 if (var[i] < 0) var[i] = 0;
268 }
269
270 return var;
271 }
272
273 Vector<RealType, Dim> getStdDev() const {
274 assert(Count_ != 0);
275
276 Vector<RealType, Dim> sd {};
277 Vector<RealType, Dim> variance = this->getVariance();
278
279 for (std::size_t i = 0; i < Dim; i++) {
280 sd[i] = std::sqrt(variance[i]);
281 }
282
283 return sd;
284 }
285
286 Vector<RealType, Dim> get95percentConfidenceInterval() const {
287 assert(Count_ != 0);
288
289 Vector<RealType, Dim> ci {};
290 Vector<RealType, Dim> stdDev = this->getStdDev();
291
292 for (std::size_t i = 0; i < Dim; i++) {
293 ci[i] = 1.960 * stdDev[i] / std::sqrt(static_cast<RealType>(Count_));
294 }
295
296 return ci;
297 }
298
299 private:
300 std::size_t Count_ {};
301 Vector<RealType, Dim> Val_ {}, Total_ {}, Avg_ {}, Avg2_ {};
302 };
303
304 template<>
306 public:
307 void add(const Mat3x3d& val) {
308 Count_++;
309
310 for (std::size_t i = 0; i < 3; i++) {
311 for (std::size_t j = 0; j < 3; j++) {
312 Val_(i, j) = val(i, j);
313 Total_(i, j) += val(i, j);
314 Avg_(i, j) +=
315 (val(i, j) - Avg_(i, j)) / static_cast<RealType>(Count_);
316 Avg2_(i, j) += (val(i, j) * val(i, j) - Avg2_(i, j)) /
317 static_cast<RealType>(Count_);
318 }
319 }
320 }
321
322 std::size_t getCount() const { return Count_; }
323
324 Mat3x3d getLastValue() const { return Val_; }
325
326 Mat3x3d getTotal() const {
327 assert(Count_ != 0);
328
329 return Total_;
330 }
331
332 Mat3x3d getAverage() const {
333 assert(Count_ != 0);
334
335 return Avg_;
336 }
337
338 Mat3x3d getVariance() const {
339 assert(Count_ != 0);
340
341 Mat3x3d var {};
342
343 for (std::size_t i = 0; i < 3; i++) {
344 for (std::size_t j = 0; j < 3; j++) {
345 var(i, j) = (Avg2_(i, j) - Avg_(i, j) * Avg_(i, j));
346 if (var(i, j) < 0) var(i, j) = 0;
347 }
348 }
349
350 return var;
351 }
352
353 Mat3x3d getStdDev() const {
354 assert(Count_ != 0);
355
356 Mat3x3d sd {};
357 Mat3x3d variance = this->getVariance();
358
359 for (std::size_t i = 0; i < 3; i++) {
360 for (std::size_t j = 0; j < 3; j++) {
361 sd(i, j) = std::sqrt(variance(i, j));
362 }
363 }
364
365 return sd;
366 }
367
368 Mat3x3d get95percentConfidenceInterval() const {
369 assert(Count_ != 0);
370
371 Mat3x3d ci {};
372 Mat3x3d stdDev = this->getStdDev();
373
374 for (std::size_t i = 0; i < 3; i++) {
375 for (std::size_t j = 0; j < 3; j++) {
376 ci(i, j) =
377 1.960 * stdDev(i, j) / std::sqrt(static_cast<RealType>(Count_));
378 }
379 }
380
381 return ci;
382 }
383
384 private:
385 std::size_t Count_ {};
386 Mat3x3d Val_ {}, Total_ {}, Avg_ {}, Avg2_ {};
387 };
388
389 // Type aliases for the most commonly used Accumulators
390 using RealAccumulator = Accumulator<RealType>;
391 using StdVectorAccumulator = Accumulator<std::vector<RealType>>;
392 using Vector3dAccumulator = Accumulator<Vector<RealType, 3>>;
393 using PotVecAccumulator =
394 Accumulator<Vector<RealType, N_INTERACTION_FAMILIES>>;
395 using Mat3x3dAccumulator = Accumulator<Mat3x3d>;
396} // namespace OpenMD::Utils
397
398#endif // OPENMD_UTILS_STATICACCUMULATOR_HPP
Fix length vector class.
Definition Vector.hpp:78