double Ewald::Adjust(double q0, double q1, double rij) { t_adjust_.Start(); t_erfc_.Start(); //double erfc = erfc_func(ew_coeff_ * rij); double erfc = ERFC(ew_coeff_ * rij); t_erfc_.Stop(); double d0 = (erfc - 1.0) / rij; t_adjust_.Stop(); return (q0 * q1 * d0); }
/* The function <p> from the paper (probability of collision of 2 points for 1 LSH function). */ RealT computeFunctionP(RealT w, RealT c){ // Pi: if ( c < Pi_EPSILON ) // c is close to zero; x->inf; then: // assume erfc(inf)->0, the second part->0 return 1.; // c->0 means the points should always conflict. else { RealT x = w / c; return 1 - ERFC(x / M_SQRT2) - M_2_SQRTPI / M_SQRT2 / x * (1 - EXP(-SQR(x) / 2)); } }
/** Calculate direct space energy. This is the slow version that doesn't * use a pair list; for debug purposes only. */ double Ewald::Direct(Matrix_3x3 const& ucell, Topology const& tIn, AtomMask const& mask) { t_direct_.Start(); double cut2 = cutoff_ * cutoff_; double Eelec = 0.0; Varray const& Image = pairList_.ImageCoords(); Varray const& Frac = pairList_.FracCoords(); unsigned int maxidx = Image.size(); for (unsigned int idx1 = 0; idx1 != maxidx; idx1++) { // Set up coord for this atom Vec3 const& crd1 = Image[idx1]; // Set up exclusion list for this atom int atom1 = mask[idx1]; Atom::excluded_iterator excluded_atom = tIn[atom1].excludedbegin(); for (unsigned int idx2 = idx1 + 1; idx2 != maxidx; idx2++) { int atom2 = mask[idx2]; // If atom is excluded, just increment to next excluded atom. if (excluded_atom != tIn[atom1].excludedend() && atom2 == *excluded_atom) { ++excluded_atom; //mprintf("ATOM: Atom %4i to %4i excluded.\n", atom1+1, atom2+1); } else { // Only need to check nearest neighbors. Vec3 const& frac2 = Frac[idx2]; for (Varray::const_iterator ixyz = Cells_.begin(); ixyz != Cells_.end(); ++ixyz) { Vec3 dxyz = ucell.TransposeMult(frac2 + *ixyz) - crd1; double rij2 = dxyz.Magnitude2(); if ( rij2 < cut2 ) { double rij = sqrt( rij2 ); // Coulomb double qiqj = Charge_[idx1] * Charge_[idx2]; t_erfc_.Start(); //double erfc = erfc_func(ew_coeff_ * rij); double erfc = ERFC(ew_coeff_ * rij); t_erfc_.Stop(); double e_elec = qiqj * erfc / rij; Eelec += e_elec; //mprintf("EELEC %4i%4i%12.5f%12.5f%12.5f%3.0f%3.0f%3.0f\n", // mprintf("EELEC %6i%6i%12.5f%12.5f%12.5f\n", atom1, atom2, rij, erfc, e_elec); // TODO can we break here? } //else //mprintf("ATOM: Atom %4i to %4i outside cut, %6.2f > %6.2f %3.0f%3.0f%3.0f\n", //mprintf("ATOM: Atom %4i to %4i outside cut, %6.2f > %6.2f\n", // atom1, atom2,sqrt(rij2),cutoff_); } } } } t_direct_.Stop(); return Eelec; }
/* The function <p> from the paper (probability of collision of 2 points for 1 LSH function). */ RealT computeFunctionP(RealT w, RealT c){ //L2 norm //两个点在一个桶中冲突的可能性 p1 //c为什么设为1 RealT x = w / c; return 1 - ERFC(x / M_SQRT2) - M_2_SQRTPI / M_SQRT2 / x * (1 - EXP(-SQR(x) / 2)); //ERFC为余误差函数,M_SQRT2为math.h中的函数,值为pi //M_2_SQRTPI= 2/sqrt(pi) ,exp(x)=e^x 程序公式1 }
/* The function <p> from the paper (probability of collision of 2 points for 1 LSH function). */ RealT computeFunctionP(RealT w, RealT c){ RealT x = w / c; return 1 - ERFC(x / M_SQRT2) - M_2_SQRTPI / M_SQRT2 / x * (1 - EXP(-SQR(x) / 2)); }
single XERFC( single *arg ) { //=========================== return( ERFC( *arg ) ); }
double Ewald::Adjust(double q0, double q1, double rij) const { double erfc = ERFC(ew_coeff_ * rij); double d0 = (erfc - 1.0) / rij; return (q0 * q1 * d0); }