OpenMD 3.1
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
MultipassCorrFunc.cpp
1/*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * This software is provided "AS IS," without a warranty of any
18 * kind. All express or implied conditions, representations and
19 * warranties, including any implied warranty of merchantability,
20 * fitness for a particular purpose or non-infringement, are hereby
21 * excluded. The University of Notre Dame and its licensors shall not
22 * be liable for any damages suffered by licensee as a result of
23 * using, modifying or distributing the software or its
24 * derivatives. In no event will the University of Notre Dame or its
25 * licensors be liable for any lost revenue, profit or data, or for
26 * direct, indirect, special, consequential, incidental or punitive
27 * damages, however caused and regardless of the theory of liability,
28 * arising out of the use of or inability to use software, even if the
29 * University of Notre Dame has been advised of the possibility of
30 * such damages.
31 *
32 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33 * research, please cite the appropriate papers when you publish your
34 * work. Good starting points are:
35 *
36 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 */
42
43#include "applications/dynamicProps/MultipassCorrFunc.hpp"
44#include "utils/simError.h"
45#include "utils/Revision.hpp"
48
49using namespace std;
50namespace OpenMD {
51
52 template<typename T>
53 MultipassCorrFunc<T>::MultipassCorrFunc(SimInfo* info,
54 const string& filename,
55 const string& sele1,
56 const string& sele2,
57 int storageLayout)
58 : storageLayout_(storageLayout), info_(info), dumpFilename_(filename),
59 seleMan1_(info_), seleMan2_(info_),
60 selectionScript1_(sele1), selectionScript2_(sele2),
61 evaluator1_(info_), evaluator2_(info_), autoCorrFunc_(false) {
62
63 // Request maximum needed storage for the simulation (including of
64 // whatever was passed down by the individual correlation
65 // function).
66
67 storageLayout_ = info->getStorageLayout() | storageLayout;
68
69 reader_ = new DumpReader(info_, dumpFilename_);
70
71 uniqueSelections_ = (sele1.compare(sele2) != 0) ? true : false;
72
73 evaluator1_.loadScriptString(selectionScript1_);
74 //if selection is static, we only need to evaluate it once
75 if (!evaluator1_.isDynamic()) {
76 seleMan1_.setSelectionSet(evaluator1_.evaluate());
77 validateSelection(seleMan1_);
78 }
79
80 if (uniqueSelections_) {
81 evaluator2_.loadScriptString(selectionScript2_);
82 if (!evaluator2_.isDynamic()) {
83 seleMan2_.setSelectionSet(evaluator2_.evaluate());
84 validateSelection(seleMan2_);
85 }
86 }
87
88 Globals* simParams = info_->getSimParams();
89 if (simParams->haveSampleTime()){
90 deltaTime_ = simParams->getSampleTime();
91 } else {
92 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
93 "MultipassCorrFunc Error: can not figure out deltaTime\n");
94 painCave.isFatal = 1;
95 simError();
96 }
97
98 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Scanning for frames.");
99 painCave.isFatal = 0;
100 painCave.severity=OPENMD_INFO;
101 simError();
102
103 nFrames_ = reader_->getNFrames();
104 nTimeBins_ = nFrames_;
105
106 T zeroType(0.0);
107 histogram_.resize(nTimeBins_, zeroType);
108 count_.resize(nTimeBins_, 0);
109
110 times_.resize(nFrames_);
111 sele1ToIndex_.resize(nFrames_);
112 if (uniqueSelections_) {
113 sele2ToIndex_.resize(nFrames_);
114 }
115
116 progressBar_ = new ProgressBar();
117 }
118
119 template<typename T> // we should check to see if this is needed for a member function that does not deal with the type
120 void MultipassCorrFunc<T>::preCorrelate() {
121
122 progressBar_->clear();
123
124 for (int istep = 0; istep < nFrames_; istep++) {
125 reader_->readFrame(istep);
126 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
127 times_[istep] = currentSnapshot_->getTime();
128
129 progressBar_->setStatus(istep+1, nFrames_);
130 progressBar_->update();
131
132 computeFrame(istep);
133 }
134
135 }
136
137 template<typename T>
138 void MultipassCorrFunc<T>::computeFrame(int istep) {
139 StuntDouble* sd;
140
141 int isd1, isd2;
142 unsigned int index;
143
144 if (evaluator1_.isDynamic()) {
145 seleMan1_.setSelectionSet(evaluator1_.evaluate());
146 validateSelection(seleMan1_);
147 }
148
149 if (uniqueSelections_ && evaluator2_.isDynamic()) {
150 seleMan2_.setSelectionSet(evaluator2_.evaluate());
151 validateSelection(seleMan2_);
152 }
153
154 for (sd = seleMan1_.beginSelected(isd1); sd != NULL;
155 sd = seleMan1_.nextSelected(isd1)) {
156
157 index = computeProperty1(istep, sd);
158
159 if (index == sele1ToIndex_[istep].size()) {
160 sele1ToIndex_[istep].push_back(sd->getGlobalIndex());
161 } else {
162 sele1ToIndex_[istep].resize(index+1);
163 sele1ToIndex_[istep][index] = sd->getGlobalIndex();
164 }
165
166 if (!uniqueSelections_) {
167 index = computeProperty2(istep, sd);
168 }
169 }
170
171 if (uniqueSelections_) {
172 for (sd = seleMan2_.beginSelected(isd2); sd != NULL;
173 sd = seleMan2_.nextSelected(isd2)) {
174
175 if (autoCorrFunc_) {
176 index = computeProperty1(istep, sd);
177 } else {
178 index = computeProperty2(istep, sd);
179 }
180 if (index == sele2ToIndex_[istep].size()) {
181 sele2ToIndex_[istep].push_back(sd->getGlobalIndex());
182 } else {
183 sele2ToIndex_[istep].resize(index+1);
184 sele2ToIndex_[istep][index] = sd->getGlobalIndex();
185 }
186 }
187 }
188 }
189
190 template<typename T>
191 void MultipassCorrFunc<T>::doCorrelate() {
192
193 painCave.isFatal = 0;
194 painCave.severity=OPENMD_INFO;
195 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Starting pre-correlate scan.");
196 simError();
197 preCorrelate();
198
199 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Calculating correlation function.");
200 simError();
201 correlation();
202
203 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Doing post-correlation calculations.");
204 simError();
205 postCorrelate();
206
207 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Writing output.");
208 simError();
209 writeCorrelate();
210 }
211
212 template<typename T>
213 void MultipassCorrFunc<T>::correlation() {
214 T zeroType(0.0);
215 for (unsigned int i =0 ; i < nTimeBins_; ++i) {
216 histogram_[i] = zeroType;
217 count_[i] = 0;
218 }
219
220 progressBar_->clear();
221 RealType samples = 0.5 * (nFrames_ + 1) * nFrames_;
222 int visited = 0;
223
224 for (int i = 0; i < nFrames_; ++i) {
225
226 RealType time1 = times_[i];
227
228 for(int j = i; j < nFrames_; ++j) {
229 visited++;
230 progressBar_->setStatus(visited, samples);
231 progressBar_->update();
232
233 // Perform a sanity check on the actual configuration times to
234 // make sure the configurations are spaced the same amount the
235 // sample time said they were spaced:
236
237 RealType time2 = times_[j];
238
239 if ( fabs( (time2 - time1) - (j-i)*deltaTime_ ) > 1.0e-4 ) {
240 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
241 "MultipassCorrFunc::correlateBlocks Error: sampleTime (%f)\n"
242 "\tin %s does not match actual time-spacing between\n"
243 "\tconfigurations %d (t = %f) and %d (t = %f).\n",
244 deltaTime_, dumpFilename_.c_str(), i, time1, j, time2);
245 painCave.isFatal = 1;
246 simError();
247 }
248
249 int timeBin = int ((time2 - time1) / deltaTime_ + 0.5);
250 correlateFrames(i,j, timeBin);
251 }
252 }
253 }
254
255
256 template<typename T>
257 void MultipassCorrFunc<T>::correlateFrames(int frame1, int frame2,
258 int timeBin) {
259 std::vector<int> s1;
260 std::vector<int> s2;
261
262 std::vector<int>::iterator i1;
263 std::vector<int>::iterator i2;
264
265 T corrVal(0.0);
266
267 s1 = sele1ToIndex_[frame1];
268
269 if (uniqueSelections_)
270 s2 = sele2ToIndex_[frame2];
271 else
272 s2 = sele1ToIndex_[frame2];
273
274 for (i1 = s1.begin(), i2 = s2.begin();
275 i1 != s1.end() && i2 != s2.end(); ++i1, ++i2){
276
277 // If the selections are dynamic, they might not have the
278 // same objects in both frames, so we need to roll either of
279 // the selections until we have the same object to
280 // correlate.
281
282 while ( i1 != s1.end() && *i1 < *i2 ) {
283 ++i1;
284 }
285
286 while ( i2 != s2.end() && *i2 < *i1 ) {
287 ++i2;
288 }
289
290 if ( i1 == s1.end() || i2 == s2.end() ) break;
291
292 corrVal = calcCorrVal(frame1, frame2, i1 - s1.begin(), i2 - s2.begin());
293 histogram_[timeBin] += corrVal;
294 count_[timeBin]++;
295
296 }
297 }
298
299 template<typename T>
300 void MultipassCorrFunc<T>::postCorrelate() {
301 T zeroType(0.0);
302 for (unsigned int i =0 ; i < nTimeBins_; ++i) {
303 if (count_[i] > 0) {
304 histogram_[i] /= count_[i];
305 } else {
306 histogram_[i] = zeroType;
307 }
308 }
309 }
310
311 template<typename T>
312 void MultipassCorrFunc<T>::writeCorrelate() {
313 ofstream ofs(outputFilename_.c_str());
314
315 if (ofs.is_open()) {
316
317 Revision r;
318
319 ofs << "# " << getCorrFuncType() << "\n";
320 ofs << "# OpenMD " << r.getFullRevision() << "\n";
321 ofs << "# " << r.getBuildDate() << "\n";
322 ofs << "# selection script1: \"" << selectionScript1_ ;
323 ofs << "\"\tselection script2: \"" << selectionScript2_ << "\"\n";
324 if (!paramString_.empty())
325 ofs << "# parameters: " << paramString_ << "\n";
326 if (!labelString_.empty())
327 ofs << "#time\t" << labelString_ << "\n";
328 else
329 ofs << "#time\tcorrVal\n";
330
331 for (unsigned int i = 0; i < nTimeBins_; ++i) {
332 ofs << times_[i]-times_[0] << "\t" << histogram_[i] << "\n";
333 }
334
335 } else {
336 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
337 "MultipassCorrFunc::writeCorrelate Error: fail to open %s\n",
338 outputFilename_.c_str());
339 painCave.isFatal = 1;
340 simError();
341 }
342
343 ofs.close();
344 }
345
346 //Template specialization of writeCorrelate for Vector3d
347 template<>
348 void MultipassCorrFunc<Vector3d>::writeCorrelate() {
349 ofstream ofs(outputFilename_.c_str());
350
351 if (ofs.is_open()) {
352
353 Revision r;
354
355 ofs << "# " << getCorrFuncType() << "\n";
356 ofs << "# OpenMD " << r.getFullRevision() << "\n";
357 ofs << "# " << r.getBuildDate() << "\n";
358 ofs << "# selection script1: \"" << selectionScript1_ ;
359 ofs << "\"\tselection script2: \"" << selectionScript2_ << "\"\n";
360 if (!paramString_.empty())
361 ofs << "# parameters: " << paramString_ << "\n";
362 if (!labelString_.empty())
363 ofs << "#time\t" << labelString_ << "\n";
364 else
365 ofs << "#time\tcorrVal\n";
366
367 for (unsigned int i = 0; i < nTimeBins_; ++i) {
368 ofs << times_[i]-times_[0] << "\t";
369 for (int j = 0; j < 3; j++) {
370 ofs << histogram_[i](j) << '\t';
371 }
372 ofs << '\n';
373 }
374
375 } else {
376 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
377 "MultipassCorrFunc::writeCorrelate Error: fail to open %s\n",
378 outputFilename_.c_str());
379 painCave.isFatal = 1;
380 simError();
381 }
382
383 ofs.close();
384 }
385
386
387 //Template specialization of writeCorrelate for Mat3x3d
388 template<>
389 void MultipassCorrFunc<Mat3x3d>::writeCorrelate() {
390 ofstream ofs(outputFilename_.c_str());
391
392 if (ofs.is_open()) {
393
394 Revision r;
395
396 ofs << "# " << getCorrFuncType() << "\n";
397 ofs << "# OpenMD " << r.getFullRevision() << "\n";
398 ofs << "# " << r.getBuildDate() << "\n";
399 ofs << "# selection script1: \"" << selectionScript1_ ;
400 ofs << "\"\tselection script2: \"" << selectionScript2_ << "\"\n";
401 if (!paramString_.empty())
402 ofs << "# parameters: " << paramString_ << "\n";
403 if (!labelString_.empty())
404 ofs << "#time\t" << labelString_ << "\n";
405 else
406 ofs << "#time\tcorrVal\n";
407
408 for (unsigned int i = 0; i < nTimeBins_; ++i) {
409 ofs << times_[i]-times_[0] << "\t";
410 for (int j = 0; j < 3; j++) {
411 for (int k = 0; k < 3; k++) {
412 ofs << histogram_[i](j,k) << '\t';
413 }
414 }
415 ofs << '\n';
416 }
417
418 } else {
419 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
420 "MultipassCorrFunc::writeCorrelate Error: fail to open %s\n",
421 outputFilename_.c_str());
422 painCave.isFatal = 1;
423 simError();
424 }
425
426 ofs.close();
427 }
428
429
430 template<typename T>
431 void MultipassCorrFunc<T>::validateSelection(SelectionManager& seleMan) {
432 // punt on validating selection to the individual correlation functions
433 }
434
435 //it is necessary to keep the constructor definitions here or the code wont be generated and linking issues will occur. Blame templating
436 template<typename T>
437 CrossCorrFunc<T>::CrossCorrFunc(SimInfo* info, const std::string& filename,
438 const std::string& sele1,
439 const std::string& sele2,
440 int storageLayout) :
441 MultipassCorrFunc<T>(info, filename, sele1, sele2, storageLayout) {
442 this->autoCorrFunc_ = false;
443 }
444
445 template<typename T>
446 AutoCorrFunc<T>::AutoCorrFunc(SimInfo* info, const std::string& filename,
447 const std::string& sele1,
448 const std::string& sele2,
449 int storageLayout) :
450 MultipassCorrFunc<T>(info, filename, sele1, sele2, storageLayout) {
451 this->autoCorrFunc_ = true;
452 }
453
454 template class AutoCorrFunc<RealType>;
455 template class MultipassCorrFunc<RealType>;
456 template class CrossCorrFunc<RealType>;
457
458 template class AutoCorrFunc<Vector3d>;
459 template class MultipassCorrFunc<Vector3d>;
460 template class CrossCorrFunc<Vector3d>;
461
462 template class AutoCorrFunc<Mat3x3d>;
463 template class MultipassCorrFunc<Mat3x3d>;
464 template class CrossCorrFunc<Mat3x3d>;
465
466 template class MultipassCorrFunc<DynamicVector<RealType> >;
467
468}
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.