45#define _LARGEFILE_SOURCE64
46#define _FILE_OFFSET_BITS 64
63#include "brains/Thermo.hpp"
66#include "utils/simError.h"
70 DumpReader::DumpReader(SimInfo* info,
const std::string& filename) :
71 info_(info), filename_(filename), isScanned_(false), nframes_(0),
72 needCOMprops_(false) {
78 std::ifstream(filename_.c_str(), ifstream::in | ifstream::binary);
81 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
82 "DumpReader: Cannot open file: %s\n", filename_.c_str());
88 strcpy(checkPointMsg,
"Dump file opened for reading successfully.");
93 DumpReader::~DumpReader() {
95 strcpy(checkPointMsg,
"Dump file closed successfully.");
100 int DumpReader::getNFrames(
void) {
101 if (!isScanned_) scanFile();
106 void DumpReader::scanFile(
void) {
107 std::streampos prevPos;
108 std::streampos currPos;
111 if (worldRank == 0) {
114 currPos = inFile_.tellg();
116 bool foundOpenSnapshotTag =
false;
117 bool foundClosedSnapshotTag =
false;
120 while (inFile_.getline(buffer, bufferSize)) {
123 std::string line = buffer;
124 currPos = inFile_.tellg();
125 if (line.find(
"<Snapshot>") != std::string::npos) {
126 if (foundOpenSnapshotTag) {
127 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
128 "DumpReader:<Snapshot> is multiply nested at line %d "
130 lineNo, filename_.c_str());
131 painCave.isFatal = 1;
134 foundOpenSnapshotTag =
true;
135 foundClosedSnapshotTag =
false;
136 framePos_.push_back(prevPos);
138 }
else if (line.find(
"</Snapshot>") != std::string::npos) {
139 if (!foundOpenSnapshotTag) {
140 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
141 "DumpReader:</Snapshot> appears before <Snapshot> at "
143 lineNo, filename_.c_str());
144 painCave.isFatal = 1;
148 if (foundClosedSnapshotTag) {
149 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
150 "DumpReader:</Snapshot> appears multiply nested at "
152 lineNo, filename_.c_str());
153 painCave.isFatal = 1;
156 foundClosedSnapshotTag =
true;
157 foundOpenSnapshotTag =
false;
164 if (foundOpenSnapshotTag) {
165 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
166 "DumpReader: last frame in %s is invalid\n",
168 painCave.isFatal = 0;
170 framePos_.pop_back();
173 nframes_ = framePos_.size();
176 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
177 "DumpReader: %s does not contain a valid frame\n",
179 painCave.isFatal = 1;
185 MPI_Bcast(&nframes_, 1, MPI_INT, 0, MPI_COMM_WORLD);
191 void DumpReader::readFrame(
int whichFrame) {
192 if (!isScanned_) scanFile();
194 int asl = info_->getSnapshotManager()->getAtomStorageLayout();
195 int rbsl = info_->getSnapshotManager()->getRigidBodyStorageLayout();
198 (asl & DataStorage::dslPosition || rbsl & DataStorage::dslPosition) ?
202 (asl & DataStorage::dslVelocity || rbsl & DataStorage::dslVelocity) ?
206 (asl & DataStorage::dslAmat || asl & DataStorage::dslDipole ||
207 asl & DataStorage::dslQuadrupole || rbsl & DataStorage::dslAmat ||
208 rbsl & DataStorage::dslDipole || rbsl & DataStorage::dslQuadrupole) ?
211 needAngMom_ = (asl & DataStorage::dslAngularMomentum ||
212 rbsl & DataStorage::dslAngularMomentum) ?
218 readField_ = (asl & DataStorage::dslElectricField) ?
true : false;
223 Thermo thermo(info_);
226 if (needPos_ && needVel_) {
229 thermo.getComAll(com, comvel);
230 comw = thermo.getAngularMomentum();
232 com = thermo.getCom();
237 void DumpReader::readSet(
int whichFrame) {
242 inFile_.seekg(framePos_[whichFrame]);
244 std::istream& inputStream = inFile_;
248 std::stringstream sstream;
249 if (worldRank == primaryNode) {
250 std::string sendBuffer;
253 inFile_.seekg(framePos_[whichFrame]);
255 while (inFile_.getline(buffer, bufferSize)) {
259 if (line.find(
"</Snapshot>") != std::string::npos) {
break; }
262 int sendBufferSize = sendBuffer.size();
263 MPI_Bcast(&sendBufferSize, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
264 MPI_Bcast((
void*)sendBuffer.c_str(), sendBufferSize, MPI_CHAR,
265 primaryNode, MPI_COMM_WORLD);
267 sstream.str(sendBuffer);
270 MPI_Bcast(&sendBufferSize, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
271 char* recvBuffer =
new char[sendBufferSize + 1];
273 recvBuffer[sendBufferSize] =
'\0';
274 MPI_Bcast(recvBuffer, sendBufferSize, MPI_CHAR, primaryNode,
276 sstream.str(recvBuffer);
280 std::istream& inputStream = sstream;
283 inputStream.getline(buffer, bufferSize);
286 if (line.find(
"<Snapshot>") == std::string::npos) {
287 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
288 "DumpReader Error: can not find <Snapshot>\n");
289 painCave.isFatal = 1;
294 readFrameProperties(inputStream);
297 int nSD = readStuntDoubles(inputStream);
299 inputStream.getline(buffer, bufferSize);
302 if (line.find(
"<SiteData>") != std::string::npos) {
304 readSiteData(inputStream);
306 if (line.find(
"</Snapshot>") == std::string::npos) {
307 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
308 "DumpReader Error: can not find </Snapshot>\n");
309 painCave.isFatal = 1;
314 if (nSD != info_->getNGlobalIntegrableObjects()) {
315 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
316 "DumpReader Error: Number of parsed StuntDouble lines (%d)\n"
317 "\tis not the same as the expected number of Objects (%d)\n",
318 nSD, info_->getNGlobalIntegrableObjects());
319 painCave.isFatal = 1;
324 void DumpReader::parseDumpLine(
const std::string& line) {
325 StringTokenizer tokenizer(line);
328 nTokens = tokenizer.countTokens();
331 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
332 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
333 painCave.isFatal = 1;
337 int index = tokenizer.nextTokenAsInt();
339 StuntDouble* sd = info_->getIOIndexToIntegrableObject(index);
341 if (sd == NULL) {
return; }
342 std::string type = tokenizer.nextToken();
343 int size = type.size();
348 found = type.find(
"p");
349 if (found == std::string::npos) {
350 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
351 "DumpReader Error: StuntDouble %d has no Position\n"
352 "\tField (\"p\") specified.\n%s\n",
353 index, line.c_str());
354 painCave.isFatal = 1;
359 if (sd->isDirectional()) {
360 if (needQuaternion_) {
361 found = type.find(
"q");
362 if (found == std::string::npos) {
363 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
364 "DumpReader Error: Directional StuntDouble %d has no\n"
365 "\tQuaternion Field (\"q\") specified.\n%s\n",
366 index, line.c_str());
367 painCave.isFatal = 1;
373 for (
int i = 0; i < size; ++i) {
377 pos[0] = tokenizer.nextTokenAsDouble();
378 pos[1] = tokenizer.nextTokenAsDouble();
379 pos[2] = tokenizer.nextTokenAsDouble();
380 if (needPos_) { sd->setPos(pos); }
385 vel[0] = tokenizer.nextTokenAsDouble();
386 vel[1] = tokenizer.nextTokenAsDouble();
387 vel[2] = tokenizer.nextTokenAsDouble();
388 if (needVel_) { sd->setVel(vel); }
394 if (sd->isDirectional()) {
395 q[0] = tokenizer.nextTokenAsDouble();
396 q[1] = tokenizer.nextTokenAsDouble();
397 q[2] = tokenizer.nextTokenAsDouble();
398 q[3] = tokenizer.nextTokenAsDouble();
400 RealType qlen = q.length();
401 if (qlen < OpenMD::epsilon) {
404 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
405 "DumpReader Error: initial quaternion error "
406 "(q0^2 + q1^2 + q2^2 + q3^2) ~ 0\n");
407 painCave.isFatal = 1;
412 if (needQuaternion_) { sd->setQ(q); }
418 if (sd->isDirectional()) {
419 ji[0] = tokenizer.nextTokenAsDouble();
420 ji[1] = tokenizer.nextTokenAsDouble();
421 ji[2] = tokenizer.nextTokenAsDouble();
422 if (needAngMom_) { sd->setJ(ji); }
428 force[0] = tokenizer.nextTokenAsDouble();
429 force[1] = tokenizer.nextTokenAsDouble();
430 force[2] = tokenizer.nextTokenAsDouble();
436 torque[0] = tokenizer.nextTokenAsDouble();
437 torque[1] = tokenizer.nextTokenAsDouble();
438 torque[2] = tokenizer.nextTokenAsDouble();
443 RealType particlePot;
444 particlePot = tokenizer.nextTokenAsDouble();
445 sd->setParticlePot(particlePot);
450 flucQPos = tokenizer.nextTokenAsDouble();
452 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
453 sd->setFlucQPos(flucQPos);
458 flucQVel = tokenizer.nextTokenAsDouble();
460 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
461 sd->setFlucQVel(flucQVel);
466 flucQFrc = tokenizer.nextTokenAsDouble();
468 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
469 sd->setFlucQFrc(flucQFrc);
474 eField[0] = tokenizer.nextTokenAsDouble();
475 eField[1] = tokenizer.nextTokenAsDouble();
476 eField[2] = tokenizer.nextTokenAsDouble();
478 if (readField_) sd->setElectricField(eField);
483 sPot = tokenizer.nextTokenAsDouble();
484 sd->setSitePotential(sPot);
489 density = tokenizer.nextTokenAsDouble();
490 sd->setDensity(density);
495 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
496 "DumpReader Error: %s is an unrecognized type\n",
498 painCave.isFatal = 1;
504 if (sd->isRigidBody()) {
505 RigidBody* rb =
static_cast<RigidBody*
>(sd);
511 if (needVel_) { rb->updateAtomVel(); }
515 void DumpReader::parseSiteLine(
const std::string& line) {
522 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
523 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
524 painCave.isFatal = 1;
533 StuntDouble* sd = info_->getIOIndexToIntegrableObject(index);
534 if (sd == NULL) {
return; }
538 if (nTokens == 1) {
return; }
546 std::istringstream i(indexTest);
548 if (i >> siteIndex) {
557 if (siteIndex >=
static_cast<int>(rb->
getNumAtoms())) {
return; }
566 std::string type = tokenizer.
nextToken();
567 int size = type.size();
569 for (
int i = 0; i < size; ++i) {
572 RealType particlePot;
581 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
589 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
597 if (
dynamic_cast<Atom*
>(sd)->isFluctuatingCharge())
622 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
623 "DumpReader Error: %s is an unrecognized type\n",
625 painCave.isFatal = 1;
633 int DumpReader::readStuntDoubles(std::istream& inputStream) {
634 inputStream.getline(buffer, bufferSize);
635 std::string line(buffer);
637 if (line.find(
"<StuntDoubles>") == std::string::npos) {
638 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
639 "DumpReader Error: Missing <StuntDoubles>\n");
640 painCave.isFatal = 1;
646 while (inputStream.getline(buffer, bufferSize)) {
649 if (line.find(
"</StuntDoubles>") != std::string::npos) {
break; }
658 void DumpReader::readSiteData(std::istream& inputStream) {
659 std::string line(buffer);
665 while (inputStream.getline(buffer, bufferSize)) {
668 if (line.find(
"</SiteData>") != std::string::npos) {
break; }
674 void DumpReader::readFrameProperties(std::istream& inputStream) {
675 Snapshot* s = info_->getSnapshotManager()->getCurrentSnapshot();
678 s->clearDerivedProperties();
680 inputStream.getline(buffer, bufferSize);
681 std::string line(buffer);
683 if (line.find(
"<FrameData>") == std::string::npos) {
684 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
685 "DumpReader Error: Missing <FrameData>\n");
686 painCave.isFatal = 1;
690 while (inputStream.getline(buffer, bufferSize)) {
693 if (line.find(
"</FrameData>") != std::string::npos) {
break; }
695 StringTokenizer tokenizer(line,
" ;\t\n\r{}:,");
696 if (!tokenizer.hasMoreTokens()) {
697 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
698 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
699 painCave.isFatal = 1;
703 std::string propertyName = tokenizer.nextToken();
704 if (propertyName ==
"Time") {
705 RealType currTime = tokenizer.nextTokenAsDouble();
706 s->setTime(currTime);
707 }
else if (propertyName ==
"Hmat") {
709 hmat(0, 0) = tokenizer.nextTokenAsDouble();
710 hmat(0, 1) = tokenizer.nextTokenAsDouble();
711 hmat(0, 2) = tokenizer.nextTokenAsDouble();
712 hmat(1, 0) = tokenizer.nextTokenAsDouble();
713 hmat(1, 1) = tokenizer.nextTokenAsDouble();
714 hmat(1, 2) = tokenizer.nextTokenAsDouble();
715 hmat(2, 0) = tokenizer.nextTokenAsDouble();
716 hmat(2, 1) = tokenizer.nextTokenAsDouble();
717 hmat(2, 2) = tokenizer.nextTokenAsDouble();
719 }
else if (propertyName ==
"Thermostat") {
720 pair<RealType, RealType> thermostat;
721 thermostat.first = tokenizer.nextTokenAsDouble();
722 thermostat.second = tokenizer.nextTokenAsDouble();
723 s->setThermostat(thermostat);
724 }
else if (propertyName ==
"Barostat") {
726 eta(0, 0) = tokenizer.nextTokenAsDouble();
727 eta(0, 1) = tokenizer.nextTokenAsDouble();
728 eta(0, 2) = tokenizer.nextTokenAsDouble();
729 eta(1, 0) = tokenizer.nextTokenAsDouble();
730 eta(1, 1) = tokenizer.nextTokenAsDouble();
731 eta(1, 2) = tokenizer.nextTokenAsDouble();
732 eta(2, 0) = tokenizer.nextTokenAsDouble();
733 eta(2, 1) = tokenizer.nextTokenAsDouble();
734 eta(2, 2) = tokenizer.nextTokenAsDouble();
736 }
else if (propertyName ==
"SPFData") {
737 std::shared_ptr<SPFData> spfData = s->getSPFData();
739 spfData->pos[0] = tokenizer.nextTokenAsDouble();
740 spfData->pos[1] = tokenizer.nextTokenAsDouble();
741 spfData->pos[2] = tokenizer.nextTokenAsDouble();
742 spfData->lambda = tokenizer.nextTokenAsDouble();
743 spfData->globalID = tokenizer.nextTokenAsInt();
745 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
746 "DumpReader Error: %s is an invalid property in <FrameData>\n",
747 propertyName.c_str());
748 painCave.isFatal = 0;
size_t getNumAtoms()
Returns the number of atoms in this rigid body.
std::vector< Atom * > getAtoms()
Returns the atoms of this rigid body.
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.