bool LatticeReduction::isReduced(const Vector&a,const Vector&b){ const int cut=5; for(int i=-cut;i<=cut;i++){ if(modulo2(b+i*a)<modulo2(b)) return false; } return modulo2(a)<=modulo2(b) && 2.0*dotProduct(a,b)<=modulo2(a); }
void LatticeReduction::reduceSlow(Tensor&t){ Vector v[3]; v[0]=t.getRow(0); v[1]=t.getRow(1); v[2]=t.getRow(2); reduce2(v[0],v[1],v[2]); double e01=dotProduct(v[0],v[1]); double e02=dotProduct(v[0],v[2]); double e12=dotProduct(v[1],v[2]); if(e01*e02*e12<0){ int eps01=0; if(e01>0.0) eps01=1; else if(e01<0.0) eps01=-1; int eps02=0; if(e02>0.0) eps02=1; else if(e02<0.0) eps02=-1; Vector n=v[0]-eps01*v[1]-eps02*v[2]; int i=0; double mx=modulo2(v[i]); for(int j=1;j<3;j++){ double f=modulo2(v[j]); if(f>mx){ i=j; mx=f; } } if(modulo2(n)<mx) v[i]=n; } sort(v); t.setRow(0,v[0]); t.setRow(1,v[1]); t.setRow(2,v[2]); }
void Pbc::buildShifts(std::vector<Vector> shifts[2][2][2])const{ const double small=1e-28; // clear all shifts for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) shifts[i][j][k].clear(); // enumerate all possible shifts // since box is reduced, only 27 shifts have to be attempted for(int l=-1;l<=1;l++) for(int m=-1;m<=1;m++) for(int n=-1;n<=1;n++){ // int/double shift vectors int ishift[3]={l,m,n}; Vector dshift(l,m,n); // count how many components are != 0 unsigned count=0; for(int s=0;s<3;s++) if(ishift[s]!=0) count++; // skips trivial (0,0,0) and cases with three shifts // only 18 shifts survive past this point if(count==0 || count==3) continue; // check if that Wigner-Seitz face is perpendicular to the axis. // this allows to eliminate shifts in symmetric cells. // e.g., if one lactice vector is orthogonal to the plane spanned // by the other two vectors, that shift should never be tried Vector cosdir=matmul(reduced,transpose(reduced),dshift); double dp=dotProduct(dshift,cosdir); double ref=modulo2(dshift)*modulo2(cosdir); if(std::fabs(ref-dp*dp)<small) continue; // here we start pruning depending on the sign of the scaled coordinate for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++){ int block[3]={2*i-1,2*j-1,2*k-1}; // skip cases where shift would bring too far from origin bool skip=false; for(int s=0;s<3;s++) if(ishift[s]*block[s]>0) skip=true; if(skip) continue; skip=true; for(int s=0;s<3;s++){ // check that the components of cosdir along the non-shifted directions // have the proper sign if(((1-ishift[s]*ishift[s])*block[s])*cosdir[s]<-small) skip=false; } if(skip)continue; // if we arrive to this point, shift is eligible and is added to the list shifts[i][j][k].push_back(matmul(transpose(reduced),dshift)); } } }
void LatticeReduction::reduce(Vector&a,Vector&b){ double ma=modulo2(a); double mb=modulo2(b); while(true){ if(mb>ma){ Vector t(a); a=b; b=t; double mt(ma); ma=mb; mb=mt; } a-=b*floor(dotProduct(a,b)/modulo2(b)+0.5); ma=modulo2(a); if(mb<=ma+epsilon) break; } Vector t(a); a=b; b=t; }
void initGPIO(int nGpio, int modulo, int direction){ switch(modulo){ case MODULO_0: GPIO0_ModuleClkConfig(); modulo0(nGpio); break; case MODULO_1: GPIO1_ModuleClkConfig(); modulo1(nGpio); break; case MODULO_2: GPIO2_ModuleClkConfig(); modulo2(nGpio); break; case MODULO_3: GPIO3_ModuleClkConfig(); modulo3(nGpio); break; } /* Enabling the GPIO module. */ GPIOModuleEnable(GPIO_INSTANCE_ADDRESS(modulo)); /* Resetting the GPIO module. */ //GPIOModuleReset(GPIO_INSTANCE_ADDRESS(modulo)); /* Setting the GPIO pin as an output pin. */ GPIODirModeSet(GPIO_INSTANCE_ADDRESS(modulo), GPIO_INSTANCE_PIN_NUMBER(nGpio), direction); }
HalfEdge* Interface::getArestaNear(QPointF p) { QList<HalfEdge *> *lista = new QList<HalfEdge *>(map.values()); //QList<HalfEdge *> *lista = kdt->find(p); HalfEdge *e, *best = NULL; QPointF p1, p2; double min = INF; double realdist2; for (int i = 0; i < lista->size(); i++) { e = lista->at(i); p1 = e->getOrigem()->getPoint(); p2 = e->getDestino()->getPoint(); double mod2 = modulo2(p1,p2); double u = ((p.x() - p1.x())*(p2.x() - p1.x())) + ((p.y() - p1.y())*(p2.y() - p1.y())); u = u / mod2; double x = p1.x() + u * (p2.x() - p1.x()); double y = p1.y() + u * (p2.y() - p1.y()); double dist2 = (p.x() - x)*(p.x() - x) + (p.y() - y)*(p.y() - y); QPointF dir = (p2 - p1)/sqrt(mod2); QPointF AP = p - p1; QPointF AB = p2 - p1; double proj = eProd(AP,dir); if (proj < 0 || proj >= sqrt(mod2)) { double dist2p1 = (p1.x()-p.x())*(p1.x()-p.x()) + (p1.y()-p.y())*(p1.y()-p.y()); double dist2p2 = (p2.x()-p.x())*(p2.x()-p.x()) + (p2.y()-p.y())*(p2.y()-p.y()); realdist2 = MIN(dist2p1,dist2p2); } else realdist2 = dist2; if (realdist2 < min) { min = realdist2; best = e; } } delete lista; return best; }
bool LatticeReduction::isReduced(const Tensor&t){ Vector v[3]; double m[3]; v[0]=t.getRow(0); v[1]=t.getRow(1); v[2]=t.getRow(2); for(int i=0;i<3;i++) m[i]=modulo2(v[i]); if(!((m[0]<=m[1]) && m[1]<=m[2])) return false; const int cut=5; for(int i=-cut;i<=cut;i++){ double mm=modulo2(v[1]+i*v[0]); if(mm<m[1]) return false; for(int j=-cut;j<=cut;j++){ double mx=modulo2(v[2]+i*v[1]+j*v[0]); if(mx<m[2])return false; } } return true; }
void LatticeReduction::reduceFast(Tensor&t){ Vector v[3]; v[0]=t.getRow(0); v[1]=t.getRow(1); v[2]=t.getRow(2); while(true){ sort(v); reduce(v[0],v[1]); double b11=modulo2(v[0]); double b22=modulo2(v[1]); double b12=dotProduct(v[0],v[1]); double b13=dotProduct(v[0],v[2]); double b23=dotProduct(v[1],v[2]); double z=b11*b22-b12*b12; double y2=-(b11*b23-b12*b13)/z; double y1=-(b22*b13-b12*b23)/z; int x1min=floor(y1); int x1max=x1min+1; int x2min=floor(y2); int x2max=x2min+1; bool first=true; double mbest,mtrial; Vector trial,best; for(int x1=x1min;x1<=x1max;x1++) for(int x2=x2min;x2<=x2max;x2++){ trial=v[2]+x2*v[1]+x1*v[0]; mtrial=modulo2(trial); if(first || mtrial<mbest){ mbest=mtrial; best=trial; first=false; } } if(modulo2(best)+epsilon>=modulo2(v[2])) break; v[2]=best; } sort(v); t.setRow(0,v[0]); t.setRow(1,v[1]); t.setRow(2,v[2]); }
Vector Pbc::distance(const Vector&v1,const Vector&v2,int*nshifts)const{ Vector d=delta(v1,v2); if(type==unset){ } else if(type==orthorombic) { #ifdef __PLUMED_PBC_WHILE for(unsigned i=0;i<3;i++){ while(d[i]>hdiag[i]) d[i]-=diag[i]; while(d[i]<=mdiag[i]) d[i]+=diag[i]; } #else for(int i=0;i<3;i++) d[i]=Tools::pbc(d[i]*invBox(i,i))*box(i,i); #endif } else if(type==generic) { Vector s=matmul(d,invReduced); // check if images have to be computed: // if((std::fabs(s[0])+std::fabs(s[1])+std::fabs(s[2])>0.5)){ // NOTICE: the check in the previous line, albeit correct, is breaking many regtest // since it does not apply Tools::pbc in many cases. Moreover, it does not // introduce a significant gain. I thus leave it out for the moment. if(true){ // bring to -0.5,+0.5 region in scaled coordinates: for(int i=0;i<3;i++) s[i]=Tools::pbc(s[i]); d=matmul(s,reduced); // check if shifts have to be attempted: if((std::fabs(s[0])+std::fabs(s[1])+std::fabs(s[2])>0.5)){ // list of shifts is specific for that "octant" (depends on signs of s[i]): const std::vector<Vector> & myshifts(shifts[(s[0]>0?1:0)][(s[1]>0?1:0)][(s[2]>0?1:0)]); Vector best(d); double lbest(modulo2(best)); // loop over possible shifts: if(nshifts) *nshifts+=myshifts.size(); for(unsigned i=0;i<myshifts.size();i++){ Vector trial=d+myshifts[i]; double ltrial=modulo2(trial); if(ltrial<lbest){ lbest=ltrial; best=trial; } } d=best; } } } else plumed_merror("unknown pbc type"); return d; }
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"; } }
void LatticeReduction::sort(Vector v[3]){ for(int i=0;i<3;i++) for(int j=i+1;j<3;j++) if(modulo2(v[i])>modulo2(v[j])){ Vector x=v[i]; v[i]=v[j]; v[j]=x; } for(int i=0;i<2;i++) plumed_assert(modulo2(v[i])<=modulo2(v[i+1])); }
double RMSD::optimalAlignment(const std::vector<double> & align, const std::vector<double> & displace, const std::vector<Vector> & positions, const std::vector<Vector> & reference , std::vector<Vector> & derivatives, bool squared) { plumed_massert(displace==align,"OPTIMAL_FAST version of RMSD can only be used when displace weights are same as align weights"); double dist(0); double norm(0); const unsigned n=reference.size(); // This is the trace of positions*positions + reference*reference double sum00w(0); // This is positions*reference Tensor sum01w; derivatives.resize(n); Vector cpositions; Vector creference; // first expensive loop: compute centers for(unsigned iat=0;iat<n;iat++){ double w=align[iat]; norm+=w; cpositions+=positions[iat]*w; creference+=reference[iat]*w; } double invnorm=1.0/norm; cpositions*=invnorm; creference*=invnorm; // second expensive loop: compute second moments wrt centers for(unsigned iat=0;iat<n;iat++){ double w=align[iat]; sum00w+=(dotProduct(positions[iat]-cpositions,positions[iat]-cpositions) +dotProduct(reference[iat]-creference,reference[iat]-creference))*w; sum01w+=Tensor(positions[iat]-cpositions,reference[iat]-creference)*w; } double rr00=sum00w*invnorm; Tensor rr01=sum01w*invnorm; Matrix<double> m=Matrix<double>(4,4); m[0][0]=rr00+2.0*(-rr01[0][0]-rr01[1][1]-rr01[2][2]); m[1][1]=rr00+2.0*(-rr01[0][0]+rr01[1][1]+rr01[2][2]); m[2][2]=rr00+2.0*(+rr01[0][0]-rr01[1][1]+rr01[2][2]); m[3][3]=rr00+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]; vector<double> eigenvals; Matrix<double> eigenvecs; int diagerror=diagMat(m, eigenvals, eigenvecs ); if (diagerror!=0){ string sdiagerror; Tools::convert(diagerror,sdiagerror); string msg="DIAGONALIZATION FAILED WITH ERROR CODE "+sdiagerror; plumed_merror(msg); } dist=eigenvals[0]; Matrix<double> ddist_dm(4,4); Vector4d q(eigenvecs[0][0],eigenvecs[0][1],eigenvecs[0][2],eigenvecs[0][3]); // 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]); double prefactor=2.0*invnorm; Vector shift=cpositions-matmul(rotation,creference); if(!squared) prefactor*=0.5/sqrt(dist); // if "safe", recompute dist here to a better accuracy if(safe) 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 // third expensive loop: derivatives for(unsigned iat=0;iat<n;iat++){ // there is no need for derivatives of rotation and shift here as it is by construction zero // (similar to Hellman-Feynman forces) Vector d(positions[iat]-shift - matmul(rotation,reference[iat])); derivatives[iat]= prefactor*align[iat]*d; if(safe) dist+=align[iat]*invnorm*modulo2(d); } if(!squared) dist=sqrt(dist); return dist; }