From 253e263c6541099696117f0997ece060fe7c8e43 Mon Sep 17 00:00:00 2001 From: Jana Pazurikova <pazurikova@ics.muni.cz> Date: Thu, 14 Sep 2017 15:36:18 +0200 Subject: [PATCH] Close structure - modify PathMSDBase --- src/colvar/PathMSDBase.cpp | 113 +++++++++++++++++++++++++++++++++++-- src/colvar/PathMSDBase.h | 13 +++++ 2 files changed, 120 insertions(+), 6 deletions(-) diff --git a/src/colvar/PathMSDBase.cpp b/src/colvar/PathMSDBase.cpp index 69f1aecf4..f908ae4a4 100644 --- a/src/colvar/PathMSDBase.cpp +++ b/src/colvar/PathMSDBase.cpp @@ -41,18 +41,27 @@ void PathMSDBase::registerKeywords(Keywords& keys){ keys.add("compulsory","REFERENCE","the pdb is needed to provide the various milestones"); keys.add("optional","NEIGH_SIZE","size of the neighbor list"); keys.add("optional","NEIGH_STRIDE","how often the neighbor list needs to be calculated in time units"); + keys.add("optional", "EPSILON", "(default=-1) the maximum distance between the close and the current structure, the positive value turn on the close structure method"); + keys.add("optional", "LOG-CLOSE", "(default=0) value 1 enables logging regarding the close structure"); + keys.add("optional", "DEBUG-CLOSE", "(default=0) value 1 enables extensive debugging info regarding the close structure, the simulation will run much slower"); } PathMSDBase::PathMSDBase(const ActionOptions&ao): PLUMED_COLVAR_INIT(ao), neigh_size(-1), neigh_stride(-1), -nframes(0) +nframes(0), +epsilonClose(-1), +debugClose(0), +logClose(0) { parse("LAMBDA",lambda); parse("NEIGH_SIZE",neigh_size); parse("NEIGH_STRIDE",neigh_stride); parse("REFERENCE",reference); + parse("EPSILON", epsilonClose); + parse("LOG-CLOSE", logClose); + parse("DEBUG-CLOSE", debugClose); // open the file FILE* fp=fopen(reference.c_str(),"r"); @@ -85,6 +94,9 @@ nframes(0) fclose (fp); log<<"Found TOTAL "<<nframes<< " PDB in the file "<<reference.c_str()<<" \n"; if(nframes==0) error("at least one frame expected"); + //set up rmsdRefClose, initialize it to the first structure loaded from reference file + rmsdPosClose.set(pdbv[0], "OPTIMAL"); + firstPosClose = true; } if(neigh_stride>0 || neigh_size>0){ if(neigh_size>int(nframes)){ @@ -98,6 +110,26 @@ nframes(0) log.printf(" Neighbor list NOT enabled \n"); } + if (epsilonClose > 0) { + log.printf(" Computing with the close structure, epsilon = %lf\n", epsilonClose); + log << " Bibliography " << plumed.cite("Pazurikova J, Krenek A, Spiwok V, Simkova M J. Chem. Phys. 146, 115101 (2017)") << "\n"; + } + else { + debugClose = 0; + logClose = 0; + } + if (debugClose) + log.printf(" Extensive debug info regarding close structure turned on\n"); + + rotationRefClose = new Tensor[nframes]; + drotationPosCloseDrr01 = new Tensor[9]; + savedIndices = vector<unsigned>(nframes); + +} + +PathMSDBase::~PathMSDBase(){ + delete[] rotationRefClose; + delete[] drotationPosCloseDrr01; } void PathMSDBase::calculate(){ @@ -124,21 +156,90 @@ void PathMSDBase::calculate(){ plumed_assert(nframes>0); plumed_assert(imgVec.size()>0); + Tensor* tmp_rotationRefClose = new Tensor[nframes]; + + if (epsilonClose > 0){ + //compute rmsd between positions and close structure, save rotation matrix, drotation_drr01 + double posclose = rmsdPosClose.calc_Rot_DRotDRr01(getPositions(), rotationPosClose, drotationPosCloseDrr01, true); + //if we compute for the first time or the existing close structure is too far from current structure + if (firstPosClose || (posclose > epsilonClose)){ + //set the current structure as close one for a few next steps + if (logClose) + log << "PLUMED-CLOSE: new close structure, rmsd pos close " << posclose << "\n"; + rmsdPosClose.clear(); + rmsdPosClose.setReference(getPositions()); + //as this is a new close structure, we need to save the rotation matrices fitted to the reference structures + // and we need to accurately recalculate for all reference structures + computeRefClose = true; + imgVec.resize(nframes); +#pragma simd + for(unsigned i=0;i<nframes;i++){ + imgVec[i].property=indexvec[i]; + imgVec[i].index=i; + } + firstPosClose = false; + } + else{ + //the current structure is pretty close to the close structure, so we use saved rotation matrices to decrease the complexity of rmsd comuptation + if (debugClose) + log << "PLUMED-CLOSE: old close structure, rmsd pos close " << posclose << "\n"; + computeRefClose = false; + } + } + std::vector<double> tmp_distances(imgVec.size(),0.0); std::vector<Vector> tmp_derivs; // this array is a merge of all tmp_derivs, so as to allow a single comm.Sum below std::vector<Vector> tmp_derivs2(imgVec.size()*nat); // if imgVec.size() is less than nframes, it means that only some msd will be calculated - for(unsigned i=rank;i<imgVec.size();i+=stride){ -// store temporary local results - tmp_distances[i]=msdv[imgVec[i].index].calculate(getPositions(),tmp_derivs,true); - plumed_assert(tmp_derivs.size()==nat); - for(unsigned j=0;j<nat;j++) tmp_derivs2[i*nat+j]=tmp_derivs[j]; + if (epsilonClose > 0){ + if (computeRefClose){ + //recompute rotation matrices accurately + for(unsigned i=rank;i<imgVec.size();i+=stride){ + tmp_distances[i] = msdv[imgVec[i].index].calc_Rot(getPositions(), tmp_derivs, tmp_rotationRefClose[imgVec[i].index], true); + plumed_assert(tmp_derivs.size()==nat); + for(unsigned j=0;j<nat;j++) tmp_derivs2[i*nat+j]=tmp_derivs[j]; + } + } + else{ + //approximate distance with saved rotation matrices + for(unsigned i=rank;i<imgVec.size();i+=stride){ + tmp_distances[i] = msdv[imgVec[i].index].calculateWithCloseStructure(getPositions(), tmp_derivs, rotationPosClose, rotationRefClose[imgVec[i].index], drotationPosCloseDrr01, true); + plumed_assert(tmp_derivs.size()==nat); + for(unsigned j=0;j<nat;j++) tmp_derivs2[i*nat+j]=tmp_derivs[j]; + if (debugClose){ + double withclose = tmp_distances[i]; + RMSD opt; + opt.setType("OPTIMAL"); + opt.setReference(msdv[imgVec[i].index].getReference()); + vector<Vector> ders; + double withoutclose = opt.calculate(getPositions(), ders, true); + float difference = fabs(withoutclose-withclose); + log.printf("PLUMED-CLOSE: difference original %lf - with close %lf = %lf, step %d, i %d imgVec[i].index %d \n", withoutclose, withclose, difference, getStep(), i, imgVec[i].index); + } + } + } } + else{ + // store temporary local results + for(unsigned i=rank;i<imgVec.size();i+=stride){ + tmp_distances[i]=msdv[imgVec[i].index].calculate(getPositions(),tmp_derivs,true); + plumed_assert(tmp_derivs.size()==nat); + for(unsigned j=0;j<nat;j++) tmp_derivs2[i*nat+j]=tmp_derivs[j]; + } + } + // reduce over all processors comm.Sum(tmp_distances); comm.Sum(tmp_derivs2); + if (epsilonClose > 0 && computeRefClose) { + comm.Sum(tmp_rotationRefClose, nframes); + for (unsigned i=0; i<nframes;i++) { + rotationRefClose[i] = tmp_rotationRefClose[i]; + } + } + delete [] tmp_rotationRefClose; // assign imgVec[i].distance and imgVec[i].distder for(unsigned i=0;i<imgVec.size();i++){ imgVec[i].distance=tmp_distances[i]; diff --git a/src/colvar/PathMSDBase.h b/src/colvar/PathMSDBase.h index 4451bffc7..d01c12854 100644 --- a/src/colvar/PathMSDBase.h +++ b/src/colvar/PathMSDBase.h @@ -67,6 +67,18 @@ class PathMSDBase : public Colvar { std::vector<Vector> derivs_s; std::vector<Vector> derivs_z; std::vector <ImagePath> imgVec; // this can be used for doing neighlist + + //variables used for the close structure method, i is the number of reference structures + double epsilonClose; //the maximal distance between the close and the current structure before reassignment + int debugClose; //turns on debug mode + int logClose; //turns on logging + RMSD rmsdPosClose; //rmsd between the current and the close structure + bool firstPosClose; //flag indicating the first time we need to calculate the distance between the close and the current structure + bool computeRefClose; //flag indicating necessity to recompute accurately all distances and rotation matrices between the close structure and reference str + Tensor *rotationRefClose; //Tensor[i] saved rotation matrices between the close structure and reference structures + Tensor rotationPosClose; //rotation matrix between the close and the current structure + Tensor *drotationPosCloseDrr01; //Tensor[3][3]; //derivation of the rotation matrix w.r.t rr01, necessary for calculation of derivations + std::vector<unsigned> savedIndices; //saved indices of imgVec from previous steps, used for recalculating after neighbourlist update protected: std::vector<PDB> pdbv; std::vector<std::string> labels; @@ -74,6 +86,7 @@ protected: unsigned nframes; public: explicit PathMSDBase(const ActionOptions&); + ~PathMSDBase(); // active methods: virtual void calculate(); // virtual void prepare(); -- GitLab