--- trunk/src/io/RestWriter.cpp 2006/06/22 15:21:01 993 +++ trunk/src/io/RestWriter.cpp 2010/01/20 16:04:40 1407 @@ -1,24 +1,15 @@ /* - * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved. + * Copyright (c) 2009 The University of Notre Dame. All Rights Reserved. * * The University of Notre Dame grants you ("Licensee") a * non-exclusive, royalty free, license to use, modify and * redistribute this software in source and binary code form, provided * that the following conditions are met: * - * 1. Acknowledgement of the program authors must be made in any - * publication of scientific results based in part on use of the - * program. An acceptable form of acknowledgement is citation of - * the article in which the program was described (Matthew - * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher - * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented - * Parallel Simulation Engine for Molecular Dynamics," - * J. Comput. Chem. 26, pp. 252-271 (2005)) - * - * 2. Redistributions of source code must retain the above copyright + * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - * 3. Redistributions in binary form must reproduce the above copyright + * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. @@ -37,186 +28,249 @@ * arising out of the use of or inability to use software, even if the * University of Notre Dame has been advised of the possibility of * such damages. + * + * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your + * research, please cite the appropriate papers when you publish your + * work. Good starting points are: + * + * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005). + * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006). + * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008). + * [4] Vardeman & Gezelter, in progress (2009). */ + +#include +#include +#include + #include "io/RestWriter.hpp" -#include "primitives/Molecule.hpp" #include "utils/simError.h" -#include "io/basic_teebuf.hpp" - +#include "brains/SnapshotManager.hpp" #ifdef IS_MPI #include -#define TAKE_THIS_TAG_INT 1 -#define TAKE_THIS_TAG_REAL 2 -#endif //is_mpi +#endif -namespace oopse { - RestWriter::RestWriter(SimInfo* info) : - info_(info), outName_(info_->getRestFileName()) { - } - - RestWriter::~RestWriter() {} - - void RestWriter::writeZAngFile() { - std::ostream* zangStream; +namespace OpenMD { + RestWriter::RestWriter(SimInfo* info, const std::string& filename, + std::vector restraints ) : + info_(info){ + createRestFile_ = true; #ifdef IS_MPI - if (worldRank == 0) { -#endif // is_mpi - - zangStream = new std::ofstream(outName_.c_str()); - + if(worldRank == 0){ +#endif + + output_ = new std::ofstream(filename.c_str()); + + if(!output_){ + sprintf( painCave.errMsg, + "Could not open %s for restraint output.\n", + filename.c_str()); + painCave.isFatal = 1; + simError(); + } + #ifdef IS_MPI } -#endif // is_mpi - - writeZangle(*zangStream); - -#ifdef IS_MPI - if (worldRank == 0) { #endif // is_mpi - delete zangStream; - + + #ifdef IS_MPI - } -#endif // is_mpi + MPI_Status istatus; +#endif - } +#ifndef IS_MPI + + (*output_) << "#time\t"; - void RestWriter::writeZangle(std::ostream& finalOut){ - const int BUFFERSIZE = 2000; - char tempBuffer[BUFFERSIZE]; - char writeLine[BUFFERSIZE]; + std::vector::const_iterator resti; + + for(resti=restraints.begin(); resti != restraints.end(); ++resti){ + if ((*resti)->getPrintRestraint()) { + + std::string myName = (*resti)->getRestraintName(); + int myType = (*resti)->getRestraintType(); + + (*output_) << myName << ":"; + + if (myType & Restraint::rtDisplacement) + (*output_) << "\tPosition(angstroms)\tEnergy(kcal/mol)"; + + if (myType & Restraint::rtTwist) + (*output_) << "\tTwistAngle(radians)\tEnergy(kcal/mol)"; + + if (myType & Restraint::rtSwingX) + (*output_) << "\tSwingXAngle(radians)\tEnergy(kcal/mol)"; + + if (myType & Restraint::rtSwingY) + (*output_) << "\tSwingYAngle(radians)\tEnergy(kcal/mol)"; + } + } + + (*output_) << "\n"; + (*output_).flush(); - Molecule* mol; - StuntDouble* integrableObject; - SimInfo::MoleculeIterator mi; - Molecule::IntegrableObjectIterator ii; +#else -#ifndef IS_MPI - // first we do output for the single processor version - finalOut - << info_->getSnapshotManager()->getCurrentSnapshot()->getTime() - << " : omega values at this time\n"; - - for (mol = info_->beginMolecule(mi); mol != NULL; - mol = info_->nextMolecule(mi)) { - - for (integrableObject = mol->beginIntegrableObject(ii); - integrableObject != NULL; - integrableObject = mol->nextIntegrableObject(ii)) { + std::string buffer; + + std::vector::const_iterator resti; + + for(resti=restraints.begin(); resti != restraints.end(); ++resti){ + if ((*resti)->getPrintRestraint()) { - sprintf( tempBuffer, - "%14.10lf\n", - integrableObject->getZangle()); - strcpy( writeLine, tempBuffer ); - - finalOut << writeLine; + std::string myName = (*resti)->getRestraintName(); + int myType = (*resti)->getRestraintType(); + buffer += (myName + ":"); + + if (myType & Restraint::rtDisplacement) + buffer += "\tPosition(angstroms)\tEnergy(kcal/mol)"; + + if (myType & Restraint::rtTwist) + buffer += "\tTwistAngle(radians)\tEnergy(kcal/mol)"; + + if (myType & Restraint::rtSwingX) + buffer += "\tSwingXAngle(radians)\tEnergy(kcal/mol)"; + + if (myType & Restraint::rtSwingY) + buffer += "\tSwingYAngle(radians)\tEnergy(kcal/mol)"; + + buffer += "\n"; } } -#else - int nproc; - MPI_Comm_size(MPI_COMM_WORLD, &nproc); const int masterNode = 0; - MPI_Status ierr; - int intObIndex; - int vecLength; - RealType zAngle; - std::vector gIndex; - std::vector zValues; - if (worldRank == masterNode) { - std::map zAngData; - for(int i = 0 ; i < nproc; ++i) { - if (i == masterNode) { - for (mol = info_->beginMolecule(mi); mol != NULL; - mol = info_->nextMolecule(mi)) { - - for (integrableObject = mol->beginIntegrableObject(ii); - integrableObject != NULL; - integrableObject = mol->nextIntegrableObject(ii)) { - - intObIndex = integrableObject->getGlobalIndex(); - - zAngle = integrableObject->getZangle(); - zAngData.insert(std::pair(intObIndex, zAngle)); - } - } + (*output_) << "#time\t"; + (*output_) << buffer; + + int nProc; + MPI_Comm_size(MPI_COMM_WORLD, &nProc); + for (int i = 1; i < nProc; ++i) { + + // receive the length of the string buffer that was + // prepared by processor i + + int recvLength; + MPI_Recv(&recvLength, 1, MPI_INT, i, 0, MPI_COMM_WORLD, &istatus); + char* recvBuffer = new char[recvLength]; + if (recvBuffer == NULL) { } else { - MPI_Recv(&vecLength, 1, MPI_INT, i, - TAKE_THIS_TAG_INT, MPI_COMM_WORLD, &ierr); - // make sure the vectors are the right size for the incoming data - gIndex.resize(vecLength); - zValues.resize(vecLength); - - MPI_Recv(&gIndex[0], vecLength, MPI_INT, i, - TAKE_THIS_TAG_INT, MPI_COMM_WORLD, &ierr); - MPI_Recv(&zValues[0], vecLength, MPI_REALTYPE, i, - TAKE_THIS_TAG_REAL, MPI_COMM_WORLD, &ierr); - - for (int k = 0; k < vecLength; k++){ - zAngData.insert(std::pair(gIndex[k], zValues[k])); - } - gIndex.clear(); - zValues.clear(); + MPI_Recv(recvBuffer, recvLength, MPI_CHAR, i, 0, MPI_COMM_WORLD, + &istatus); + (*output_) << recvBuffer; + delete [] recvBuffer; } + } + (*output_).flush(); + } else { + int sendBufferLength = buffer.size() + 1; + MPI_Send(&sendBufferLength, 1, MPI_INT, masterNode, 0, MPI_COMM_WORLD); + MPI_Send((void *)buffer.c_str(), sendBufferLength, MPI_CHAR, masterNode, + 0, MPI_COMM_WORLD); + } + +#endif // is_mpi + + } + + void RestWriter::writeRest(std::vector > restInfo) { + +#ifdef IS_MPI + MPI_Status istatus; +#endif + +#ifndef IS_MPI + (*output_) << info_->getSnapshotManager()->getCurrentSnapshot()->getTime(); + + // output some information about the molecules + std::vector >::const_iterator i; + std::map::const_iterator j; + + for( i = restInfo.begin(); i != restInfo.end(); ++i){ + for(j = (*i).begin(); j != (*i).end(); ++j){ + (*output_) << "\t" << (j->second).first << "\t" << (j->second).second; } - - finalOut << info_->getSnapshotManager()->getCurrentSnapshot()->getTime() - << " : omega values at this time\n"; - - std::map::iterator l; - for (l = zAngData.begin(); l != zAngData.end(); ++l) { - - sprintf( tempBuffer, - "%14.10lf\n", - l->second); - strcpy( writeLine, tempBuffer ); - - finalOut << writeLine; + (*output_) << std::endl; + } + (*output_).flush(); +#else + std::string buffer, first, second; + std::stringstream ss; + + std::vector >::const_iterator i; + std::map::const_iterator j; + + for( i = restInfo.begin(); i != restInfo.end(); ++i){ + for(j = (*i).begin(); j != (*i).end(); ++j){ + ss.clear(); + ss << (j->second).first; + ss >> first; + ss.clear(); + ss << (j->second).second; + ss >> second; + buffer += ("\t" + first + "\t" + second); } + buffer += "\n"; + } + + const int masterNode = 0; + + if (worldRank == masterNode) { + (*output_) << info_->getSnapshotManager()->getCurrentSnapshot()->getTime(); + (*output_) << buffer; + int nProc; + MPI_Comm_size(MPI_COMM_WORLD, &nProc); + for (int i = 1; i < nProc; ++i) { + + // receive the length of the string buffer that was + // prepared by processor i + + int recvLength; + MPI_Recv(&recvLength, 1, MPI_INT, i, 0, MPI_COMM_WORLD, &istatus); + char* recvBuffer = new char[recvLength]; + if (recvBuffer == NULL) { + } else { + MPI_Recv(recvBuffer, recvLength, MPI_CHAR, i, 0, MPI_COMM_WORLD, + &istatus); + (*output_) << recvBuffer; + + delete [] recvBuffer; + } + } + (*output_).flush(); } else { - // pack up and send the appropriate info to the master node - for(int j = 1; j < nproc; ++j) { - if (worldRank == j) { - for (mol = info_->beginMolecule(mi); mol != NULL; - mol = info_->nextMolecule(mi)) { - - for (integrableObject = mol->beginIntegrableObject(ii); - integrableObject != NULL; - integrableObject = mol->nextIntegrableObject(ii)) { - - // build a vector of the indicies - intObIndex = integrableObject->getGlobalIndex(); - gIndex.push_back(intObIndex); - - // build a vector of the zAngle values - zAngle = integrableObject->getZangle(); - zValues.push_back(zAngle); - - } - } - - // let's send these vectors to the master node so that it - // can sort them and write to the disk - vecLength = gIndex.size(); - - MPI_Send(&vecLength, 1, MPI_INT, masterNode, - TAKE_THIS_TAG_INT, MPI_COMM_WORLD); - MPI_Send(&gIndex[0], vecLength, MPI_INT, masterNode, - TAKE_THIS_TAG_INT, MPI_COMM_WORLD); - MPI_Send(&zValues[0], vecLength, MPI_REALTYPE, masterNode, - TAKE_THIS_TAG_REAL, MPI_COMM_WORLD); - - } + int sendBufferLength = buffer.size() + 1; + MPI_Send(&sendBufferLength, 1, MPI_INT, masterNode, 0, MPI_COMM_WORLD); + MPI_Send((void *)buffer.c_str(), sendBufferLength, MPI_CHAR, masterNode, + 0, MPI_COMM_WORLD); + } +#endif // is_mpi + } + + + RestWriter::~RestWriter() { + +#ifdef IS_MPI + + if (worldRank == 0) { +#endif // is_mpi + if (createRestFile_){ + writeClosing(*output_); + delete output_; } +#ifdef IS_MPI } - -#endif +#endif // is_mpi } -} + void RestWriter::writeClosing(std::ostream& os) { + os.flush(); + } + +}// end namespace OpenMD +