📄 scfgradient.cc
字号:
//// scfgradient.cc --- implementation of SCF::compute_gradient//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Edward Seidl <seidl@janed.com>// Maintainer: LPS//// This file is part of the SC Toolkit.//// The SC Toolkit is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// The SC Toolkit is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Library General Public License for more details.//// You should have received a copy of the GNU Library General Public License// along with the SC Toolkit; see the file COPYING.LIB. If not, write to// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.//// The U.S. Government is granted a limited license as per AL 91-7.//#include <iostream>#include <util/misc/timer.h>#include <util/misc/formio.h>#include <math/scmat/offset.h>#include <math/scmat/local.h>#include <chemistry/qc/basis/obint.h>#include <chemistry/qc/scf/scf.h>#include <chemistry/qc/scf/scflocal.h>using namespace sc;//////////////////////////////////////////////////////////////////////////////static voidnuc_repulsion(double * g, const Ref<Molecule>& m){ // handy things Molecule& mol = *m.pointer(); for (int x=0; x < mol.natom(); x++) { double xyz[3]; mol.nuclear_repulsion_1der(x, xyz); for (int x1=0, x3=x*3; x1 < 3; x1++,x3++) g[x3] += xyz[x1]; }}static voidob_gradient(const Ref<OneBodyDerivInt>& derint, double * gradient, const RefSymmSCMatrix& density, const Ref<GaussianBasisSet>& gbs_, const Ref<MessageGrp>& grp){ int gsh=0; GaussianBasisSet& gbs = *gbs_.pointer(); Molecule& mol = *gbs_->molecule().pointer(); Ref<SCMatrixSubblockIter> diter = density->local_blocks(SCMatrixSubblockIter::Read); for (diter->begin(); diter->ready(); diter->next()) { SCMatrixBlock *dblk = diter->block(); double *ddata; int istart, iend; int jstart, jend; int sub=0; ddata = get_tri_block(dblk, istart, iend, jstart, jend, sub); if (!ddata) { ExEnv::errn() << indent << "ob_gradient: can't figure out what density block is\n"; abort(); } if (istart >= iend || jstart >= jend) continue; int ishstart = gbs.function_to_shell(istart); int ishend = (iend) ? gbs.function_to_shell(iend-1) : 0; int jshstart = gbs.function_to_shell(jstart); int jshend = (jend) ? gbs.function_to_shell(jend-1) : 0; for (int ish=ishstart; ish <= ishend; ish++) { GaussianShell& gsi = gbs(ish); int ist = gbs.shell_to_function(ish); int ien = ist + gsi.nfunction(); for (int jsh=jshstart; jsh <= jshend; jsh++, gsh++) { if (jsh > ish) break; GaussianShell& gsj = gbs(jsh); int jst = gbs.shell_to_function(jsh); int jen = jst + gsj.nfunction(); for (int x=0; x < mol.natom(); x++) { derint->compute_shell(ish,jsh,x); const double *buf = derint->buffer(); int index=0; double dx=0, dy=0, dz=0; for (int i=ist; i < ien; i++) { for (int j=jst; j < jen; j++) { if (i < istart || i >= iend || j < jstart || j >= jend || j > i) { index += 3; } else { int doff = (sub) ? ij_offset(i,j) : ij_offset(i-istart,j-jstart); double denij = ddata[doff]; if (j!=i) denij *= 2.0; dx += buf[index++] * denij; dy += buf[index++] * denij; dz += buf[index++] * denij; } } } gradient[x*3+0] += dx; gradient[x*3+1] += dy; gradient[x*3+2] += dz; } } } }}//////////////////////////////////////////////////////////////////////////////voidSCF::compute_gradient(const RefSCVector& gradient){ tim_enter("compute gradient"); int i; init_gradient(); int n3=gradient.n(); double *g = new double[n3]; memset(g,0,sizeof(double)*gradient.n()); // do the nuclear contribution tim_enter("nuc rep"); nuc_repulsion(g, molecule()); if (debug_) { gradient.assign(g); print_natom_3(gradient,"Nuclear Contribution to the Gradient:"); } double *o = new double[n3]; memset(o,0,sizeof(double)*gradient.n()); // form overlap contribution tim_change("overlap gradient"); RefSymmSCMatrix dens = lagrangian(); Ref<OneBodyDerivInt> derint = integral()->overlap_deriv(); ob_gradient(derint, o, dens, basis(), scf_grp_); scf_grp_->sum(o,n3); if (debug_) { gradient.assign(o); print_natom_3(gradient,"Overlap Contribution to the Gradient:"); } for (i=0; i < n3; i++) g[i] += o[i]; // other one electron contributions tim_change("one electron gradient"); memset(o,0,sizeof(double)*gradient.n()); dens = gradient_density(); derint = integral()->hcore_deriv(); ob_gradient(derint, o, dens, basis(), scf_grp_); scf_grp_->sum(o,n3); if (debug_) { gradient.assign(o); print_natom_3(gradient,"One-Electron Contribution to the Gradient:"); } for (i=0; i < n3; i++) g[i] += o[i]; dens=0; derint=0; // now calculate two electron contribution tim_change("two electron gradient"); memset(o,0,sizeof(double)*gradient.n()); two_body_deriv(o); tim_exit("two electron gradient"); if (debug_) { gradient.assign(o); print_natom_3(gradient,"Two-Electron Contribution to the Gradient:"); } for (i=0; i < n3; i++) g[i] += o[i]; gradient.assign(g); delete[] g; delete[] o; if (debug_) { print_natom_3(gradient,"Total Gradient:"); } done_gradient(); tim_exit("compute gradient"); //tim_print(0);}//////////////////////////////////////////////////////////////////////////////voidSCF::compute_hessian(const RefSymmSCMatrix& hessian){}/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "ETS"// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -