📄 gaussshell.cc
字号:
//// gaussshell.cc//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@limitpt.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.//#ifdef __GNUC__#pragma implementation#endif#include <stdlib.h>#include <math.h>#include <util/misc/formio.h>#include <util/keyval/keyval.h>#include <util/state/stateio.h>#include <chemistry/qc/basis/gaussshell.h>#include <chemistry/qc/basis/integral.h>#include <chemistry/qc/basis/cartiter.h>using namespace std;using namespace sc;const char* GaussianShell::amtypes = "spdfghiklmn";const char* GaussianShell::AMTYPES = "SPDFGHIKLMN";static ClassDesc GaussianShell_cd( typeid(GaussianShell),"GaussianShell",2,"public SavableState", 0, create<GaussianShell>, create<GaussianShell>);// this GaussianShell ctor allocates and computes normalization constants// and computes nfuncGaussianShell::GaussianShell( int ncn,int nprm,double*e,int*am,int*pure,double**c,PrimitiveType pt ):nprim(nprm),ncon(ncn),l(am),puream(pure),exp(e),coef(c){ // Compute the number of basis functions in this shell init_computed_data(); // Convert the coefficients to coefficients for unnormalized primitives, // if needed. if (pt == Normalized) convert_coef(); // Compute the normalization constants normalize_shell();}// this GaussianShell ctor is much like the above except the puream// array is generated according to the value of pureGaussianShell::GaussianShell( int ncn,int nprm,double*e,int*am,GaussianType pure,double**c,PrimitiveType pt ): nprim(nprm), ncon(ncn), l(am), exp(e), coef(c){ puream = new int [ncontraction()]; for (int i=0; i<ncontraction(); i++) puream[i] = (pure == Pure); // Compute the number of basis functions in this shell init_computed_data(); // Convert the coefficients to coefficients for unnormalized primitives, // if needed. if (pt == Normalized) convert_coef(); // Compute the normalization constants normalize_shell();}GaussianShell::GaussianShell(const Ref<KeyVal>&keyval){ // read in the shell PrimitiveType pt = keyval_init(keyval,0,0); // Compute the number of basis functions in this shell init_computed_data(); // Convert the coefficients to coefficients for unnormalized primitives, // if needed. if (pt == Normalized) convert_coef(); // Compute the normalization constants normalize_shell();}GaussianShell::GaussianShell(StateIn&s): SavableState(s){ s.get(nprim); s.get(ncon); if (s.version(::class_desc<GaussianShell>()) < 2) s.get(nfunc); s.get(l); s.get(puream); s.get(exp); coef = new double*[ncon]; for (int i=0; i<ncon; i++) { s.get(coef[i]); } init_computed_data();}voidGaussianShell::save_data_state(StateOut&s){ s.put(nprim); s.put(ncon); s.put(l,ncon); s.put(puream,ncon); s.put(exp,nprim); for (int i=0; i<ncon; i++) { s.put(coef[i],nprim); }}GaussianShell::GaussianShell(const Ref<KeyVal>&keyval,int pure){ // read in the shell PrimitiveType pt = keyval_init(keyval,1,pure); // Compute the number of basis functions in this shell init_computed_data(); // Convert the coefficients to coefficients for unnormalized primitives, // if needed. if (pt == Normalized) convert_coef(); // Compute the normalization constants normalize_shell();}GaussianShell::PrimitiveTypeGaussianShell::keyval_init(const Ref<KeyVal>& keyval,int havepure,int pure){ ncon = keyval->count("type"); if (keyval->error() != KeyVal::OK) { ExEnv::err0() << indent << "GaussianShell couldn't find the \"type\" array:\n"; keyval->dump(ExEnv::err0()); abort(); } nprim = keyval->count("exp"); if (keyval->error() != KeyVal::OK) { ExEnv::err0() << indent << "GaussianShell couldn't find the \"exp\" array:\n"; keyval->dump(ExEnv::err0()); abort(); } int normalized = keyval->booleanvalue("normalized"); if (keyval->error() != KeyVal::OK) normalized = 1; l = new int[ncon]; puream = new int[ncon]; exp = new double[nprim]; coef = new double*[ncon]; int i,j; for (i=0; i<nprim; i++) { exp[i] = keyval->doublevalue("exp",i); if (keyval->error() != KeyVal::OK) { ExEnv::err0() << indent << scprintf("GaussianShell: error reading exp:%d: %s\n", i,keyval->errormsg()); keyval->errortrace(ExEnv::err0()); exit(1); } } for (i=0; i<ncon; i++) { Ref<KeyVal> prefixkeyval = new PrefixKeyVal(keyval,"type",i); coef[i] = new double[nprim]; char* am = prefixkeyval->pcharvalue("am"); if (prefixkeyval->error() != KeyVal::OK) { ExEnv::err0() << indent << scprintf("GaussianShell: error reading am: \"%s\"\n", prefixkeyval->errormsg()); prefixkeyval->errortrace(ExEnv::err0()); exit(1); } l[i] = -1; for (int li=0; amtypes[li] != '\0'; li++) { if (amtypes[li] == am[0] || AMTYPES[li] == am[0]) { l[i] = li; break; } } if (l[i] == -1 || strlen(am) != 1) { ExEnv::err0() << indent << scprintf("GaussianShell: bad angular momentum: \"%s\"\n", am); prefixkeyval->errortrace(ExEnv::err0()); exit(1); } if (l[i] <= 1) puream[i] = 0; else if (havepure) { puream[i] = pure; } else { puream[i] = prefixkeyval->booleanvalue("puream"); if (prefixkeyval->error() != KeyVal::OK) { puream[i] = 0; //ExEnv::err0() << indent // << scprintf("GaussianShell: error reading puream: \"%s\"\n", // prefixkeyval->errormsg()); //exit(1); } } for (j=0; j<nprim; j++) { coef[i][j] = keyval->doublevalue("coef",i,j); if (keyval->error() != KeyVal::OK) { ExEnv::err0() << indent << scprintf("GaussianShell: error reading coef:%d:%d: %s\n", i,j,keyval->errormsg()); keyval->errortrace(ExEnv::err0()); exit(1); } } delete[] am; } if (normalized) return Normalized; else return Unnormalized;}voidGaussianShell::init_computed_data(){ int max = 0; int min = 0; int nc = 0; int nf = 0; has_pure_ = 0; for (int i=0; i<ncontraction(); i++) { int maxi = l[i]; if (max < maxi) max = maxi; int mini = l[i]; if (min > mini || i == 0) min = mini; nc += ncartesian(i); nf += nfunction(i); if (is_pure(i)) has_pure_ = 1; } max_am_ = max; min_am_ = min; ncart_ = nc; nfunc = nf;}int GaussianShell::max_cartesian() const{ int max = 0; for (int i=0; i<ncontraction(); i++) { int maxi = ncartesian(i); if (max < maxi) max = maxi; } return max;}int GaussianShell::ncartesian_with_aminc(int aminc) const{ int ret = 0; for (int i=0; i<ncontraction(); i++) { ret += (((l[i]+2+aminc)*(l[i]+1+aminc))>>1); } return ret;}/* Compute the norm for ((x^x1)||(x^x2)). This is slower than need be. */static doublenorm(int x1,int x2,double c,double ss){ if (x1 < x2) return norm(x2,x1,c,ss); if (x1 == 1) { if (x2 == 1) return c * ss; else return 0.0; } if (x1 == 0) return ss; return c * ( (x1-1) * norm(x1-2,x2,c,ss) + (x2 * norm(x1-1,x2-1,c,ss)));}void GaussianShell::convert_coef(){ int i,gc; double c,ss; // Convert the contraction coefficients from coefficients over // normalized primitives to coefficients over unnormalized primitives for (gc=0; gc<ncon; gc++) { for (i=0; i<nprim; i++) { c = 0.25/exp[i]; ss = pow(3.141592653589793/(exp[i]+exp[i]),1.5); coef[gc][i] *= 1.0/sqrt(::norm(l[gc],l[gc],c,ss)); } }}double GaussianShell::coefficient_norm(int con,int prim) const{ double c = 0.25/exp[prim]; double ss = pow(3.141592653589793/(exp[prim]+exp[prim]),1.5); return coef[con][prim] * sqrt(::norm(l[con],l[con],c,ss));}// Compute the normalization constant for a shell.// returns 1/sqrt(<(x^l 0 0|(x^l 0 0)>).// The formula is from Obara and Saika (for the basis functions within// the shell that have powers of x only (a and b refer to the power// of x):// (a||b) = 1/(4 alpha) * ( a (a-1||b) + b (a||b-1) )doubleGaussianShell::shell_normalization(int gc){ int i,j; double result,c,ss; result = 0.0; for (i=0; i<nprim; i++) { for (j=0; j<nprim; j++) { c = 0.50/(exp[i] + exp[j]); ss = pow(3.141592653589793/(exp[i]+exp[j]),1.5); result += coef[gc][i] * coef[gc][j] * ::norm(l[gc],l[gc],c,ss); } } return 1.0/sqrt(result);} void GaussianShell::normalize_shell(){ int i,gc; for (gc=0; gc<ncon; gc++) { // Normalize the contraction coefficients double normalization = shell_normalization(gc); for (i=0; i<nprim; i++) { coef[gc][i] *= normalization; } }}static intcomp_relative_overlap(int i1, int j1, int k1, int i2, int j2, int k2){ int result = 0; if (i1) { if (i1>1) result += (i1-1)*comp_relative_overlap(i1-2,j1,k1,i2,j2,k2); if (i2>0) result += i2*comp_relative_overlap(i1-1,j1,k1,i2-1,j2,k2); return result; } if (j1) { if (j1>1) result += (j1-1)*comp_relative_overlap(i1,j1-2,k1,i2,j2,k2); if (j2>0) result += j2*comp_relative_overlap(i1,j1-1,k1,i2,j2-1,k2); return result; } if (k1) { if (k1>1) result += (k1-1)*comp_relative_overlap(i1,j1,k1-2,i2,j2,k2); if (k2>0) result += k2*comp_relative_overlap(i1,j1,k1-1,i2,j2,k2-1); return result; } if (i2) { if (i2>1) result += (i2-1)*comp_relative_overlap(i1,j1,k1,i2-2,j2,k2); if (i1>0) result += i1*comp_relative_overlap(i1-1,j1,k1,i2-1,j2,k2); return result; } if (j2) { if (j2>1) result += (j2-1)*comp_relative_overlap(i1,j1,k1,i2,j2-2,k2); if (j1>0) result += j1*comp_relative_overlap(i1,j1-1,k1,i2,j2-1,k2); return result; } if (k2) { if (k2>1) result += (k2-1)*comp_relative_overlap(i1,j1,k1,i2,j2,k2-2); if (k1>0) result += k1*comp_relative_overlap(i1,j1,k1-1,i2,j2,k2-1); return result; } return 1;}doubleGaussianShell::relative_overlap(int con, int a1, int b1, int c1, int a2, int b2, int c2) const{ int result = comp_relative_overlap(a1,b1,c1,a2,b2,c2); return (double) result;}doubleGaussianShell::relative_overlap(const Ref<Integral>& ints, int con, int func1, int func2) const{ if (puream[con]) { // depends on how intv2 currently normalizes things ExEnv::err0() << indent << "GaussianShell::relative_overlap " << "only implemented for Cartesians\n"; abort(); } CartesianIter *i1p = ints->new_cartesian_iter(l[con]); CartesianIter *i2p = ints->new_cartesian_iter(l[con]); CartesianIter& i1 = *i1p; CartesianIter& i2 = *i2p; int i; for (i1.start(), i=0; i<func1; i1.next(), i++); for (i2.start(), i=0; i<func2; i2.next(), i++); double ret = relative_overlap(con, i1.a(), i1.b(), i1.c(), i2.a(), i2.b(), i2.c()); delete i1p; delete i2p; return ret;}voidGaussianShell::print(ostream& os) const{ int i,j; os << indent << "GaussianShell:\n" << incindent << indent << "ncontraction = " << ncon << endl << indent << "nprimitive = " << nprim << endl << indent << "exponents:"; for (i=0; i<nprim; i++) os << scprintf(" %f",exp[i]); os << endl << indent << "l:"; for (i=0; i<ncon; i++) os << scprintf(" %d", l[i]); os << endl << indent << "type:"; for (i=0; i<ncon; i++) os << scprintf(" %s", puream[i]?"pure":"cart"); os << endl; for (i=0; i<ncon; i++) { os << indent << scprintf("coef[%d]:",i); for (j=0; j<nprim; j++) os << scprintf(" %f",coef[i][j]); os << endl; } os << decindent;}GaussianShell::~GaussianShell(){ delete[] l; delete[] puream; delete[] exp; for (int i=0; i<ncon; i++) { delete[] coef[i]; } delete[] coef;}intGaussianShell::nfunction(int con) const{ return puream[con]? ((l[con]<<1)+1): (((l[con]+2)*(l[con]+1))>>1);}intGaussianShell::equiv(const GaussianShell *s){ if (nprim != s->nprim) return 0; if (ncon != s->ncon) return 0; for (int i=0; i<ncon; i++) { if (l[i] != s->l[i]) return 0; if (puream[i] != s->puream[i]) return 0; if (exp[i] != s->exp[i]) return 0; for (int j=0; j<nprim; j++) { if (coef[i][j] != s->coef[i][j]) return 0; } } return 1;}doubleGaussianShell::extent(double threshold) const{ double tol = 0.1; double r0 = tol; double r1 = 3.0*r0; double b0 = monobound(r0); double b1 = monobound(r1); //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl; //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b1 << endl; if (b0 <= threshold) { return r0; } // step out until r0 and r1 bracket the return value while (b1 > threshold) { r0 = r1; r1 = 3.0*r0; b0 = b1; b1 = monobound(r1); //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl; //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b1 << endl; } while (r1 - r0 > 0.1) { double rtest = 0.5*(r0+r1); double btest = monobound(rtest); if (btest <= threshold) { b1 = btest; r1 = rtest; //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b0 << endl; } else { b0 = btest; r0 = rtest; //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl; } } return r1;}/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "CLJ"// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -