| [0b990d] | 1 | //
 | 
|---|
 | 2 | // fjt.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 __GNUG__
 | 
|---|
 | 29 | #pragma implementation
 | 
|---|
 | 30 | #endif
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | /* These routines are based on the gamfun program of
 | 
|---|
 | 33 |  * Trygve Ulf Helgaker (fall 1984)
 | 
|---|
 | 34 |  * and calculates the incomplete gamma function as
 | 
|---|
 | 35 |  * described by McMurchie & Davidson, J. Comp. Phys. 26 (1978) 218.
 | 
|---|
 | 36 |  * The original routine computed the function for maximum j = 20.
 | 
|---|
 | 37 |  */
 | 
|---|
 | 38 | 
 | 
|---|
 | 39 | #include <stdlib.h>
 | 
|---|
 | 40 | #include <math.h>
 | 
|---|
 | 41 | 
 | 
|---|
 | 42 | #include <iostream>
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | #include <util/misc/formio.h>
 | 
|---|
 | 45 | #include <util/misc/exenv.h>
 | 
|---|
 | 46 | #include <chemistry/qc/intv3/fjt.h>
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | using namespace std;
 | 
|---|
 | 49 | using namespace sc;
 | 
|---|
 | 50 | 
 | 
|---|
 | 51 |  /* Tablesize should always be at least 121. */
 | 
|---|
 | 52 | #define TABLESIZE 121
 | 
|---|
 | 53 | 
 | 
|---|
 | 54 | /* Tabulate the incomplete gamma function and put in gtable. */
 | 
|---|
 | 55 | /*
 | 
|---|
 | 56 |  *     For J = JMAX a power series expansion is used, see for
 | 
|---|
 | 57 |  *     example Eq.(39) given by V. Saunders in "Computational
 | 
|---|
 | 58 |  *     Techniques in Quantum Chemistry and Molecular Physics",
 | 
|---|
 | 59 |  *     Reidel 1975.  For J < JMAX the values are calculated
 | 
|---|
 | 60 |  *     using downward recursion in J.
 | 
|---|
 | 61 |  */
 | 
|---|
 | 62 | FJT::FJT(int max)
 | 
|---|
 | 63 | {
 | 
|---|
 | 64 |   int i,j;
 | 
|---|
 | 65 |   double denom,d2jmax1,r2jmax1,wval,d2wval,sum,term,rexpw;
 | 
|---|
 | 66 | 
 | 
|---|
 | 67 |   maxj = max;
 | 
|---|
 | 68 | 
 | 
|---|
 | 69 |   /* Allocate storage for gtable and int_fjttable. */
 | 
|---|
 | 70 |   int_fjttable = new double[maxj+1];
 | 
|---|
 | 71 |   gtable = new double*[ngtable()];
 | 
|---|
 | 72 |   for (i=0; i<ngtable(); i++) {
 | 
|---|
 | 73 |       gtable[i] = new double[TABLESIZE];
 | 
|---|
 | 74 |     }
 | 
|---|
 | 75 | 
 | 
|---|
 | 76 |   /* Tabulate the gamma function for t(=wval)=0.0. */
 | 
|---|
 | 77 |   denom = 1.0;
 | 
|---|
 | 78 |   for (i=0; i<ngtable(); i++) {
 | 
|---|
 | 79 |     gtable[i][0] = 1.0/denom;
 | 
|---|
 | 80 |     denom += 2.0;
 | 
|---|
 | 81 |     }
 | 
|---|
 | 82 | 
 | 
|---|
 | 83 |   /* Tabulate the gamma function from t(=wval)=0.1, to 12.0. */
 | 
|---|
 | 84 |   d2jmax1 = 2.0*(ngtable()-1) + 1.0;
 | 
|---|
 | 85 |   r2jmax1 = 1.0/d2jmax1;
 | 
|---|
 | 86 |   for (i=1; i<TABLESIZE; i++) {
 | 
|---|
 | 87 |     wval = 0.1 * i;
 | 
|---|
 | 88 |     d2wval = 2.0 * wval;
 | 
|---|
 | 89 |     term = r2jmax1;
 | 
|---|
 | 90 |     sum = term;
 | 
|---|
 | 91 |     denom = d2jmax1;
 | 
|---|
 | 92 |     for (j=2; j<=200; j++) {
 | 
|---|
 | 93 |       denom = denom + 2.0;
 | 
|---|
 | 94 |       term = term * d2wval / denom;
 | 
|---|
 | 95 |       sum = sum + term;
 | 
|---|
 | 96 |       if (term <= 1.0e-15) break;
 | 
|---|
 | 97 |       }
 | 
|---|
 | 98 |     rexpw = exp(-wval);
 | 
|---|
 | 99 | 
 | 
|---|
 | 100 |     /* Fill in the values for the highest j gtable entries (top row). */
 | 
|---|
 | 101 |     gtable[ngtable()-1][i] = rexpw * sum;
 | 
|---|
 | 102 | 
 | 
|---|
 | 103 |     /* Work down the table filling in the rest of the column. */
 | 
|---|
 | 104 |     denom = d2jmax1;
 | 
|---|
 | 105 |     for (j=ngtable() - 2; j>=0; j--) {
 | 
|---|
 | 106 |       denom = denom - 2.0;
 | 
|---|
 | 107 |       gtable[j][i] = (gtable[j+1][i]*d2wval + rexpw)/denom;
 | 
|---|
 | 108 |       }
 | 
|---|
 | 109 |     }
 | 
|---|
 | 110 | 
 | 
|---|
 | 111 |   /* Form some denominators, so divisions can be eliminated below. */
 | 
|---|
 | 112 |   denomarray = new double[max+1];
 | 
|---|
 | 113 |   denomarray[0] = 0.0;
 | 
|---|
 | 114 |   for (i=1; i<=max; i++) {
 | 
|---|
 | 115 |     denomarray[i] = 1.0/(2*i - 1);
 | 
|---|
 | 116 |     }
 | 
|---|
 | 117 | 
 | 
|---|
 | 118 |   wval_infinity = 2*max + 37.0;
 | 
|---|
 | 119 |   itable_infinity = (int) (10 * wval_infinity);
 | 
|---|
 | 120 | 
 | 
|---|
 | 121 |   }
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 | FJT::~FJT()
 | 
|---|
 | 124 | {
 | 
|---|
 | 125 |   delete[] int_fjttable;
 | 
|---|
 | 126 |   for (int i=0; i<maxj+7; i++) {
 | 
|---|
 | 127 |       delete[] gtable[i];
 | 
|---|
 | 128 |     }
 | 
|---|
 | 129 |   delete[] gtable;
 | 
|---|
 | 130 |   delete[] denomarray;
 | 
|---|
 | 131 |   }
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 | /* Using the tabulated incomplete gamma function in gtable, compute
 | 
|---|
 | 134 |  * the incomplete gamma function for a particular wval for all 0<=j<=J.
 | 
|---|
 | 135 |  * The result is placed in the global intermediate int_fjttable.
 | 
|---|
 | 136 |  */
 | 
|---|
 | 137 | double *
 | 
|---|
 | 138 | FJT::values(int J,double wval)
 | 
|---|
 | 139 | {
 | 
|---|
 | 140 |   const double sqrpih =  0.886226925452758;
 | 
|---|
 | 141 |   const double coef2 =  0.5000000000000000;
 | 
|---|
 | 142 |   const double coef3 = -0.1666666666666667;
 | 
|---|
 | 143 |   const double coef4 =  0.0416666666666667;
 | 
|---|
 | 144 |   const double coef5 = -0.0083333333333333;
 | 
|---|
 | 145 |   const double coef6 =  0.0013888888888889;
 | 
|---|
 | 146 |   const double gfac30 =  0.4999489092;
 | 
|---|
 | 147 |   const double gfac31 = -0.2473631686;
 | 
|---|
 | 148 |   const double gfac32 =  0.321180909;
 | 
|---|
 | 149 |   const double gfac33 = -0.3811559346;
 | 
|---|
 | 150 |   const double gfac20 =  0.4998436875;
 | 
|---|
 | 151 |   const double gfac21 = -0.24249438;
 | 
|---|
 | 152 |   const double gfac22 =  0.24642845;
 | 
|---|
 | 153 |   const double gfac10 =  0.499093162;
 | 
|---|
 | 154 |   const double gfac11 = -0.2152832;
 | 
|---|
 | 155 |   const double gfac00 = -0.490;
 | 
|---|
 | 156 | 
 | 
|---|
 | 157 |   double wdif, d2wal, rexpw, /* denom, */ gval, factor, rwval, term;
 | 
|---|
 | 158 |   int i, itable, irange;
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 |   if (J>maxj) {
 | 
|---|
 | 161 |     ExEnv::errn()
 | 
|---|
 | 162 |       << scprintf("the int_fjt routine has been incorrectly used")
 | 
|---|
 | 163 |       << endl;
 | 
|---|
 | 164 |     ExEnv::errn()
 | 
|---|
 | 165 |       << scprintf("J = %d but maxj = %d",J,maxj)
 | 
|---|
 | 166 |       << endl;
 | 
|---|
 | 167 |     abort();
 | 
|---|
 | 168 |     }
 | 
|---|
 | 169 | 
 | 
|---|
 | 170 |   /* Compute an index into the table. */
 | 
|---|
 | 171 |   /* The test is needed to avoid floating point exceptions for
 | 
|---|
 | 172 |    * large values of wval. */
 | 
|---|
 | 173 |   if (wval > wval_infinity) {
 | 
|---|
 | 174 |     itable = itable_infinity;
 | 
|---|
 | 175 |     }
 | 
|---|
 | 176 |   else {
 | 
|---|
 | 177 |     itable = (int) (10.0 * wval);
 | 
|---|
 | 178 |     }
 | 
|---|
 | 179 | 
 | 
|---|
 | 180 |   /* If itable is small enough use the table to compute int_fjttable. */
 | 
|---|
 | 181 |   if (itable < TABLESIZE) {
 | 
|---|
 | 182 | 
 | 
|---|
 | 183 |     wdif = wval - 0.1 * itable;
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |     /* Compute fjt for J. */
 | 
|---|
 | 186 |     int_fjttable[J] = (((((coef6 * gtable[J+6][itable]*wdif
 | 
|---|
 | 187 |                             + coef5 * gtable[J+5][itable])*wdif
 | 
|---|
 | 188 |                              + coef4 * gtable[J+4][itable])*wdif
 | 
|---|
 | 189 |                               + coef3 * gtable[J+3][itable])*wdif
 | 
|---|
 | 190 |                                + coef2 * gtable[J+2][itable])*wdif
 | 
|---|
 | 191 |                                 -  gtable[J+1][itable])*wdif
 | 
|---|
 | 192 |                          +  gtable[J][itable];
 | 
|---|
 | 193 | 
 | 
|---|
 | 194 |     /* Compute the rest of the fjt. */
 | 
|---|
 | 195 |     d2wal = 2.0 * wval;
 | 
|---|
 | 196 |     rexpw = exp(-wval);
 | 
|---|
 | 197 |     /* denom = 2*J + 1; */
 | 
|---|
 | 198 |     for (i=J; i>0; i--) {
 | 
|---|
 | 199 |       /* denom = denom - 2.0; */
 | 
|---|
 | 200 |       int_fjttable[i-1] = (d2wal*int_fjttable[i] + rexpw)*denomarray[i];
 | 
|---|
 | 201 |       }
 | 
|---|
 | 202 |     }
 | 
|---|
 | 203 |   /* If wval <= 2*J + 36.0, use the following formula. */
 | 
|---|
 | 204 |   else if (itable <= 20*J + 360) {
 | 
|---|
 | 205 |     rwval = 1.0/wval;
 | 
|---|
 | 206 |     rexpw = exp(-wval);
 | 
|---|
 | 207 | 
 | 
|---|
 | 208 |     /* Subdivide wval into 6 ranges. */
 | 
|---|
 | 209 |     irange = itable/30 - 3;
 | 
|---|
 | 210 |     if (irange == 1) {
 | 
|---|
 | 211 |       gval = gfac30 + rwval*(gfac31 + rwval*(gfac32 + rwval*gfac33));
 | 
|---|
 | 212 |       int_fjttable[0] = sqrpih*sqrt(rwval) - rexpw*gval*rwval;
 | 
|---|
 | 213 |       }
 | 
|---|
 | 214 |     else if (irange == 2) {
 | 
|---|
 | 215 |       gval = gfac20 + rwval*(gfac21 + rwval*gfac22);
 | 
|---|
 | 216 |       int_fjttable[0] = sqrpih*sqrt(rwval) - rexpw*gval*rwval;
 | 
|---|
 | 217 |       }
 | 
|---|
 | 218 |     else if (irange == 3 || irange == 4) {
 | 
|---|
 | 219 |       gval = gfac10 + rwval*gfac11;
 | 
|---|
 | 220 |       int_fjttable[0] = sqrpih*sqrt(rwval) - rexpw*gval*rwval;
 | 
|---|
 | 221 |       }
 | 
|---|
 | 222 |     else if (irange == 5 || irange == 6) {
 | 
|---|
 | 223 |       gval = gfac00;
 | 
|---|
 | 224 |       int_fjttable[0] = sqrpih*sqrt(rwval) - rexpw*gval*rwval;
 | 
|---|
 | 225 |       }
 | 
|---|
 | 226 |     else {
 | 
|---|
 | 227 |       int_fjttable[0] = sqrpih*sqrt(rwval);
 | 
|---|
 | 228 |       }
 | 
|---|
 | 229 | 
 | 
|---|
 | 230 |     /* Compute the rest of the int_fjttable from int_fjttable[0]. */
 | 
|---|
 | 231 |     factor = 0.5 * rwval;
 | 
|---|
 | 232 |     term = factor * rexpw;
 | 
|---|
 | 233 |     for (i=1; i<=J; i++) {
 | 
|---|
 | 234 |       int_fjttable[i] = factor * int_fjttable[i-1] - term;
 | 
|---|
 | 235 |       factor = rwval + factor;
 | 
|---|
 | 236 |       }
 | 
|---|
 | 237 |     }
 | 
|---|
 | 238 |   /* For large values of wval use this algorithm: */
 | 
|---|
 | 239 |   else {
 | 
|---|
 | 240 |     rwval = 1.0/wval;
 | 
|---|
 | 241 |     int_fjttable[0] = sqrpih*sqrt(rwval);
 | 
|---|
 | 242 |     factor = 0.5 * rwval;
 | 
|---|
 | 243 |     for (i=1; i<=J; i++) {
 | 
|---|
 | 244 |       int_fjttable[i] = factor * int_fjttable[i-1];
 | 
|---|
 | 245 |       factor = rwval + factor;
 | 
|---|
 | 246 |       }
 | 
|---|
 | 247 |     }
 | 
|---|
 | 248 |   /* printf(" %2d %12.8f %4d %12.8f\n",J,wval,itable,int_fjttable[0]); */
 | 
|---|
 | 249 | 
 | 
|---|
 | 250 |   return int_fjttable;
 | 
|---|
 | 251 |   }
 | 
|---|
 | 252 | 
 | 
|---|
 | 253 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 254 | 
 | 
|---|
 | 255 | // Local Variables:
 | 
|---|
 | 256 | // mode: c++
 | 
|---|
 | 257 | // c-file-style: "CLJ-CONDENSED"
 | 
|---|
 | 258 | // End:
 | 
|---|