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; }
double DRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool& squared ){ plumed_dbg_assert( !targets.empty() ); Vector distance; double drmsd=0.; for(std::map< std::pair <unsigned,unsigned> , double>::const_iterator it=targets.begin();it!=targets.end();++it){ unsigned i=getAtomIndex( it->first.first ); unsigned j=getAtomIndex( it->first.second ); if(nopbc){ distance=delta( pos[i] , pos[j] ); } else{ distance=pbc.distance( pos[i] , pos[j] ); } double len = distance.modulo(); double diff = len - it->second; drmsd += diff * diff; addAtomicDerivatives( i, -( diff / len ) * distance ); addAtomicDerivatives( j, ( diff / len ) * distance ); addBoxDerivatives( -( diff / len ) * Tensor(distance,distance) ); } double npairs = static_cast<double>(targets.size()); double idrmsd; if(squared){ drmsd = drmsd / npairs; idrmsd = 2.0 / npairs; } else { drmsd = sqrt( drmsd / npairs ); idrmsd = 1.0/( drmsd * npairs ); } virial *= idrmsd; for(unsigned i=0;i<getNumberOfAtoms();++i){atom_ders[i] *= idrmsd;} return drmsd; }
void Pbc::test(){ Random r; r.setSeed(-20); for(int i=0;i<1000;i++){ // random matrix with some zero element Tensor box; for(int j=0;j<3;j++) for(int k=0;k<3;k++) if(r.U01()>0.2){ box[j][k]=2.0*r.U01()-1.0; } int boxtype=i%10; switch(boxtype){ case 0: // cubic for(int j=0;j<3;j++) for(int k=0;k<3;k++) if(j!=k) box[j][k]=0.0; for(int j=1;j<3;j++) box[j][j]=box[0][0]; break; case 1: // orthorombic for(int j=0;j<3;j++) for(int k=0;k<3;k++) if(j!=k) box[j][k]=0.0; break; case 2: // hexagonal { int perm=r.U01()*100; Vector a; a(0)=r.U01()*2-2; a(1)=0.0;a(2)=0.0; double d=r.U01()*2-2; Vector b(0.0,d,0.0); Vector c(0.0,0.5*d,sqrt(3.0)*d*0.5); box.setRow((perm+0)%3,a); box.setRow((perm+1)%3,b); box.setRow((perm+2)%3,c); } break; case 3: // bcc { int perm=r.U01()*100; double d=r.U01()*2-2; Vector a(d,d,d); Vector b(d,-d,d); Vector c(d,d,-d); box.setRow((perm+0)%3,a); box.setRow((perm+1)%3,b); box.setRow((perm+2)%3,c); } break; case 4: // fcc { int perm=r.U01()*100; double d=r.U01()*2-2; Vector a(d,d,0); Vector b(d,0,d); Vector c(0,d,d); box.setRow((perm+0)%3,a); box.setRow((perm+1)%3,b); box.setRow((perm+2)%3,c); } break; default: // triclinic break; } Pbc pbc; pbc.setBox(box); std::cerr<<"( "<<boxtype<<" )\n"; std::cerr<<"Box:"; for(int j=0;j<3;j++) for(int k=0;k<3;k++) std::cerr<<" "<<box[j][k]; std::cerr<<"\n"; std::cerr<<"Determinant: "<<determinant(box)<<"\n"; std::cerr<<"Shifts:"; for(int j=0;j<2;j++) for(int k=0;k<2;k++) for(int l=0;l<2;l++) std::cerr<<" "<<pbc.shifts[j][k][l].size(); std::cerr<<"\n"; int nshifts=0; int ntot=10000; for(int j=0;j<ntot;j++){ Vector v(r.U01()-0.5,r.U01()-0.5,r.U01()-0.5); v*=5; for(int j=0;j<3;j++) if(r.U01()>0.2) v(j)=0.0; Vector full(v); Vector fast=pbc.distance(Vector(0,0,0),v,&nshifts); full=fast; pbc.fullSearch(full); if(modulo2(fast-full)>1e-10) { std::cerr<<"orig "<<v[0]<<" "<<v[1]<<" "<<v[2]<<"\n"; std::cerr<<"fast "<<fast[0]<<" "<<fast[1]<<" "<<fast[2]<<"\n"; std::cerr<<"full "<<full[0]<<" "<<full[1]<<" "<<full[2]<<"\n"; std::cerr<<"diff "<<modulo2(fast)-modulo2(full)<<std::endl; if(std::fabs(modulo2(fast)-modulo2(full))>1e-15) plumed_error(); } } std::cerr<<"Average number of shifts: "<<double(nshifts)/double(ntot)<<"\n"; } }