double OptimalRMSD::projectAtomicDisplacementOnVector( const bool& normalized, const std::vector<Vector>& vecs, ReferenceValuePack& mypack ) const { plumed_dbg_assert( mypack.calcUsingPCAOption() ); double proj=0.0; mypack.clear(); for(unsigned i=0; i<vecs.size(); ++i) { proj += dotProduct( mypack.getAtomsDisplacementVector()[i], vecs[i] ); } for(unsigned a=0; a<3; a++) { for(unsigned b=0; b<3; b++) { for(unsigned iat=0; iat<getNumberOfAtoms(); iat++) { double tmp1=0.; for(unsigned n=0; n<getNumberOfAtoms(); n++) tmp1+=mypack.centeredpos[n][b]*vecs[n][a]; if( normalized ) mypack.addAtomDerivatives( iat, getDisplace()[iat]*mypack.DRotDPos[a][b][iat]*tmp1 ); else mypack.addAtomDerivatives( iat, mypack.DRotDPos[a][b][iat]*tmp1 ); } } } Tensor trot=mypack.rot[0].transpose(); Vector v1; v1.zero(); double prefactor = 1. / static_cast<double>( getNumberOfAtoms() ); for(unsigned n=0; n<getNumberOfAtoms(); n++) v1+=prefactor*matmul(trot,vecs[n]); if( normalized ) { for(unsigned iat=0; iat<getNumberOfAtoms(); iat++) mypack.addAtomDerivatives( iat, getDisplace()[iat]*(matmul(trot,vecs[iat]) - v1) ); } else { for(unsigned iat=0; iat<getNumberOfAtoms(); iat++) mypack.addAtomDerivatives( iat, (matmul(trot,vecs[iat]) - v1) ); } if( !mypack.updateComplete() ) mypack.updateDynamicLists(); return proj; }
double DRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert(!targets.empty()); Vector distance; myder.clear(); double drmsd=0.; for(std::map< std::pair <unsigned,unsigned> , double>::const_iterator it=targets.begin();it!=targets.end();++it){ const unsigned i=getAtomIndex( it->first.first ); const unsigned j=getAtomIndex( it->first.second ); if(nopbc) distance=delta( pos[i] , pos[j] ); else distance=pbc.distance( pos[i] , pos[j] ); const double len = distance.modulo(); const double diff = len - it->second; const double der = diff / len; drmsd += diff * diff; myder.addAtomDerivatives( i, -der * distance ); myder.addAtomDerivatives( j, der * distance ); myder.addBoxDerivatives( - der * Tensor(distance,distance) ); } const double inpairs = 1./static_cast<double>(targets.size()); double idrmsd; if(squared){ drmsd = drmsd * inpairs; idrmsd = 2.0 * inpairs; } else { drmsd = sqrt( drmsd * inpairs ); idrmsd = inpairs / drmsd ; } myder.scaleAllDerivatives( idrmsd ); return drmsd; }