--- trunk/src/io/RestWriter.cpp 2009/11/25 20:02:06 1390 +++ branches/development/src/io/RestWriter.cpp 2012/09/13 14:10:11 1798 @@ -36,10 +36,13 @@ * [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). + * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010). + * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011). */ +#include +#include #include #include "io/RestWriter.hpp" @@ -53,14 +56,14 @@ namespace OpenMD { RestWriter::RestWriter(SimInfo* info, const std::string& filename, std::vector restraints ) : info_(info){ - - //use master - slave mode, only master node writes to disk + createRestFile_ = true; + #ifdef IS_MPI if(worldRank == 0){ #endif - - output_.open(filename.c_str()); - + + output_ = new std::ofstream(filename.c_str()); + if(!output_){ sprintf( painCave.errMsg, "Could not open %s for restraint output.\n", @@ -69,63 +72,205 @@ namespace OpenMD { simError(); } - output_ << "#time\t"; - - // TODO: get Restraint info from slave nodes: - std::vector::const_iterator resti; - for(resti=restraints.begin(); resti != restraints.end(); ++resti){ +#ifdef IS_MPI + } +#endif // is_mpi - if ((*resti)->getPrintRestraint()) { - std::string myName = (*resti)->getRestraintName(); - int myType = (*resti)->getRestraintType(); + +#ifdef IS_MPI + MPI::Status istatus; +#endif + +#ifndef IS_MPI + + (*output_) << "#time\t"; + + 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)"; - 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)"; - - } + if (myType & Restraint::rtSwingY) + (*output_) << "\tSwingYAngle(radians)\tEnergy(kcal/mol)"; } - output_ << "\n"; -#ifdef IS_MPI } -#endif - } + + (*output_) << "\n"; + (*output_).flush(); + +#else + + std::string buffer; + + 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(); + + 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"; + } + } + + const int masterNode = 0; + + if (worldRank == masterNode) { + (*output_) << "#time\t"; + (*output_) << buffer; + + int nProc = MPI::COMM_WORLD.Get_size(); + for (int i = 1; i < nProc; ++i) { + + // receive the length of the string buffer that was + // prepared by processor i + + int recvLength; + MPI::COMM_WORLD.Recv(&recvLength, 1, MPI::INT, i, 0, istatus); + char* recvBuffer = new char[recvLength]; + if (recvBuffer == NULL) { + } else { + MPI::COMM_WORLD.Recv(recvBuffer, recvLength, MPI::CHAR, i, 0, + istatus); + (*output_) << recvBuffer; + delete [] recvBuffer; + } + } + (*output_).flush(); + } else { + int sendBufferLength = buffer.size() + 1; + MPI::COMM_WORLD.Send(&sendBufferLength, 1, MPI::INT, masterNode, 0); + MPI::COMM_WORLD.Send((void *)buffer.c_str(), sendBufferLength, MPI::CHAR, + masterNode, 0); + } + +#endif // is_mpi + + } - RestWriter::~RestWriter() { + void RestWriter::writeRest(std::vector > restInfo) { + #ifdef IS_MPI - if(worldRank == 0 ){ -#endif - output_.close(); -#ifdef IS_MPI - } + MPI::Status istatus; #endif - } - - void RestWriter::writeRest(std::vector > restInfo){ - - output_ << info_->getSnapshotManager()->getCurrentSnapshot()->getTime(); - +#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; + (*output_) << "\t" << (j->second).first << "\t" << (j->second).second; } - output_ << std::endl; + (*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; + nProc = MPI::COMM_WORLD.Get_size(); + for (int i = 1; i < nProc; ++i) { + + // receive the length of the string buffer that was + // prepared by processor i + + int recvLength; + MPI::COMM_WORLD.Recv(&recvLength, 1, MPI::INT, i, 0, istatus); + char* recvBuffer = new char[recvLength]; + if (recvBuffer == NULL) { + } else { + MPI::COMM_WORLD.Recv(recvBuffer, recvLength, MPI::CHAR, i, 0, + istatus); + (*output_) << recvBuffer; + + delete [] recvBuffer; + } + } + (*output_).flush(); + } else { + int sendBufferLength = buffer.size() + 1; + MPI::COMM_WORLD.Send(&sendBufferLength, 1, MPI::INT, masterNode, 0); + MPI::COMM_WORLD.Send((void *)buffer.c_str(), sendBufferLength, + MPI::CHAR, masterNode, 0); + } +#endif // is_mpi } -}// end namespace OpenMD + RestWriter::~RestWriter() { + +#ifdef IS_MPI + + if (worldRank == 0) { +#endif // is_mpi + if (createRestFile_){ + writeClosing(*output_); + delete output_; + } +#ifdef IS_MPI + } +#endif // is_mpi + } + + void RestWriter::writeClosing(std::ostream& os) { + os.flush(); + } + +}// end namespace OpenMD +