source: ThirdParty/mpqc_open/src/lib/chemistry/qc/intv3/fjt.cc

Candidate_v1.6.1
Last change on this file was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 7.4 KB
Line 
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
48using namespace std;
49using 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 */
62FJT::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
123FJT::~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 */
137double *
138FJT::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:
Note: See TracBrowser for help on using the repository browser.