Home
Manual
Packages
Global Index
Keywords
Quick Reference
|
/*
* fermii.i - $Id$
* incomplete Fermi-Dirac integrals of orders -1/2, 1/2, 3/2, 5/2
*/
local fermii ;
/* DOCUMENT #include "fermii.i"
* Incomplete Fermi-Dirac integrals of orders -1/2, 1/2, 3/2, 5/2
*
* after M. Goano, Algorithm 745, ACM TOMS 21, #3, pp 221-232 (Sept. 95)
*
* SEE ALSO: fdim12, fdi12, fdi32, fdi52
*/
require, "fermi.i";
require, "dawson.i";
func fdim12 (x, b)
/* DOCUMENT fdim12(x, b)
* return incomplete Fermi-Dirac integral of order -1/2,
* fdim12(x, b) = integral[b to inf]{ dt * t^-0.5 / (exp(t-x)+1) }
* default accuracy to about 1e-10
* SEE ALSO: fdi12, fdi32, fdi52
*/
{
name = "FDIM12";
x += 0.*b; b += 0.*x;
big = (x > b);
list = where(big);
if (numberof(list)) {
xx = x(list); bb = b(list);
fl = _fd_work(bb, exp(bb-xx), _s_m12);
fl = fdm12(xx) - sqrt(bb)/.5*(1.-fl);
}
list = where(!big);
if (numberof(list)) {
fs = x(list); bb = b(list);
fs = 1.77245385090551603*_fd_work(bb, exp(fs-bb), _b_m12);
}
return merge(fl, fs, big);
}
func fdi12 (x, b)
/* DOCUMENT fdi12(x, b)
* return incomplete Fermi-Dirac integral of order 1/2,
* fdi12(x, b) = integral[b to inf]{ dt * t^0.5 / (exp(t-x)+1) }
* default accuracy to about 1e-10
* SEE ALSO: fdim12, fdi32, fdi52
*/
{
name = "FDI12";
x += 0.*b; b += 0.*x;
big = (x > b);
list = where(big);
if (numberof(list)) {
xx = x(list); bb = b(list);
fl = _fd_work(bb, exp(bb-xx), _s_12);
fl = fd12(xx) - bb*sqrt(bb)/1.5*(1.-fl);
}
list = where(!big);
if (numberof(list)) {
fs = x(list); bb = b(list);
fs = 0.5*1.77245385090551603*_fd_work(bb, exp(fs-bb), _b_12);
}
return merge(fl, fs, big);
}
func fdi32 (x, b)
/* DOCUMENT fdi32(x, b)
* return incomplete Fermi-Dirac integral of order 1/2,
* fdi32(x, b) = integral[b to inf]{ dt * t^1.5 / (exp(t-x)+1) }
* default accuracy to about 1e-10
* SEE ALSO: fdim12, fdi12, fdi52
*/
{
name = "FDI32";
x += 0.*b; b += 0.*x;
big = (x > b);
list = where(big);
if (numberof(list)) {
xx = x(list); bb = b(list);
fl = _fd_work(bb, exp(bb-xx), _s_32);
fl = fd32(xx) - bb*bb*sqrt(bb)/2.5*(1.-fl);
}
list = where(!big);
if (numberof(list)) {
fs = x(list); bb = b(list);
fs = 0.75*1.77245385090551603*_fd_work(bb, exp(fs-bb), _b_32);
}
return merge(fl, fs, big);
}
func fdi52 (x, b)
/* DOCUMENT fdi52(x, b)
* return incomplete Fermi-Dirac integral of order 1/2,
* fdi32(x, b) = integral[b to inf]{ dt * t^2.5 / (exp(t-x)+1) }
* default accuracy to about 1e-10
* SEE ALSO: fdim12, fdi12, fdi32
*/
{
name = "FDI52";
x += 0.*b; b += 0.*x;
big = (x > b);
list = where(big);
if (numberof(list)) {
xx = x(list); bb = b(list);
fl = _fd_work(bb, exp(bb-xx), _s_52);
fl = fd52(xx) - bb*bb*bb*sqrt(bb)/3.5*(1.-fl);
}
list = where(!big);
if (numberof(list)) {
fs = x(list); bb = b(list);
fs = 1.875*1.77245385090551603*_fd_work(bb, exp(fs-bb), _b_52);
}
return merge(fl, fs, big);
}
/* power series coefficients involve
* x<b (_s_xx): related to half-integer incomplete gamma functions
* x>b (_b_xx): Kummer's M(1, k/2, -x) == Hypergeometric 1F1[1, k/2, -x]
*/
func _s_m12 (b, list)
{
small = (b<=0.005);
list = where(small);
if (numberof(list)) {
/* 1e-13 rational fit to 2/3(-x+2/5(x-2/7(x+2/9(x-2/11 x ...)))) */
bs = b(list);
bs = 1.-0.666666666666666667*bs*(1.+bs* 0.044572733182971606) /
(1.+bs*(0.44457273316463447+0.06354339731587551*bs));
}
list = where(!small);
if (numberof(list)) {
bl = sqrt(b(list));
bl = dawson(bl)/bl;
}
return merge(bs,bl, small);
}
func _b_m12 (b, i)
{
return _fd_eerfc(sqrt(b))/sqrt(i);
}
func _s_12 (b, list)
{
small = (b<=0.05);
list = where(small);
if (numberof(list)) {
/* 1e-13 rational fit to 2/5(-x+2/7(x-2/9(x+2/11(x-2/13 x ...)))) */
bs = b(list);
bs = 1. -
0.4*bs*(1.+bs*(0.022623753252252726+0.0035112573452158458*bs)) /
(1.+bs*(0.3083380389584768+0.028115777703514408*bs));
}
list= where(!small);
if (numberof(list)) {
bl = b(list);
b = sqrt(bl);
bl = 1.5*(1.-dawson(b)/b)/bl;
}
return merge(bs,bl, small);
}
func _b_12 (b, i)
{ /* 1.12837916709551257 = 2/sqrt(pi) */
bs = sqrt(b);
i = double(i);
return (_fd_eerfc(bs)+1.12837916709551257*bs)/(i*sqrt(i));
}
func _s_32 (b, list)
{
small = (b<=0.15);
list = where(small);
if (numberof(list)) {
/* 1e-13 rational fit to 2/7(-x+2/9(x-2/11(x+2/13(x-2/15 x ...)))) */
bs = b(list);
bs = 1. - 0.2857142857142857*bs*
(1.+bs*(0.13216490580251333+0.0091563412585936*bs)) /
(1.+bs*(0.3543871280251466+
bs*(0.047504995939997935+0.0024540010292377927*bs)));
}
list = where(!small);
if (numberof(list)) {
bl = b(list);
b = sqrt(bl);
bl = 1./bl;
bl = 2.5*(1.-1.5*(1.-dawson(b)/b)*bl)*bl;
}
return merge(bs,bl, small);
}
func _b_32 (b, i)
{ /* 1.12837916709551257 = 2/sqrt(pi) */
bs = sqrt(b);
i = double(i);
return (_fd_eerfc(bs)+1.12837916709551257*bs*
(1.+b*0.666666666666666667)) / (i*i*sqrt(i));
}
func _s_52 (b, list)
{
small = (b<=0.3);
list = where(small);
if (numberof(list)) {
/* 1e-13 rational fit to 2/9(-x+2/11(x-2/13(x+2/15(x-2/17 x ...)))) */
bs = b(list);
bs = 1. - 0.2222222222222222*bs*
(1.+bs*(0.13615817872751315 +0.007895641703391007*bs)) /
(1.+bs*(0.3179763605496484 +
bs*(0.037737497320199126+0.0016965253200319766*bs)));
}
list= where(!small);
if (numberof(list)) {
bl = b(list);
b = sqrt(bl);
bl = 1./bl;
bl = 3.5*(1.-2.5*(1.-1.5*(1.-dawson(b)/b)*bl)*bl)*bl;
}
return merge(bs,bl, small);
}
func _b_52 (b, i)
{ /* 1.12837916709551257 = 2/sqrt(pi) */
bs = sqrt(b);
i = double(i);
return (_fd_eerfc(bs)+1.12837916709551257*bs*
(1.+b*0.666666666666666667*(1.+b*.4))) / (i*i*i*sqrt(i));
}
func _fd_eerfc (x)
{
/* exp(x^2) * erfc(x), see erfc in dawson.i */
{ local mask1,mask2,mask3,mask4,xx,yy,zz; }
y = x*x;
if (any_in(,y,1., mask1, yy, x,xx))
e1 = exp(yy)*(1.0 - xx * (1.0 + _cheby_eval(_erf_1, 2.*yy-1.)));
if (any_in(1.,y,, mask2, z, x,xx)) {
yy = 1./xx;
if (any_in(,z,4., mask3, zz, yy,y))
e3 = y * (0.5 + _cheby_eval(_erfc_1, (8./zz-5.)/3.));
if (any_in(4.,z,, mask4, zz, yy,y))
e4 = y * (0.5 + _cheby_eval(_erfc_2, 8./zz-1.));
e2 = merge_n(e3,mask3, e4,mask4);
}
return merge_n(e1,mask1, e2,mask2);
}
func _fd_work (bb, fac, f)
{
/* note that fac always <=1 */
n = numberof(bb); /* always scalar or 1d */
if (n==1) { bb=[bb(1)]; fac=[fac(1)]; }
fd = fac*f(bb,1);
master = where(abs(fd) > 1e-99);
if (numberof(master)) {
bb = bb(master);
fac = fac(master);
facn = fac*fac;
sfacn = -1.;
bn = bb+bb;
fdi = summi = fd(master);
frac = [1.,1./summi];
/* biggest i recorded is 15 for _fd_tol=1e-9, 22 for 1e-13 */
for (i=2; i<=_fd_itmax; i++,bn+=bb,facn*=fac,sfacn*=-1.) {
fdiold = fdi;
/* levin u-algorithm to accelerate series convergence */
ri = 1./double(i);
summi += sfacn*(fdi = facn*f(bn,i));
cofb = (((1.-ri)^indgen(i-2:0:-1)*indgen(i-1)*ri))(-,-,);
frac = (cofb*frac)(,,cum);
frac += ([summi,1.]*(sfacn*ri*ri)/(fdi+1.e-99) - frac(,,0));
fd(master) = fdi = frac(,1,1)/frac(,2,1);
/* -- */
list = where(abs(fdi-fdiold) >= _fd_tol*abs(fdi));
if (!(n = numberof(list))) break;
if (n==numberof(fdi)) continue;
master = master(list);
fdi = fdi(list);
summi = summi(list);
frac = frac(list,,);
bn = bn(list);
bb = bb(list);
facn = facn(list);
fac = fac(list);
}
if (i > _fd_itmax) error, "convergence failure in "+name;
}
return fd;
}
_fd_itmax = 100;
_fd_tol = 1.e-9;
|