48#include "io/DumpWriter.hpp"
56#include "io/Globals.hpp"
57#include "io/basic_teebuf.hpp"
59#include "utils/simError.h"
61#include "io/gzstream.hpp"
67 DumpWriter::DumpWriter(
SimInfo* info) :
68 info_(info), filename_(info->getDumpFileName()),
69 eorFilename_(info->getFinalConfigFileName()) {
70 Globals* simParams = info->getSimParams();
71 needCompression_ = simParams->getCompressDumpFile();
72 needForceVector_ = simParams->getOutputForceVector();
73 needParticlePot_ = simParams->getOutputParticlePotential();
74 needFlucQ_ = simParams->getOutputFluctuatingCharges();
75 needElectricField_ = simParams->getOutputElectricField();
76 needSitePotential_ = simParams->getOutputSitePotential();
77 needDensity_ = simParams->getOutputDensity();
79 if (needParticlePot_ || needFlucQ_ || needElectricField_ ||
80 needSitePotential_ || needDensity_) {
86 createDumpFile_ =
true;
88 if (needCompression_) {
90 eorFilename_ +=
".gz";
99 dumpFile_ = createOStream(filename_);
102 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
103 "Could not open \"%s\" for dump output.\n", filename_.c_str());
104 painCave.isFatal = 1;
114 DumpWriter::DumpWriter(SimInfo* info,
const std::string& filename) :
115 info_(info), filename_(filename) {
116 Globals* simParams = info->getSimParams();
117 eorFilename_ = filename_.substr(0, filename_.rfind(
".")) +
".eor";
119 needCompression_ = simParams->getCompressDumpFile();
120 needForceVector_ = simParams->getOutputForceVector();
121 needParticlePot_ = simParams->getOutputParticlePotential();
122 needFlucQ_ = simParams->getOutputFluctuatingCharges();
123 needElectricField_ = simParams->getOutputElectricField();
124 needSitePotential_ = simParams->getOutputSitePotential();
125 needDensity_ = simParams->getOutputDensity();
127 if (needParticlePot_ || needFlucQ_ || needElectricField_ ||
128 needSitePotential_ || needDensity_) {
134 createDumpFile_ =
true;
136 if (needCompression_) {
138 eorFilename_ +=
".gz";
144 if (worldRank == 0) {
147 dumpFile_ = createOStream(filename_);
150 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
151 "Could not open \"%s\" for dump output.\n", filename_.c_str());
152 painCave.isFatal = 1;
162 DumpWriter::DumpWriter(SimInfo* info,
const std::string& filename,
163 bool writeDumpFile) :
165 filename_(filename) {
166 Globals* simParams = info->getSimParams();
167 eorFilename_ = filename_.substr(0, filename_.rfind(
".")) +
".eor";
169 needCompression_ = simParams->getCompressDumpFile();
170 needForceVector_ = simParams->getOutputForceVector();
171 needParticlePot_ = simParams->getOutputParticlePotential();
172 needFlucQ_ = simParams->getOutputFluctuatingCharges();
173 needElectricField_ = simParams->getOutputElectricField();
174 needSitePotential_ = simParams->getOutputSitePotential();
175 needDensity_ = simParams->getOutputDensity();
177 if (needParticlePot_ || needFlucQ_ || needElectricField_ ||
178 needSitePotential_ || needDensity_) {
185 if (needCompression_) {
187 eorFilename_ +=
".gz";
193 if (worldRank == 0) {
196 createDumpFile_ = writeDumpFile;
197 if (createDumpFile_) {
198 dumpFile_ = createOStream(filename_);
201 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
202 "Could not open \"%s\" for dump output.\n",
204 painCave.isFatal = 1;
214 DumpWriter::~DumpWriter() {
217 if (worldRank == 0) {
219 if (createDumpFile_) {
220 writeClosing(*dumpFile_);
229 void DumpWriter::writeFrameProperties(std::ostream& os, Snapshot* s) {
232 os <<
" <FrameData>\n";
234 RealType currentTime = s->getTime();
236 if (std::isinf(currentTime) || std::isnan(currentTime)) {
237 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
238 "DumpWriter detected a numerical error writing the time");
239 painCave.isFatal = 1;
243 snprintf(buffer, 1024,
" Time: %.10g\n", currentTime);
249 for (
unsigned int i = 0; i < 3; i++) {
250 for (
unsigned int j = 0; j < 3; j++) {
251 if (std::isinf(hmat(i, j)) || std::isnan(hmat(i, j))) {
252 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
253 "DumpWriter detected a numerical error writing the box");
254 painCave.isFatal = 1;
262 " Hmat: {{ %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }, { "
265 hmat(0, 0), hmat(1, 0), hmat(2, 0), hmat(0, 1), hmat(1, 1), hmat(2, 1),
266 hmat(0, 2), hmat(1, 2), hmat(2, 2));
269 pair<RealType, RealType> thermostat = s->getThermostat();
271 if (std::isinf(thermostat.first) || std::isnan(thermostat.first) ||
272 std::isinf(thermostat.second) || std::isnan(thermostat.second)) {
273 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
274 "DumpWriter detected a numerical error writing the thermostat");
275 painCave.isFatal = 1;
278 snprintf(buffer, 1024,
" Thermostat: %.10g , %.10g\n", thermostat.first,
283 eta = s->getBarostat();
285 for (
unsigned int i = 0; i < 3; i++) {
286 for (
unsigned int j = 0; j < 3; j++) {
287 if (std::isinf(eta(i, j)) || std::isnan(eta(i, j))) {
289 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
290 "DumpWriter detected a numerical error writing the barostat");
291 painCave.isFatal = 1;
299 " Barostat: {{ %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }, { "
302 eta(0, 0), eta(1, 0), eta(2, 0), eta(0, 1), eta(1, 1), eta(2, 1),
303 eta(0, 2), eta(1, 2), eta(2, 2));
307 std::shared_ptr<SPFData> spfData = s->getSPFData();
309 if (std::isinf(spfData->pos[0]) || std::isnan(spfData->pos[0]) ||
310 std::isinf(spfData->pos[1]) || std::isnan(spfData->pos[1]) ||
311 std::isinf(spfData->pos[2]) || std::isnan(spfData->pos[2]) ||
312 std::isinf(spfData->lambda) || std::isnan(spfData->lambda)) {
313 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
314 "DumpWriter detected a numerical error writing the spf data "
316 painCave.isFatal = 1;
319 snprintf(buffer, 1024,
320 " SPFData: {{ %.10g, %.10g, %.10g }, %.10g, %d }\n",
321 spfData->pos[0], spfData->pos[1], spfData->pos[2], spfData->lambda,
325 os <<
" </FrameData>\n";
328 void DumpWriter::writeFrame(std::ostream& os) {
335 SimInfo::MoleculeIterator mi;
336 Molecule::IntegrableObjectIterator ii;
337 RigidBody::AtomIterator ai;
340 os <<
" <Snapshot>\n";
342 writeFrameProperties(os, info_->getSnapshotManager()->getCurrentSnapshot());
344 os <<
" <StuntDoubles>\n";
345 for (mol = info_->beginMolecule(mi); mol != NULL;
346 mol = info_->nextMolecule(mi)) {
347 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
348 sd = mol->nextIntegrableObject(ii)) {
349 os << prepareDumpLine(sd);
352 os <<
" </StuntDoubles>\n";
355 os <<
" <SiteData>\n";
356 for (mol = info_->beginMolecule(mi); mol != NULL;
357 mol = info_->nextMolecule(mi)) {
358 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
359 sd = mol->nextIntegrableObject(ii)) {
360 int ioIndex = sd->getGlobalIntegrableObjectIndex();
362 os << prepareSiteLine(sd, ioIndex, 0);
364 if (sd->isRigidBody()) {
365 RigidBody* rb =
static_cast<RigidBody*
>(sd);
367 for (Atom* atom = rb->beginAtom(ai); atom != NULL;
368 atom = rb->nextAtom(ai)) {
369 os << prepareSiteLine(atom, ioIndex, siteIndex);
375 os <<
" </SiteData>\n";
377 os <<
" </Snapshot>\n";
380 os.rdbuf()->pubsync();
383 const int primaryNode = 0;
387 MPI_Comm_size(MPI_COMM_WORLD, &nProc);
388 MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
390 if (worldRank == primaryNode) {
391 os <<
" <Snapshot>\n";
392 writeFrameProperties(os,
393 info_->getSnapshotManager()->getCurrentSnapshot());
394 os <<
" <StuntDoubles>\n";
400 for (mol = info_->beginMolecule(mi); mol != NULL;
401 mol = info_->nextMolecule(mi)) {
402 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
403 sd = mol->nextIntegrableObject(ii)) {
404 buffer += prepareDumpLine(sd);
408 if (worldRank == primaryNode) {
411 for (
int i = 1; i < nProc; ++i) {
414 MPI_Bcast(&i, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
419 MPI_Recv(&recvLength, 1, MPI_INT, i, MPI_ANY_TAG, MPI_COMM_WORLD,
423 char* recvBuffer =
new char[recvLength];
424 if (recvBuffer == NULL) {
427 MPI_Recv(recvBuffer, recvLength, MPI_CHAR, i, MPI_ANY_TAG,
428 MPI_COMM_WORLD, &istatus);
436 int sendBufferLength = buffer.size() + 1;
438 for (
int i = 1; i < nProc; ++i) {
440 MPI_Bcast(&myturn, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
441 if (myturn == worldRank) {
444 MPI_Send(&sendBufferLength, 1, MPI_INT, primaryNode, 0,
448 MPI_Send((
void*)buffer.c_str(), sendBufferLength, MPI_CHAR,
449 primaryNode, 0, MPI_COMM_WORLD);
454 if (worldRank == primaryNode) { os <<
" </StuntDoubles>\n"; }
457 if (worldRank == primaryNode) { os <<
" <SiteData>\n"; }
459 for (mol = info_->beginMolecule(mi); mol != NULL;
460 mol = info_->nextMolecule(mi)) {
461 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
462 sd = mol->nextIntegrableObject(ii)) {
463 int ioIndex = sd->getGlobalIntegrableObjectIndex();
465 buffer += prepareSiteLine(sd, ioIndex, 0);
467 if (sd->isRigidBody()) {
468 RigidBody* rb =
static_cast<RigidBody*
>(sd);
470 for (Atom* atom = rb->beginAtom(ai); atom != NULL;
471 atom = rb->nextAtom(ai)) {
472 buffer += prepareSiteLine(atom, ioIndex, siteIndex);
479 if (worldRank == primaryNode) {
482 for (
int i = 1; i < nProc; ++i) {
484 MPI_Bcast(&i, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
489 MPI_Recv(&recvLength, 1, MPI_INT, i, MPI_ANY_TAG, MPI_COMM_WORLD,
493 char* recvBuffer =
new char[recvLength];
494 if (recvBuffer == NULL) {
497 MPI_Recv(recvBuffer, recvLength, MPI_CHAR, i, MPI_ANY_TAG,
498 MPI_COMM_WORLD, &istatus);
506 int sendBufferLength = buffer.size() + 1;
508 for (
int i = 1; i < nProc; ++i) {
510 MPI_Bcast(&myturn, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
511 if (myturn == worldRank) {
513 MPI_Send(&sendBufferLength, 1, MPI_INT, primaryNode, 0,
516 MPI_Send((
void*)buffer.c_str(), sendBufferLength, MPI_CHAR,
517 primaryNode, 0, MPI_COMM_WORLD);
522 if (worldRank == primaryNode) { os <<
" </SiteData>\n"; }
525 if (worldRank == primaryNode) {
526 os <<
" </Snapshot>\n";
528 os.rdbuf()->pubsync();
534 std::string DumpWriter::prepareDumpLine(StuntDouble* sd) {
535 int index = sd->getGlobalIntegrableObjectIndex();
536 std::string type(
"pv");
538 char tempBuffer[4096];
544 if (std::isinf(pos[0]) || std::isnan(pos[0]) || std::isinf(pos[1]) ||
545 std::isnan(pos[1]) || std::isinf(pos[2]) || std::isnan(pos[2])) {
546 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
547 "DumpWriter detected a numerical error writing the position"
550 painCave.isFatal = 1;
556 if (std::isinf(vel[0]) || std::isnan(vel[0]) || std::isinf(vel[1]) ||
557 std::isnan(vel[1]) || std::isinf(vel[2]) || std::isnan(vel[2])) {
558 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
559 "DumpWriter detected a numerical error writing the velocity"
562 painCave.isFatal = 1;
566 snprintf(tempBuffer, 4096,
"%18.10g %18.10g %18.10g %13e %13e %13e", pos[0],
567 pos[1], pos[2], vel[0], vel[1], vel[2]);
570 if (sd->isDirectional()) {
576 if (std::isinf(q[0]) || std::isnan(q[0]) || std::isinf(q[1]) ||
577 std::isnan(q[1]) || std::isinf(q[2]) || std::isnan(q[2]) ||
578 std::isinf(q[3]) || std::isnan(q[3])) {
579 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
580 "DumpWriter detected a numerical error writing the quaternion"
583 painCave.isFatal = 1;
589 if (std::isinf(ji[0]) || std::isnan(ji[0]) || std::isinf(ji[1]) ||
590 std::isnan(ji[1]) || std::isinf(ji[2]) || std::isnan(ji[2])) {
591 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
592 "DumpWriter detected a numerical error writing the angular"
593 " momentum for object %d",
595 painCave.isFatal = 1;
599 snprintf(tempBuffer, 4096,
" %13e %13e %13e %13e %13e %13e %13e", q[0],
600 q[1], q[2], q[3], ji[0], ji[1], ji[2]);
604 if (needForceVector_) {
606 Vector3d frc = sd->getFrc();
607 if (std::isinf(frc[0]) || std::isnan(frc[0]) || std::isinf(frc[1]) ||
608 std::isnan(frc[1]) || std::isinf(frc[2]) || std::isnan(frc[2])) {
609 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
610 "DumpWriter detected a numerical error writing the force"
613 painCave.isFatal = 1;
616 snprintf(tempBuffer, 4096,
" %13e %13e %13e", frc[0], frc[1], frc[2]);
619 if (sd->isDirectional()) {
621 Vector3d trq = sd->getTrq();
622 if (std::isinf(trq[0]) || std::isnan(trq[0]) || std::isinf(trq[1]) ||
623 std::isnan(trq[1]) || std::isinf(trq[2]) || std::isnan(trq[2])) {
624 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
625 "DumpWriter detected a numerical error writing the torque"
628 painCave.isFatal = 1;
631 snprintf(tempBuffer, 4096,
" %13e %13e %13e", trq[0], trq[1], trq[2]);
636 snprintf(tempBuffer, 4096,
"%10d %7s %s\n", index, type.c_str(),
638 return std::string(tempBuffer);
641 std::string DumpWriter::prepareSiteLine(StuntDouble* sd,
int ioIndex,
643 int asl = info_->getSnapshotManager()->getAtomStorageLayout();
644 int rbsl = info_->getSnapshotManager()->getRigidBodyStorageLayout();
650 char tempBuffer[4096];
652 if (sd->isRigidBody()) {
654 snprintf(tempBuffer, 4096,
"%10d ", ioIndex);
655 id = std::string(tempBuffer);
658 snprintf(tempBuffer, 4096,
"%10d %10d", ioIndex, siteIndex);
659 id = std::string(tempBuffer);
663 if (sl & DataStorage::dslFlucQPosition) {
665 RealType fqPos = sd->getFlucQPos();
666 if (std::isinf(fqPos) || std::isnan(fqPos)) {
667 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
668 "DumpWriter detected a numerical error writing the"
669 " fluctuating charge for object %s",
671 painCave.isFatal = 1;
674 snprintf(tempBuffer, 4096,
" %13e ", fqPos);
678 if (sl & DataStorage::dslFlucQVelocity) {
680 RealType fqVel = sd->getFlucQVel();
681 if (std::isinf(fqVel) || std::isnan(fqVel)) {
682 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
683 "DumpWriter detected a numerical error writing the"
684 " fluctuating charge velocity for object %s",
686 painCave.isFatal = 1;
689 snprintf(tempBuffer, 4096,
" %13e ", fqVel);
693 if (needForceVector_) {
694 if (sl & DataStorage::dslFlucQForce) {
696 RealType fqFrc = sd->getFlucQFrc();
697 if (std::isinf(fqFrc) || std::isnan(fqFrc)) {
698 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
699 "DumpWriter detected a numerical error writing the"
700 " fluctuating charge force for object %s",
702 painCave.isFatal = 1;
705 snprintf(tempBuffer, 4096,
" %13e ", fqFrc);
711 if (needElectricField_) {
712 if (sl & DataStorage::dslElectricField) {
714 Vector3d eField = sd->getElectricField();
715 if (std::isinf(eField[0]) || std::isnan(eField[0]) ||
716 std::isinf(eField[1]) || std::isnan(eField[1]) ||
717 std::isinf(eField[2]) || std::isnan(eField[2])) {
718 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
719 "DumpWriter detected a numerical error writing the electric"
720 " field for object %s",
722 painCave.isFatal = 1;
725 snprintf(tempBuffer, 4096,
" %13e %13e %13e", eField[0], eField[1],
731 if (needSitePotential_) {
732 if (sl & DataStorage::dslSitePotential) {
734 RealType sPot = sd->getSitePotential();
735 if (std::isinf(sPot) || std::isnan(sPot)) {
736 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
737 "DumpWriter detected a numerical error writing the"
738 " site potential for object %s",
740 painCave.isFatal = 1;
743 snprintf(tempBuffer, 4096,
" %13e ", sPot);
748 if (needParticlePot_) {
749 if (sl & DataStorage::dslParticlePot) {
751 RealType particlePot = sd->getParticlePot();
752 if (std::isinf(particlePot) || std::isnan(particlePot)) {
753 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
754 "DumpWriter detected a numerical error writing the particle "
755 " potential for object %s",
757 painCave.isFatal = 1;
760 snprintf(tempBuffer, 4096,
" %13e", particlePot);
766 if (sl & DataStorage::dslDensity) {
768 RealType density = sd->getDensity();
769 if (std::isinf(density) || std::isnan(density)) {
770 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
771 "DumpWriter detected a numerical error writing the density "
774 painCave.isFatal = 1;
777 snprintf(tempBuffer, 4096,
" %13e", density);
782 snprintf(tempBuffer, 4096,
"%s %7s %s\n",
id.c_str(), type.c_str(),
784 return std::string(tempBuffer);
787 void DumpWriter::writeDump() { writeFrame(*dumpFile_); }
789 void DumpWriter::writeEor() {
790 std::ostream* eorStream = NULL;
793 if (worldRank == 0) {
796 eorStream = createOStream(eorFilename_);
802 writeFrame(*eorStream);
805 if (worldRank == 0) {
808 writeClosing(*eorStream);
816 void DumpWriter::writeDumpAndEor() {
817 std::vector<std::streambuf*> buffers;
818 std::ostream* eorStream = NULL;
820 if (worldRank == 0) {
822 buffers.push_back(dumpFile_->rdbuf());
823 eorStream = createOStream(eorFilename_);
824 buffers.push_back(eorStream->rdbuf());
829 TeeBuf tbuf(buffers.begin(), buffers.end());
830 std::ostream os(&tbuf);
834 if (worldRank == 0) {
836 writeClosing(*eorStream);
843 std::ostream* DumpWriter::createOStream(
const std::string& filename) {
844 std::ostream* newOStream;
846 if (needCompression_) {
847 newOStream =
new ogzstream(filename.c_str());
849 newOStream =
new std::ofstream(filename.c_str());
852 newOStream =
new std::ofstream(filename.c_str());
855 (*newOStream) <<
"<OpenMD version=2>" << std::endl;
856 (*newOStream) <<
" <MetaData>" << std::endl;
857 (*newOStream) << info_->getRawMetaData();
858 (*newOStream) <<
" </MetaData>" << std::endl;
862 void DumpWriter::writeClosing(std::ostream& os) {
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.