48#define _LARGEFILE_SOURCE64
49#define _FILE_OFFSET_BITS 64
66#include "brains/Thermo.hpp"
69#include "utils/simError.h"
73 DumpReader::DumpReader(
SimInfo* info,
const std::string& filename) :
74 info_(info), filename_(filename), isScanned_(false), nframes_(0),
75 needCOMprops_(false) {
81 std::ifstream(filename_.c_str(), ifstream::in | ifstream::binary);
84 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
85 "DumpReader: Cannot open file: %s\n", filename_.c_str());
91 strcpy(checkPointMsg,
"Dump file opened for reading successfully.");
96 DumpReader::~DumpReader() {
98 strcpy(checkPointMsg,
"Dump file closed successfully.");
104 if (!isScanned_) scanFile();
109 void DumpReader::scanFile(
void) {
110 std::streampos prevPos;
111 std::streampos currPos;
114 if (worldRank == 0) {
117 currPos = inFile_.tellg();
119 bool foundOpenSnapshotTag =
false;
120 bool foundClosedSnapshotTag =
false;
123 while (inFile_.getline(buffer, bufferSize)) {
126 std::string line = buffer;
127 currPos = inFile_.tellg();
128 if (line.find(
"<Snapshot>") != std::string::npos) {
129 if (foundOpenSnapshotTag) {
130 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
131 "DumpReader:<Snapshot> is multiply nested at line %d "
133 lineNo, filename_.c_str());
134 painCave.isFatal = 1;
137 foundOpenSnapshotTag =
true;
138 foundClosedSnapshotTag =
false;
139 framePos_.push_back(prevPos);
141 }
else if (line.find(
"</Snapshot>") != std::string::npos) {
142 if (!foundOpenSnapshotTag) {
143 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
144 "DumpReader:</Snapshot> appears before <Snapshot> at "
146 lineNo, filename_.c_str());
147 painCave.isFatal = 1;
151 if (foundClosedSnapshotTag) {
152 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
153 "DumpReader:</Snapshot> appears multiply nested at "
155 lineNo, filename_.c_str());
156 painCave.isFatal = 1;
159 foundClosedSnapshotTag =
true;
160 foundOpenSnapshotTag =
false;
167 if (foundOpenSnapshotTag) {
168 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
169 "DumpReader: last frame in %s is invalid\n",
171 painCave.isFatal = 0;
173 framePos_.pop_back();
176 nframes_ = framePos_.size();
179 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
180 "DumpReader: %s does not contain a valid frame\n",
182 painCave.isFatal = 1;
188 MPI_Bcast(&nframes_, 1, MPI_INT, 0, MPI_COMM_WORLD);
194 void DumpReader::readFrame(
int whichFrame) {
195 if (!isScanned_) scanFile();
197 int asl = info_->getSnapshotManager()->getAtomStorageLayout();
198 int rbsl = info_->getSnapshotManager()->getRigidBodyStorageLayout();
201 (asl & DataStorage::dslPosition || rbsl & DataStorage::dslPosition) ?
205 (asl & DataStorage::dslVelocity || rbsl & DataStorage::dslVelocity) ?
209 (asl & DataStorage::dslAmat || asl & DataStorage::dslDipole ||
210 asl & DataStorage::dslQuadrupole || rbsl & DataStorage::dslAmat ||
211 rbsl & DataStorage::dslDipole || rbsl & DataStorage::dslQuadrupole) ?
214 needAngMom_ = (asl & DataStorage::dslAngularMomentum ||
215 rbsl & DataStorage::dslAngularMomentum) ?
221 readField_ = (asl & DataStorage::dslElectricField) ?
true : false;
226 Thermo thermo(info_);
229 if (needPos_ && needVel_) {
232 thermo.getComAll(com, comvel);
233 comw = thermo.getAngularMomentum();
235 com = thermo.getCom();
240 void DumpReader::readSet(
int whichFrame) {
245 inFile_.seekg(framePos_[whichFrame]);
247 std::istream& inputStream = inFile_;
251 std::stringstream sstream;
252 if (worldRank == primaryNode) {
253 std::string sendBuffer;
256 inFile_.seekg(framePos_[whichFrame]);
258 while (inFile_.getline(buffer, bufferSize)) {
262 if (line.find(
"</Snapshot>") != std::string::npos) {
break; }
265 int sendBufferSize = sendBuffer.size();
266 MPI_Bcast(&sendBufferSize, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
267 MPI_Bcast((
void*)sendBuffer.c_str(), sendBufferSize, MPI_CHAR,
268 primaryNode, MPI_COMM_WORLD);
270 sstream.str(sendBuffer);
273 MPI_Bcast(&sendBufferSize, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
274 char* recvBuffer =
new char[sendBufferSize + 1];
276 recvBuffer[sendBufferSize] =
'\0';
277 MPI_Bcast(recvBuffer, sendBufferSize, MPI_CHAR, primaryNode,
279 sstream.str(recvBuffer);
283 std::istream& inputStream = sstream;
286 inputStream.getline(buffer, bufferSize);
289 if (line.find(
"<Snapshot>") == std::string::npos) {
290 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
291 "DumpReader Error: can not find <Snapshot>\n");
292 painCave.isFatal = 1;
297 readFrameProperties(inputStream);
300 int nSD = readStuntDoubles(inputStream);
302 inputStream.getline(buffer, bufferSize);
305 if (line.find(
"<SiteData>") != std::string::npos) {
307 readSiteData(inputStream);
309 if (line.find(
"</Snapshot>") == std::string::npos) {
310 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
311 "DumpReader Error: can not find </Snapshot>\n");
312 painCave.isFatal = 1;
317 if (nSD != info_->getNGlobalIntegrableObjects()) {
318 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
319 "DumpReader Error: Number of parsed StuntDouble lines (%d)\n"
320 "\tis not the same as the expected number of Objects (%d)\n",
321 nSD, info_->getNGlobalIntegrableObjects());
322 painCave.isFatal = 1;
327 void DumpReader::parseDumpLine(
const std::string& line) {
328 StringTokenizer tokenizer(line);
331 nTokens = tokenizer.countTokens();
334 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
335 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
336 painCave.isFatal = 1;
340 int index = tokenizer.nextTokenAsInt();
342 StuntDouble* sd = info_->getIOIndexToIntegrableObject(index);
344 if (sd == NULL) {
return; }
345 std::string type = tokenizer.nextToken();
346 int size = type.size();
351 found = type.find(
"p");
352 if (found == std::string::npos) {
353 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
354 "DumpReader Error: StuntDouble %d has no Position\n"
355 "\tField (\"p\") specified.\n%s\n",
356 index, line.c_str());
357 painCave.isFatal = 1;
362 if (sd->isDirectional()) {
363 if (needQuaternion_) {
364 found = type.find(
"q");
365 if (found == std::string::npos) {
366 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
367 "DumpReader Error: Directional StuntDouble %d has no\n"
368 "\tQuaternion Field (\"q\") specified.\n%s\n",
369 index, line.c_str());
370 painCave.isFatal = 1;
376 for (
int i = 0; i < size; ++i) {
380 pos[0] = tokenizer.nextTokenAsDouble();
381 pos[1] = tokenizer.nextTokenAsDouble();
382 pos[2] = tokenizer.nextTokenAsDouble();
383 if (needPos_) { sd->setPos(pos); }
388 vel[0] = tokenizer.nextTokenAsDouble();
389 vel[1] = tokenizer.nextTokenAsDouble();
390 vel[2] = tokenizer.nextTokenAsDouble();
391 if (needVel_) { sd->setVel(vel); }
397 if (sd->isDirectional()) {
398 q[0] = tokenizer.nextTokenAsDouble();
399 q[1] = tokenizer.nextTokenAsDouble();
400 q[2] = tokenizer.nextTokenAsDouble();
401 q[3] = tokenizer.nextTokenAsDouble();
403 RealType qlen = q.length();
404 if (qlen < OpenMD::epsilon) {
407 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
408 "DumpReader Error: initial quaternion error "
409 "(q0^2 + q1^2 + q2^2 + q3^2) ~ 0\n");
410 painCave.isFatal = 1;
415 if (needQuaternion_) { sd->setQ(q); }
421 if (sd->isDirectional()) {
422 ji[0] = tokenizer.nextTokenAsDouble();
423 ji[1] = tokenizer.nextTokenAsDouble();
424 ji[2] = tokenizer.nextTokenAsDouble();
425 if (needAngMom_) { sd->setJ(ji); }
431 force[0] = tokenizer.nextTokenAsDouble();
432 force[1] = tokenizer.nextTokenAsDouble();
433 force[2] = tokenizer.nextTokenAsDouble();
439 torque[0] = tokenizer.nextTokenAsDouble();
440 torque[1] = tokenizer.nextTokenAsDouble();
441 torque[2] = tokenizer.nextTokenAsDouble();
446 RealType particlePot;
447 particlePot = tokenizer.nextTokenAsDouble();
448 sd->setParticlePot(particlePot);
453 flucQPos = tokenizer.nextTokenAsDouble();
455 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
456 sd->setFlucQPos(flucQPos);
461 flucQVel = tokenizer.nextTokenAsDouble();
463 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
464 sd->setFlucQVel(flucQVel);
469 flucQFrc = tokenizer.nextTokenAsDouble();
471 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
472 sd->setFlucQFrc(flucQFrc);
477 eField[0] = tokenizer.nextTokenAsDouble();
478 eField[1] = tokenizer.nextTokenAsDouble();
479 eField[2] = tokenizer.nextTokenAsDouble();
481 if (readField_) sd->setElectricField(eField);
486 sPot = tokenizer.nextTokenAsDouble();
487 sd->setSitePotential(sPot);
492 density = tokenizer.nextTokenAsDouble();
493 sd->setDensity(density);
498 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
499 "DumpReader Error: %s is an unrecognized type\n",
501 painCave.isFatal = 1;
507 if (sd->isRigidBody()) {
508 RigidBody* rb =
static_cast<RigidBody*
>(sd);
514 if (needVel_) { rb->updateAtomVel(); }
525 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
526 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
527 painCave.isFatal = 1;
536 StuntDouble* sd = info_->getIOIndexToIntegrableObject(index);
537 if (sd == NULL) {
return; }
541 if (nTokens == 1) {
return; }
549 std::istringstream i(indexTest);
551 if (i >> siteIndex) {
560 if (siteIndex >=
static_cast<int>(rb->
getNumAtoms())) {
return; }
569 std::string type = tokenizer.
nextToken();
570 int size = type.size();
572 for (
int i = 0; i < size; ++i) {
575 RealType particlePot;
584 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
592 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
600 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
625 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
626 "DumpReader Error: %s is an unrecognized type\n",
628 painCave.isFatal = 1;
636 int DumpReader::readStuntDoubles(std::istream& inputStream) {
637 inputStream.getline(buffer, bufferSize);
638 std::string line(buffer);
640 if (line.find(
"<StuntDoubles>") == std::string::npos) {
641 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
642 "DumpReader Error: Missing <StuntDoubles>\n");
643 painCave.isFatal = 1;
649 while (inputStream.getline(buffer, bufferSize)) {
652 if (line.find(
"</StuntDoubles>") != std::string::npos) {
break; }
661 void DumpReader::readSiteData(std::istream& inputStream) {
662 std::string line(buffer);
668 while (inputStream.getline(buffer, bufferSize)) {
671 if (line.find(
"</SiteData>") != std::string::npos) {
break; }
677 void DumpReader::readFrameProperties(std::istream& inputStream) {
678 Snapshot* s = info_->getSnapshotManager()->getCurrentSnapshot();
681 s->clearDerivedProperties();
683 inputStream.getline(buffer, bufferSize);
684 std::string line(buffer);
686 if (line.find(
"<FrameData>") == std::string::npos) {
687 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
688 "DumpReader Error: Missing <FrameData>\n");
689 painCave.isFatal = 1;
693 while (inputStream.getline(buffer, bufferSize)) {
696 if (line.find(
"</FrameData>") != std::string::npos) {
break; }
698 StringTokenizer tokenizer(line,
" ;\t\n\r{}:,");
699 if (!tokenizer.hasMoreTokens()) {
700 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
701 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
702 painCave.isFatal = 1;
706 std::string propertyName = tokenizer.nextToken();
707 if (propertyName ==
"Time") {
708 RealType currTime = tokenizer.nextTokenAsDouble();
709 s->setTime(currTime);
710 }
else if (propertyName ==
"Hmat") {
712 hmat(0, 0) = tokenizer.nextTokenAsDouble();
713 hmat(0, 1) = tokenizer.nextTokenAsDouble();
714 hmat(0, 2) = tokenizer.nextTokenAsDouble();
715 hmat(1, 0) = tokenizer.nextTokenAsDouble();
716 hmat(1, 1) = tokenizer.nextTokenAsDouble();
717 hmat(1, 2) = tokenizer.nextTokenAsDouble();
718 hmat(2, 0) = tokenizer.nextTokenAsDouble();
719 hmat(2, 1) = tokenizer.nextTokenAsDouble();
720 hmat(2, 2) = tokenizer.nextTokenAsDouble();
722 }
else if (propertyName ==
"Thermostat") {
723 pair<RealType, RealType> thermostat;
724 thermostat.first = tokenizer.nextTokenAsDouble();
725 thermostat.second = tokenizer.nextTokenAsDouble();
726 s->setThermostat(thermostat);
727 }
else if (propertyName ==
"Barostat") {
729 eta(0, 0) = tokenizer.nextTokenAsDouble();
730 eta(0, 1) = tokenizer.nextTokenAsDouble();
731 eta(0, 2) = tokenizer.nextTokenAsDouble();
732 eta(1, 0) = tokenizer.nextTokenAsDouble();
733 eta(1, 1) = tokenizer.nextTokenAsDouble();
734 eta(1, 2) = tokenizer.nextTokenAsDouble();
735 eta(2, 0) = tokenizer.nextTokenAsDouble();
736 eta(2, 1) = tokenizer.nextTokenAsDouble();
737 eta(2, 2) = tokenizer.nextTokenAsDouble();
739 }
else if (propertyName ==
"SPFData") {
740 std::shared_ptr<SPFData> spfData = s->getSPFData();
742 spfData->pos[0] = tokenizer.nextTokenAsDouble();
743 spfData->pos[1] = tokenizer.nextTokenAsDouble();
744 spfData->pos[2] = tokenizer.nextTokenAsDouble();
745 spfData->lambda = tokenizer.nextTokenAsDouble();
746 spfData->globalID = tokenizer.nextTokenAsInt();
748 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
749 "DumpReader Error: %s is an invalid property in <FrameData>\n",
750 propertyName.c_str());
751 painCave.isFatal = 0;
void parseSiteLine(const std::string &)
int getNFrames()
Returns the number of frames in the dump file.
size_t getNumAtoms()
Returns the number of atoms in this rigid body.
std::vector< Atom * > getAtoms()
Returns the atoms of this rigid body.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
The string tokenizer class allows an application to break a string into tokens The set of delimiters ...
std::string peekNextToken()
Returns the next token without advancing the position of the StringTokenizer.
std::string nextToken()
Returns the next token from this string tokenizer.
int countTokens()
Calculates the number of times that this tokenizer's nextToken method can be called before it generat...
int nextTokenAsInt()
Returns the next token from this string tokenizer as an integer.
RealType nextTokenAsDouble()
Returns the next token from this string tokenizer as a RealType.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
void setFlucQVel(RealType cvel)
Sets the current charge velocity of this stuntDouble.
void setFlucQPos(RealType charge)
Sets the current fluctuating charge of this stuntDouble.
void setParticlePot(const RealType &particlePot)
Sets the current particlePot of this stuntDouble.
void setSitePotential(RealType spot)
Sets the current site potential of this stuntDouble.
void setElectricField(const Vector3d &eField)
Sets the current electric field of this stuntDouble.
bool isRigidBody()
Tests if this stuntDouble is a rigid body.
bool isAtom()
Tests if this stuntDouble is an atom.
void setFlucQFrc(RealType cfrc)
Sets the current charge force of this stuntDouble.
void setDensity(RealType dens)
Sets the current density of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.