| [0b990d] | 1 | //
 | 
|---|
 | 2 | // gaussshell.cc
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
 | 7 | // Maintainer: LPS
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // This file is part of the SC Toolkit.
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
 | 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | // any later version.
 | 
|---|
 | 15 | //
 | 
|---|
 | 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
 | 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 19 | // GNU Library General Public License for more details.
 | 
|---|
 | 20 | //
 | 
|---|
 | 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
 | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
 | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | //
 | 
|---|
 | 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
 | 26 | //
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #ifdef __GNUC__
 | 
|---|
 | 29 | #pragma implementation
 | 
|---|
 | 30 | #endif
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | #include <stdlib.h>
 | 
|---|
 | 33 | #include <math.h>
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | #include <util/misc/formio.h>
 | 
|---|
 | 36 | #include <util/misc/math.h>
 | 
|---|
 | 37 | #include <util/keyval/keyval.h>
 | 
|---|
 | 38 | #include <util/state/stateio.h>
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | #include <chemistry/qc/basis/gaussshell.h>
 | 
|---|
 | 41 | #include <chemistry/qc/basis/integral.h>
 | 
|---|
 | 42 | #include <chemistry/qc/basis/cartiter.h>
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | using namespace std;
 | 
|---|
 | 45 | using namespace sc;
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 | const char* GaussianShell::amtypes = "spdfghiklmn";
 | 
|---|
 | 48 | const char* GaussianShell::AMTYPES = "SPDFGHIKLMN";
 | 
|---|
 | 49 | 
 | 
|---|
 | 50 | static ClassDesc GaussianShell_cd(
 | 
|---|
 | 51 |   typeid(GaussianShell),"GaussianShell",2,"public SavableState",
 | 
|---|
 | 52 |   0, create<GaussianShell>, create<GaussianShell>);
 | 
|---|
 | 53 | 
 | 
|---|
 | 54 | // this GaussianShell ctor allocates and computes normalization constants
 | 
|---|
 | 55 | // and computes nfunc
 | 
|---|
 | 56 | GaussianShell::GaussianShell(
 | 
|---|
 | 57 |   int ncn,int nprm,double*e,int*am,int*pure,double**c,PrimitiveType pt,
 | 
|---|
 | 58 |   bool do_normalize_shell
 | 
|---|
 | 59 |   ):
 | 
|---|
 | 60 | nprim(nprm),
 | 
|---|
 | 61 | ncon(ncn),
 | 
|---|
 | 62 | l(am),
 | 
|---|
 | 63 | puream(pure),
 | 
|---|
 | 64 | exp(e),
 | 
|---|
 | 65 | coef(c)
 | 
|---|
 | 66 | {
 | 
|---|
 | 67 |   // Compute the number of basis functions in this shell
 | 
|---|
 | 68 |   init_computed_data();
 | 
|---|
 | 69 | 
 | 
|---|
 | 70 |   // Convert the coefficients to coefficients for unnormalized primitives,
 | 
|---|
 | 71 |   // if needed.
 | 
|---|
 | 72 |   if (pt == Normalized) convert_coef();
 | 
|---|
 | 73 | 
 | 
|---|
 | 74 |   // Compute the normalization constants
 | 
|---|
 | 75 |   if (do_normalize_shell) normalize_shell();
 | 
|---|
 | 76 | }
 | 
|---|
 | 77 | 
 | 
|---|
 | 78 | // this GaussianShell ctor is much like the above except the puream
 | 
|---|
 | 79 | // array is generated according to the value of pure
 | 
|---|
 | 80 | GaussianShell::GaussianShell(
 | 
|---|
 | 81 |   int ncn,int nprm,double*e,int*am,GaussianType pure,double**c,PrimitiveType pt
 | 
|---|
 | 82 |   ):
 | 
|---|
 | 83 |   nprim(nprm),
 | 
|---|
 | 84 |   ncon(ncn),
 | 
|---|
 | 85 |   l(am),
 | 
|---|
 | 86 |   exp(e),
 | 
|---|
 | 87 |   coef(c)
 | 
|---|
 | 88 | {
 | 
|---|
 | 89 |   puream = new int [ncontraction()];
 | 
|---|
 | 90 |   for (int i=0; i<ncontraction(); i++) puream[i] = (pure == Pure);
 | 
|---|
 | 91 | 
 | 
|---|
 | 92 |   // Compute the number of basis functions in this shell
 | 
|---|
 | 93 |   init_computed_data();
 | 
|---|
 | 94 | 
 | 
|---|
 | 95 |   // Convert the coefficients to coefficients for unnormalized primitives,
 | 
|---|
 | 96 |   // if needed.
 | 
|---|
 | 97 |   if (pt == Normalized) convert_coef();
 | 
|---|
 | 98 | 
 | 
|---|
 | 99 |   // Compute the normalization constants
 | 
|---|
 | 100 |   normalize_shell();
 | 
|---|
 | 101 | }
 | 
|---|
 | 102 | 
 | 
|---|
 | 103 | GaussianShell::GaussianShell(const Ref<KeyVal>&keyval)
 | 
|---|
 | 104 | {
 | 
|---|
 | 105 |   // read in the shell
 | 
|---|
 | 106 |   PrimitiveType pt = keyval_init(keyval,0,0);
 | 
|---|
 | 107 | 
 | 
|---|
 | 108 |   // Compute the number of basis functions in this shell
 | 
|---|
 | 109 |   init_computed_data();
 | 
|---|
 | 110 | 
 | 
|---|
 | 111 |   // Convert the coefficients to coefficients for unnormalized primitives,
 | 
|---|
 | 112 |   // if needed.
 | 
|---|
 | 113 |   if (pt == Normalized) convert_coef();
 | 
|---|
 | 114 | 
 | 
|---|
 | 115 |   // Compute the normalization constants
 | 
|---|
 | 116 |   normalize_shell();
 | 
|---|
 | 117 | }
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 | GaussianShell::GaussianShell(StateIn&s):
 | 
|---|
 | 120 |   SavableState(s)
 | 
|---|
 | 121 | {
 | 
|---|
 | 122 |   s.get(nprim);
 | 
|---|
 | 123 |   s.get(ncon);
 | 
|---|
 | 124 |   if (s.version(::class_desc<GaussianShell>()) < 2) s.get(nfunc);
 | 
|---|
 | 125 |   s.get(l);
 | 
|---|
 | 126 |   s.get(puream);
 | 
|---|
 | 127 |   s.get(exp);
 | 
|---|
 | 128 |   coef = new double*[ncon];
 | 
|---|
 | 129 |   for (int i=0; i<ncon; i++) {
 | 
|---|
 | 130 |       s.get(coef[i]);
 | 
|---|
 | 131 |     }
 | 
|---|
 | 132 |   init_computed_data();
 | 
|---|
 | 133 | }
 | 
|---|
 | 134 | 
 | 
|---|
 | 135 | void
 | 
|---|
 | 136 | GaussianShell::save_data_state(StateOut&s)
 | 
|---|
 | 137 | {
 | 
|---|
 | 138 |   s.put(nprim);
 | 
|---|
 | 139 |   s.put(ncon);
 | 
|---|
 | 140 |   s.put(l,ncon);
 | 
|---|
 | 141 |   s.put(puream,ncon);
 | 
|---|
 | 142 |   s.put(exp,nprim);
 | 
|---|
 | 143 |   for (int i=0; i<ncon; i++) {
 | 
|---|
 | 144 |       s.put(coef[i],nprim);
 | 
|---|
 | 145 |     }
 | 
|---|
 | 146 | }
 | 
|---|
 | 147 | 
 | 
|---|
 | 148 | GaussianShell::GaussianShell(const Ref<KeyVal>&keyval,int pure)
 | 
|---|
 | 149 | {
 | 
|---|
 | 150 |   // read in the shell
 | 
|---|
 | 151 |   PrimitiveType pt = keyval_init(keyval,1,pure);
 | 
|---|
 | 152 | 
 | 
|---|
 | 153 |   // Compute the number of basis functions in this shell
 | 
|---|
 | 154 |   init_computed_data();
 | 
|---|
 | 155 | 
 | 
|---|
 | 156 |   // Convert the coefficients to coefficients for unnormalized primitives,
 | 
|---|
 | 157 |   // if needed.
 | 
|---|
 | 158 |   if (pt == Normalized) convert_coef();
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 |   // Compute the normalization constants
 | 
|---|
 | 161 |   normalize_shell();
 | 
|---|
 | 162 | }
 | 
|---|
 | 163 | 
 | 
|---|
 | 164 | GaussianShell::PrimitiveType
 | 
|---|
 | 165 | GaussianShell::keyval_init(const Ref<KeyVal>& keyval,int havepure,int pure)
 | 
|---|
 | 166 | {
 | 
|---|
 | 167 |   ncon = keyval->count("type");
 | 
|---|
 | 168 |   if (keyval->error() != KeyVal::OK) {
 | 
|---|
 | 169 |       ExEnv::err0() << indent
 | 
|---|
 | 170 |            << "GaussianShell couldn't find the \"type\" array:\n";
 | 
|---|
 | 171 |       keyval->dump(ExEnv::err0());
 | 
|---|
 | 172 |       abort();
 | 
|---|
 | 173 |     }
 | 
|---|
 | 174 |   nprim = keyval->count("exp");
 | 
|---|
 | 175 |   if (keyval->error() != KeyVal::OK) {
 | 
|---|
 | 176 |       ExEnv::err0() << indent
 | 
|---|
 | 177 |            << "GaussianShell couldn't find the \"exp\" array:\n";
 | 
|---|
 | 178 |       keyval->dump(ExEnv::err0());
 | 
|---|
 | 179 |       abort();
 | 
|---|
 | 180 |     }
 | 
|---|
 | 181 |   int normalized = keyval->booleanvalue("normalized");
 | 
|---|
 | 182 |   if (keyval->error() != KeyVal::OK) normalized = 1;
 | 
|---|
 | 183 |   
 | 
|---|
 | 184 |   l = new int[ncon];
 | 
|---|
 | 185 |   puream = new int[ncon];
 | 
|---|
 | 186 |   exp = new double[nprim];
 | 
|---|
 | 187 |   coef = new double*[ncon];
 | 
|---|
 | 188 | 
 | 
|---|
 | 189 |   int i,j;
 | 
|---|
 | 190 |   for (i=0; i<nprim; i++) {
 | 
|---|
 | 191 |       exp[i] = keyval->doublevalue("exp",i);
 | 
|---|
 | 192 |       if (keyval->error() != KeyVal::OK) {
 | 
|---|
 | 193 |           ExEnv::err0() << indent
 | 
|---|
 | 194 |                << scprintf("GaussianShell: error reading exp:%d: %s\n",
 | 
|---|
 | 195 |                            i,keyval->errormsg());
 | 
|---|
 | 196 |           keyval->errortrace(ExEnv::err0());
 | 
|---|
 | 197 |           exit(1);
 | 
|---|
 | 198 |         }
 | 
|---|
 | 199 |     }
 | 
|---|
 | 200 |   for (i=0; i<ncon; i++) {
 | 
|---|
 | 201 |       Ref<KeyVal> prefixkeyval = new PrefixKeyVal(keyval,"type",i);
 | 
|---|
 | 202 |       coef[i] = new double[nprim];
 | 
|---|
 | 203 |       char* am = prefixkeyval->pcharvalue("am");
 | 
|---|
 | 204 |       if (prefixkeyval->error() != KeyVal::OK) {
 | 
|---|
 | 205 |           ExEnv::err0() << indent
 | 
|---|
 | 206 |                << scprintf("GaussianShell: error reading am: \"%s\"\n",
 | 
|---|
 | 207 |                            prefixkeyval->errormsg());
 | 
|---|
 | 208 |           prefixkeyval->errortrace(ExEnv::err0());
 | 
|---|
 | 209 |           exit(1);
 | 
|---|
 | 210 |         }
 | 
|---|
 | 211 |       l[i] = -1;
 | 
|---|
 | 212 |       for (int li=0; amtypes[li] != '\0'; li++) {
 | 
|---|
 | 213 |           if (amtypes[li] == am[0] || AMTYPES[li] == am[0]) { l[i] = li; break; }
 | 
|---|
 | 214 |         }
 | 
|---|
 | 215 |       if (l[i] == -1 || strlen(am) != 1) {
 | 
|---|
 | 216 |           ExEnv::err0() << indent
 | 
|---|
 | 217 |                << scprintf("GaussianShell: bad angular momentum: \"%s\"\n",
 | 
|---|
 | 218 |                            am);
 | 
|---|
 | 219 |           prefixkeyval->errortrace(ExEnv::err0());
 | 
|---|
 | 220 |           exit(1);
 | 
|---|
 | 221 |         }
 | 
|---|
 | 222 |       if (l[i] <= 1) puream[i] = 0;
 | 
|---|
 | 223 |       else if (havepure) {
 | 
|---|
 | 224 |           puream[i] = pure;
 | 
|---|
 | 225 |         }
 | 
|---|
 | 226 |       else {
 | 
|---|
 | 227 |           puream[i] = prefixkeyval->booleanvalue("puream");
 | 
|---|
 | 228 |           if (prefixkeyval->error() != KeyVal::OK) {
 | 
|---|
 | 229 |               puream[i] = 0;
 | 
|---|
 | 230 |               //ExEnv::err0() << indent
 | 
|---|
 | 231 |               //     << scprintf("GaussianShell: error reading puream: \"%s\"\n",
 | 
|---|
 | 232 |               //                 prefixkeyval->errormsg());
 | 
|---|
 | 233 |               //exit(1);
 | 
|---|
 | 234 |             }
 | 
|---|
 | 235 |         }
 | 
|---|
 | 236 |       for (j=0; j<nprim; j++) {
 | 
|---|
 | 237 |         coef[i][j] = keyval->doublevalue("coef",i,j);
 | 
|---|
 | 238 |         if (keyval->error() != KeyVal::OK) {
 | 
|---|
 | 239 |             ExEnv::err0() << indent
 | 
|---|
 | 240 |                  << scprintf("GaussianShell: error reading coef:%d:%d: %s\n",
 | 
|---|
 | 241 |                              i,j,keyval->errormsg());
 | 
|---|
 | 242 |             keyval->errortrace(ExEnv::err0());
 | 
|---|
 | 243 |             exit(1);
 | 
|---|
 | 244 |             }
 | 
|---|
 | 245 |         }
 | 
|---|
 | 246 |       delete[] am;
 | 
|---|
 | 247 |     }
 | 
|---|
 | 248 | 
 | 
|---|
 | 249 |   if (normalized) return Normalized;
 | 
|---|
 | 250 |   else return Unnormalized;
 | 
|---|
 | 251 | }
 | 
|---|
 | 252 | 
 | 
|---|
 | 253 | void
 | 
|---|
 | 254 | GaussianShell::init_computed_data()
 | 
|---|
 | 255 | {
 | 
|---|
 | 256 |   int max = 0;
 | 
|---|
 | 257 |   int min = 0;
 | 
|---|
 | 258 |   int nc = 0;
 | 
|---|
 | 259 |   int nf = 0;
 | 
|---|
 | 260 |   has_pure_ = 0;
 | 
|---|
 | 261 |   for (int i=0; i<ncontraction(); i++) {
 | 
|---|
 | 262 |       int maxi = l[i];
 | 
|---|
 | 263 |       if (max < maxi) max = maxi;
 | 
|---|
 | 264 | 
 | 
|---|
 | 265 |       int mini = l[i];
 | 
|---|
 | 266 |       if (min > mini || i == 0) min = mini;
 | 
|---|
 | 267 | 
 | 
|---|
 | 268 |       nc += ncartesian(i);
 | 
|---|
 | 269 | 
 | 
|---|
 | 270 |       nf += nfunction(i);
 | 
|---|
 | 271 | 
 | 
|---|
 | 272 |       if (is_pure(i)) has_pure_ = 1;
 | 
|---|
 | 273 |     }
 | 
|---|
 | 274 |   max_am_ = max;
 | 
|---|
 | 275 |   min_am_ = min;
 | 
|---|
 | 276 |   ncart_ = nc;
 | 
|---|
 | 277 |   nfunc = nf;
 | 
|---|
 | 278 | }
 | 
|---|
 | 279 | 
 | 
|---|
 | 280 | int GaussianShell::max_cartesian() const
 | 
|---|
 | 281 | {
 | 
|---|
 | 282 |   int max = 0;
 | 
|---|
 | 283 |   for (int i=0; i<ncontraction(); i++) {
 | 
|---|
 | 284 |       int maxi = ncartesian(i);
 | 
|---|
 | 285 |       if (max < maxi) max = maxi;
 | 
|---|
 | 286 |     }
 | 
|---|
 | 287 |   return max;
 | 
|---|
 | 288 | }
 | 
|---|
 | 289 | 
 | 
|---|
 | 290 | int GaussianShell::ncartesian_with_aminc(int aminc) const
 | 
|---|
 | 291 | {
 | 
|---|
 | 292 |   int ret = 0;
 | 
|---|
 | 293 |   for (int i=0; i<ncontraction(); i++) {
 | 
|---|
 | 294 |       ret += (((l[i]+2+aminc)*(l[i]+1+aminc))>>1);
 | 
|---|
 | 295 |     }
 | 
|---|
 | 296 |   return ret;
 | 
|---|
 | 297 | }
 | 
|---|
 | 298 | 
 | 
|---|
 | 299 | /* Compute the norm for ((x^x1)||(x^x2)).  This is slower than need be. */
 | 
|---|
 | 300 | static double
 | 
|---|
 | 301 | norm(int x1,int x2,double c,double ss)
 | 
|---|
 | 302 | {
 | 
|---|
 | 303 |   if (x1 < x2) return norm(x2,x1,c,ss);
 | 
|---|
 | 304 |   if (x1 == 1) {
 | 
|---|
 | 305 |     if (x2 == 1) return c * ss;
 | 
|---|
 | 306 |     else return 0.0;
 | 
|---|
 | 307 |     }
 | 
|---|
 | 308 |   if (x1 == 0) return ss;
 | 
|---|
 | 309 |   return c * ( (x1-1) * norm(x1-2,x2,c,ss) + (x2 * norm(x1-1,x2-1,c,ss)));
 | 
|---|
 | 310 | }
 | 
|---|
 | 311 | 
 | 
|---|
 | 312 | void GaussianShell::convert_coef()
 | 
|---|
 | 313 | {
 | 
|---|
 | 314 |   int i,gc;
 | 
|---|
 | 315 |   double c,ss;
 | 
|---|
 | 316 | 
 | 
|---|
 | 317 |   // Convert the contraction coefficients from coefficients over
 | 
|---|
 | 318 |   // normalized primitives to coefficients over unnormalized primitives
 | 
|---|
 | 319 |   for (gc=0; gc<ncon; gc++) {
 | 
|---|
 | 320 |       for (i=0; i<nprim; i++) {
 | 
|---|
 | 321 |           c = 0.25/exp[i];
 | 
|---|
 | 322 |           ss = pow(M_PI/(exp[i]+exp[i]),1.5);
 | 
|---|
 | 323 |           coef[gc][i]
 | 
|---|
 | 324 |             *= 1.0/sqrt(::norm(l[gc],l[gc],c,ss));
 | 
|---|
 | 325 |         }
 | 
|---|
 | 326 |     }
 | 
|---|
 | 327 | }
 | 
|---|
 | 328 | 
 | 
|---|
 | 329 | double GaussianShell::coefficient_norm(int con,int prim) const
 | 
|---|
 | 330 | {
 | 
|---|
 | 331 |   double c = 0.25/exp[prim];
 | 
|---|
 | 332 |   double ss = pow(M_PI/(exp[prim]+exp[prim]),1.5);
 | 
|---|
 | 333 |   return coef[con][prim] * sqrt(::norm(l[con],l[con],c,ss));
 | 
|---|
 | 334 | }
 | 
|---|
 | 335 | 
 | 
|---|
 | 336 | // Compute the normalization constant for a shell.
 | 
|---|
 | 337 | // returns 1/sqrt(<(x^l 0 0|(x^l 0 0)>).
 | 
|---|
 | 338 | // The formula is from Obara and Saika (for the basis functions within
 | 
|---|
 | 339 | // the shell that have powers of x only (a and b refer to the power
 | 
|---|
 | 340 | // of x):
 | 
|---|
 | 341 | // (a||b) = 1/(4 alpha) * ( a (a-1||b) + b (a||b-1) )
 | 
|---|
 | 342 | double
 | 
|---|
 | 343 | GaussianShell::shell_normalization(int gc)
 | 
|---|
 | 344 | {
 | 
|---|
 | 345 |   int i,j;
 | 
|---|
 | 346 |   double result,c,ss;
 | 
|---|
 | 347 | 
 | 
|---|
 | 348 |   result = 0.0;
 | 
|---|
 | 349 |   for (i=0; i<nprim; i++) {
 | 
|---|
 | 350 |     for (j=0; j<nprim; j++) {
 | 
|---|
 | 351 |       c = 0.50/(exp[i] + exp[j]);
 | 
|---|
 | 352 |       ss = pow(M_PI/(exp[i]+exp[j]),1.5);
 | 
|---|
 | 353 |       result += coef[gc][i] * coef[gc][j] *
 | 
|---|
 | 354 |                ::norm(l[gc],l[gc],c,ss);
 | 
|---|
 | 355 |       }
 | 
|---|
 | 356 |     }
 | 
|---|
 | 357 | 
 | 
|---|
 | 358 |   return 1.0/sqrt(result);
 | 
|---|
 | 359 | }
 | 
|---|
 | 360 |  
 | 
|---|
 | 361 | void GaussianShell::normalize_shell()
 | 
|---|
 | 362 | {
 | 
|---|
 | 363 |   int i,gc;
 | 
|---|
 | 364 | 
 | 
|---|
 | 365 |   for (gc=0; gc<ncon; gc++) {
 | 
|---|
 | 366 |       // Normalize the contraction coefficients
 | 
|---|
 | 367 |       double normalization = shell_normalization(gc);
 | 
|---|
 | 368 |       for (i=0; i<nprim; i++) {
 | 
|---|
 | 369 |           coef[gc][i] *= normalization;
 | 
|---|
 | 370 |         }
 | 
|---|
 | 371 |     }
 | 
|---|
 | 372 | 
 | 
|---|
 | 373 | }
 | 
|---|
 | 374 | 
 | 
|---|
 | 375 | static int
 | 
|---|
 | 376 | comp_relative_overlap(int i1, int j1, int k1, int i2, int j2, int k2)
 | 
|---|
 | 377 | {
 | 
|---|
 | 378 |   int result = 0;
 | 
|---|
 | 379 | 
 | 
|---|
 | 380 |   if (i1) {
 | 
|---|
 | 381 |       if (i1>1) result += (i1-1)*comp_relative_overlap(i1-2,j1,k1,i2,j2,k2);
 | 
|---|
 | 382 |       if (i2>0) result += i2*comp_relative_overlap(i1-1,j1,k1,i2-1,j2,k2);
 | 
|---|
 | 383 |       return result;      
 | 
|---|
 | 384 |     }                   
 | 
|---|
 | 385 |   if (j1) {             
 | 
|---|
 | 386 |       if (j1>1) result += (j1-1)*comp_relative_overlap(i1,j1-2,k1,i2,j2,k2);
 | 
|---|
 | 387 |       if (j2>0) result += j2*comp_relative_overlap(i1,j1-1,k1,i2,j2-1,k2);
 | 
|---|
 | 388 |       return result;
 | 
|---|
 | 389 |     }
 | 
|---|
 | 390 |   if (k1) {
 | 
|---|
 | 391 |       if (k1>1) result += (k1-1)*comp_relative_overlap(i1,j1,k1-2,i2,j2,k2);
 | 
|---|
 | 392 |       if (k2>0) result += k2*comp_relative_overlap(i1,j1,k1-1,i2,j2,k2-1);
 | 
|---|
 | 393 |       return result;
 | 
|---|
 | 394 |     }
 | 
|---|
 | 395 |   
 | 
|---|
 | 396 |   if (i2) {
 | 
|---|
 | 397 |       if (i2>1) result += (i2-1)*comp_relative_overlap(i1,j1,k1,i2-2,j2,k2);
 | 
|---|
 | 398 |       if (i1>0) result += i1*comp_relative_overlap(i1-1,j1,k1,i2-1,j2,k2);
 | 
|---|
 | 399 |       return result;
 | 
|---|
 | 400 |     }
 | 
|---|
 | 401 |   if (j2) {
 | 
|---|
 | 402 |       if (j2>1) result += (j2-1)*comp_relative_overlap(i1,j1,k1,i2,j2-2,k2);
 | 
|---|
 | 403 |       if (j1>0) result += j1*comp_relative_overlap(i1,j1-1,k1,i2,j2-1,k2);
 | 
|---|
 | 404 |       return result;
 | 
|---|
 | 405 |     }
 | 
|---|
 | 406 |   if (k2) {
 | 
|---|
 | 407 |       if (k2>1) result += (k2-1)*comp_relative_overlap(i1,j1,k1,i2,j2,k2-2);
 | 
|---|
 | 408 |       if (k1>0) result += k1*comp_relative_overlap(i1,j1,k1-1,i2,j2,k2-1);
 | 
|---|
 | 409 |       return result;
 | 
|---|
 | 410 |     }
 | 
|---|
 | 411 | 
 | 
|---|
 | 412 |   return 1;
 | 
|---|
 | 413 | }
 | 
|---|
 | 414 | 
 | 
|---|
 | 415 | double
 | 
|---|
 | 416 | GaussianShell::relative_overlap(int con,
 | 
|---|
 | 417 |                                 int a1, int b1, int c1,
 | 
|---|
 | 418 |                                 int a2, int b2, int c2) const
 | 
|---|
 | 419 | {
 | 
|---|
 | 420 |   int result = comp_relative_overlap(a1,b1,c1,a2,b2,c2);
 | 
|---|
 | 421 |   return (double) result;
 | 
|---|
 | 422 | }
 | 
|---|
 | 423 | 
 | 
|---|
 | 424 | double
 | 
|---|
 | 425 | GaussianShell::relative_overlap(const Ref<Integral>& ints,
 | 
|---|
 | 426 |                                 int con, int func1, int func2) const
 | 
|---|
 | 427 | {
 | 
|---|
 | 428 |   if (puream[con]) {
 | 
|---|
 | 429 |       // depends on how intv2 currently normalizes things
 | 
|---|
 | 430 |       ExEnv::err0() << indent
 | 
|---|
 | 431 |            << "GaussianShell::relative_overlap "
 | 
|---|
 | 432 |            << "only implemented for Cartesians\n";
 | 
|---|
 | 433 |       abort();
 | 
|---|
 | 434 |     }
 | 
|---|
 | 435 | 
 | 
|---|
 | 436 |   CartesianIter *i1p = ints->new_cartesian_iter(l[con]);
 | 
|---|
 | 437 |   CartesianIter *i2p = ints->new_cartesian_iter(l[con]);
 | 
|---|
 | 438 | 
 | 
|---|
 | 439 |   CartesianIter& i1 = *i1p;
 | 
|---|
 | 440 |   CartesianIter& i2 = *i2p;
 | 
|---|
 | 441 | 
 | 
|---|
 | 442 |   int i;
 | 
|---|
 | 443 |   for (i1.start(), i=0; i<func1; i1.next(), i++);
 | 
|---|
 | 444 |   for (i2.start(), i=0; i<func2; i2.next(), i++);
 | 
|---|
 | 445 | 
 | 
|---|
 | 446 |   double ret = relative_overlap(con, i1.a(), i1.b(), i1.c(),
 | 
|---|
 | 447 |                                 i2.a(), i2.b(), i2.c());
 | 
|---|
 | 448 | 
 | 
|---|
 | 449 |   delete i1p;
 | 
|---|
 | 450 |   delete i2p;
 | 
|---|
 | 451 | 
 | 
|---|
 | 452 |   return ret;
 | 
|---|
 | 453 | }
 | 
|---|
 | 454 | 
 | 
|---|
 | 455 | void
 | 
|---|
 | 456 | GaussianShell::print(ostream& os) const
 | 
|---|
 | 457 | {
 | 
|---|
 | 458 |   int i,j;
 | 
|---|
 | 459 | 
 | 
|---|
 | 460 |   os << indent << "GaussianShell:\n" << incindent
 | 
|---|
 | 461 |      << indent << "ncontraction = " << ncon << endl
 | 
|---|
 | 462 |      << indent << "nprimitive = " << nprim << endl << indent
 | 
|---|
 | 463 |      << "exponents:";
 | 
|---|
 | 464 | 
 | 
|---|
 | 465 |   for (i=0; i<nprim; i++)
 | 
|---|
 | 466 |       os << scprintf(" %f",exp[i]);
 | 
|---|
 | 467 | 
 | 
|---|
 | 468 |   os << endl << indent << "l:";
 | 
|---|
 | 469 |   for (i=0; i<ncon; i++)
 | 
|---|
 | 470 |       os << scprintf(" %d", l[i]);
 | 
|---|
 | 471 | 
 | 
|---|
 | 472 |   os << endl << indent << "type:";
 | 
|---|
 | 473 |   for (i=0; i<ncon; i++)
 | 
|---|
 | 474 |       os << scprintf(" %s", puream[i]?"pure":"cart");
 | 
|---|
 | 475 |   os << endl;
 | 
|---|
 | 476 | 
 | 
|---|
 | 477 |   for (i=0; i<ncon; i++) {
 | 
|---|
 | 478 |       os << indent << scprintf("coef[%d]:",i);
 | 
|---|
 | 479 |       for (j=0; j<nprim; j++)
 | 
|---|
 | 480 |           os << scprintf(" %f",coef[i][j]);
 | 
|---|
 | 481 |       os << endl;
 | 
|---|
 | 482 |     }
 | 
|---|
 | 483 | 
 | 
|---|
 | 484 |   os << decindent;
 | 
|---|
 | 485 | }
 | 
|---|
 | 486 | 
 | 
|---|
 | 487 | GaussianShell::~GaussianShell()
 | 
|---|
 | 488 | {
 | 
|---|
 | 489 |   delete[] l;
 | 
|---|
 | 490 |   delete[] puream;
 | 
|---|
 | 491 |   delete[] exp;
 | 
|---|
 | 492 | 
 | 
|---|
 | 493 |   for (int i=0; i<ncon; i++) {
 | 
|---|
 | 494 |       delete[] coef[i];
 | 
|---|
 | 495 |     }
 | 
|---|
 | 496 | 
 | 
|---|
 | 497 |   delete[] coef;
 | 
|---|
 | 498 | }
 | 
|---|
 | 499 | 
 | 
|---|
 | 500 | int
 | 
|---|
 | 501 | GaussianShell::nfunction(int con) const
 | 
|---|
 | 502 | {
 | 
|---|
 | 503 |   return puream[con]?
 | 
|---|
 | 504 |            ((l[con]<<1)+1):
 | 
|---|
 | 505 |            (((l[con]+2)*(l[con]+1))>>1);
 | 
|---|
 | 506 | }
 | 
|---|
 | 507 | 
 | 
|---|
 | 508 | int
 | 
|---|
 | 509 | GaussianShell::equiv(const GaussianShell *s)
 | 
|---|
 | 510 | {
 | 
|---|
 | 511 |   if (nprim != s->nprim) return 0;
 | 
|---|
 | 512 |   if (ncon != s->ncon) return 0;
 | 
|---|
 | 513 |   for (int i=0; i<ncon; i++) {
 | 
|---|
 | 514 |       if (l[i] != s->l[i]) return 0;
 | 
|---|
 | 515 |       if (puream[i] != s->puream[i]) return 0;
 | 
|---|
 | 516 |       if (fabs((exp[i] - s->exp[i])/exp[i]) > 1.0e-13) return 0;
 | 
|---|
 | 517 |       for (int j=0; j<nprim; j++) {
 | 
|---|
 | 518 |         if (coef[i][j] != 0.0) { 
 | 
|---|
 | 519 |           if (fabs((coef[i][j] - s->coef[i][j])/coef[i][j]) > 1.0e-13) return 0;
 | 
|---|
 | 520 |         }
 | 
|---|
 | 521 |         else {
 | 
|---|
 | 522 |           if (fabs((coef[i][j] - s->coef[i][j])) > 1.0e-13) return 0;
 | 
|---|
 | 523 |         }
 | 
|---|
 | 524 |       }
 | 
|---|
 | 525 |     }
 | 
|---|
 | 526 |   return 1;
 | 
|---|
 | 527 | }
 | 
|---|
 | 528 | 
 | 
|---|
 | 529 | double
 | 
|---|
 | 530 | GaussianShell::extent(double threshold) const
 | 
|---|
 | 531 | {
 | 
|---|
 | 532 |   double tol = 0.1;
 | 
|---|
 | 533 |   double r0 = tol;
 | 
|---|
 | 534 |   double r1 = 3.0*r0;
 | 
|---|
 | 535 |   double b0 = monobound(r0);
 | 
|---|
 | 536 |   double b1 = monobound(r1);
 | 
|---|
 | 537 |   //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl;
 | 
|---|
 | 538 |   //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b1 << endl;
 | 
|---|
 | 539 |   if (b0 <= threshold) {
 | 
|---|
 | 540 |       return r0;
 | 
|---|
 | 541 |     }
 | 
|---|
 | 542 |   // step out until r0 and r1 bracket the return value
 | 
|---|
 | 543 |   while (b1 > threshold) {
 | 
|---|
 | 544 |       r0 = r1;
 | 
|---|
 | 545 |       r1 = 3.0*r0;
 | 
|---|
 | 546 |       b0 = b1;
 | 
|---|
 | 547 |       b1 = monobound(r1);
 | 
|---|
 | 548 |       //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl;
 | 
|---|
 | 549 |       //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b1 << endl;
 | 
|---|
 | 550 |     }
 | 
|---|
 | 551 |   while (r1 - r0 > 0.1) {
 | 
|---|
 | 552 |       double rtest = 0.5*(r0+r1);
 | 
|---|
 | 553 |       double btest = monobound(rtest);
 | 
|---|
 | 554 |       if (btest <= threshold) {
 | 
|---|
 | 555 |           b1 = btest;
 | 
|---|
 | 556 |           r1 = rtest;
 | 
|---|
 | 557 |           //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b0 << endl;
 | 
|---|
 | 558 |         }
 | 
|---|
 | 559 |       else {
 | 
|---|
 | 560 |           b0 = btest;
 | 
|---|
 | 561 |           r0 = rtest;
 | 
|---|
 | 562 |           //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl;
 | 
|---|
 | 563 |         }
 | 
|---|
 | 564 |     }
 | 
|---|
 | 565 |   return r1;
 | 
|---|
 | 566 | }
 | 
|---|
 | 567 | 
 | 
|---|
 | 568 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 569 | 
 | 
|---|
 | 570 | // Local Variables:
 | 
|---|
 | 571 | // mode: c++
 | 
|---|
 | 572 | // c-file-style: "CLJ"
 | 
|---|
 | 573 | // End:
 | 
|---|