OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
AccumulatorView.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_ACCUMULATORVIEW_HPP
46#define OPENMD_UTILS_ACCUMULATORVIEW_HPP
47
48#include <cmath>
49#include <cstddef>
50#include <iostream>
51#include <string>
52#include <typeinfo>
53#include <vector>
54
56#include "math/Vector3.hpp"
57#include "nonbonded/NonBondedInteraction.hpp"
58#include "utils/Accumulator.hpp"
59#include "utils/BaseAccumulator.hpp"
60#include "utils/simError.h"
61
62namespace OpenMD::Utils {
63
64 template<typename T>
66
67 template<>
69 public BaseAccumulator,
70 private RealAccumulator {
71 public:
72 void add(RealType val) override { RealAccumulator::add(val); }
73
74 // Other overrides for invalid entries
75 void add(const std::vector<RealType>&) override {
76 accumulatorFunctionCallMismatch();
77 }
78 void add(const Vector3d&) override { accumulatorFunctionCallMismatch(); }
79 void add(const potVec&) override { accumulatorFunctionCallMismatch(); }
80 void add(const Mat3x3d&) override { accumulatorFunctionCallMismatch(); }
81
82 void writeData(std::ostream& stream, const std::string& errorMessage,
83 DataHandling dataHandling) const override {
84 RealType dat;
85 std::size_t count = RealAccumulator::getCount();
86
87 switch (dataHandling) {
88 case DataHandling::Average:
90 break;
91 case DataHandling::Last:
93 break;
94 case DataHandling::Max:
96 break;
97 case DataHandling::Min:
99 break;
100 case DataHandling::Total:
102 break;
103 default:
104 break;
105 }
106
107 if (std::isinf(dat) || std::isnan(dat)) {
108 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
109 errorMessage.c_str());
110 painCave.isFatal = 1;
111 simError();
112 } else {
113 if (count == 0)
114 stream << "\t";
115 else
116 stream << "\t" << dat;
117 }
118 }
119
120 void writeErrorBars(std::ostream& stream, const std::string& errorMessage,
121 ErrorHandling errorHandling) const override {
122 RealType err;
123 std::size_t count = RealAccumulator::getCount();
124
125 switch (errorHandling) {
126 case ErrorHandling::CI95:
128 break;
129 case ErrorHandling::StdDev:
131 break;
132 case ErrorHandling::Variance:
134 break;
135 default:
136 break;
137 }
138
139 if (count == 0 && errorHandling == ErrorHandling::CI95) {
140 stream << "\t";
141 } else {
142 if (std::isinf(err) || std::isnan(err)) {
143 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
144 errorMessage.c_str());
145 painCave.isFatal = 1;
146 simError();
147 } else {
148 if (count == 0)
149 stream << "\t";
150 else
151 stream << "\t" << err;
152 }
153 }
154 }
155
156 std::type_index getType() const override { return typeid(RealType); }
157
158 std::size_t getCount() const override {
159 return RealAccumulator::getCount();
160 }
161 };
162
163 template<>
165 public BaseAccumulator,
166 private StdVectorAccumulator {
167 public:
168 void add(const std::vector<RealType>& val) override {
169 StdVectorAccumulator::add(val);
170 }
171
172 // Other overrides for invalid entries
173 void add(RealType val) override { accumulatorFunctionCallMismatch(); }
174 void add(const Vector3d&) override { accumulatorFunctionCallMismatch(); }
175 void add(const potVec&) override { accumulatorFunctionCallMismatch(); }
176 void add(const Mat3x3d&) override { accumulatorFunctionCallMismatch(); }
177
178 void writeData(std::ostream& stream, const std::string& errorMessage,
179 DataHandling dataHandling) const override {
180 std::vector<RealType> dat;
181 std::size_t count = StdVectorAccumulator::getCount();
182
183 switch (dataHandling) {
184 case DataHandling::Average:
185 dat = StdVectorAccumulator::getAverage();
186 break;
187 case DataHandling::Last:
188 dat = StdVectorAccumulator::getLastValue();
189 break;
190 case DataHandling::Total:
191 dat = StdVectorAccumulator::getTotal();
192 break;
193 case DataHandling::Max:
194 case DataHandling::Min:
195 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
196 "Max and Min functions are not defined for a "
197 "std::vector Accumulator.");
198 painCave.isFatal = 1;
199 simError();
200 break;
201 default:
202 break;
203 }
204
205 for (int i = 0; i < StdVectorAccumulator::getAverage().size(); i++) {
206 if (std::isinf(dat[i]) || std::isnan(dat[i])) {
207 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
208 errorMessage.c_str());
209 painCave.isFatal = 1;
210 simError();
211 } else {
212 if (count == 0)
213 stream << '\t';
214 else
215 stream << '\t' << dat[i];
216 }
217 }
218 }
219
220 void writeErrorBars(std::ostream& stream, const std::string& errorMessage,
221 ErrorHandling errorHandling) const override {
222 std::vector<RealType> err;
223 std::size_t count = StdVectorAccumulator::getCount();
224
225 switch (errorHandling) {
226 case ErrorHandling::CI95:
227 err = StdVectorAccumulator::get95percentConfidenceInterval();
228 break;
229 case ErrorHandling::StdDev:
230 err = StdVectorAccumulator::getStdDev();
231 break;
232 case ErrorHandling::Variance:
233 err = StdVectorAccumulator::getVariance();
234 break;
235 default:
236 break;
237 }
238
239 for (int i = 0; i < StdVectorAccumulator::getAverage().size(); i++) {
240 if (count == 0 && errorHandling == ErrorHandling::CI95) {
241 stream << "\t";
242 } else {
243 if (std::isinf(err[i]) || std::isnan(err[i])) {
244 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
245 errorMessage.c_str());
246 painCave.isFatal = 1;
247 simError();
248 } else {
249 if (count == 0)
250 stream << "\t";
251 else
252 stream << "\t" << err[i];
253 }
254 }
255 }
256 }
257
258 std::type_index getType() const override {
259 return typeid(std::vector<RealType>);
260 }
261
262 std::size_t getCount() const override {
263 std::size_t count = StdVectorAccumulator::getCount();
264
265 return count;
266 }
267 };
268
269 template<>
271 public BaseAccumulator,
272 private Vector3dAccumulator {
273 public:
274 void add(const Vector3d& val) override { Vector3dAccumulator::add(val); }
275
276 // Other overrides for invalid entries
277 void add(RealType val) override { accumulatorFunctionCallMismatch(); }
278 void add(const std::vector<RealType>&) override {
279 accumulatorFunctionCallMismatch();
280 }
281 void add(const potVec&) override { accumulatorFunctionCallMismatch(); }
282 void add(const Mat3x3d&) override { accumulatorFunctionCallMismatch(); }
283
284 void writeData(std::ostream& stream, const std::string& errorMessage,
285 DataHandling dataHandling) const override {
286 Vector3d dat;
287 std::size_t count = Vector3dAccumulator::getCount();
288
289 switch (dataHandling) {
290 case DataHandling::Average:
291 dat = Vector3dAccumulator::getAverage();
292 break;
293 case DataHandling::Last:
294 dat = Vector3dAccumulator::getLastValue();
295 break;
296 case DataHandling::Total:
297 dat = Vector3dAccumulator::getTotal();
298 break;
299 case DataHandling::Max:
300 case DataHandling::Min:
301 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
302 "Max and Min functions are not defined for a "
303 "std::vector Accumulator.");
304 painCave.isFatal = 1;
305 simError();
306 break;
307 default:
308 break;
309 }
310
311 for (int i = 0; i < Vector3dAccumulator::getAverage().size(); i++) {
312 if (std::isinf(dat[i]) || std::isnan(dat[i])) {
313 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
314 errorMessage.c_str());
315 painCave.isFatal = 1;
316 simError();
317 } else {
318 if (count == 0)
319 stream << "\t";
320 else
321 stream << "\t" << dat[i];
322 }
323 }
324 }
325
326 void writeErrorBars(std::ostream& stream, const std::string& errorMessage,
327 ErrorHandling errorHandling) const override {
328 Vector3d err;
329 std::size_t count = Vector3dAccumulator::getCount();
330
331 switch (errorHandling) {
332 case ErrorHandling::CI95:
333 err = Vector3dAccumulator::get95percentConfidenceInterval();
334 break;
335 case ErrorHandling::StdDev:
336 err = Vector3dAccumulator::getStdDev();
337 break;
338 case ErrorHandling::Variance:
339 err = Vector3dAccumulator::getVariance();
340 break;
341 default:
342 break;
343 }
344
345 for (int i = 0; i < Vector3dAccumulator::getAverage().size(); i++) {
346 if (count == 0 && errorHandling == ErrorHandling::CI95) {
347 stream << "\t";
348 } else {
349 if (std::isinf(err[i]) || std::isnan(err[i])) {
350 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
351 errorMessage.c_str());
352 painCave.isFatal = 1;
353 simError();
354 } else {
355 if (count == 0)
356 stream << "\t";
357 else
358 stream << "\t" << err[i];
359 }
360 }
361 }
362 }
363
364 std::type_index getType() const override { return typeid(Vector3d); }
365
366 std::size_t getCount() const override {
367 return Vector3dAccumulator::getCount();
368 }
369 };
370
371 template<>
373 public BaseAccumulator,
374 private PotVecAccumulator {
375 public:
376 void add(const potVec& val) override { PotVecAccumulator::add(val); }
377
378 // Other overrides for invalid entries
379 void add(RealType val) override { accumulatorFunctionCallMismatch(); }
380 void add(const std::vector<RealType>&) override {
381 accumulatorFunctionCallMismatch();
382 }
383 void add(const Vector3d&) override { accumulatorFunctionCallMismatch(); }
384 void add(const Mat3x3d&) override { accumulatorFunctionCallMismatch(); }
385
386 void writeData(std::ostream& stream, const std::string& errorMessage,
387 DataHandling dataHandling) const override {
388 potVec dat;
389 std::size_t count = PotVecAccumulator::getCount();
390
391 switch (dataHandling) {
392 case DataHandling::Average:
393 dat = PotVecAccumulator::getAverage();
394 break;
395 case DataHandling::Last:
396 dat = PotVecAccumulator::getLastValue();
397 break;
398 case DataHandling::Total:
399 dat = PotVecAccumulator::getTotal();
400 break;
401 case DataHandling::Max:
402 case DataHandling::Min:
403 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
404 "Max and Min functions are not defined for a "
405 "std::vector Accumulator.");
406 painCave.isFatal = 1;
407 simError();
408 break;
409 default:
410 break;
411 }
412
413 for (int i = 0; i < PotVecAccumulator::getAverage().size(); i++) {
414 if (std::isinf(dat[i]) || std::isnan(dat[i])) {
415 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
416 errorMessage.c_str());
417 painCave.isFatal = 1;
418 simError();
419 } else {
420 if (count == 0)
421 stream << "\t";
422 else
423 stream << "\t" << dat[i];
424 }
425 }
426 }
427
428 void writeErrorBars(std::ostream& stream, const std::string& errorMessage,
429 ErrorHandling errorHandling) const override {
430 potVec err;
431 std::size_t count = PotVecAccumulator::getCount();
432
433 switch (errorHandling) {
434 case ErrorHandling::CI95:
435 err = PotVecAccumulator::get95percentConfidenceInterval();
436 break;
437 case ErrorHandling::StdDev:
438 err = PotVecAccumulator::getStdDev();
439 break;
440 case ErrorHandling::Variance:
441 err = PotVecAccumulator::getVariance();
442 break;
443 default:
444 break;
445 }
446
447 for (int i = 0; i < PotVecAccumulator::getAverage().size(); i++) {
448 if (count == 0 && errorHandling == ErrorHandling::CI95) {
449 stream << "\t";
450 } else {
451 if (std::isinf(err[i]) || std::isnan(err[i])) {
452 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
453 errorMessage.c_str());
454 painCave.isFatal = 1;
455 simError();
456 } else {
457 if (count == 0)
458 stream << "\t";
459 else
460 stream << "\t" << err[i];
461 }
462 }
463 }
464 }
465
466 std::type_index getType() const override { return typeid(potVec); }
467
468 std::size_t getCount() const override {
469 return PotVecAccumulator::getCount();
470 }
471 };
472
473 template<>
475 public BaseAccumulator,
476 private Mat3x3dAccumulator {
477 public:
478 void add(const Mat3x3d& val) override { Mat3x3dAccumulator::add(val); }
479
480 // Other overrides for invalid entries
481 void add(RealType val) override { accumulatorFunctionCallMismatch(); }
482 void add(const std::vector<RealType>&) override {
483 accumulatorFunctionCallMismatch();
484 }
485 void add(const Vector3d&) override { accumulatorFunctionCallMismatch(); }
486 void add(const potVec&) override { accumulatorFunctionCallMismatch(); }
487
488 void writeData(std::ostream& stream, const std::string& errorMessage,
489 DataHandling dataHandling) const override {
490 Mat3x3d dat;
491 std::size_t count = Mat3x3dAccumulator::getCount();
492
493 switch (dataHandling) {
494 case DataHandling::Average:
495 dat = Mat3x3dAccumulator::getAverage();
496 break;
497 case DataHandling::Last:
498 dat = Mat3x3dAccumulator::getLastValue();
499 break;
500 case DataHandling::Total:
501 dat = Mat3x3dAccumulator::getTotal();
502 break;
503 case DataHandling::Max:
504 case DataHandling::Min:
505 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
506 "Max and Min functions are not defined for a "
507 "std::vector Accumulator.");
508 painCave.isFatal = 1;
509 simError();
510 break;
511 default:
512 break;
513 }
514
515 for (unsigned int i = 0; i < 3; i++) {
516 for (unsigned int j = 0; j < 3; j++) {
517 if (std::isinf(dat(i, j)) || std::isnan(dat(i, j))) {
518 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
519 errorMessage.c_str());
520 painCave.isFatal = 1;
521 simError();
522 } else {
523 if (count == 0)
524 stream << "\t";
525 else
526 stream << "\t" << dat(i, j);
527 }
528 }
529 }
530 }
531
532 void writeErrorBars(std::ostream& stream, const std::string& errorMessage,
533 ErrorHandling errorHandling) const override {
534 Mat3x3d err;
535 std::size_t count = Mat3x3dAccumulator::getCount();
536
537 switch (errorHandling) {
538 case ErrorHandling::CI95:
539 err = Mat3x3dAccumulator::get95percentConfidenceInterval();
540 break;
541 case ErrorHandling::StdDev:
542 err = Mat3x3dAccumulator::getStdDev();
543 break;
544 case ErrorHandling::Variance:
545 err = Mat3x3dAccumulator::getVariance();
546 break;
547 default:
548 break;
549 }
550
551 for (unsigned int i = 0; i < 3; i++) {
552 for (unsigned int j = 0; j < 3; j++) {
553 if (count == 0 && errorHandling == ErrorHandling::CI95) {
554 stream << "\t";
555 } else {
556 if (std::isinf(err(i, j)) || std::isnan(err(i, j))) {
557 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "%s",
558 errorMessage.c_str());
559 painCave.isFatal = 1;
560 simError();
561 } else {
562 if (count == 0)
563 stream << "\t";
564 else
565 stream << "\t" << err(i, j);
566 }
567 }
568 }
569 }
570 }
571
572 std::type_index getType() const override { return typeid(Mat3x3d); }
573
574 std::size_t getCount() const override {
575 return Mat3x3dAccumulator::getCount();
576 }
577 };
578} // namespace OpenMD::Utils
579
580#endif
void getTotal(ResultType &ret)
return the Total accumulated sum
void getAverage(ResultType &ret)
compute the Mean
void getMin(ElementType &ret)
return the smallest value
void getMax(ElementType &ret)
return the largest value
void get95percentConfidenceInterval(ResultType &ret)
return the 95% confidence interval:
void getLastValue(ElementType &ret)
return the most recently added value
virtual void add(ElementType const &val)
Accumulate another value.
void getVariance(ResultType &ret)
compute the Variance
void getStdDev(ResultType &ret)
compute error of average value