45#include "io/DumpWriter.hpp"
53#include "io/Globals.hpp"
54#include "io/basic_teebuf.hpp"
56#include "utils/simError.h"
58#include "io/gzstream.hpp"
64 DumpWriter::DumpWriter(SimInfo* info) :
65 info_(info), filename_(info->getDumpFileName()),
66 eorFilename_(info->getFinalConfigFileName()) {
67 Globals* simParams = info->getSimParams();
68 needCompression_ = simParams->getCompressDumpFile();
69 needForceVector_ = simParams->getOutputForceVector();
70 needParticlePot_ = simParams->getOutputParticlePotential();
71 needFlucQ_ = simParams->getOutputFluctuatingCharges();
72 needElectricField_ = simParams->getOutputElectricField();
73 needSitePotential_ = simParams->getOutputSitePotential();
74 needDensity_ = simParams->getOutputDensity();
76 if (needParticlePot_ || needFlucQ_ || needElectricField_ ||
77 needSitePotential_ || needDensity_) {
83 createDumpFile_ =
true;
85 if (needCompression_) {
87 eorFilename_ +=
".gz";
96 dumpFile_ = createOStream(filename_);
99 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
100 "Could not open \"%s\" for dump output.\n", filename_.c_str());
101 painCave.isFatal = 1;
111 DumpWriter::DumpWriter(SimInfo* info,
const std::string& filename) :
112 info_(info), filename_(filename) {
113 Globals* simParams = info->getSimParams();
114 eorFilename_ = filename_.substr(0, filename_.rfind(
".")) +
".eor";
116 needCompression_ = simParams->getCompressDumpFile();
117 needForceVector_ = simParams->getOutputForceVector();
118 needParticlePot_ = simParams->getOutputParticlePotential();
119 needFlucQ_ = simParams->getOutputFluctuatingCharges();
120 needElectricField_ = simParams->getOutputElectricField();
121 needSitePotential_ = simParams->getOutputSitePotential();
122 needDensity_ = simParams->getOutputDensity();
124 if (needParticlePot_ || needFlucQ_ || needElectricField_ ||
125 needSitePotential_ || needDensity_) {
131 createDumpFile_ =
true;
133 if (needCompression_) {
135 eorFilename_ +=
".gz";
141 if (worldRank == 0) {
144 dumpFile_ = createOStream(filename_);
147 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
148 "Could not open \"%s\" for dump output.\n", filename_.c_str());
149 painCave.isFatal = 1;
159 DumpWriter::DumpWriter(SimInfo* info,
const std::string& filename,
160 bool writeDumpFile) :
162 filename_(filename) {
163 Globals* simParams = info->getSimParams();
164 eorFilename_ = filename_.substr(0, filename_.rfind(
".")) +
".eor";
166 needCompression_ = simParams->getCompressDumpFile();
167 needForceVector_ = simParams->getOutputForceVector();
168 needParticlePot_ = simParams->getOutputParticlePotential();
169 needFlucQ_ = simParams->getOutputFluctuatingCharges();
170 needElectricField_ = simParams->getOutputElectricField();
171 needSitePotential_ = simParams->getOutputSitePotential();
172 needDensity_ = simParams->getOutputDensity();
174 if (needParticlePot_ || needFlucQ_ || needElectricField_ ||
175 needSitePotential_ || needDensity_) {
182 if (needCompression_) {
184 eorFilename_ +=
".gz";
190 if (worldRank == 0) {
193 createDumpFile_ = writeDumpFile;
194 if (createDumpFile_) {
195 dumpFile_ = createOStream(filename_);
198 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
199 "Could not open \"%s\" for dump output.\n",
201 painCave.isFatal = 1;
211 DumpWriter::~DumpWriter() {
214 if (worldRank == 0) {
216 if (createDumpFile_) {
217 writeClosing(*dumpFile_);
226 void DumpWriter::writeFrameProperties(std::ostream& os, Snapshot* s) {
229 os <<
" <FrameData>\n";
231 RealType currentTime = s->getTime();
233 if (std::isinf(currentTime) || std::isnan(currentTime)) {
234 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
235 "DumpWriter detected a numerical error writing the time");
236 painCave.isFatal = 1;
240 snprintf(buffer, 1024,
" Time: %.10g\n", currentTime);
246 for (
unsigned int i = 0; i < 3; i++) {
247 for (
unsigned int j = 0; j < 3; j++) {
248 if (std::isinf(hmat(i, j)) || std::isnan(hmat(i, j))) {
249 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
250 "DumpWriter detected a numerical error writing the box");
251 painCave.isFatal = 1;
259 " Hmat: {{ %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }, { "
262 hmat(0, 0), hmat(1, 0), hmat(2, 0), hmat(0, 1), hmat(1, 1), hmat(2, 1),
263 hmat(0, 2), hmat(1, 2), hmat(2, 2));
266 pair<RealType, RealType> thermostat = s->getThermostat();
268 if (std::isinf(thermostat.first) || std::isnan(thermostat.first) ||
269 std::isinf(thermostat.second) || std::isnan(thermostat.second)) {
270 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
271 "DumpWriter detected a numerical error writing the thermostat");
272 painCave.isFatal = 1;
275 snprintf(buffer, 1024,
" Thermostat: %.10g , %.10g\n", thermostat.first,
280 eta = s->getBarostat();
282 for (
unsigned int i = 0; i < 3; i++) {
283 for (
unsigned int j = 0; j < 3; j++) {
284 if (std::isinf(eta(i, j)) || std::isnan(eta(i, j))) {
286 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
287 "DumpWriter detected a numerical error writing the barostat");
288 painCave.isFatal = 1;
296 " Barostat: {{ %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }, { "
299 eta(0, 0), eta(1, 0), eta(2, 0), eta(0, 1), eta(1, 1), eta(2, 1),
300 eta(0, 2), eta(1, 2), eta(2, 2));
304 std::shared_ptr<SPFData> spfData = s->getSPFData();
306 if (std::isinf(spfData->pos[0]) || std::isnan(spfData->pos[0]) ||
307 std::isinf(spfData->pos[1]) || std::isnan(spfData->pos[1]) ||
308 std::isinf(spfData->pos[2]) || std::isnan(spfData->pos[2]) ||
309 std::isinf(spfData->lambda) || std::isnan(spfData->lambda) ||
310 std::isinf(spfData->globalID) || std::isnan(spfData->globalID)) {
311 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
312 "DumpWriter detected a numerical error writing the spf data "
314 painCave.isFatal = 1;
317 snprintf(buffer, 1024,
318 " SPFData: {{ %.10g, %.10g, %.10g }, %.10g, %d }\n",
319 spfData->pos[0], spfData->pos[1], spfData->pos[2], spfData->lambda,
323 os <<
" </FrameData>\n";
326 void DumpWriter::writeFrame(std::ostream& os) {
333 SimInfo::MoleculeIterator mi;
334 Molecule::IntegrableObjectIterator ii;
335 RigidBody::AtomIterator ai;
338 os <<
" <Snapshot>\n";
340 writeFrameProperties(os, info_->getSnapshotManager()->getCurrentSnapshot());
342 os <<
" <StuntDoubles>\n";
343 for (mol = info_->beginMolecule(mi); mol != NULL;
344 mol = info_->nextMolecule(mi)) {
345 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
346 sd = mol->nextIntegrableObject(ii)) {
347 os << prepareDumpLine(sd);
350 os <<
" </StuntDoubles>\n";
353 os <<
" <SiteData>\n";
354 for (mol = info_->beginMolecule(mi); mol != NULL;
355 mol = info_->nextMolecule(mi)) {
356 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
357 sd = mol->nextIntegrableObject(ii)) {
358 int ioIndex = sd->getGlobalIntegrableObjectIndex();
360 os << prepareSiteLine(sd, ioIndex, 0);
362 if (sd->isRigidBody()) {
363 RigidBody* rb =
static_cast<RigidBody*
>(sd);
365 for (Atom* atom = rb->beginAtom(ai); atom != NULL;
366 atom = rb->nextAtom(ai)) {
367 os << prepareSiteLine(atom, ioIndex, siteIndex);
373 os <<
" </SiteData>\n";
375 os <<
" </Snapshot>\n";
378 os.rdbuf()->pubsync();
381 const int primaryNode = 0;
385 MPI_Comm_size(MPI_COMM_WORLD, &nProc);
386 MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
388 if (worldRank == primaryNode) {
389 os <<
" <Snapshot>\n";
390 writeFrameProperties(os,
391 info_->getSnapshotManager()->getCurrentSnapshot());
392 os <<
" <StuntDoubles>\n";
398 for (mol = info_->beginMolecule(mi); mol != NULL;
399 mol = info_->nextMolecule(mi)) {
400 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
401 sd = mol->nextIntegrableObject(ii)) {
402 buffer += prepareDumpLine(sd);
406 if (worldRank == primaryNode) {
409 for (
int i = 1; i < nProc; ++i) {
412 MPI_Bcast(&i, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
417 MPI_Recv(&recvLength, 1, MPI_INT, i, MPI_ANY_TAG, MPI_COMM_WORLD,
421 char* recvBuffer =
new char[recvLength];
422 if (recvBuffer == NULL) {
425 MPI_Recv(recvBuffer, recvLength, MPI_CHAR, i, MPI_ANY_TAG,
426 MPI_COMM_WORLD, &istatus);
434 int sendBufferLength = buffer.size() + 1;
436 for (
int i = 1; i < nProc; ++i) {
438 MPI_Bcast(&myturn, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
439 if (myturn == worldRank) {
442 MPI_Send(&sendBufferLength, 1, MPI_INT, primaryNode, 0,
446 MPI_Send((
void*)buffer.c_str(), sendBufferLength, MPI_CHAR,
447 primaryNode, 0, MPI_COMM_WORLD);
452 if (worldRank == primaryNode) { os <<
" </StuntDoubles>\n"; }
455 if (worldRank == primaryNode) { os <<
" <SiteData>\n"; }
457 for (mol = info_->beginMolecule(mi); mol != NULL;
458 mol = info_->nextMolecule(mi)) {
459 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
460 sd = mol->nextIntegrableObject(ii)) {
461 int ioIndex = sd->getGlobalIntegrableObjectIndex();
463 buffer += prepareSiteLine(sd, ioIndex, 0);
465 if (sd->isRigidBody()) {
466 RigidBody* rb =
static_cast<RigidBody*
>(sd);
468 for (Atom* atom = rb->beginAtom(ai); atom != NULL;
469 atom = rb->nextAtom(ai)) {
470 buffer += prepareSiteLine(atom, ioIndex, siteIndex);
477 if (worldRank == primaryNode) {
480 for (
int i = 1; i < nProc; ++i) {
482 MPI_Bcast(&i, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
487 MPI_Recv(&recvLength, 1, MPI_INT, i, MPI_ANY_TAG, MPI_COMM_WORLD,
491 char* recvBuffer =
new char[recvLength];
492 if (recvBuffer == NULL) {
495 MPI_Recv(recvBuffer, recvLength, MPI_CHAR, i, MPI_ANY_TAG,
496 MPI_COMM_WORLD, &istatus);
504 int sendBufferLength = buffer.size() + 1;
506 for (
int i = 1; i < nProc; ++i) {
508 MPI_Bcast(&myturn, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
509 if (myturn == worldRank) {
511 MPI_Send(&sendBufferLength, 1, MPI_INT, primaryNode, 0,
514 MPI_Send((
void*)buffer.c_str(), sendBufferLength, MPI_CHAR,
515 primaryNode, 0, MPI_COMM_WORLD);
520 if (worldRank == primaryNode) { os <<
" </SiteData>\n"; }
523 if (worldRank == primaryNode) {
524 os <<
" </Snapshot>\n";
526 os.rdbuf()->pubsync();
532 std::string DumpWriter::prepareDumpLine(StuntDouble* sd) {
533 int index = sd->getGlobalIntegrableObjectIndex();
534 std::string type(
"pv");
536 char tempBuffer[4096];
542 if (std::isinf(pos[0]) || std::isnan(pos[0]) || std::isinf(pos[1]) ||
543 std::isnan(pos[1]) || std::isinf(pos[2]) || std::isnan(pos[2])) {
544 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
545 "DumpWriter detected a numerical error writing the position"
548 painCave.isFatal = 1;
554 if (std::isinf(vel[0]) || std::isnan(vel[0]) || std::isinf(vel[1]) ||
555 std::isnan(vel[1]) || std::isinf(vel[2]) || std::isnan(vel[2])) {
556 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
557 "DumpWriter detected a numerical error writing the velocity"
560 painCave.isFatal = 1;
564 snprintf(tempBuffer, 4096,
"%18.10g %18.10g %18.10g %13e %13e %13e", pos[0],
565 pos[1], pos[2], vel[0], vel[1], vel[2]);
568 if (sd->isDirectional()) {
574 if (std::isinf(q[0]) || std::isnan(q[0]) || std::isinf(q[1]) ||
575 std::isnan(q[1]) || std::isinf(q[2]) || std::isnan(q[2]) ||
576 std::isinf(q[3]) || std::isnan(q[3])) {
577 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
578 "DumpWriter detected a numerical error writing the quaternion"
581 painCave.isFatal = 1;
587 if (std::isinf(ji[0]) || std::isnan(ji[0]) || std::isinf(ji[1]) ||
588 std::isnan(ji[1]) || std::isinf(ji[2]) || std::isnan(ji[2])) {
589 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
590 "DumpWriter detected a numerical error writing the angular"
591 " momentum for object %d",
593 painCave.isFatal = 1;
597 snprintf(tempBuffer, 4096,
" %13e %13e %13e %13e %13e %13e %13e", q[0],
598 q[1], q[2], q[3], ji[0], ji[1], ji[2]);
602 if (needForceVector_) {
604 Vector3d frc = sd->getFrc();
605 if (std::isinf(frc[0]) || std::isnan(frc[0]) || std::isinf(frc[1]) ||
606 std::isnan(frc[1]) || std::isinf(frc[2]) || std::isnan(frc[2])) {
607 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
608 "DumpWriter detected a numerical error writing the force"
611 painCave.isFatal = 1;
614 snprintf(tempBuffer, 4096,
" %13e %13e %13e", frc[0], frc[1], frc[2]);
617 if (sd->isDirectional()) {
619 Vector3d trq = sd->getTrq();
620 if (std::isinf(trq[0]) || std::isnan(trq[0]) || std::isinf(trq[1]) ||
621 std::isnan(trq[1]) || std::isinf(trq[2]) || std::isnan(trq[2])) {
622 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
623 "DumpWriter detected a numerical error writing the torque"
626 painCave.isFatal = 1;
629 snprintf(tempBuffer, 4096,
" %13e %13e %13e", trq[0], trq[1], trq[2]);
634 snprintf(tempBuffer, 4096,
"%10d %7s %s\n", index, type.c_str(),
636 return std::string(tempBuffer);
639 std::string DumpWriter::prepareSiteLine(StuntDouble* sd,
int ioIndex,
641 int asl = info_->getSnapshotManager()->getAtomStorageLayout();
642 int rbsl = info_->getSnapshotManager()->getRigidBodyStorageLayout();
648 char tempBuffer[4096];
650 if (sd->isRigidBody()) {
652 snprintf(tempBuffer, 4096,
"%10d ", ioIndex);
653 id = std::string(tempBuffer);
656 snprintf(tempBuffer, 4096,
"%10d %10d", ioIndex, siteIndex);
657 id = std::string(tempBuffer);
661 if (sl & DataStorage::dslFlucQPosition) {
663 RealType fqPos = sd->getFlucQPos();
664 if (std::isinf(fqPos) || std::isnan(fqPos)) {
665 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
666 "DumpWriter detected a numerical error writing the"
667 " fluctuating charge for object %s",
669 painCave.isFatal = 1;
672 snprintf(tempBuffer, 4096,
" %13e ", fqPos);
676 if (sl & DataStorage::dslFlucQVelocity) {
678 RealType fqVel = sd->getFlucQVel();
679 if (std::isinf(fqVel) || std::isnan(fqVel)) {
680 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
681 "DumpWriter detected a numerical error writing the"
682 " fluctuating charge velocity for object %s",
684 painCave.isFatal = 1;
687 snprintf(tempBuffer, 4096,
" %13e ", fqVel);
691 if (needForceVector_) {
692 if (sl & DataStorage::dslFlucQForce) {
694 RealType fqFrc = sd->getFlucQFrc();
695 if (std::isinf(fqFrc) || std::isnan(fqFrc)) {
696 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
697 "DumpWriter detected a numerical error writing the"
698 " fluctuating charge force for object %s",
700 painCave.isFatal = 1;
703 snprintf(tempBuffer, 4096,
" %13e ", fqFrc);
709 if (needElectricField_) {
710 if (sl & DataStorage::dslElectricField) {
712 Vector3d eField = sd->getElectricField();
713 if (std::isinf(eField[0]) || std::isnan(eField[0]) ||
714 std::isinf(eField[1]) || std::isnan(eField[1]) ||
715 std::isinf(eField[2]) || std::isnan(eField[2])) {
716 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
717 "DumpWriter detected a numerical error writing the electric"
718 " field for object %s",
720 painCave.isFatal = 1;
723 snprintf(tempBuffer, 4096,
" %13e %13e %13e", eField[0], eField[1],
729 if (needSitePotential_) {
730 if (sl & DataStorage::dslSitePotential) {
732 RealType sPot = sd->getSitePotential();
733 if (std::isinf(sPot) || std::isnan(sPot)) {
734 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
735 "DumpWriter detected a numerical error writing the"
736 " site potential for object %s",
738 painCave.isFatal = 1;
741 snprintf(tempBuffer, 4096,
" %13e ", sPot);
746 if (needParticlePot_) {
747 if (sl & DataStorage::dslParticlePot) {
749 RealType particlePot = sd->getParticlePot();
750 if (std::isinf(particlePot) || std::isnan(particlePot)) {
751 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
752 "DumpWriter detected a numerical error writing the particle "
753 " potential for object %s",
755 painCave.isFatal = 1;
758 snprintf(tempBuffer, 4096,
" %13e", particlePot);
764 if (sl & DataStorage::dslDensity) {
766 RealType density = sd->getDensity();
767 if (std::isinf(density) || std::isnan(density)) {
768 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
769 "DumpWriter detected a numerical error writing the density "
772 painCave.isFatal = 1;
775 snprintf(tempBuffer, 4096,
" %13e", density);
780 snprintf(tempBuffer, 4096,
"%s %7s %s\n",
id.c_str(), type.c_str(),
782 return std::string(tempBuffer);
785 void DumpWriter::writeDump() { writeFrame(*dumpFile_); }
787 void DumpWriter::writeEor() {
788 std::ostream* eorStream = NULL;
791 if (worldRank == 0) {
794 eorStream = createOStream(eorFilename_);
800 writeFrame(*eorStream);
803 if (worldRank == 0) {
806 writeClosing(*eorStream);
814 void DumpWriter::writeDumpAndEor() {
815 std::vector<std::streambuf*> buffers;
816 std::ostream* eorStream = NULL;
818 if (worldRank == 0) {
820 buffers.push_back(dumpFile_->rdbuf());
821 eorStream = createOStream(eorFilename_);
822 buffers.push_back(eorStream->rdbuf());
827 TeeBuf tbuf(buffers.begin(), buffers.end());
828 std::ostream os(&tbuf);
832 if (worldRank == 0) {
834 writeClosing(*eorStream);
841 std::ostream* DumpWriter::createOStream(
const std::string& filename) {
842 std::ostream* newOStream;
844 if (needCompression_) {
845 newOStream =
new ogzstream(filename.c_str());
847 newOStream =
new std::ofstream(filename.c_str());
850 newOStream =
new std::ofstream(filename.c_str());
853 (*newOStream) <<
"<OpenMD version=2>" << std::endl;
854 (*newOStream) <<
" <MetaData>" << std::endl;
855 (*newOStream) << info_->getRawMetaData();
856 (*newOStream) <<
" </MetaData>" << std::endl;
860 void DumpWriter::writeClosing(std::ostream& os) {
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.