// // gaussshell.cc // // Copyright (C) 1996 Limit Point Systems, Inc. // // Author: Curtis Janssen // 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 #include #include #include #include #include #include #include #include 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, create); // this GaussianShell ctor allocates and computes normalization constants // and computes nfunc GaussianShell::GaussianShell( int ncn,int nprm,double*e,int*am,int*pure,double**c,PrimitiveType pt, bool do_normalize_shell ): 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 if (do_normalize_shell) normalize_shell(); } // this GaussianShell ctor is much like the above except the puream // array is generated according to the value of pure GaussianShell::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&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()) < 2) s.get(nfunc); s.get(l); s.get(puream); s.get(exp); coef = new double*[ncon]; for (int i=0; i&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::PrimitiveType GaussianShell::keyval_init(const Ref& 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; idoublevalue("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 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; jdoublevalue("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; } void GaussianShell::init_computed_data() { int max = 0; int min = 0; int nc = 0; int nf = 0; has_pure_ = 0; for (int i=0; i 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>1); } return ret; } /* Compute the norm for ((x^x1)||(x^x2)). This is slower than need be. */ static double norm(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). // 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) ) double GaussianShell::shell_normalization(int gc) { int i,j; double result,c,ss; result = 0.0; for (i=0; i1) 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; } double GaussianShell::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; } double GaussianShell::relative_overlap(const Ref& 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>1); } int GaussianShell::equiv(const GaussianShell *s) { if (nprim != s->nprim) return 0; if (ncon != s->ncon) return 0; for (int i=0; il[i]) return 0; if (puream[i] != s->puream[i]) return 0; if (fabs((exp[i] - s->exp[i])/exp[i]) > 1.0e-13) return 0; for (int j=0; jcoef[i][j])/coef[i][j]) > 1.0e-13) return 0; } else { if (fabs((coef[i][j] - s->coef[i][j])) > 1.0e-13) return 0; } } } return 1; } double GaussianShell::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: