From da9faf032d61faf8591b6f0ff4431f501d1ce1dd Mon Sep 17 00:00:00 2001 From: Gareth Tribello <gareth.tribello@gmail.com> Date: Sun, 8 Jun 2014 14:07:06 +0100 Subject: [PATCH] Made it so that my RMSD uses code from old RMSD --- src/colvar/PathMSDBase.cpp | 2 +- src/reference/OptimalRMSD.cpp | 202 +-------------------------------- src/reference/ReferenceAtoms.h | 7 -- src/reference/SimpleRMSD.cpp | 66 +---------- src/tools/RMSD.cpp | 7 +- src/tools/RMSD.h | 4 +- 6 files changed, 13 insertions(+), 275 deletions(-) diff --git a/src/colvar/PathMSDBase.cpp b/src/colvar/PathMSDBase.cpp index 7537ee824..c1f8f9411 100644 --- a/src/colvar/PathMSDBase.cpp +++ b/src/colvar/PathMSDBase.cpp @@ -62,7 +62,7 @@ nframes(0) bool do_read=true; while (do_read){ PDB mypdb; - RMSD mymsd(log); + RMSD mymsd; do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); if(do_read){ unsigned nat=0; diff --git a/src/reference/OptimalRMSD.cpp b/src/reference/OptimalRMSD.cpp index d73fe473b..f9a0ef336 100644 --- a/src/reference/OptimalRMSD.cpp +++ b/src/reference/OptimalRMSD.cpp @@ -22,22 +22,18 @@ #include "MetricRegister.h" #include "RMSDBase.h" #include "tools/Matrix.h" +#include "tools/RMSD.h" namespace PLMD{ class OptimalRMSD : public RMSDBase { private: bool fast; + RMSD myrmsd; public: OptimalRMSD(const ReferenceConfigurationOptions& ro); void read( const PDB& ); double calc( const std::vector<Vector>& pos, const bool& squared ); - - template <bool safe,bool alEqDis> - double optimalAlignment(const std::vector<double> & align, - const std::vector<double> & displace, - const std::vector<Vector> & positions, - bool squared=false); }; PLUMED_REGISTER_METRIC(OptimalRMSD,"OPTIMAL") @@ -55,198 +51,12 @@ void OptimalRMSD::read( const PDB& pdb ){ double OptimalRMSD::calc( const std::vector<Vector>& pos, const bool& squared ){ if( fast ){ - if( getAlign()==getDisplace() ) return optimalAlignment<false,true>(getAlign(),getDisplace(),pos,squared); - return optimalAlignment<false,false>(getAlign(),getDisplace(),pos,squared); + if( getAlign()==getDisplace() ) return myrmsd.optimalAlignment<false,true>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared); + return myrmsd.optimalAlignment<false,false>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared); } else { - if( getAlign()==getDisplace() ) return optimalAlignment<true,true>(getAlign(),getDisplace(),pos,squared); - return optimalAlignment<true,false>(getAlign(),getDisplace(),pos,squared); - } -} - -template <bool safe,bool alEqDis> -double OptimalRMSD::optimalAlignment(const std::vector<double> & align, - const std::vector<double> & displace, - const std::vector<Vector> & positions, - bool squared){ - double dist(0); - unsigned n=getNumberOfReferencePositions(); -// This is the trace of positions*positions + reference*reference - double rr00(0); - double rr11(0); -// This is positions*reference - Tensor rr01; Vector rpos; - - Vector cpositions; - -// first expensive loop: compute centers - for(unsigned iat=0;iat<n;iat++){ - double w=align[iat]; - cpositions+=positions[iat]*w; - } - -// second expensive loop: compute second moments wrt centers - for(unsigned iat=0;iat<n;iat++){ - double w=align[iat]; rpos=getReferencePosition(iat); - rr00+=dotProduct(positions[iat]-cpositions,positions[iat]-cpositions)*w; - rr11+=dotProduct(rpos,rpos)*w; - rr01+=Tensor(positions[iat]-cpositions,rpos)*w; - } - - Matrix<double> m=Matrix<double>(4,4); - m[0][0]=2.0*(-rr01[0][0]-rr01[1][1]-rr01[2][2]); - m[1][1]=2.0*(-rr01[0][0]+rr01[1][1]+rr01[2][2]); - m[2][2]=2.0*(+rr01[0][0]-rr01[1][1]+rr01[2][2]); - m[3][3]=2.0*(+rr01[0][0]+rr01[1][1]-rr01[2][2]); - m[0][1]=2.0*(-rr01[1][2]+rr01[2][1]); - m[0][2]=2.0*(+rr01[0][2]-rr01[2][0]); - m[0][3]=2.0*(-rr01[0][1]+rr01[1][0]); - m[1][2]=2.0*(-rr01[0][1]-rr01[1][0]); - m[1][3]=2.0*(-rr01[0][2]-rr01[2][0]); - m[2][3]=2.0*(-rr01[1][2]-rr01[2][1]); - m[1][0] = m[0][1]; - m[2][0] = m[0][2]; - m[2][1] = m[1][2]; - m[3][0] = m[0][3]; - m[3][1] = m[1][3]; - m[3][2] = m[2][3]; - - Tensor dm_drr01[4][4]; - if(!alEqDis){ - dm_drr01[0][0] = 2.0*Tensor(-1.0, 0.0, 0.0, 0.0,-1.0, 0.0, 0.0, 0.0,-1.0); - dm_drr01[1][1] = 2.0*Tensor(-1.0, 0.0, 0.0, 0.0,+1.0, 0.0, 0.0, 0.0,+1.0); - dm_drr01[2][2] = 2.0*Tensor(+1.0, 0.0, 0.0, 0.0,-1.0, 0.0, 0.0, 0.0,+1.0); - dm_drr01[3][3] = 2.0*Tensor(+1.0, 0.0, 0.0, 0.0,+1.0, 0.0, 0.0, 0.0,-1.0); - dm_drr01[0][1] = 2.0*Tensor( 0.0, 0.0, 0.0, 0.0, 0.0,-1.0, 0.0,+1.0, 0.0); - dm_drr01[0][2] = 2.0*Tensor( 0.0, 0.0,+1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0); - dm_drr01[0][3] = 2.0*Tensor( 0.0,-1.0, 0.0, +1.0, 0.0, 0.0, 0.0, 0.0, 0.0); - dm_drr01[1][2] = 2.0*Tensor( 0.0,-1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0); - dm_drr01[1][3] = 2.0*Tensor( 0.0, 0.0,-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0); - dm_drr01[2][3] = 2.0*Tensor( 0.0, 0.0, 0.0, 0.0, 0.0,-1.0, 0.0,-1.0, 0.0); - dm_drr01[1][0] = dm_drr01[0][1]; - dm_drr01[2][0] = dm_drr01[0][2]; - dm_drr01[2][1] = dm_drr01[1][2]; - dm_drr01[3][0] = dm_drr01[0][3]; - dm_drr01[3][1] = dm_drr01[1][3]; - dm_drr01[3][2] = dm_drr01[2][3]; - } - - std::vector<double> eigenvals; - Matrix<double> eigenvecs; - int diagerror=diagMat(m, eigenvals, eigenvecs ); - - if (diagerror!=0){ - std::string sdiagerror; - Tools::convert(diagerror,sdiagerror); - std::string msg="DIAGONALIZATION FAILED WITH ERROR CODE "+sdiagerror; - plumed_merror(msg); + if( getAlign()==getDisplace() ) return myrmsd.optimalAlignment<true,true>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared); + return myrmsd.optimalAlignment<true,false>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared); } - - dist=eigenvals[0]+rr00+rr11; - - Matrix<double> ddist_dm(4,4); - - Vector4d q(eigenvecs[0][0],eigenvecs[0][1],eigenvecs[0][2],eigenvecs[0][3]); - - Tensor dq_drr01[4]; - if(!alEqDis){ - double dq_dm[4][4][4]; - for(unsigned i=0;i<4;i++) for(unsigned j=0;j<4;j++) for(unsigned k=0;k<4;k++){ - double tmp=0.0; -// perturbation theory for matrix m - for(unsigned l=1;l<4;l++) tmp+=eigenvecs[l][j]*eigenvecs[l][i]/(eigenvals[0]-eigenvals[l])*eigenvecs[0][k]; - dq_dm[i][j][k]=tmp; - } -// propagation to _drr01 - for(unsigned i=0;i<4;i++){ - Tensor tmp; - for(unsigned j=0;j<4;j++) for(unsigned k=0;k<4;k++) { - tmp+=dq_dm[i][j][k]*dm_drr01[j][k]; - } - dq_drr01[i]=tmp; - } - } - -// This is the rotation matrix that brings reference to positions -// i.e. matmul(rotation,reference[iat])+shift is fitted to positions[iat] - - Tensor rotation; - rotation[0][0]=q[0]*q[0]+q[1]*q[1]-q[2]*q[2]-q[3]*q[3]; - rotation[1][1]=q[0]*q[0]-q[1]*q[1]+q[2]*q[2]-q[3]*q[3]; - rotation[2][2]=q[0]*q[0]-q[1]*q[1]-q[2]*q[2]+q[3]*q[3]; - rotation[0][1]=2*(+q[0]*q[3]+q[1]*q[2]); - rotation[0][2]=2*(-q[0]*q[2]+q[1]*q[3]); - rotation[1][2]=2*(+q[0]*q[1]+q[2]*q[3]); - rotation[1][0]=2*(-q[0]*q[3]+q[1]*q[2]); - rotation[2][0]=2*(+q[0]*q[2]+q[1]*q[3]); - rotation[2][1]=2*(-q[0]*q[1]+q[2]*q[3]); - - - Tensor drotation_drr01[3][3]; - if(!alEqDis){ - drotation_drr01[0][0]=2*q[0]*dq_drr01[0]+2*q[1]*dq_drr01[1]-2*q[2]*dq_drr01[2]-2*q[3]*dq_drr01[3]; - drotation_drr01[1][1]=2*q[0]*dq_drr01[0]-2*q[1]*dq_drr01[1]+2*q[2]*dq_drr01[2]-2*q[3]*dq_drr01[3]; - drotation_drr01[2][2]=2*q[0]*dq_drr01[0]-2*q[1]*dq_drr01[1]-2*q[2]*dq_drr01[2]+2*q[3]*dq_drr01[3]; - drotation_drr01[0][1]=2*(+(q[0]*dq_drr01[3]+dq_drr01[0]*q[3])+(q[1]*dq_drr01[2]+dq_drr01[1]*q[2])); - drotation_drr01[0][2]=2*(-(q[0]*dq_drr01[2]+dq_drr01[0]*q[2])+(q[1]*dq_drr01[3]+dq_drr01[1]*q[3])); - drotation_drr01[1][2]=2*(+(q[0]*dq_drr01[1]+dq_drr01[0]*q[1])+(q[2]*dq_drr01[3]+dq_drr01[2]*q[3])); - drotation_drr01[1][0]=2*(-(q[0]*dq_drr01[3]+dq_drr01[0]*q[3])+(q[1]*dq_drr01[2]+dq_drr01[1]*q[2])); - drotation_drr01[2][0]=2*(+(q[0]*dq_drr01[2]+dq_drr01[0]*q[2])+(q[1]*dq_drr01[3]+dq_drr01[1]*q[3])); - drotation_drr01[2][1]=2*(-(q[0]*dq_drr01[1]+dq_drr01[0]*q[1])+(q[2]*dq_drr01[3]+dq_drr01[2]*q[3])); - } - - double prefactor=2.0; - - if(!squared && alEqDis) prefactor*=0.5/sqrt(dist); - -// if "safe", recompute dist here to a better accuracy - if(safe || !alEqDis) dist=0.0; - -// If safe is set to "false", MSD is taken from the eigenvalue of the M matrix -// If safe is set to "true", MSD is recomputed from the rotational matrix -// For some reason, this last approach leads to less numerical noise but adds an overhead - - Tensor ddist_drotation; - Vector ddist_dcpositions; - -// third expensive loop: derivatives - for(unsigned iat=0;iat<n;iat++){ - Vector d(positions[iat]-cpositions - matmul(rotation,getReferencePosition(iat))); - if(alEqDis){ -// there is no need for derivatives of rotation and shift here as it is by construction zero -// (similar to Hellman-Feynman forces) - addAtomicDerivatives( iat, prefactor*align[iat]*d ); - if(safe) dist+=align[iat]*modulo2(d); - } else { -// the case for align != displace is different, sob: - dist+=displace[iat]*modulo2(d); -// these are the derivatives assuming the roto-translation as frozen - atom_ders[iat]=2*displace[iat]*d; -// here I accumulate derivatives wrt rotation matrix .. - ddist_drotation+=-2*displace[iat]*extProduct(d,getReferencePosition(iat)); -// .. and cpositions - ddist_dcpositions+=-2*displace[iat]*d; - } - } - - if(!alEqDis){ - Tensor ddist_drr01; - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) ddist_drr01+=ddist_drotation[i][j]*drotation_drr01[i][j]; - for(unsigned iat=0;iat<n;iat++){ -// this is propagating to positions. -// I am implicitly using the derivative of rr01 wrt positions here - addAtomicDerivatives( iat, matmul(ddist_drr01,getReferencePosition(iat))*align[iat] ); - addAtomicDerivatives( iat, ddist_dcpositions*align[iat] ); - } - } - if(!squared){ - dist=sqrt(dist); - if(!alEqDis){ - double xx=0.5/dist; - for(unsigned iat=0;iat<atom_ders.size();iat++) atom_ders[iat]*=xx; - } - } - - return dist; } } diff --git a/src/reference/ReferenceAtoms.h b/src/reference/ReferenceAtoms.h index 2ea7ca1f2..1772c62d1 100644 --- a/src/reference/ReferenceAtoms.h +++ b/src/reference/ReferenceAtoms.h @@ -100,8 +100,6 @@ public: virtual void setReferenceAtoms( const std::vector<Vector>& conf, const std::vector<double>& align_in, const std::vector<double>& displace_in )=0; /// Print the atomic positions void printAtoms( OFile& ofile ) const ; -/// Return all the reference positions - const std::vector<Vector>& getReferencePositions(); /// Return all atom indexes const std::vector<AtomNumber>& getAbsoluteIndexes(); }; @@ -160,11 +158,6 @@ void ReferenceAtoms::addBoxDerivatives( const Tensor& vir ){ virialWasSet=true; virial+=vir; } -inline -const std::vector<Vector>& ReferenceAtoms::getReferencePositions(){ - return reference_atoms; -} - inline const std::vector<AtomNumber>& ReferenceAtoms::getAbsoluteIndexes(){ return indices; diff --git a/src/reference/SimpleRMSD.cpp b/src/reference/SimpleRMSD.cpp index 06ec688f3..a40850c13 100644 --- a/src/reference/SimpleRMSD.cpp +++ b/src/reference/SimpleRMSD.cpp @@ -21,20 +21,17 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "RMSDBase.h" #include "MetricRegister.h" +#include "tools/RMSD.h" namespace PLMD{ class SimpleRMSD : public RMSDBase { private: - std::vector<double> weights; + RMSD myrmsd; public: SimpleRMSD( const ReferenceConfigurationOptions& ro ); void read( const PDB& ); double calc( const std::vector<Vector>& pos, const bool& squared ); - double simpleAlignment(const std::vector<double> & align, - const std::vector<double> & displace, - const std::vector<Vector> & positions, - bool squared); }; PLUMED_REGISTER_METRIC(SimpleRMSD,"SIMPLE") @@ -46,66 +43,11 @@ RMSDBase( ro ) } void SimpleRMSD::read( const PDB& pdb ){ - readAtomsFromPDB( pdb ); weights.resize( pdb.getAtomNumbers().size() ); - for(unsigned i=0;i<weights.size();++i) weights[i]=getDisplace()[i]; + readReference( pdb ); } double SimpleRMSD::calc( const std::vector<Vector>& pos, const bool& squared ){ - return simpleAlignment( getAlign(), getDisplace(), pos, squared ); -} - -double SimpleRMSD::simpleAlignment(const std::vector<double> & align, - const std::vector<double> & displace, - const std::vector<Vector> & positions, - bool squared) { - - double dist(0), anorm(0), dnorm(0); - unsigned n=getNumberOfReferencePositions(); - // Number of members of align and displace is the number of reference positions - plumed_dbg_assert( n==align.size() && n==displace.size() ); - // Positions array might contain vectors that are not particularly interesting - plumed_dbg_assert( positions.size()==getNumberOfAtoms() ); - - Vector iref, apositions, areference; - Vector dpositions, dreference; - - for(unsigned i=0;i<n;i++){ - unsigned iatom=getAtomIndex(i); - double aw=align[i]; - double dw=displace[i]; - anorm+=aw; - dnorm+=dw; - iref=getReferencePosition(i); - apositions+=positions[iatom]*aw; - areference+=iref*aw; - dpositions+=positions[iatom]*dw; - dreference+=iref*dw; - } - - double invdnorm=1.0/dnorm; - double invanorm=1.0/anorm; - - apositions*=invanorm; - areference*=invanorm; - dpositions*=invdnorm; - dreference*=invdnorm; - - Vector shift=((apositions-areference)-(dpositions-dreference)); - for(unsigned i=0;i<n;i++){ - unsigned iatom=getAtomIndex(i); - Vector d=(positions[iatom]-apositions)-(getReferencePosition(i)-areference); - dist+=displace[i]*d.modulo2(); - addAtomicDerivatives( i,2*(invdnorm*displace[i]*d+invanorm*align[i]*shift) ); - } - dist*=invdnorm; - - if(!squared){ - // sqrt and normalization - dist=sqrt(dist); - ///// sqrt and normalization on derivatives - for(unsigned i=0;i<getNumberOfAtoms();i++){atom_ders[i]*=(0.5/dist);} - } - return dist; + return myrmsd.simpleAlignment( getAlign(), getDisplace(), pos, getReferencePositions(), atom_ders, squared ); } } diff --git a/src/tools/RMSD.cpp b/src/tools/RMSD.cpp index 9c3e3a9d6..9a400b83f 100644 --- a/src/tools/RMSD.cpp +++ b/src/tools/RMSD.cpp @@ -32,9 +32,7 @@ using namespace std; namespace PLMD{ -RMSD::RMSD(Log & log ): - alignmentMethod(SIMPLE), - log(&log){} +RMSD::RMSD() : alignmentMethod(SIMPLE) {} void RMSD::set(const PDB&pdb, string mytype ){ @@ -49,15 +47,12 @@ void RMSD::setType(string mytype){ alignmentMethod=SIMPLE; // initialize with the simplest case: no rotation if (mytype=="SIMPLE"){ alignmentMethod=SIMPLE; - log->printf("RMSD IS DONE WITH SIMPLE METHOD(NO ROTATION)\n"); } else if (mytype=="OPTIMAL"){ alignmentMethod=OPTIMAL; - log->printf("RMSD IS DONE WITH OPTIMAL ALIGNMENT METHOD\n"); } else if (mytype=="OPTIMAL-FAST"){ alignmentMethod=OPTIMAL_FAST; - log->printf("RMSD IS DONE WITH OPTIMAL-FAST ALIGNMENT METHOD (fast version, numerically less stable, only valid with align==displace)\n"); } else plumed_merror("unknown RMSD type" + mytype); diff --git a/src/tools/RMSD.h b/src/tools/RMSD.h index 5d1636c3c..2d79a4c30 100644 --- a/src/tools/RMSD.h +++ b/src/tools/RMSD.h @@ -68,11 +68,9 @@ class RMSD std::vector<double> align; // Weights for deviation std::vector<double> displace; -// Logfile - Log *log; public: /// Constructor - RMSD(Log & log ); + RMSD(); /// clear the structure void clear(); /// set reference, align and displace from input pdb structure -- GitLab