OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
StatWriter.cpp
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 following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include <config.h>
49
50#define _LARGEFILE_SOURCE64
51#define _FILE_OFFSET_BITS 64
52
53#include "brains/Stats.hpp"
54#include "io/StatWriter.hpp"
55#include "utils/Revision.hpp"
56#include "utils/simError.h"
57
58using namespace std;
59
60namespace OpenMD {
61
62 StatWriter::StatWriter(const std::string& filename, Stats* stats) :
63 stats_(stats) {
64#ifdef IS_MPI
65 if (worldRank == 0) {
66#endif
67
68 statfile_.open(filename.c_str(), std::ios::out | std::ios::trunc);
69
70 if (!statfile_) {
71 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
72 "Could not open \"%s\" for stat output.\n", filename.c_str());
73 painCave.isFatal = 1;
74 simError();
75 }
76
77 // Create the string for embedding the version information in the MetaData
78 version.assign("## Last run using OpenMD version: ");
79 version.append(OPENMD_VERSION_MAJOR);
80 version.append(".");
81 version.append(OPENMD_VERSION_MINOR);
82 version.append(",");
83
84 std::string rev(revision, strnlen(revision, 40));
85 rev.append(40 - rev.length(), ' ');
86 version.append(" revision: ");
87 // If there's no GIT revision, just call this the RELEASE revision.
88 if (!rev.empty()) {
89 version.append(rev);
90 } else {
91 version.append("RELEASE");
92 }
93
94 writeTitle();
95
96#ifdef IS_MPI
97 }
98
99 snprintf(checkPointMsg, MAX_SIM_ERROR_MSG_LENGTH,
100 "Sucessfully opened output file for stating.\n");
101 errorCheckPoint();
102#endif
103 }
104
105 StatWriter::~StatWriter() {
106#ifdef IS_MPI
107 if (worldRank == 0) {
108#endif
109
110 statfile_.close();
111
112#ifdef IS_MPI
113 }
114#endif
115 }
116
117 void StatWriter::writeTitle() {
118 Stats::StatsBitSet mask = stats_->getStatsMask();
119
120#ifdef IS_MPI
121 if (worldRank == 0) {
122#endif
123
124 // write revision
125 statfile_ << version << std::endl;
126 // write title
127 statfile_ << "#";
128 for (unsigned int i = 0; i < mask.size(); ++i) {
129 if (mask[i]) {
130 statfile_ << "\t" << stats_->getTitle(i) << "(" << stats_->getUnits(i)
131 << ")";
132 }
133 }
134 statfile_ << std::endl;
135
136#ifdef IS_MPI
137 }
138#endif
139 }
140
141 void StatWriter::writeStat() {
142#ifdef IS_MPI
143 if (worldRank == 0) {
144#endif
145
146 Stats::StatsBitSet mask = stats_->getStatsMask();
147 statfile_.precision(stats_->getPrecision());
148
149 for (unsigned int i = 0; i < mask.size(); ++i) {
150 if (mask[i]) {
151 if (stats_->getDataType(i) == "RealType")
152 writeReal(i);
153 else if (stats_->getDataType(i) == "Vector3d")
154 writeVector(i);
155 else if (stats_->getDataType(i) == "potVec")
156 writePotVec(i);
157 else if (stats_->getDataType(i) == "Mat3x3d")
158 writeMatrix(i);
159 else if (stats_->getDataType(i) == "Array2d")
160 writeArray(i);
161 else {
162 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
163 "StatWriter found an unknown data type for: %s ",
164 stats_->getTitle(i).c_str());
165 painCave.isFatal = 1;
166 simError();
167 }
168 }
169 }
170
171 statfile_ << std::endl;
172 statfile_.rdbuf()->pubsync();
173
174#ifdef IS_MPI
175 }
176 errorCheckPoint();
177#endif
178 }
179
180 void StatWriter::writeReal(int i) {
181 RealType s = stats_->getRealData(i);
182
183 if (!std::isinf(s) && !std::isnan(s)) {
184 statfile_ << "\t" << s;
185 } else {
186 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
187 "StatWriter detected a numerical error writing: %s ",
188 stats_->getTitle(i).c_str());
189 painCave.isFatal = 1;
190 simError();
191 }
192 }
193
194 void StatWriter::writeVector(int i) {
195 Vector3d s = stats_->getVectorData(i);
196 if (std::isinf(s[0]) || std::isnan(s[0]) || std::isinf(s[1]) ||
197 std::isnan(s[1]) || std::isinf(s[2]) || std::isnan(s[2])) {
198 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
199 "StatWriter detected a numerical error writing: %s",
200 stats_->getTitle(i).c_str());
201 painCave.isFatal = 1;
202 simError();
203 } else {
204 statfile_ << "\t" << s[0] << "\t" << s[1] << "\t" << s[2];
205 }
206 }
207
208 void StatWriter::writePotVec(int i) {
209 potVec s = stats_->getPotVecData(i);
210
211 bool foundError = false;
212
213 for (unsigned int j = 0; j < N_INTERACTION_FAMILIES; j++) {
214 if (std::isinf(s[j]) || std::isnan(s[j])) foundError = true;
215 }
216 if (foundError) {
217 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
218 "StatWriter detected a numerical error writing: %s",
219 stats_->getTitle(i).c_str());
220 painCave.isFatal = 1;
221 simError();
222 } else {
223 for (unsigned int j = 0; j < N_INTERACTION_FAMILIES; j++) {
224 statfile_ << "\t" << s[j];
225 }
226 }
227 }
228
229 void StatWriter::writeMatrix(int i) {
230 Mat3x3d s = stats_->getMatrixData(i);
231
232 for (unsigned int i1 = 0; i1 < 3; i1++) {
233 for (unsigned int j1 = 0; j1 < 3; j1++) {
234 if (std::isinf(s(i1, j1)) || std::isnan(s(i1, j1))) {
235 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
236 "StatWriter detected a numerical error writing: %s",
237 stats_->getTitle(i).c_str());
238 painCave.isFatal = 1;
239 simError();
240 } else {
241 statfile_ << "\t" << s(i1, j1);
242 }
243 }
244 }
245 }
246
247 void StatWriter::writeArray(int i) {
248 std::vector<RealType> s = stats_->getArrayData(i);
249
250 for (unsigned int j = 0; j < s.size(); ++j) {
251 if (std::isinf(s[j]) || std::isnan(s[j])) {
252 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
253 "StatWriter detected a numerical error writing: %s",
254 stats_->getTitle(i).c_str());
255 painCave.isFatal = 1;
256 simError();
257 } else {
258 statfile_ << "\t" << s[j];
259 }
260 }
261 }
262
263 void StatWriter::writeStatReport() {
264#ifdef IS_MPI
265 if (worldRank == 0) {
266#endif
267 reportfile_.open(reportFileName_.c_str(),
268 std::ios::out | std::ios::trunc);
269
270 if (!reportfile_) {
271 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
272 "Could not open \"%s\" for report output.\n",
273 reportFileName_.c_str());
274 painCave.isFatal = 1;
275 simError();
276 }
277
278 reportfile_ << stats_->getStatsReport();
279 std::cout << stats_->getStatsReport();
280 reportfile_.close();
281
282#ifdef IS_MPI
283 }
284#endif
285 }
286} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.