ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/io/DumpReader.cpp
Revision: 1714
Committed: Sat May 19 18:12:46 2012 UTC (12 years, 11 months ago) by gezelter
File size: 18347 byte(s)
Log Message:
Added ability to read / write dump files with fluctuating charges and
electric fields.

File Contents

# Content
1 /*
2 * Copyright (c) 2009 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, 24107 (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 #define _LARGEFILE_SOURCE64
44 #define _FILE_OFFSET_BITS 64
45
46 #include <sys/types.h>
47 #include <sys/stat.h>
48
49 #include <iostream>
50 #include <math.h>
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include "io/DumpReader.hpp"
57 #include "primitives/Molecule.hpp"
58 #include "utils/simError.h"
59 #include "utils/MemoryUtils.hpp"
60 #include "utils/StringTokenizer.hpp"
61
62 #ifdef IS_MPI
63
64 #include <mpi.h>
65 #define TAKE_THIS_TAG_CHAR 0
66 #define TAKE_THIS_TAG_INT 1
67
68 #endif // is_mpi
69
70
71 namespace OpenMD {
72
73 DumpReader::DumpReader(SimInfo* info, const std::string& filename)
74 : info_(info), filename_(filename), isScanned_(false), nframes_(0), needCOMprops_(false) {
75
76 #ifdef IS_MPI
77
78 if (worldRank == 0) {
79 #endif
80
81 inFile_ = new std::ifstream(filename_.c_str());
82
83 if (inFile_->fail()) {
84 sprintf(painCave.errMsg,
85 "DumpReader: Cannot open file: %s\n",
86 filename_.c_str());
87 painCave.isFatal = 1;
88 simError();
89 }
90
91 #ifdef IS_MPI
92
93 }
94
95 strcpy(checkPointMsg, "Dump file opened for reading successfully.");
96 errorCheckPoint();
97
98 #endif
99
100 return;
101 }
102
103 DumpReader::~DumpReader() {
104
105 #ifdef IS_MPI
106
107 if (worldRank == 0) {
108 #endif
109
110 delete inFile_;
111
112 #ifdef IS_MPI
113
114 }
115
116 strcpy(checkPointMsg, "Dump file closed successfully.");
117 errorCheckPoint();
118
119 #endif
120
121 return;
122 }
123
124 int DumpReader::getNFrames(void) {
125
126 if (!isScanned_)
127 scanFile();
128
129 return nframes_;
130 }
131
132 void DumpReader::scanFile(void) {
133 int lineNo = 0;
134 std::streampos prevPos;
135 std::streampos currPos;
136
137 #ifdef IS_MPI
138
139 if (worldRank == 0) {
140 #endif // is_mpi
141
142 currPos = inFile_->tellg();
143 prevPos = currPos;
144 bool foundOpenSnapshotTag = false;
145 bool foundClosedSnapshotTag = false;
146 while(inFile_->getline(buffer, bufferSize)) {
147 ++lineNo;
148
149 std::string line = buffer;
150 currPos = inFile_->tellg();
151 if (line.find("<Snapshot>")!= std::string::npos) {
152 if (foundOpenSnapshotTag) {
153 sprintf(painCave.errMsg,
154 "DumpReader:<Snapshot> is multiply nested at line %d in %s \n", lineNo,
155 filename_.c_str());
156 painCave.isFatal = 1;
157 simError();
158 }
159 foundOpenSnapshotTag = true;
160 foundClosedSnapshotTag = false;
161 framePos_.push_back(prevPos);
162
163 } else if (line.find("</Snapshot>") != std::string::npos){
164 if (!foundOpenSnapshotTag) {
165 sprintf(painCave.errMsg,
166 "DumpReader:</Snapshot> appears before <Snapshot> at line %d in %s \n", lineNo,
167 filename_.c_str());
168 painCave.isFatal = 1;
169 simError();
170 }
171
172 if (foundClosedSnapshotTag) {
173 sprintf(painCave.errMsg,
174 "DumpReader:</Snapshot> appears multiply nested at line %d in %s \n", lineNo,
175 filename_.c_str());
176 painCave.isFatal = 1;
177 simError();
178 }
179 foundClosedSnapshotTag = true;
180 foundOpenSnapshotTag = false;
181 }
182 prevPos = currPos;
183 }
184
185 // only found <Snapshot> for the last frame means the file is corrupted, we should discard
186 // it and give a warning message
187 if (foundOpenSnapshotTag) {
188 sprintf(painCave.errMsg,
189 "DumpReader: last frame in %s is invalid\n", filename_.c_str());
190 painCave.isFatal = 0;
191 simError();
192 framePos_.pop_back();
193 }
194
195 nframes_ = framePos_.size();
196
197 if (nframes_ == 0) {
198 sprintf(painCave.errMsg,
199 "DumpReader: %s does not contain a valid frame\n", filename_.c_str());
200 painCave.isFatal = 1;
201 simError();
202 }
203 #ifdef IS_MPI
204 }
205
206 MPI_Bcast(&nframes_, 1, MPI_INT, 0, MPI_COMM_WORLD);
207
208 #endif // is_mpi
209
210 isScanned_ = true;
211 }
212
213 void DumpReader::readFrame(int whichFrame) {
214 if (!isScanned_)
215 scanFile();
216
217 int storageLayout = info_->getSnapshotManager()->getStorageLayout();
218
219 if (storageLayout & DataStorage::dslPosition) {
220 needPos_ = true;
221 } else {
222 needPos_ = false;
223 }
224
225 if (storageLayout & DataStorage::dslVelocity) {
226 needVel_ = true;
227 } else {
228 needVel_ = false;
229 }
230
231 if (storageLayout & DataStorage::dslAmat || storageLayout & DataStorage::dslElectroFrame) {
232 needQuaternion_ = true;
233 } else {
234 needQuaternion_ = false;
235 }
236
237 if (storageLayout & DataStorage::dslAngularMomentum) {
238 needAngMom_ = true;
239 } else {
240 needAngMom_ = false;
241 }
242
243 readSet(whichFrame);
244
245 if (needCOMprops_) {
246 Snapshot* s = info_->getSnapshotManager()->getCurrentSnapshot();
247 Vector3d com;
248 Vector3d comvel;
249 Vector3d comw;
250 if (needPos_ && needVel_){
251 info_->getComAll(com, comvel);
252 comw = info_->getAngularMomentum();
253 }else{
254 com = info_->getCom();
255 comvel = 0.0;
256 comw = 0.0;
257 }
258 s->setCOMprops(com, comvel, comw);
259 }
260
261 }
262
263 void DumpReader::readSet(int whichFrame) {
264 std::string line;
265
266 #ifndef IS_MPI
267 inFile_->clear();
268 inFile_->seekg(framePos_[whichFrame]);
269
270 std::istream& inputStream = *inFile_;
271
272 #else
273 int masterNode = 0;
274 std::stringstream sstream;
275 if (worldRank == masterNode) {
276 std::string sendBuffer;
277
278 inFile_->clear();
279 inFile_->seekg(framePos_[whichFrame]);
280
281 while (inFile_->getline(buffer, bufferSize)) {
282
283 line = buffer;
284 sendBuffer += line;
285 sendBuffer += '\n';
286 if (line.find("</Snapshot>") != std::string::npos) {
287 break;
288 }
289 }
290
291 int sendBufferSize = sendBuffer.size();
292 MPI_Bcast(&sendBufferSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
293 MPI_Bcast((void *)sendBuffer.c_str(), sendBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
294
295 sstream.str(sendBuffer);
296 } else {
297 int sendBufferSize;
298 MPI_Bcast(&sendBufferSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
299 char * recvBuffer = new char[sendBufferSize+1];
300 assert(recvBuffer);
301 recvBuffer[sendBufferSize] = '\0';
302 MPI_Bcast(recvBuffer, sendBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
303 sstream.str(recvBuffer);
304 delete [] recvBuffer;
305 }
306
307 std::istream& inputStream = sstream;
308 #endif
309
310 inputStream.getline(buffer, bufferSize);
311
312 line = buffer;
313 if (line.find("<Snapshot>") == std::string::npos) {
314 sprintf(painCave.errMsg,
315 "DumpReader Error: can not find <Snapshot>\n");
316 painCave.isFatal = 1;
317 simError();
318 }
319
320 //read frameData
321 readFrameProperties(inputStream);
322
323 //read StuntDoubles
324 readStuntDoubles(inputStream);
325
326 inputStream.getline(buffer, bufferSize);
327 line = buffer;
328 if (line.find("</Snapshot>") == std::string::npos) {
329 sprintf(painCave.errMsg,
330 "DumpReader Error: can not find </Snapshot>\n");
331 painCave.isFatal = 1;
332 simError();
333 }
334
335 }
336
337 void DumpReader::parseDumpLine(const std::string& line) {
338
339
340 StringTokenizer tokenizer(line);
341 int nTokens;
342
343 nTokens = tokenizer.countTokens();
344
345 if (nTokens < 2) {
346 sprintf(painCave.errMsg,
347 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
348 painCave.isFatal = 1;
349 simError();
350 }
351
352 int index = tokenizer.nextTokenAsInt();
353
354 StuntDouble* integrableObject = info_->getIOIndexToIntegrableObject(index);
355
356 if (integrableObject == NULL) {
357 return;
358 }
359 std::string type = tokenizer.nextToken();
360 int size = type.size();
361
362 size_t found;
363
364 if (needPos_) {
365 found = type.find("p");
366 if (found == std::string::npos) {
367 sprintf(painCave.errMsg,
368 "DumpReader Error: StuntDouble %d has no Position\n"
369 "\tField (\"p\") specified.\n%s\n", index,
370 line.c_str());
371 painCave.isFatal = 1;
372 simError();
373 }
374 }
375
376 if (integrableObject->isDirectional()) {
377 if (needQuaternion_) {
378 found = type.find("q");
379 if (found == std::string::npos) {
380 sprintf(painCave.errMsg,
381 "DumpReader Error: Directional StuntDouble %d has no\n"
382 "\tQuaternion Field (\"q\") specified.\n%s\n", index,
383 line.c_str());
384 painCave.isFatal = 1;
385 simError();
386 }
387 }
388 }
389
390 for(int i = 0; i < size; ++i) {
391 switch(type[i]) {
392
393 case 'p': {
394 Vector3d pos;
395 pos[0] = tokenizer.nextTokenAsDouble();
396 pos[1] = tokenizer.nextTokenAsDouble();
397 pos[2] = tokenizer.nextTokenAsDouble();
398 if (needPos_) {
399 integrableObject->setPos(pos);
400 }
401 break;
402 }
403 case 'v' : {
404 Vector3d vel;
405 vel[0] = tokenizer.nextTokenAsDouble();
406 vel[1] = tokenizer.nextTokenAsDouble();
407 vel[2] = tokenizer.nextTokenAsDouble();
408 if (needVel_) {
409 integrableObject->setVel(vel);
410 }
411 break;
412 }
413
414 case 'q' : {
415 Quat4d q;
416 if (integrableObject->isDirectional()) {
417
418 q[0] = tokenizer.nextTokenAsDouble();
419 q[1] = tokenizer.nextTokenAsDouble();
420 q[2] = tokenizer.nextTokenAsDouble();
421 q[3] = tokenizer.nextTokenAsDouble();
422
423 RealType qlen = q.length();
424 if (qlen < OpenMD::epsilon) { //check quaternion is not equal to 0
425
426 sprintf(painCave.errMsg,
427 "DumpReader Error: initial quaternion error (q0^2 + q1^2 + q2^2 + q3^2) ~ 0\n");
428 painCave.isFatal = 1;
429 simError();
430
431 }
432
433 q.normalize();
434 if (needQuaternion_) {
435 integrableObject->setQ(q);
436 }
437 }
438 break;
439 }
440 case 'j' : {
441 Vector3d ji;
442 if (integrableObject->isDirectional()) {
443 ji[0] = tokenizer.nextTokenAsDouble();
444 ji[1] = tokenizer.nextTokenAsDouble();
445 ji[2] = tokenizer.nextTokenAsDouble();
446 if (needAngMom_) {
447 integrableObject->setJ(ji);
448 }
449 }
450 break;
451 }
452 case 'f': {
453
454 Vector3d force;
455 force[0] = tokenizer.nextTokenAsDouble();
456 force[1] = tokenizer.nextTokenAsDouble();
457 force[2] = tokenizer.nextTokenAsDouble();
458 integrableObject->setFrc(force);
459 break;
460 }
461 case 't' : {
462
463 Vector3d torque;
464 torque[0] = tokenizer.nextTokenAsDouble();
465 torque[1] = tokenizer.nextTokenAsDouble();
466 torque[2] = tokenizer.nextTokenAsDouble();
467 integrableObject->setTrq(torque);
468 break;
469 }
470 case 'u' : {
471
472 RealType particlePot;
473 particlePot = tokenizer.nextTokenAsDouble();
474 integrableObject->setParticlePot(particlePot);
475 break;
476 }
477 case 'c' : {
478
479 RealType flucQPos;
480 flucQPos = tokenizer.nextTokenAsDouble();
481 integrableObject->setFlucQPos(flucQPos);
482 break;
483 }
484 case 'w' : {
485
486 RealType flucQVel;
487 flucQVel = tokenizer.nextTokenAsDouble();
488 integrableObject->setFlucQVel(flucQVel);
489 break;
490 }
491 case 'g' : {
492
493 RealType flucQFrc;
494 flucQFrc = tokenizer.nextTokenAsDouble();
495 integrableObject->setFlucQFrc(flucQFrc);
496 break;
497 }
498 case 'e' : {
499
500 Vector3d eField;
501 eField[0] = tokenizer.nextTokenAsDouble();
502 eField[1] = tokenizer.nextTokenAsDouble();
503 eField[2] = tokenizer.nextTokenAsDouble();
504 integrableObject->setElectricField(eField);
505 break;
506 }
507 default: {
508 sprintf(painCave.errMsg,
509 "DumpReader Error: %s is an unrecognized type\n", type.c_str());
510 painCave.isFatal = 1;
511 simError();
512 break;
513 }
514
515 }
516 }
517
518 }
519
520
521 void DumpReader::readStuntDoubles(std::istream& inputStream) {
522
523 inputStream.getline(buffer, bufferSize);
524 std::string line(buffer);
525
526 if (line.find("<StuntDoubles>") == std::string::npos) {
527 sprintf(painCave.errMsg,
528 "DumpReader Error: Missing <StuntDoubles>\n");
529 painCave.isFatal = 1;
530 simError();
531 }
532
533 while(inputStream.getline(buffer, bufferSize)) {
534 line = buffer;
535
536 if(line.find("</StuntDoubles>") != std::string::npos) {
537 break;
538 }
539
540 parseDumpLine(line);
541 }
542
543 }
544
545 void DumpReader::readFrameProperties(std::istream& inputStream) {
546
547 Snapshot* s = info_->getSnapshotManager()->getCurrentSnapshot();
548 inputStream.getline(buffer, bufferSize);
549 std::string line(buffer);
550
551 if (line.find("<FrameData>") == std::string::npos) {
552 sprintf(painCave.errMsg,
553 "DumpReader Error: Missing <FrameData>\n");
554 painCave.isFatal = 1;
555 simError();
556 }
557
558 while(inputStream.getline(buffer, bufferSize)) {
559 line = buffer;
560
561 if(line.find("</FrameData>") != std::string::npos) {
562 break;
563 }
564
565 StringTokenizer tokenizer(line, " ;\t\n\r{}:,");
566 if (!tokenizer.hasMoreTokens()) {
567 sprintf(painCave.errMsg,
568 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
569 painCave.isFatal = 1;
570 simError();
571 }
572
573 std::string propertyName = tokenizer.nextToken();
574 if (propertyName == "Time") {
575 RealType currTime = tokenizer.nextTokenAsDouble();
576 s->setTime(currTime);
577 } else if (propertyName == "Hmat"){
578 Mat3x3d hmat;
579 hmat(0, 0) = tokenizer.nextTokenAsDouble();
580 hmat(0, 1) = tokenizer.nextTokenAsDouble();
581 hmat(0, 2) = tokenizer.nextTokenAsDouble();
582 hmat(1, 0) = tokenizer.nextTokenAsDouble();
583 hmat(1, 1) = tokenizer.nextTokenAsDouble();
584 hmat(1, 2) = tokenizer.nextTokenAsDouble();
585 hmat(2, 0) = tokenizer.nextTokenAsDouble();
586 hmat(2, 1) = tokenizer.nextTokenAsDouble();
587 hmat(2, 2) = tokenizer.nextTokenAsDouble();
588 s->setHmat(hmat);
589 } else if (propertyName == "Thermostat") {
590 RealType chi = tokenizer.nextTokenAsDouble();
591 RealType integralOfChiDt = tokenizer.nextTokenAsDouble();
592 s->setChi(chi);
593 s->setIntegralOfChiDt(integralOfChiDt);
594 } else if (propertyName == "Barostat") {
595 Mat3x3d eta;
596 eta(0, 0) = tokenizer.nextTokenAsDouble();
597 eta(0, 1) = tokenizer.nextTokenAsDouble();
598 eta(0, 2) = tokenizer.nextTokenAsDouble();
599 eta(1, 0) = tokenizer.nextTokenAsDouble();
600 eta(1, 1) = tokenizer.nextTokenAsDouble();
601 eta(1, 2) = tokenizer.nextTokenAsDouble();
602 eta(2, 0) = tokenizer.nextTokenAsDouble();
603 eta(2, 1) = tokenizer.nextTokenAsDouble();
604 eta(2, 2) = tokenizer.nextTokenAsDouble();
605 s->setEta(eta);
606 } else {
607 sprintf(painCave.errMsg,
608 "DumpReader Error: %s is an invalid property in <FrameData>\n", propertyName.c_str());
609 painCave.isFatal = 0;
610 simError();
611 }
612
613 }
614
615 }
616
617
618 }//end namespace OpenMD

Properties

Name Value
svn:keywords Author Id Revision Date