📄 integrator.cc
字号:
double densij; double bvi, bvix, bviy, bviz; double bvixx, bviyx, bviyy, bvizx, bvizy, bvizz; const int X = PointInputData::X; const int Y = PointInputData::Y; const int Z = PointInputData::Z; const int XX = PointInputData::XX; const int YX = PointInputData::YX; const int YY = PointInputData::YY; const int ZX = PointInputData::ZX; const int ZY = PointInputData::ZY; const int ZZ = PointInputData::ZZ; double grad[3], hess[6]; if (need_gradient_) for (i=0; i<3; i++) grad[i] = 0.0; if (need_hessian_) for (i=0; i<6; i++) hess[i] = 0.0; CHECK_ALIGN(tmp); CHECK_ALIGN(grad[0]); if (need_gradient_) { for (i=0; i < ncontrib_bf_; i++) { int it = contrib_bf_[i]; bvi = bs_values_[i]; if (need_gradient_) { bvix = bsg_values_[i*3+X]; bviy = bsg_values_[i*3+Y]; bviz = bsg_values_[i*3+Z]; } if (need_hessian_) { bvixx = bsh_values_[i*6+XX]; bviyx = bsh_values_[i*6+YX]; bviyy = bsh_values_[i*6+YY]; bvizx = bsh_values_[i*6+ZX]; bvizy = bsh_values_[i*6+ZY]; bvizz = bsh_values_[i*6+ZZ]; } int j3 = 0, j6 = 0; int itoff = (it*(it+1))>>1; int itjt; double t = 0.0; for (j=0; j < i; j++) { int jt = contrib_bf_[j]; itjt = itoff+jt; densij = dmat[itjt]; double bvj = bs_values_[j]; CHECK_ALIGN(densij); CHECK_ALIGN(bvj); t += densij*bvi*bvj; double bvjx, bvjy, bvjz; if (need_gradient_) { bvjx = bsg_values_[j3+X]; bvjy = bsg_values_[j3+Y]; bvjz = bsg_values_[j3+Z]; grad[X] += densij*(bvi*bvjx + bvj*bvix); grad[Y] += densij*(bvi*bvjy + bvj*bviy); grad[Z] += densij*(bvi*bvjz + bvj*bviz); j3 += 3; } if (need_hessian_) { double bvjxx = bsh_values_[j6+XX]; double bvjyx = bsh_values_[j6+YX]; double bvjyy = bsh_values_[j6+YY]; double bvjzx = bsh_values_[j6+ZX]; double bvjzy = bsh_values_[j6+ZY]; double bvjzz = bsh_values_[j6+ZZ]; hess[XX] += densij*(bvi*bvjxx+bvix*bvjx+bvjx*bvix+bvixx*bvj); hess[YX] += densij*(bvi*bvjyx+bviy*bvjx+bvjy*bvix+bviyx*bvj); hess[YY] += densij*(bvi*bvjyy+bviy*bvjy+bvjy*bviy+bviyy*bvj); hess[ZX] += densij*(bvi*bvjzx+bviz*bvjx+bvjz*bvix+bvizx*bvj); hess[ZY] += densij*(bvi*bvjzy+bviz*bvjy+bvjz*bviy+bvizy*bvj); hess[ZZ] += densij*(bvi*bvjzz+bviz*bvjz+bvjz*bviz+bvizz*bvj); j6 += 6; } } densij = dmat[itoff+it]*bvi; tmp += t + 0.5*densij*bvi; if (need_gradient_) { grad[X] += densij*bvix; grad[Y] += densij*bviy; grad[Z] += densij*bviz; } if (need_hessian_) { hess[XX] += densij*bvixx; hess[YX] += densij*bviyx; hess[YY] += densij*bviyy; hess[ZX] += densij*bvizx; hess[ZY] += densij*bvizy; hess[ZZ] += densij*bvizz; } } } else { for (i=0; i < ncontrib_bf_; i++) { int it = contrib_bf_[i]; bvi = bs_values_[i]; int itoff = (it*(it+1))>>1; int itjt; double t = 0.0; for (j=0; j < i; j++) { int jt = contrib_bf_[j]; itjt = itoff+jt; densij = dmat[itjt]; double bvj = bs_values_[j]; CHECK_ALIGN(densij); CHECK_ALIGN(bvj); t += densij*bvi*bvj; } densij = dmat[itoff+it]*bvi; tmp += t + 0.5*densij*bvi; } } d.rho = 2.0 * tmp; if (need_gradient_) { for (i=0; i<3; i++) d.del_rho[i] = 2.0 * grad[i]; d.gamma = dot(d.del_rho,d.del_rho); } if (need_hessian_) { for (i=0; i<6; i++) d.hes_rho[i] = 2.0 * hess[i]; d.lap_rho = d.hes_rho[XX] + d.hes_rho[YY] + d.hes_rho[ZZ]; }}doubleDenIntegratorThread::do_point(int acenter, const SCVector3 &r, double weight, double multiplier, double *nuclear_gradient, double *f_gradient, double *w_gradient){ int i,j; double w_mult = weight * multiplier; CHECK_ALIGN(w_mult); // only consider those shells for which phi_i * (Max_j D_ij phi_j) > tol if (linear_scaling_ && use_dmat_bound_) { const std::vector<ExtentData> &cs = extent_->contributing_shells(r[0],r[1],r[2]); ncontrib_ = 0; for (i=0; i<cs.size(); i++) { int ish = cs[i].shell; int contrib = 0; for (j=0; j<cs.size(); j++) { int jsh = cs[j].shell; int ijsh = (ish>jsh)?((ish*(ish+1))/2+jsh):((jsh*(jsh+1))/2+ish); if (cs[i].bound*cs[j].bound*dmat_bound_[ijsh] > 0.00001*accuracy_) { contrib = 1; break; } } if (contrib) { contrib_[ncontrib_++] = ish; } } } else if (linear_scaling_) { const std::vector<ExtentData> &cs = extent_->contributing_shells(r[0],r[1],r[2]); ncontrib_ = cs.size(); for (i=0; i<ncontrib_; i++) { contrib_[i] = cs[i].shell; } } else { ncontrib_ = nshell_; for (i=0; i<nshell_; i++) contrib_[i] = i; } if (ncontrib_ > nshell_) { ExEnv::outn() << "DenIntegratorThread::do_point: ncontrib invalid" << endl; abort(); } ncontrib_bf_ = 0; for (i=0; i<ncontrib_; i++) { int nbf = basis_->shell(contrib_[i]).nfunction(); int bf = basis_->shell_to_function(contrib_[i]); for (j=0; j<nbf; j++, bf++) { contrib_bf_[ncontrib_bf_++] = bf; } } // compute the basis set values double *bsh = bsh_values_, *bsg = bsg_values_, *bsv = bs_values_; for (i=0; i<ncontrib_; i++) { basis_->hessian_shell_values(r,contrib_[i],valdat_,bsh,bsg,bsv); int shsize = basis_->shell(contrib_[i]).nfunction(); if (bsh) bsh += 6 * shsize; if (bsg) bsg += 3 * shsize; if (bsv) bsv += shsize; } // loop over basis functions adding contributions to the density PointInputData id(r); get_density(alpha_dmat_, id.a); if (spin_polarized_) { get_density(beta_dmat_, id.b); if (need_gradient_) { id.gamma_ab = id.a.del_rho[0]*id.b.del_rho[0] + id.a.del_rho[1]*id.b.del_rho[1] + id.a.del_rho[2]*id.b.del_rho[2]; } } id.compute_derived(spin_polarized_, need_gradient_); PointOutputData od; if ( (id.a.rho + id.b.rho) > 1e2*DBL_EPSILON) { if (nuclear_gradient == 0) { func_->point(id, od); } else { func_->gradient(id, od, f_gradient, acenter, basis_, alpha_dmat_, (spin_polarized_?beta_dmat_:alpha_dmat_), ncontrib_, contrib_, ncontrib_bf_, contrib_bf_, bs_values_, bsg_values_, bsh_values_); } } else { return id.a.rho + id.b.rho; } value_ += od.energy * w_mult; if (compute_potential_integrals_) { // the contribution to the potential integrals if (need_gradient_) { double gradsa[3], gradsb[3]; gradsa[0] = w_mult*(2.0*od.df_dgamma_aa*id.a.del_rho[0] + od.df_dgamma_ab*id.b.del_rho[0]); gradsa[1] = w_mult*(2.0*od.df_dgamma_aa*id.a.del_rho[1] + od.df_dgamma_ab*id.b.del_rho[1]); gradsa[2] = w_mult*(2.0*od.df_dgamma_aa*id.a.del_rho[2] + od.df_dgamma_ab*id.b.del_rho[2]); double drhoa = w_mult*od.df_drho_a, drhob=0.0; if (spin_polarized_) { drhob = w_mult*od.df_drho_b; gradsb[0] = w_mult*(2.0*od.df_dgamma_bb*id.b.del_rho[0] + od.df_dgamma_ab*id.a.del_rho[0]); gradsb[1] = w_mult*(2.0*od.df_dgamma_bb*id.b.del_rho[1] + od.df_dgamma_ab*id.a.del_rho[1]); gradsb[2] = w_mult*(2.0*od.df_dgamma_bb*id.b.del_rho[2] + od.df_dgamma_ab*id.a.del_rho[2]); } for (int j=0; j<ncontrib_bf_; j++) { int jt = contrib_bf_[j]; double dfdra_phi_m = drhoa*bs_values_[j]; double dfdga_phi_m = gradsa[0]*bsg_values_[j*3+0] + gradsa[1]*bsg_values_[j*3+1] + gradsa[2]*bsg_values_[j*3+2]; double vamu = dfdra_phi_m + dfdga_phi_m, vbmu=0.0; double dfdrb_phi_m, dfdgb_phi_m; if (spin_polarized_) { dfdrb_phi_m = drhob*bs_values_[j]; dfdgb_phi_m = gradsb[0]*bsg_values_[j*3+0] + gradsb[1]*bsg_values_[j*3+1] + gradsb[2]*bsg_values_[j*3+2]; vbmu = dfdrb_phi_m + dfdgb_phi_m; } int jtoff = (jt*(jt+1))>>1; for (int k=0; k <= j; k++) { int kt = contrib_bf_[k]; int jtkt = jtoff + kt; double dfdga_phi_n = gradsa[0]*bsg_values_[k*3+0] + gradsa[1]*bsg_values_[k*3+1] + gradsa[2]*bsg_values_[k*3+2]; alpha_vmat_[jtkt] += vamu * bs_values_[k] + dfdga_phi_n * bs_values_[j]; if (spin_polarized_) { double dfdgb_phi_n = gradsb[0]*bsg_values_[k*3+0] + gradsb[1]*bsg_values_[k*3+1] + gradsb[2]*bsg_values_[k*3+2]; beta_vmat_[jtkt] += vbmu * bs_values_[k] + dfdgb_phi_n * bs_values_[j]; } } } } else { double drhoa = w_mult*od.df_drho_a; double drhob = w_mult*od.df_drho_b; for (int j=0; j<ncontrib_bf_; j++) { int jt = contrib_bf_[j]; double bsj = bs_values_[j]; double dfa_phi_m = drhoa * bsj; double dfb_phi_m = drhob * bsj; int jtoff = (jt*(jt+1))>>1; for (int k=0; k <= j; k++) { int kt = contrib_bf_[k]; int jtkt = jtoff + kt; double bsk = bs_values_[k]; alpha_vmat_[jtkt] += dfa_phi_m * bsk; if (spin_polarized_) beta_vmat_[jtkt] += dfb_phi_m * bsk; } } } } if (nuclear_gradient != 0) { // the contribution from f dw/dx if (w_gradient) { for (i=0; i<natom_*3; i++) { nuclear_gradient[i] += w_gradient[i] * od.energy * multiplier; } } // the contribution from (df/dx) w for (i=0; i<natom_*3; i++) { nuclear_gradient[i] += f_gradient[i] * w_mult; } } return id.a.rho + id.b.rho;}///////////////////////////////////////////////////////////////////////////// IntegrationWeightstatic ClassDesc IntegrationWeight_cd( typeid(IntegrationWeight),"IntegrationWeight",1,"public SavableState", 0, 0, 0);IntegrationWeight::IntegrationWeight(StateIn& s): SavableState(s){}IntegrationWeight::IntegrationWeight(){}IntegrationWeight::IntegrationWeight(const Ref<KeyVal>& keyval){}IntegrationWeight::~IntegrationWeight(){}voidIntegrationWeight::save_data_state(StateOut& s){}voidIntegrationWeight::init(const Ref<Molecule> &mol, double tolerance){ mol_ = mol; tol_ = tolerance;}voidIntegrationWeight::done(){}voidIntegrationWeight::fd_w(int icenter, SCVector3 &point, double *fd_grad_w){ if (!fd_grad_w) return; double delta = 0.001; int natom = mol_->natom(); Ref<Molecule> molsav = mol_; Ref<Molecule> dmol = new Molecule(*mol_.pointer()); for (int i=0; i<natom; i++) { for (int j=0; j<3; j++) { dmol->r(i,j) += delta; if (icenter == i) point[j] += delta; init(dmol,tol_); double w_plus = w(icenter, point); dmol->r(i,j) -= 2*delta; if (icenter == i) point[j] -= 2*delta; init(dmol,tol_); double w_minus = w(icenter, point); dmol->r(i,j) += delta; if (icenter == i) point[j] += delta; fd_grad_w[i*3+j] = (w_plus-w_minus)/(2.0*delta);// ExEnv::outn() << scprintf("%d,%d %12.10f %12.10f %12.10f",// i,j,w_plus,w_minus,fd_grad_w[i*3+j])// << endl; } } init(molsav, tol_);}voidIntegrationWeight::test(int icenter, SCVector3 &point){ int natom = mol_->natom(); int natom3 = natom*3; // tests over sums of weights int i; double sum_weight = 0.0; for (i=0; i<natom; i++) { double weight = w(i,point); sum_weight += weight; } if (fabs(1.0 - sum_weight) > DBL_EPSILON) { ExEnv::out0() << "IntegrationWeight::test: failed on weight" << endl; ExEnv::out0() << "sum_w = " << sum_weight << endl; } // finite displacement tests of weight gradients double *fd_grad_w = new double[natom3]; double *an_grad_w = new double[natom3]; w(icenter, point, an_grad_w); fd_w(icenter, point, fd_grad_w); for (i=0; i<natom3; i++) { double mag = fabs(fd_grad_w[i]); double err = fabs(fd_grad_w[i]-an_grad_w[i]); int bad = 0; if (mag > 0.00001 && err/mag > 0.01) bad = 1; else if (err > 0.00001) bad = 1; if (bad) { ExEnv::out0() << "iatom = " << i/3 << " ixyx = " << i%3 << " icenter = " << icenter << " point = " << point << endl; ExEnv::out0() << scprintf("dw/dx bad: fd_val=%16.13f an_val=%16.13f err=%16.13f", fd_grad_w[i], an_grad_w[i], fd_grad_w[i]-an_grad_w[i]) << endl; } } delete[] fd_grad_w; delete[] an_grad_w; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -