From 0a9bb6600d608f40dec8736f043dd8a69abc1497 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi <giovanni.bussi@gmail.com> Date: Thu, 20 Sep 2012 18:25:31 +0200 Subject: [PATCH] Implementation of RESTART Using a RESTART keyword in the input, files are automatically appended. When not used, files are backed up (a la gromacs). Notice that this works only when using open("file"). The rationale is that if you say open("file","a") or open("file","w") then you know what you are doing. I also removed the extra mode specifier for PlumedIFile (it was redundant: always "r"). If the behavior is not clear enough we can change it... --- src/BiasMetaD.cpp | 11 ++++------- src/GenericPrint.cpp | 2 +- src/PlumedFile.cpp | 45 +++++++++++++++++++++++++++++++++++++++++--- src/PlumedFile.h | 10 ++++++++-- src/PlumedMain.cpp | 9 +++++++-- src/PlumedMain.h | 10 ++++++++++ 6 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/BiasMetaD.cpp b/src/BiasMetaD.cpp index adec967c9..03e4b116c 100644 --- a/src/BiasMetaD.cpp +++ b/src/BiasMetaD.cpp @@ -127,7 +127,6 @@ private: int stride_; int wgridstride_; bool welltemp_; - bool restart_; bool grid_; int adaptive_; FlexibleBin *flexbin; @@ -166,7 +165,6 @@ void BiasMetaD::registerKeywords(Keywords& keys){ keys.add("compulsory","HEIGHT","the heights of the Gaussian hills"); keys.add("compulsory","PACE","the frequency for hill addition"); keys.add("compulsory","FILE","HILLS","a file in which the list of added hills is stored"); - keys.addFlag("RESTART",false,"restart the calculation from a previous metadynamics calculation."); keys.add("optional","BIASFACTOR","use well tempered metadynamics and use this biasfactor. Please note you must also specify temp"); keys.add("optional","TEMP","the system temperature - this is only needed if you are doing well-tempered metadynamics"); keys.add("optional","GRID_MIN","the lower bounds for the grid"); @@ -203,7 +201,7 @@ PLUMED_BIAS_INIT(ao), BiasGrid_(NULL), gridfile_(NULL), wgridstride_(0), grid_(false), // Metadynamics basic parameters height0_(0.0), biasf_(1.0), temp_(0.0), -stride_(0), welltemp_(false), restart_(false), +stride_(0), welltemp_(false), // Other stuff dp_(NULL), adaptive_(FlexibleBin::none), // Multiple walkers initialization @@ -243,7 +241,6 @@ mw_n_(-1), mw_dir_("./"), mw_id_(0), mw_rstride_(1) plumed_assert(stride_>0); string hillsfname="HILLS"; parse("FILE",hillsfname); - parseFlag("RESTART",restart_); parse("BIASFACTOR",biasf_); plumed_assert(biasf_>=1.0); parse("TEMP",temp_); @@ -346,19 +343,19 @@ mw_n_(-1), mw_dir_("./"), mw_id_(0), mw_rstride_(1) ifilesnames.push_back(fname); PlumedIFile *ifile = new PlumedIFile(); ifile->link(*this); - ifile->open(fname,"r"); + ifile->open(fname); ifiles.push_back(ifile); } }else{ ifilesnames.push_back(hillsfname); PlumedIFile *ifile = new PlumedIFile(); ifile->link(*this); - ifile->open(hillsfname,"r"); + ifile->open(hillsfname); ifiles.push_back(ifile); } // restarting from HILLS file - if(restart_){ + if(plumed.getRestart()){ for(unsigned i=0;i<ifilesnames.size();++i){ log.printf(" Restarting from %s:",ifilesnames[i].c_str()); readGaussians(ifiles[i]); diff --git a/src/GenericPrint.cpp b/src/GenericPrint.cpp index 009c1d8a3..9fe64214d 100644 --- a/src/GenericPrint.cpp +++ b/src/GenericPrint.cpp @@ -101,7 +101,7 @@ rotate(0) ofile.link(*this); parse("FILE",file); if(file.length()>0){ - ofile.open(file.c_str(),"wa"); + ofile.open(file.c_str()); log.printf(" on file %s\n",file.c_str()); } else { log.printf(" on plumed log file\n"); diff --git a/src/PlumedFile.cpp b/src/PlumedFile.cpp index d547767ae..b8935b91c 100644 --- a/src/PlumedFile.cpp +++ b/src/PlumedFile.cpp @@ -34,7 +34,7 @@ using namespace PLMD; void PlumedFileBase::test(){ PLMD::PlumedOFile pof; - pof.open("ciao","w"); + pof.open("ciao"); pof.printf("%s\n","test1"); pof.setLinePrefix("plumed: "); pof.printf("%s\n","test2"); @@ -48,7 +48,7 @@ void PlumedFileBase::test(){ PLMD::PlumedIFile pif; std::string s; - pif.open("ciao","r"); + pif.open("ciao"); pif.getline(s); std::printf("%s\n",s.c_str()); pif.getline(s); std::printf("%s\n",s.c_str()); @@ -87,7 +87,6 @@ PlumedFileBase& PlumedFileBase::link(FILE*fp){ PlumedFileBase& PlumedFileBase::flush(){ fflush(fp); -std::cerr<<"FLUSHING "<<path<<"\n"; if(heavyFlush){ fclose(fp); fp=std::fopen(const_cast<char*>(path.c_str()),"a"); @@ -292,6 +291,41 @@ PlumedOFile& PlumedOFile::printField(){ return *this; } +PlumedOFile& PlumedOFile::open(const std::string&path){ + plumed_assert(!cloned); + eof=false; + err=false; + fp=NULL; + this->path=path; + if(plumed && plumed->getRestart()){ + fp=std::fopen(const_cast<char*>(this->path.c_str()),"a"); + } else { + if(!comm || comm->Get_rank()==0){ + FILE* ff=std::fopen(const_cast<char*>(this->path.c_str()),"r"); + FILE* fff=NULL; + if(ff){ + std::string backup; + for(int i=0;;i++){ + std::string num; + Tools::convert(i,num); + backup="bck."+num+"."+path; + fff=std::fopen(backup.c_str(),"r"); + if(!fff) break; + } + int check=rename(path.c_str(),backup.c_str()); + plumed_massert(check==0,"renaming "+path+" into "+backup+" failed for some reason"); + } + if(ff) std::fclose(ff); + if(fff) std::fclose(fff); + } + comm->Barrier(); + fp=std::fopen(const_cast<char*>(this->path.c_str()),"w"); + } + if(plumed) plumed->insertFile(*this); + return *this; +} + + PlumedIFile& PlumedIFile::advanceField(){ plumed_assert(!inMiddleOfField); std::string line; @@ -354,6 +388,11 @@ PlumedIFile& PlumedIFile::advanceField(){ return *this; } +PlumedIFile& PlumedIFile::open(const std::string&name){ + PlumedFileBase::open(name,"r"); + return *this; +} + PlumedIFile& PlumedIFile::scanFieldList(std::vector<std::string>&s){ if(!inMiddleOfField) advanceField(); if(!*this) return *this; diff --git a/src/PlumedFile.h b/src/PlumedFile.h index 71e9a349c..5fec82886 100644 --- a/src/PlumedFile.h +++ b/src/PlumedFile.h @@ -89,8 +89,6 @@ public: PlumedFileBase& link(Action&); /// Flushes the file to disk PlumedFileBase& flush(); -/// Opens the file - PlumedFileBase& open(const std::string&name,const std::string& mode); /// Closes the file /// Should be used only for explicitely opened files. void close(); @@ -102,6 +100,8 @@ public: operator bool () const; /// Set heavyFlush flag void setHeavyFlush(){ heavyFlush=true;}; +/// Opens the file (without auto-backup) + PlumedFileBase& open(const std::string&name,const std::string& mode); }; /** @@ -195,11 +195,15 @@ public: ~PlumedOFile(); /// Allows overloading of link using PlumedFileBase::link; +/// Allows overloading of open + using PlumedFileBase::open; /// Allows linking this PlumedOFile to another one. /// In this way, everything written to this PlumedOFile will be immediately /// written on the linked PlumedOFile. Notice that a PlumedOFile should /// be either opened explicitly, linked to a FILE or linked to a PlumedOFile PlumedOFile& link(PlumedOFile&); +/// Opens the file using automatic append/backup + PlumedOFile& open(const std::string&name); /// Set the prefix for output. /// Typically "PLUMED: ". Notice that lines with a prefix cannot /// be parsed using fields in a PlumedIFile. @@ -270,6 +274,8 @@ public: PlumedIFile(); /// Destructor ~PlumedIFile(); +/// Opens the file + PlumedIFile& open(const std::string&name); /// Gets the list of all fields PlumedIFile& scanFieldList(std::vector<std::string>&); /// Read a double field diff --git a/src/PlumedMain.cpp b/src/PlumedMain.cpp index eec2949cd..4a1c34018 100644 --- a/src/PlumedMain.cpp +++ b/src/PlumedMain.cpp @@ -60,7 +60,8 @@ PlumedMain::PlumedMain(): atoms(*new Atoms(*this)), actionSet(*new ActionSet(*this)), bias(0.0), - novirial(false) + novirial(false), + restart(false) { log.link(comm); log.setLinePrefix("PLUMED: "); @@ -356,7 +357,7 @@ void PlumedMain::readInputFile(std::string str){ log.printf("FILE: %s\n",str.c_str()); PlumedIFile ifile; ifile.link(*this); - ifile.open(str,"r"); + ifile.open(str); std::vector<std::string> words; exchangepatterns.setFlag(exchangepatterns.NONE); while(Tools::getParsedLine(ifile,words)){ @@ -372,6 +373,10 @@ void PlumedMain::readInputFile(std::string str){ // I convert the seed to -seed because I think it is more general to use a positive seed in input if(words.size()>2&&words[1]=="SEED") {int seed; Tools::convert(words[2],seed); exchangepatterns.setSeed(-seed); } } + else if(words[0]=="RESTART"){ + restart=true; + log<<"Restarting simulation: files will be appended\n"; + } else if(words[0]=="INCLUDE"){ plumed_assert(words.size()==2); readInputFile(words[1]); diff --git a/src/PlumedMain.h b/src/PlumedMain.h index a795b85e3..73dacb067 100644 --- a/src/PlumedMain.h +++ b/src/PlumedMain.h @@ -122,6 +122,9 @@ private: /// Class of possible exchange patterns, used for BIASEXCHANGE but also for future parallel tempering ExchangePatterns exchangepatterns; +/// Flag for restart + bool restart; + std::set<PlumedFileBase*> files; typedef std::set<PlumedFileBase*>::iterator files_iterator; @@ -231,6 +234,8 @@ public: void eraseFile(PlumedFileBase&); /// Flush all files void fflush(); +/// Check if restarting + bool getRestart()const; }; ///// @@ -256,6 +261,11 @@ void PlumedMain::setSuffix(const std::string&s){ suffix=s; } +inline +bool PlumedMain::getRestart()const{ + return restart; +} + } #endif -- GitLab