void Cell::brute_force(VECTOR& rij, int degree, vector<triple>& res,triple& central_translation){ /** \brief Brute force generation of the neighbor list for a given pair of atoms \param[in] rij Vector connecting the two atoms for which we want to construct neighbor list \param[in] degree The maximal number of unit cells to consider in all directions (usually, if the cell is large and the cutoff distance is not, it may be sufficient to have degree=1). Degree = 0 implies only the original unit cell with no periodic re[licas. Set degree to a larger value, if the simulation cell is small. \param[out] res The list of triples with each triple describing the integer translations (for given specific pair of atoms) of the original cell needed to account for all neighbors \param[out] central_translation The triple that makes the two atoms to be minimally separated (be in the central cell). For instance, if the two atoms are near the opposite sides of the box, the 1 box translation will put them together (nearby). That translation is then the central translation. */ double Roff2 = Roff * Roff; VECTOR r; if(res.size()>0){ res.clear(); } central_translation.n1 = -degree; central_translation.n2 = -degree; central_translation.n3 = -degree; r = rij; central_translation.n1 = 0; central_translation.n2 = 0; central_translation.n3 = 0; double min_dist = r.length2(); for(int n1=-degree;n1<=degree;n1++){ for(int n2=-degree;n2<=degree;n2++){ for(int n3=-degree;n3<=degree;n3++){ r = (rij - n1*t1 - n2*t2 - n3*t3); double d = r.length2(); if(d<=Roff2){ triple t; t.n1 = n1; t.n2 = n2; t.n3 = n3; if(d<=min_dist){ central_translation = t; min_dist = d;} res.push_back(t); } } } } }
void bruteforce(int Nat,VECTOR* r,MATRIX3x3& H,int maxa,int maxb,int maxc,double Roff,vector< vector<quartet> >& nlist){ /** \brief The function for the brute force formation of the neighbor list \param[in] Nat The number of atoms \param[in] r The pointer to the array of atomic coordinates \param[in] H Matrix describing the size and shape of the simulation cell \param[in] maxa The maximal number of periodic translation of the unit cell along a axis \param[in] maxb The maximal number of periodic translation of the unit cell along b axis \param[in] maxc The maximal number of periodic translation of the unit cell along c axis \param[in] cellx The size of the sub-cells in x direction \param[in] celly The size of the sub-cells in y direction \param[in] cellz The size of the sub-cells in z direction \param[in] Roff The cutoff distance which controls the formation of the neighbor list \param[in,out] nlist Indices of the neighboring sub-cells for all sub-cells */ VECTOR t1,t2,t3,g1,g2,g3; VECTOR t; // Calculate constants double Roff2 = Roff * Roff; // Get cell translation vectors and their reciprocal // and find biggest vector in simulation cell H.get_vectors(t1,t2,t3); H.inverse().T().get_vectors(g1,g2,g3); // Clean the results array if(nlist.size()>0){ nlist.clear(); } vector<quartet> qdummy; nlist = std::vector< vector<quartet> >(Nat,qdummy); for(int i=0;i<Nat;i++){ for(int j=0;j<Nat;j++){ for(int a=-maxa;a<=maxa;a++){ for(int b=-maxb;b<=maxb;b++){ for(int c=-maxc;c<=maxc;c++){ t = r[i] - (r[j] + a*t1 + b*t2 + c*t3); if(t.length2()<Roff2){ quartet qt; qt.j = j; qt.n1 = a; qt.n2 = b; qt.n3 = c; nlist[i].push_back(qt); }// if }// for c }// for b }// for a }// for j }// for i }
void Cell::calculate(VECTOR& rij,vector<triple>& res,triple& central_translation){ /** \brief Function for generation of the neighbor list for a given pair of atoms. This is more efficient version than the brute force. Use the brute force only for verification. \param[in] rij Vector connecting the two atoms for which we want to construct neighbor list \param[out] res The list of triples with each triple describing the integer translations (for given specific pair of atoms) of the original cell needed to account for all neighbors \param[out] central_translation The triple that makes the two atoms to be minimally separated (be in the central cell). For instance, if the two atoms are near the opposite sides of the box, the 1 box translation will put them together (nearby). That translation is then the central translation. */ // int db = 0; // if(fabs(rij.x-3.5)<0.001 && fabs(rij.y+4.033)<0.001 && fabs(rij.z-0.747)<0.001){ db = 1; } // if(db){ cout<<"In Cell::calculate function\n"; } double nm,np,delta,det,det1,det2; int n1,n2,n3; int N1_min,N1_max; int N2_min,N2_max; int N3_min,N3_max; central_translation.n1 = floor(g1*rij + 0.5); central_translation.n2 = floor(g2*rij + 0.5); central_translation.n3 = floor(g3*rij + 0.5); //Pre-calculate the parameters, which depend on rij A = t1*rij; B = t2*rij; C = t3*rij; C2 = C*C; D = Roff*Roff - rij.length2(); N = (B - T23*C/c2); Q = (A - T13*C/c2); R = (D+C2/c2); Yb = (Q*Xa + M*N); Yc =-(R*Xa + N*N); // Clean results: if(res.size()>0){ res.clear(); } det = Yb*Yb - Ya*Yc; if(det<0.0 && fabs(det)<1e-5){ det = 0.0; } // if(db){ cout<<"det = "<<det; } if(det >= 0.0){ delta = sqrt(det); nm = (Yb - delta)/Ya; np = (Yb + delta)/Ya; N1_min = ceil(nm); N1_max = floor(np); // if(db){ cout<<" N1_min="<<N1_min<<" N1_max="<<N1_max<<endl; } // Now run loop in n1 for(n1=N1_min;n1<=N1_max;n1++){ Xb = n1*M+N; Xc = n1*n1*P - 2.0*Q*n1 - R; det1 = Xb*Xb - Xa*Xc; if(det1<0.0 && fabs(det1)<1e-5){ det1 = 0.0; } delta = sqrt(det1); nm = (Xb - delta)/Xa; np = (Xb + delta)/Xa; N2_min = ceil(nm); N2_max = floor(np); // if(db){cout<<" n1="<<n1<<" N2_min="<<N2_min<<" N2_max="<<N2_max<<" delta^2="<<(Xb*Xb - Xa*Xc)<<" nm="<<nm<<" np="<<np<<" Xa="<<Xa<<endl; } // Now run loop in n2 for(n2=N2_min;n2<=N2_max;n2++){ Zb = (C - n1*T13 - n2*T23); Zc = (n1*n1*a2 - 2.0*A*n1 + n2*n2*b2 - 2.0*B*n2 - D + 2.0*n1*n2*T12); det2 = Zb*Zb - Za*Zc; if(det2<0.0 && fabs(det2)<1e-5){ det2 = 0.0; } delta = sqrt(det2); nm = (Zb - delta)/Za; np = (Zb + delta)/Za; N3_min = ceil(nm); N3_max = floor(np); // if(db){ cout<<" n2="<<n2<<" N3_min="<<N3_min<<" N3_max="<<N3_max<<" delta^2 = "<<(Zb*Zb - Za*Zc)<<" nm="<<nm<<" np="<<np<<" Za = "<<Za<<endl; } // Now run loop in n3 for(n3=N3_min;n3<=N3_max;n3++){ triple t; t.n1 = n1; t.n2 = n2; t.n3 = n3; if( (n1==central_translation.n1) && (n2==central_translation.n2) && (n3==central_translation.n3) ){ t.is_central = 1; } else{t.is_central = 0; } res.push_back(t); }// for n3 }// for n2 }// for n1 }// if det>=0.0 // central_translation.n1 = floor(g1*rij + 0.5); // central_translation.n2 = floor(g2*rij + 0.5); // central_translation.n3 = floor(g3*rij + 0.5); }