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