📄 fjt.cc
字号:
//// fjt.cc//// Copyright (C) 2001 Edward Valeev//// Author: Edward Valeev <edward.valeev@chemistry.gatech.edu>// Maintainer: EV//// 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 __GNUG__#pragma implementation#endif/* These routines are based on the gamfun program of * Trygve Ulf Helgaker (fall 1984) * and calculates the incomplete gamma function as * described by McMurchie & Davidson, J. Comp. Phys. 26 (1978) 218. * The original routine computed the function for maximum j = 20. */#include <stdlib.h>#include <math.h>#include <iostream>#include <chemistry/qc/cints/fjt.h>using namespace std;/*------------------------------------------------------ Initialize Taylor_Fm_Eval object (computes incomplete gamma function via Taylor interpolation) ------------------------------------------------------*/Taylor_Fjt_Eval::Taylor_Fjt_Eval(unsigned int mmax, double accuracy){ int i, m; int T_idx; double T, T_new; double egamma, func, dfuncdT; double term, sum, denom, rel_error; cutoff = epsilon; /*--------------------------------------- We are doing Taylor interpolation with n=TAYLOR_ORDER terms here: error <= delT^n/(n+1)! ---------------------------------------*/ order_interp = TAYLOR_ORDER; delT = 2.0*pow(cutoff*fac[order_interp+1], 1.0/order_interp); max_m = mmax + order_interp - 1; /*------------------------------------------------ Check if Taylor_Fm_Eval has been initialized with the same mmax before: 2) yes - re-initialize again 3) no - initialize ------------------------------------------------*/ if (grid != NULL || T_crit != NULL) { free_Taylor_Fm_Eval(); } T_crit = new double[max_m + 1]; /*--- m=0 is included! ---*/ max_T = 0; /*--- Figure out T_crit for each m and put into the T_crit ---*/ for(m=max_m;m>=0;m--) { /*------------------------------------------ Newton-Raphson method to solve T^{m-0.5}*exp(-T) = epsilon*Gamma(m+0.5) The solution is the max T for which to do the interpolation ------------------------------------------*/ T = -log(epsilon); egamma = epsilon*sqrt(M_PI)*df[2*m]/pow(2,m); T_new = T; do { T = T_new; func = pow(T,m-0.5) * exp(-T) - egamma; dfuncdT = ((m-0.5) * pow(T,m-1.5) - pow(T,m-0.5)) * exp(-T); if (dfuncdT >= 0.0) { T_new *= 2.5; continue; } T_new = T - func/dfuncdT; if ( T_new <= 0.0 ) { T_new = T / 2.0; } } while (fabs(func/egamma) >= SOFT_ZERO); T_crit[m] = T_new; T_idx = floor(T_new/delT); if (T_idx > max_T) max_T = T_idx; } /*------------------------------------------------------- Tabulate the gamma function from t=delT to T_crit[m]: 1) include T=0 though the table is empty for T=0 since Fm(0) is simple to compute 2) modified MacLaurin series converges fastest for the largest m -> use it to compute Fmmax(T) see JPC 94, 5564 (1990). 3) then either use the series to compute the rest of the row or maybe use downward recursion -------------------------------------------------------*/ grid = block_matrix(max_T+1,max_m+1); /*--- do the mmax first ---*/ for(m=0;m<=max_m;m++) for(T_idx = max_T; T_idx >= 0; T_idx--) { T = T_idx*delT; denom = (m+0.5); term = 0.5*exp(-T)/denom; sum = term; do { denom += 1.0; term *= T/denom; sum += term; rel_error = term/sum; } while (rel_error >= cutoff); grid[T_idx][m] = sum; }}Taylor_Fjt_Eval::~Taylor_Fm_Eval(){ delete[] T_crit; T_crit = NULL; free_block(grid); grid = NULL;}/* Using the tabulated incomplete gamma function in gtable, compute * the incomplete gamma function for a particular wval for all 0<=j<=J. * The result is placed in the global intermediate int_fjttable. */double *Taylor_Fjt_Eval::compute_Fjt(double T, unsigned int l){ int m; unsigned int T_ind; double T_crit, two_T, exp_mT, h, F_m, F_mp1; double *F_row;#define STATIC_OO2NP1#define STATIC_OON#include "static.h" T_crit = Taylor_Fm_Eval.T_crit[l]; two_T = 2.0*T; /*------------------------ First compute Fl(T) ... ------------------------*/ if (T > T_crit) { /*--- Asymptotic formula ---*/ F[l] = df[2*l]*sqrt(M_PI/2)/pow(two_T,l+0.5); } else { /*--- Taylor interpolation ---*/ T_ind = floor(0.5+T/Taylor_Fm_Eval.delT); h = T_ind*Taylor_Fm_Eval.delT - T; F_row = Taylor_Fm_Eval.grid[T_ind] + l; F[l] = F_row[0] + h*(F_row[1] + oon[2]*h*(F_row[2] + oon[3]*h*(F_row[3] + oon[4]*h*(F_row[4] + oon[5]*h*(F_row[5]))))); } /*------------------------------------ And then do downward recursion in m ------------------------------------*/ if (l > 0) { F_mp1 = F[l]; exp_mT = exp(-T); for(m=l-1;m>=0;m--) { F_m = (exp_mT + two_T*F_mp1)*oo2np1[m]; F[m] = F_m; F_mp1 = F_m; } } return Fjt_buffer;}/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "CLJ-CONDENSED"// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -