📄 integrator.cc
字号:
voidIntegrationWeight::test(){ SCVector3 point; for (int icenter=0; icenter<mol_->natom(); icenter++) { for (point[0]=-1; point[0]<=1; point[0]++) { for (point[1]=-1; point[1]<=1; point[1]++) { for (point[2]=-1; point[2]<=1; point[2]++) { test(icenter, point); } } } }}///////////////////////////////////////////////////////////////////////////// BeckeIntegrationWeight// utility functionsinline static doublecalc_s(double m){ double m1 = 1.5*m - 0.5*m*m*m; double m2 = 1.5*m1 - 0.5*m1*m1*m1; double m3 = 1.5*m2 - 0.5*m2*m2*m2; return 0.5*(1.0-m3);}inline static doublecalc_f3_prime(double m){ double m1 = 1.5*m - 0.5*m*m*m; double m2 = 1.5*m1 - 0.5*m1*m1*m1; double m3 = 1.5 *(1.0 - m2*m2); double n2 = 1.5 *(1.0 - m1*m1); double o1 = 1.5 *(1.0 - m*m); return m3*n2*o1;}static ClassDesc BeckeIntegrationWeight_cd( typeid(BeckeIntegrationWeight),"BeckeIntegrationWeight",1,"public IntegrationWeight", 0, create<BeckeIntegrationWeight>, create<BeckeIntegrationWeight>);BeckeIntegrationWeight::BeckeIntegrationWeight(StateIn& s): SavableState(s), IntegrationWeight(s){ atomic_radius = 0; a_mat = 0; oorab = 0; centers = 0;}BeckeIntegrationWeight::BeckeIntegrationWeight(){ centers = 0; atomic_radius = 0; a_mat = 0; oorab = 0;}BeckeIntegrationWeight::BeckeIntegrationWeight(const Ref<KeyVal>& keyval): IntegrationWeight(keyval){ centers = 0; atomic_radius = 0; a_mat = 0; oorab = 0;}BeckeIntegrationWeight::~BeckeIntegrationWeight(){ done();}voidBeckeIntegrationWeight::save_data_state(StateOut& s){ IntegrationWeight::save_data_state(s);}voidBeckeIntegrationWeight::init(const Ref<Molecule> &mol, double tolerance){ done(); IntegrationWeight::init(mol, tolerance); ncenters = mol->natom(); double *atomic_radius = new double[ncenters]; int icenter; for (icenter=0; icenter<ncenters; icenter++) { // atomic_radius[icenter] = mol->atominfo()->bragg_radius(mol->Z(icenter)); atomic_radius[icenter] = mol->atominfo()->maxprob_radius(mol->Z(icenter)); } centers = new SCVector3[ncenters]; for (icenter=0; icenter<ncenters; icenter++) { centers[icenter].x() = mol->r(icenter,0); centers[icenter].y() = mol->r(icenter,1); centers[icenter].z() = mol->r(icenter,2); } a_mat = new double*[ncenters]; a_mat[0] = new double[ncenters*ncenters]; oorab = new double*[ncenters]; oorab[0] = new double[ncenters*ncenters]; for (icenter=0; icenter < ncenters; icenter++) { if (icenter) { a_mat[icenter] = &a_mat[icenter-1][ncenters]; oorab[icenter] = &oorab[icenter-1][ncenters]; } double atomic_radius_a = atomic_radius[icenter]; for (int jcenter=0; jcenter < ncenters; jcenter++) { double chi=atomic_radius_a/atomic_radius[jcenter]; double uab=(chi-1.)/(chi+1.); a_mat[icenter][jcenter] = uab/(uab*uab-1.); if (icenter!=jcenter) { oorab[icenter][jcenter] = 1./centers[icenter].dist(centers[jcenter]); } else { oorab[icenter][jcenter] = 0.0; } } }}voidBeckeIntegrationWeight::done(){ delete[] atomic_radius; atomic_radius = 0; delete[] centers; centers = 0; if (a_mat) { delete[] a_mat[0]; delete[] a_mat; a_mat = 0; } if (oorab) { delete[] oorab[0]; delete[] oorab; oorab = 0; }}doubleBeckeIntegrationWeight::compute_p(int icenter, SCVector3&point){ double ra = point.dist(centers[icenter]); double *ooraba = oorab[icenter]; double *aa = a_mat[icenter]; double p = 1.0; for (int jcenter=0; jcenter < ncenters; jcenter++) { if (icenter != jcenter) { double mu = (ra-point.dist(centers[jcenter]))*ooraba[jcenter]; if (mu <= -1.) continue; // s(-1) == 1.0 else if (mu >= 1.) { return 0.0; // s(1) == 0.0 } else p *= calc_s(mu + aa[jcenter]*(1.-mu*mu)); } } return p;}// compute derivative of mu(grad_center,bcenter) wrt grad_center;// NB: the derivative is independent of the (implicit) wcenter// provided that wcenter!=grad_centervoidBeckeIntegrationWeight::compute_grad_nu(int grad_center, int bcenter, SCVector3 &point, SCVector3 &grad){ SCVector3 r_g = point - centers[grad_center]; SCVector3 r_b = point - centers[bcenter]; SCVector3 r_gb = centers[grad_center] - centers[bcenter]; double mag_r_g = r_g.norm(); double mag_r_b = r_b.norm(); double oorgb = oorab[grad_center][bcenter]; double mu = (mag_r_g-mag_r_b)*oorgb; double a_gb = a_mat[grad_center][bcenter]; double coef = 1.0-2.0*a_gb*mu; double r_g_coef; if (mag_r_g < 10.0 * DBL_EPSILON) r_g_coef = 0.0; else r_g_coef = -coef*oorgb/mag_r_g; int ixyz; for (ixyz=0; ixyz<3; ixyz++) grad[ixyz] = r_g_coef * r_g[ixyz]; double r_gb_coef = coef*(mag_r_b - mag_r_g)*oorgb*oorgb*oorgb; for (ixyz=0; ixyz<3; ixyz++) grad[ixyz] += r_gb_coef * r_gb[ixyz];}// compute t(nu_ij)doubleBeckeIntegrationWeight::compute_t(int icenter, int jcenter, SCVector3 &point){ // Cf. Johnson et al., JCP v. 98, p. 5612 (1993) (Appendix B) // NB: t is zero if s is zero SCVector3 r_i = point - centers[icenter]; SCVector3 r_j = point - centers[jcenter]; SCVector3 r_ij = centers[icenter] - centers[jcenter]; double t; double mag_r_j = r_j.norm(); double mag_r_i = r_i.norm(); double mu = (mag_r_i-mag_r_j)*oorab[icenter][jcenter]; if (mu >= 1.0-100*DBL_EPSILON) { t = 0.0; return t; } double a_ij = a_mat[icenter][jcenter]; double nu = mu + a_ij*(1.-mu*mu); double s; if (mu <= -1.0) s = 1.0; else s = calc_s(nu); if (fabs(s) < 10*DBL_EPSILON) { t = 0.0; return t; } double p1 = 1.5*nu - 0.5*nu*nu*nu; double p2 = 1.5*p1 - 0.5*p1*p1*p1; t = -(27.0/16.0) * (1 - p2*p2) * (1 - p1*p1) * (1 - nu*nu) / s; return t;}voidBeckeIntegrationWeight::compute_grad_p(int grad_center, int bcenter, int wcenter, SCVector3&point, double p, SCVector3&grad){ // the gradient of p is computed using the formulae from // Johnson et al., JCP v. 98, p. 5612 (1993) (Appendix B) if (grad_center == bcenter) { grad = 0.0; for (int dcenter=0; dcenter<ncenters; dcenter++) { if (dcenter == bcenter) continue; SCVector3 grad_nu; compute_grad_nu(grad_center, dcenter, point, grad_nu); double t = compute_t(grad_center,dcenter,point); for (int ixyz=0; ixyz<3; ixyz++) grad[ixyz] += t * grad_nu[ixyz]; } } else { SCVector3 grad_nu; compute_grad_nu(grad_center, bcenter, point, grad_nu); double t = compute_t(bcenter,grad_center,point); for (int ixyz=0; ixyz<3; ixyz++) grad[ixyz] = -t * grad_nu[ixyz]; } grad *= p;}doubleBeckeIntegrationWeight::w(int acenter, SCVector3 &point, double *w_gradient){ int icenter; double p_sum=0.0, p_a=0.0; for (icenter=0; icenter<ncenters; icenter++) { double p_tmp = compute_p(icenter, point); if (icenter==acenter) p_a=p_tmp; p_sum += p_tmp; } double w_a = p_a/p_sum; if (w_gradient) { // w_gradient is computed using the formulae from // Johnson et al., JCP v. 98, p. 5612 (1993) (Appendix B) int i,j; for (i=0; i<ncenters*3; i++ ) w_gradient[i] = 0.0;// fd_w(acenter, point, w_gradient); // imbn commented out for debug// ExEnv::outn() << point << " ";// for (int i=0; i<ncenters*3; i++) {// ExEnv::outn() << scprintf(" %10.6f", w_gradient[i]);// }// ExEnv::outn() << endl;// return w_a; // imbn commented out for debug for (int ccenter = 0; ccenter < ncenters; ccenter++) { // NB: for ccenter==acenter, use translational invariance // to get the corresponding component of the gradient if (ccenter != acenter) { SCVector3 grad_c_w_a; SCVector3 grad_c_p_a; compute_grad_p(ccenter, acenter, acenter, point, p_a, grad_c_p_a); for (i=0; i<3; i++) grad_c_w_a[i] = grad_c_p_a[i]/p_sum; for (int bcenter=0; bcenter<ncenters; bcenter++) { SCVector3 grad_c_p_b; double p_b = compute_p(bcenter,point); compute_grad_p(ccenter, bcenter, acenter, point, p_b, grad_c_p_b); for (i=0; i<3; i++) grad_c_w_a[i] -= w_a*grad_c_p_b[i]/p_sum; } for (i=0; i<3; i++) w_gradient[ccenter*3+i] = grad_c_w_a[i]; } } // fill in w_gradient for ccenter==acenter for (j=0; j<3; j++) { for (i=0; i<ncenters; i++) { if (i != acenter) { w_gradient[acenter*3+j] -= w_gradient[i*3+j]; } } } } return w_a;}///////////////////////////////////////////////////// RadialIntegratorstatic ClassDesc RadialIntegrator_cd( typeid(RadialIntegrator),"RadialIntegrator",1,"public SavableState", 0, 0, 0);RadialIntegrator::RadialIntegrator(StateIn& s): SavableState(s){}RadialIntegrator::RadialIntegrator(){}RadialIntegrator::RadialIntegrator(const Ref<KeyVal>& keyval){}RadialIntegrator::~RadialIntegrator(){}voidRadialIntegrator::save_data_state(StateOut& s){}///////////////////////////////////////// AngularIntegratorstatic ClassDesc AngularIntegrator_cd( typeid(AngularIntegrator),"AngularIntegrator",1,"public SavableState", 0, 0, 0);AngularIntegrator::AngularIntegrator(StateIn& s): SavableState(s){}AngularIntegrator::AngularIntegrator(){}AngularIntegrator::AngularIntegrator(const Ref<KeyVal>& keyval){}AngularIntegrator::~AngularIntegrator(){}voidAngularIntegrator::save_data_state(StateOut& s){}///////////////////////////////////////// EulerMaclaurinRadialIntegratorstatic ClassDesc EulerMaclaurinRadialIntegrator_cd( typeid(EulerMaclaurinRadialIntegrator),"EulerMaclaurinRadialIntegrator",1,"public RadialIntegrator", 0, create<EulerMaclaurinRadialIntegrator>, create<EulerMaclaurinRadialIntegrator>);EulerMaclaurinRadialIntegrator::EulerMaclaurinRadialIntegrator(StateIn& s): SavableState(s), RadialIntegrator(s){ s.get(nr_);}EulerMaclaurinRadialIntegrator::EulerMaclaurinRadialIntegrator(){ nr_ = 75;}EulerMaclaurinRadialIntegrator::EulerMaclaurinRadialIntegrator(int nr_points){ nr_ = nr_points;}EulerMaclaurinRadialIntegrator::EulerMaclaurinRadialIntegrator(const Ref<KeyVal>& keyval): RadialIntegrator(keyval){ nr_ = keyval->intvalue("nr", KeyValValueint(75));}EulerMaclaurinRadialIntegrator::~EulerMaclaurinRadialIntegrator(){}voidEulerMaclaurinRadialIntegrator::save_data_state(StateOut& s){ RadialIntegrator::save_data_state(s); s.put(nr_);}intEulerMaclaurinRadialIntegrator::nr() const{ return nr_;}doubleEulerMaclaurinRadialIntegrator::radial_value(int ir, int nr, double radii, double &multiplier){ double q = (double)ir/(double)nr; double value = q/(1.-q); double r = radii*value*value; double dr_dq = 2.*radii*q*pow(1.-q,-3.); double dr_dqr2 = dr_dq*r*r; multiplier = dr_dqr2/nr; return r;}void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -