diff --git a/patches/gromacs-4.5.3.diff b/patches/gromacs-4.5.3.diff index f5da3ceb6d8751301890f7d63c7652c4d1ee4268..73f1014d0cac3162566b7d92bdcd48052ab7a696 100644 --- a/patches/gromacs-4.5.3.diff +++ b/patches/gromacs-4.5.3.diff @@ -1,3 +1,83 @@ +patch -u -l -b -F 5 --suffix=.preplumed "./src/kernel/repl_ex.c" << \EOF_EOF +--- ./src/kernel/repl_ex.c.preplumed ++++ ./src/kernel/repl_ex.c +@@ -49,10 +49,16 @@ + #include "names.h" + #include "mvdata.h" + #include "domdec.h" + #include "partdec.h" + ++/* PLUMED */ ++#include "../../Plumed.h" ++extern int plumedswitch; ++extern plumed plumedmain; ++/* END PLUMED */ ++ + typedef struct gmx_repl_ex { + int repl; + int nrepl; + real temp; + int type; +@@ -538,10 +544,25 @@ + snew(bEx,re->nrepl); + snew(prob,re->nrepl); + + exchange = -1; + m = (step / re->nst) % 2; ++ ++ if(plumedswitch){ ++ int partner=re->repl; ++ ++ for(i=1; i<re->nrepl; i++) { ++ if (i % 2 != m) continue; ++ a = re->ind[i-1]; ++ b = re->ind[i]; ++ if(re->repl==a) partner=b; ++ if(re->repl==b) partner=a; ++ } ++ plumed_cmd(plumedmain,"GREX setPartner",&partner); ++ plumed_cmd(plumedmain,"GREX calculate",NULL); ++ } ++ + for(i=1; i<re->nrepl; i++) { + a = re->ind[i-1]; + b = re->ind[i]; + bPrint = (re->repl==a || re->repl==b); + if (i % 2 == m) { +@@ -572,10 +593,19 @@ + dpV = (betaA*re->pres[a]-betaB*re->pres[b])*(Vol[b]-Vol[a])/PRESFAC; + if (bPrint) + fprintf(fplog," dpV = %10.3e d = %10.3e",dpV,delta + dpV); + delta += dpV; + } ++ if(plumedswitch){ ++ real ldb,fdb,dplumed; ++ plumed_cmd(plumedmain,"GREX getLocalDeltaBias",&ldb); ++ plumed_cmd(plumedmain,"GREX getForeignDeltaBias",&fdb); ++ dplumed=ldb*betaA+fdb*betaB; ++ delta+=dplumed; ++ if (bPrint) ++ fprintf(fplog," dplumed = %10.3e d = %10.3e",dplumed,delta); ++ } + if (bPrint) + fprintf(fplog,"\n"); + if (delta <= 0) { + prob[i] = 1; + bEx[i] = TRUE; +@@ -633,10 +663,12 @@ + gmx_multisim_t *ms; + int exchange=-1,shift; + gmx_bool bExchanged=FALSE; + + ms = cr->ms; ++ ++ if(plumedswitch)plumed_cmd(plumedmain,"GREX prepare",NULL); + + if (MASTER(cr)) + { + exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box), + step,time); +EOF_EOF patch -u -l -b -F 5 --suffix=.preplumed "./src/kernel/Makefile" << \EOF_EOF --- ./src/kernel/Makefile.preplumed +++ ./src/kernel/Makefile @@ -47,7 +127,46 @@ patch -u -l -b -F 5 --suffix=.preplumed "./src/kernel/md.c" << \EOF_EOF #endif #ifdef GMX_THREADS #include "tmpi.h" -@@ -1522,10 +1528,41 @@ +@@ -1375,13 +1381,37 @@ + for(i=0; (i<gnx); i++) { + grpindex[i] = i; + } + } + +- if (repl_ex_nst > 0 && MASTER(cr)) ++ if (repl_ex_nst > 0 && MASTER(cr)){ + repl_ex = init_replica_exchange(fplog,cr->ms,state_global,ir, + repl_ex_nst,repl_ex_seed); ++ if(plumedswitch) { ++ plumed_cmd(plumedmain,"GREX setMPIIntercomm",&cr->ms->mpi_comm_masters); ++ if(PAR(cr)){ ++ if(DOMAINDECOMP(cr)) { ++ plumed_cmd(plumedmain,"GREX setMPIIntracomm",&cr->dd->mpi_comm_all); ++ }else{ ++ plumed_cmd(plumedmain,"GREX setMPIIntracomm",&cr->mpi_comm_mysim); ++ } ++ } ++ plumed_cmd(plumedmain,"GREX init",NULL); ++ } ++ } ++ ++ if (repl_ex_nst>0 && plumedswitch && ! MASTER(cr)){ ++ if(PAR(cr)){ ++ if(DOMAINDECOMP(cr)) { ++ plumed_cmd(plumedmain,"GREX setMPIIntracomm",&cr->dd->mpi_comm_all); ++ }else{ ++ plumed_cmd(plumedmain,"GREX setMPIIntracomm",&cr->mpi_comm_mysim); ++ } ++ } ++ plumed_cmd(plumedmain,"GREX init",NULL); ++ } ++ + + if (!ir->bContinuation && !bRerunMD) + { + if (mdatoms->cFREEZE && (state->flags & (1<<estV))) + { +@@ -1522,10 +1552,41 @@ } } fprintf(fplog,"\n"); @@ -89,7 +208,7 @@ patch -u -l -b -F 5 --suffix=.preplumed "./src/kernel/md.c" << \EOF_EOF print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime); wallcycle_start(wcycle,ewcRUN); if (fplog) -@@ -1802,10 +1839,17 @@ +@@ -1802,10 +1863,17 @@ state,&f,mdatoms,top,fr, vsite,shellfc,constr, nrnb,wcycle,do_verbose); @@ -107,7 +226,7 @@ patch -u -l -b -F 5 --suffix=.preplumed "./src/kernel/md.c" << \EOF_EOF if (MASTER(cr) && do_log && !bFFscan) { -@@ -1928,16 +1972,37 @@ +@@ -1928,16 +1996,40 @@ * in do_force. * This is parallellized as well, and does communication too. * Check comments in sim_util.c @@ -121,6 +240,7 @@ patch -u -l -b -F 5 --suffix=.preplumed "./src/kernel/md.c" << \EOF_EOF + plumed_cmd(plumedmain,"setMasses",&mdatoms->massT[mdatoms->start]); + plumed_cmd(plumedmain,"setCharges",&mdatoms->chargeA[mdatoms->start]); + plumed_cmd(plumedmain,"setBox",&state->box[0][0]); ++ + plumed_cmd(plumedmain,"prepareCalc",NULL); + } + /* END PLUMED */ @@ -137,6 +257,8 @@ patch -u -l -b -F 5 --suffix=.preplumed "./src/kernel/md.c" << \EOF_EOF + plumed_cmd(plumedmain,"setForces",&f[mdatoms->start][0]); + plumed_cmd(plumedmain,"setVirial",&force_vir[0][0]); + plumed_cmd(plumedmain,"performCalc",NULL); ++ if ((repl_ex_nst > 0) && (step > 0) && !bLastStep && ++ do_per_step(step,repl_ex_nst)) plumed_cmd(plumedmain,"GREX savePositions",NULL); + } + /* END PLUMED */ + diff --git a/src/GREX.cpp b/src/GREX.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9536ef7b7f1615f5be8c8385fc7a028067ecc33d --- /dev/null +++ b/src/GREX.cpp @@ -0,0 +1,105 @@ +#include "GREX.h" +#include "sstream" +#include "PlumedMain.h" + +using namespace std; +using namespace PLMD; + +GREX::GREX(PlumedMain&p): + initialized(false), + plumedMain(p), + atoms(p.getAtoms()), + partner(-1), // = unset + myreplica(-1) // = unset +{ + p.setSuffix(".NA"); +} + +GREX::~GREX(){ +} + +void GREX::cmd(const string&key,void*val){ + if(false){ + }else if(key=="initialized"){ + *static_cast<int*>(val)=initialized; + }else if(key=="setMPIIntracomm"){ + assert(!initialized); + intracomm.Set_comm(val); + }else if(key=="setMPIIntercomm"){ + assert(!initialized); + intercomm.Set_comm(val); + }else if(key=="init"){ + assert(!initialized); + initialized=true; + std::string s; +// note that for PEs!=root this is automatically 0 (comm defaults to MPI_COMM_SELF) + myreplica=intercomm.Get_rank(); + intracomm.Sum(&myreplica,1); + Tools::convert(myreplica,s); + plumedMain.setSuffix("."+s); + }else if(key=="prepare"){ + assert(initialized); + if(intracomm.Get_rank()==0) return; + intracomm.Bcast(&partner,1,0); + calculate(); + }else if(key=="setPartner"){ + assert(initialized); + partner=*static_cast<int*>(val); + }else if(key=="savePositions"){ + assert(initialized); + savePositions(); + }else if(key=="calculate"){ + assert(initialized); + if(intracomm.Get_rank()!=0) return; + intracomm.Bcast(&partner,1,0); + calculate(); + }else if(key=="getLocalDeltaBias"){ + assert(initialized); + double x=localDeltaBias/(atoms.getMDUnits().energy/atoms.getUnits().energy); + atoms.double2MD(x,val); + }else if(key=="getForeignDeltaBias"){ + assert(initialized); + double x=foreignDeltaBias/(atoms.getMDUnits().energy/atoms.getUnits().energy); + atoms.double2MD(x,val); + } else { + fprintf(stderr,"+++ PLUMED GREX ERROR\n"); + fprintf(stderr,"+++ CANNOT INTERPRET CALL TO cmd() ROUTINE WITH ARG %s\n",key.c_str()); + fprintf(stderr,"+++ There might be a mistake in the MD code\n"); + fprintf(stderr,"+++ or you may be using an out-dated plumed version\n"); + assert(0); + } +} + +void GREX::savePositions(){ + plumedMain.prepareDependencies(); + atoms.shareAll(); + plumedMain.waitData(); + ostringstream o; + atoms.writeBinary(o); + buffer=o.str(); +} + +void GREX::calculate(){ +//fprintf(stderr,"CALCULATE %d %d\n",intercomm.Get_rank(),partner); + unsigned nn=buffer.size(); + vector<char> rbuf(nn); + localDeltaBias=-plumedMain.getBias(); + if(intracomm.Get_rank()==0){ + PlumedCommunicator::Request req=intercomm.Isend(&buffer.c_str()[0],nn,partner,1066); + intercomm.Recv(&rbuf[0],rbuf.size(),partner,1066); + req.wait(); + } + intracomm.Bcast(&rbuf[0],nn,0); + istringstream i(string(&rbuf[0],rbuf.size())); + atoms.readBinary(i); + plumedMain.prepareDependencies(); + plumedMain.justCalculate(); + localDeltaBias+=plumedMain.getBias(); + if(intracomm.Get_rank()==0){ + PlumedCommunicator::Request req=intercomm.Isend(&localDeltaBias,1,partner,1067); + intercomm.Recv(&foreignDeltaBias,1,partner,1067); + req.wait(); +//fprintf(stderr,">>> %d %d %20.12f %20.12f\n",intercomm.Get_rank(),partner,localDeltaBias,foreignDeltaBias); + } + intracomm.Bcast(&foreignDeltaBias,1,0); +} diff --git a/src/GREX.h b/src/GREX.h new file mode 100644 index 0000000000000000000000000000000000000000..a240029be39272d8434178f88d8dbc1a6dc13506 --- /dev/null +++ b/src/GREX.h @@ -0,0 +1,36 @@ +#ifndef __PLUMED_Grex_h +#define __PLUMED_Grex_h + +#include "WithCmd.h" +#include "PlumedCommunicator.h" +#include <string> + +namespace PLMD{ + +class PlumedMain; +class Atoms; + +class GREX: + public WithCmd +{ + bool initialized; + PlumedCommunicator intracomm; + PlumedCommunicator intercomm; + PlumedMain& plumedMain; + Atoms& atoms; + int partner; + double localDeltaBias; + double foreignDeltaBias; + std::string buffer; + int myreplica; +public: + GREX(PlumedMain&); + ~GREX(); + void cmd(const std::string&key,void*val=NULL); + void calculate(); + void savePositions(); +}; + +} + +#endif diff --git a/src/PlumedMain.cpp b/src/PlumedMain.cpp index 2fa4350c190fe1cd20af5666635c062f4a934177..c944c753cf199e4031667e75cfc95ff6cc2b6f03 100644 --- a/src/PlumedMain.cpp +++ b/src/PlumedMain.cpp @@ -14,6 +14,8 @@ #include "ActionRegister.h" +#include "GREX.h" + using namespace PLMD; using namespace std; @@ -265,6 +267,7 @@ void PlumedMain::cmd(const std::string & word,void*val){ if(actionRegister().check(words[1])) check=1; *(static_cast<int*>(val))=check; } else if(nw==2 && words[0]=="GREX"){ + if(!grex) grex=new GREX(*this); assert(grex); grex->cmd(words[1],val); } else{