ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/io/DumpReader.cpp
Revision: 2069
Committed: Thu Mar 5 16:30:23 2015 UTC (10 years, 1 month ago) by gezelter
File size: 21693 byte(s)
Log Message:
More g++ warning fixes

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, 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 #define _LARGEFILE_SOURCE64
44 #define _FILE_OFFSET_BITS 64
45
46 #ifdef IS_MPI
47 #include <mpi.h>
48 #endif
49
50 #include <sys/types.h>
51 #include <sys/stat.h>
52
53 #include <iostream>
54 #include <math.h>
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59
60 #include "io/DumpReader.hpp"
61 #include "primitives/Molecule.hpp"
62 #include "utils/simError.h"
63 #include "utils/MemoryUtils.hpp"
64 #include "utils/StringTokenizer.hpp"
65 #include "brains/Thermo.hpp"
66
67
68 namespace OpenMD {
69
70 DumpReader::DumpReader(SimInfo* info, const std::string& filename)
71 : info_(info), filename_(filename), isScanned_(false), nframes_(0), needCOMprops_(false) {
72
73 #ifdef IS_MPI
74
75 if (worldRank == 0) {
76 #endif
77
78 inFile_ = new std::ifstream(filename_.c_str(),
79 ifstream::in | ifstream::binary);
80
81 if (inFile_->fail()) {
82 sprintf(painCave.errMsg,
83 "DumpReader: Cannot open file: %s\n",
84 filename_.c_str());
85 painCave.isFatal = 1;
86 simError();
87 }
88
89 #ifdef IS_MPI
90
91 }
92
93 strcpy(checkPointMsg, "Dump file opened for reading successfully.");
94 errorCheckPoint();
95
96 #endif
97
98 return;
99 }
100
101 DumpReader::~DumpReader() {
102
103 #ifdef IS_MPI
104
105 if (worldRank == 0) {
106 #endif
107
108 delete inFile_;
109
110 #ifdef IS_MPI
111
112 }
113
114 strcpy(checkPointMsg, "Dump file closed successfully.");
115 errorCheckPoint();
116
117 #endif
118
119 return;
120 }
121
122 int DumpReader::getNFrames(void) {
123
124 if (!isScanned_)
125 scanFile();
126
127 return nframes_;
128 }
129
130 void DumpReader::scanFile(void) {
131
132 std::streampos prevPos;
133 std::streampos currPos;
134
135 #ifdef IS_MPI
136
137 if (worldRank == 0) {
138 #endif // is_mpi
139
140 currPos = inFile_->tellg();
141 prevPos = currPos;
142 bool foundOpenSnapshotTag = false;
143 bool foundClosedSnapshotTag = false;
144
145 int lineNo = 0;
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 ||
232 storageLayout & DataStorage::dslDipole ||
233 storageLayout & DataStorage::dslQuadrupole) {
234 needQuaternion_ = true;
235 } else {
236 needQuaternion_ = false;
237 }
238
239 if (storageLayout & DataStorage::dslAngularMomentum) {
240 needAngMom_ = true;
241 } else {
242 needAngMom_ = false;
243 }
244
245 readSet(whichFrame);
246
247 if (needCOMprops_) {
248 Thermo thermo(info_);
249 Vector3d com;
250
251 if (needPos_ && needVel_) {
252 Vector3d comvel;
253 Vector3d comw;
254 thermo.getComAll(com, comvel);
255 comw = thermo.getAngularMomentum();
256 } else {
257 com = thermo.getCom();
258 }
259 }
260 }
261
262 void DumpReader::readSet(int whichFrame) {
263 std::string line;
264
265 #ifndef IS_MPI
266 inFile_->clear();
267 inFile_->seekg(framePos_[whichFrame]);
268
269 std::istream& inputStream = *inFile_;
270
271 #else
272 int masterNode = 0;
273 std::stringstream sstream;
274 if (worldRank == masterNode) {
275 std::string sendBuffer;
276
277 inFile_->clear();
278 inFile_->seekg(framePos_[whichFrame]);
279
280 while (inFile_->getline(buffer, bufferSize)) {
281
282 line = buffer;
283 sendBuffer += line;
284 sendBuffer += '\n';
285 if (line.find("</Snapshot>") != std::string::npos) {
286 break;
287 }
288 }
289
290 int sendBufferSize = sendBuffer.size();
291 MPI_Bcast(&sendBufferSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
292 MPI_Bcast((void *)sendBuffer.c_str(), sendBufferSize,
293 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
329 if (line.find("<SiteData>") != std::string::npos) {
330 //read SiteData
331 readSiteData(inputStream);
332 } else {
333 if (line.find("</Snapshot>") == std::string::npos) {
334 sprintf(painCave.errMsg,
335 "DumpReader Error: can not find </Snapshot>\n");
336 painCave.isFatal = 1;
337 simError();
338 }
339 }
340 }
341
342 void DumpReader::parseDumpLine(const std::string& line) {
343
344
345 StringTokenizer tokenizer(line);
346 int nTokens;
347
348 nTokens = tokenizer.countTokens();
349
350 if (nTokens < 2) {
351 sprintf(painCave.errMsg,
352 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
353 painCave.isFatal = 1;
354 simError();
355 }
356
357 int index = tokenizer.nextTokenAsInt();
358
359 StuntDouble* sd = info_->getIOIndexToIntegrableObject(index);
360
361 if (sd == NULL) {
362 return;
363 }
364 std::string type = tokenizer.nextToken();
365 int size = type.size();
366
367 size_t found;
368
369 if (needPos_) {
370 found = type.find("p");
371 if (found == std::string::npos) {
372 sprintf(painCave.errMsg,
373 "DumpReader Error: StuntDouble %d has no Position\n"
374 "\tField (\"p\") specified.\n%s\n", index,
375 line.c_str());
376 painCave.isFatal = 1;
377 simError();
378 }
379 }
380
381 if (sd->isDirectional()) {
382 if (needQuaternion_) {
383 found = type.find("q");
384 if (found == std::string::npos) {
385 sprintf(painCave.errMsg,
386 "DumpReader Error: Directional StuntDouble %d has no\n"
387 "\tQuaternion Field (\"q\") specified.\n%s\n", index,
388 line.c_str());
389 painCave.isFatal = 1;
390 simError();
391 }
392 }
393 }
394
395 for(int i = 0; i < size; ++i) {
396 switch(type[i]) {
397
398 case 'p': {
399 Vector3d pos;
400 pos[0] = tokenizer.nextTokenAsDouble();
401 pos[1] = tokenizer.nextTokenAsDouble();
402 pos[2] = tokenizer.nextTokenAsDouble();
403 if (needPos_) {
404 sd->setPos(pos);
405 }
406 break;
407 }
408 case 'v' : {
409 Vector3d vel;
410 vel[0] = tokenizer.nextTokenAsDouble();
411 vel[1] = tokenizer.nextTokenAsDouble();
412 vel[2] = tokenizer.nextTokenAsDouble();
413 if (needVel_) {
414 sd->setVel(vel);
415 }
416 break;
417 }
418
419 case 'q' : {
420 Quat4d q;
421 if (sd->isDirectional()) {
422
423 q[0] = tokenizer.nextTokenAsDouble();
424 q[1] = tokenizer.nextTokenAsDouble();
425 q[2] = tokenizer.nextTokenAsDouble();
426 q[3] = tokenizer.nextTokenAsDouble();
427
428 RealType qlen = q.length();
429 if (qlen < OpenMD::epsilon) { //check quaternion is not equal to 0
430
431 sprintf(painCave.errMsg,
432 "DumpReader Error: initial quaternion error (q0^2 + q1^2 + q2^2 + q3^2) ~ 0\n");
433 painCave.isFatal = 1;
434 simError();
435
436 }
437
438 q.normalize();
439 if (needQuaternion_) {
440 sd->setQ(q);
441 }
442 }
443 break;
444 }
445 case 'j' : {
446 Vector3d ji;
447 if (sd->isDirectional()) {
448 ji[0] = tokenizer.nextTokenAsDouble();
449 ji[1] = tokenizer.nextTokenAsDouble();
450 ji[2] = tokenizer.nextTokenAsDouble();
451 if (needAngMom_) {
452 sd->setJ(ji);
453 }
454 }
455 break;
456 }
457 case 'f': {
458
459 Vector3d force;
460 force[0] = tokenizer.nextTokenAsDouble();
461 force[1] = tokenizer.nextTokenAsDouble();
462 force[2] = tokenizer.nextTokenAsDouble();
463 sd->setFrc(force);
464 break;
465 }
466 case 't' : {
467
468 Vector3d torque;
469 torque[0] = tokenizer.nextTokenAsDouble();
470 torque[1] = tokenizer.nextTokenAsDouble();
471 torque[2] = tokenizer.nextTokenAsDouble();
472 sd->setTrq(torque);
473 break;
474 }
475 case 'u' : {
476
477 RealType particlePot;
478 particlePot = tokenizer.nextTokenAsDouble();
479 sd->setParticlePot(particlePot);
480 break;
481 }
482 case 'c' : {
483
484 RealType flucQPos;
485 flucQPos = tokenizer.nextTokenAsDouble();
486 sd->setFlucQPos(flucQPos);
487 break;
488 }
489 case 'w' : {
490
491 RealType flucQVel;
492 flucQVel = tokenizer.nextTokenAsDouble();
493 sd->setFlucQVel(flucQVel);
494 break;
495 }
496 case 'g' : {
497
498 RealType flucQFrc;
499 flucQFrc = tokenizer.nextTokenAsDouble();
500 sd->setFlucQFrc(flucQFrc);
501 break;
502 }
503 case 'e' : {
504
505 Vector3d eField;
506 eField[0] = tokenizer.nextTokenAsDouble();
507 eField[1] = tokenizer.nextTokenAsDouble();
508 eField[2] = tokenizer.nextTokenAsDouble();
509 sd->setElectricField(eField);
510 break;
511 }
512 case 's' : {
513
514 RealType sPot;
515 sPot = tokenizer.nextTokenAsDouble();
516 sd->setSitePotential(sPot);
517 break;
518 }
519 default: {
520 sprintf(painCave.errMsg,
521 "DumpReader Error: %s is an unrecognized type\n", type.c_str());
522 painCave.isFatal = 1;
523 simError();
524 break;
525 }
526
527 }
528 }
529 }
530
531
532 void DumpReader::parseSiteLine(const std::string& line) {
533
534 StringTokenizer tokenizer(line);
535 int nTokens;
536
537 nTokens = tokenizer.countTokens();
538
539 if (nTokens < 2) {
540 sprintf(painCave.errMsg,
541 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
542 painCave.isFatal = 1;
543 simError();
544 }
545
546 /**
547 * The first token is the global integrable object index.
548 */
549
550 int index = tokenizer.nextTokenAsInt();
551 StuntDouble* sd = info_->getIOIndexToIntegrableObject(index);
552 if (sd == NULL) {
553 return;
554 }
555
556 /**
557 * Test to see if the next token is an integer or not. If not,
558 * we've got data on the integrable object itself. If there is an
559 * integer, we're parsing data for a site on a rigid body.
560 */
561
562 std::string indexTest = tokenizer.peekNextToken();
563 std::istringstream i(indexTest);
564 int siteIndex;
565 if (i >> siteIndex) {
566 // chew up this token and parse as an int:
567 siteIndex = tokenizer.nextTokenAsInt();
568
569 if (sd->isRigidBody()) {
570 RigidBody* rb = static_cast<RigidBody*>(sd);
571 sd = rb->getAtoms()[siteIndex];
572 }
573 }
574
575 /**
576 * The next token contains information on what follows.
577 */
578 std::string type = tokenizer.nextToken();
579 int size = type.size();
580
581 for(int i = 0; i < size; ++i) {
582 switch(type[i]) {
583
584 case 'u' : {
585
586 RealType particlePot;
587 particlePot = tokenizer.nextTokenAsDouble();
588 sd->setParticlePot(particlePot);
589 break;
590 }
591 case 'c' : {
592
593 RealType flucQPos;
594 flucQPos = tokenizer.nextTokenAsDouble();
595 sd->setFlucQPos(flucQPos);
596 break;
597 }
598 case 'w' : {
599
600 RealType flucQVel;
601 flucQVel = tokenizer.nextTokenAsDouble();
602 sd->setFlucQVel(flucQVel);
603 break;
604 }
605 case 'g' : {
606
607 RealType flucQFrc;
608 flucQFrc = tokenizer.nextTokenAsDouble();
609 sd->setFlucQFrc(flucQFrc);
610 break;
611 }
612 case 'e' : {
613
614 Vector3d eField;
615 eField[0] = tokenizer.nextTokenAsDouble();
616 eField[1] = tokenizer.nextTokenAsDouble();
617 eField[2] = tokenizer.nextTokenAsDouble();
618 sd->setElectricField(eField);
619 break;
620 }
621 case 's' : {
622
623 RealType sPot;
624 sPot = tokenizer.nextTokenAsDouble();
625 sd->setSitePotential(sPot);
626 break;
627 }
628 default: {
629 sprintf(painCave.errMsg,
630 "DumpReader Error: %s is an unrecognized type\n", type.c_str());
631 painCave.isFatal = 1;
632 simError();
633 break;
634 }
635 }
636 }
637 }
638
639
640 void DumpReader::readStuntDoubles(std::istream& inputStream) {
641
642 inputStream.getline(buffer, bufferSize);
643 std::string line(buffer);
644
645 if (line.find("<StuntDoubles>") == std::string::npos) {
646 sprintf(painCave.errMsg,
647 "DumpReader Error: Missing <StuntDoubles>\n");
648 painCave.isFatal = 1;
649 simError();
650 }
651
652 while(inputStream.getline(buffer, bufferSize)) {
653 line = buffer;
654
655 if(line.find("</StuntDoubles>") != std::string::npos) {
656 break;
657 }
658
659 parseDumpLine(line);
660 }
661
662 }
663
664 void DumpReader::readSiteData(std::istream& inputStream) {
665
666 std::string line(buffer);
667
668 // We already found the starting <SiteData> tag or we wouldn't be
669 // here, so just start parsing until we get to the ending
670 // </SiteData> tag:
671
672 while(inputStream.getline(buffer, bufferSize)) {
673 line = buffer;
674
675 if(line.find("</SiteData>") != std::string::npos) {
676 break;
677 }
678
679 parseSiteLine(line);
680 }
681
682 }
683
684 void DumpReader::readFrameProperties(std::istream& inputStream) {
685
686 Snapshot* s = info_->getSnapshotManager()->getCurrentSnapshot();
687 inputStream.getline(buffer, bufferSize);
688 std::string line(buffer);
689
690 if (line.find("<FrameData>") == std::string::npos) {
691 sprintf(painCave.errMsg,
692 "DumpReader Error: Missing <FrameData>\n");
693 painCave.isFatal = 1;
694 simError();
695 }
696
697 while(inputStream.getline(buffer, bufferSize)) {
698 line = buffer;
699
700 if(line.find("</FrameData>") != std::string::npos) {
701 break;
702 }
703
704 StringTokenizer tokenizer(line, " ;\t\n\r{}:,");
705 if (!tokenizer.hasMoreTokens()) {
706 sprintf(painCave.errMsg,
707 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
708 painCave.isFatal = 1;
709 simError();
710 }
711
712 std::string propertyName = tokenizer.nextToken();
713 if (propertyName == "Time") {
714 RealType currTime = tokenizer.nextTokenAsDouble();
715 s->setTime(currTime);
716 } else if (propertyName == "Hmat"){
717 Mat3x3d hmat;
718 hmat(0, 0) = tokenizer.nextTokenAsDouble();
719 hmat(0, 1) = tokenizer.nextTokenAsDouble();
720 hmat(0, 2) = tokenizer.nextTokenAsDouble();
721 hmat(1, 0) = tokenizer.nextTokenAsDouble();
722 hmat(1, 1) = tokenizer.nextTokenAsDouble();
723 hmat(1, 2) = tokenizer.nextTokenAsDouble();
724 hmat(2, 0) = tokenizer.nextTokenAsDouble();
725 hmat(2, 1) = tokenizer.nextTokenAsDouble();
726 hmat(2, 2) = tokenizer.nextTokenAsDouble();
727 s->setHmat(hmat);
728 } else if (propertyName == "Thermostat") {
729 pair<RealType, RealType> thermostat;
730 thermostat.first = tokenizer.nextTokenAsDouble();
731 thermostat.second = tokenizer.nextTokenAsDouble();
732 s->setThermostat(thermostat);
733 } else if (propertyName == "Barostat") {
734 Mat3x3d eta;
735 eta(0, 0) = tokenizer.nextTokenAsDouble();
736 eta(0, 1) = tokenizer.nextTokenAsDouble();
737 eta(0, 2) = tokenizer.nextTokenAsDouble();
738 eta(1, 0) = tokenizer.nextTokenAsDouble();
739 eta(1, 1) = tokenizer.nextTokenAsDouble();
740 eta(1, 2) = tokenizer.nextTokenAsDouble();
741 eta(2, 0) = tokenizer.nextTokenAsDouble();
742 eta(2, 1) = tokenizer.nextTokenAsDouble();
743 eta(2, 2) = tokenizer.nextTokenAsDouble();
744 s->setBarostat(eta);
745 } else {
746 sprintf(painCave.errMsg,
747 "DumpReader Error: %s is an invalid property in <FrameData>\n", propertyName.c_str());
748 painCave.isFatal = 0;
749 simError();
750 }
751
752 }
753
754 }
755
756
757 }//end namespace OpenMD

Properties

Name Value
svn:keywords Author Id Revision Date