00001 """Compute Hermite-Gauss basis functions very quickly and efficiently using
00002 Numerov's method to solve the underlying differential equations"""
00003 _rcsid="$Id: hermite_numerov.py,v 1.7 2003/10/03 14:38:45 mendenhall Exp $"
00004
00005 import math
00006 import Numeric
00007 import spline
00008 import time
00009
00010 hermite_x_bound=15.0
00011 hermite_n_points=5000
00012
00013 def generate_table(order, final_x=None, npoints=None):
00014 "generate a spline table of H[n](x) exp(-x^2/2) ... a Hermite-Gauss basis function, using the Numerov method"
00015 if final_x is None:
00016 final_x=hermite_x_bound
00017
00018 if npoints is None:
00019 npoints=hermite_n_points
00020
00021 Y=Numeric.zeros(npoints+1, Numeric.Float)
00022 dx=float(final_x)/npoints
00023 dx2=dx*dx
00024 e2=2*order+1
00025 x=-final_x+Numeric.array(range(npoints+1),Numeric.Float)*dx
00026 V=(x*x-e2)
00027
00028 ypsifact=1.0/(1.0-(dx*dx/12.0)*V)
00029 coef=2.0+dx2*V*ypsifact
00030
00031 Y[0]=1.0/ypsifact[0]
00032 Y[1]=math.exp(math.sqrt(V[0])*dx))/ypsifact[1]
00033
00034 for i in range(1,npoints):
00035 yy=Y[i+1]=Y[i]*coef[i]-Y[i-1]
00036 if abs(yy) > 1e20:
00037 Y*=1e-20
00038
00039 psi = Y*ypsifact
00040
00041 x=-final_x+Numeric.array(range(2*npoints+1),Numeric.Float)*dx
00042
00043 if order%2 == 0:
00044 y=Numeric.concatenate((psi, psi[::-1][1:]))
00045 else:
00046 psi[-1]=0
00047 y=Numeric.concatenate((psi, -psi[::-1][1:]))
00048
00049 y=y*math.sqrt(1.0/(Numeric.dot(y,y)*dx))
00050 y2=spline.spline(x, y)
00051 return (final_x, x,y,y2)
00052
00053 hermite_cache={}
00054
00055 def hermite_gauss(order,x, cache_key=None):
00056 "compute h[order](x)*exp(-x^2/2). x may be an array, and cache_key should be a unique identifier for x if cacheing is desired."
00057 if type(x) is not type(1.0):
00058 xmax=max(abs(x))
00059 else:
00060 xmax=abs(x)
00061
00062 if (not hermite_cache.has_key(order)) or hermite_cache[order][0] < xmax:
00063 q=generate_table(order, max(1.5*xmax, hermite_x_bound))
00064 hermite_cache[order]=q
00065
00066 if cache_key and hermite_cache.has_key((order, cache_key)):
00067 hermite_cache[(order, cache_key)][0]=time.time()
00068 return hermite_cache[(order, cache_key)][1]
00069 else:
00070 xmax, xa, ya, y2a=hermite_cache[order]
00071 y= spline.splint(xa, ya, y2a, x)
00072 if cache_key:
00073 hermite_cache[(order,cache_key)]=[time.time(), y]
00074 return y
00075
00076 def purge_cache():
00077 "purge_cache() clears all pre-gridded datasets from the cache, leaving the raw interpolating functions"
00078 k=hermite_cache.keys()
00079 for i in k:
00080 if type(i) is not type(1):
00081 del hermite_cache[i]
00082
00083 integral_cache={}
00084
00085 def hermite_gauss_integral(m, n, x0, x1, stepsize=0.01):
00086 "compute integral(h[m](x}*h[n](x)*exp(-x^2),{x,x0,x1})"
00087 if m>n:
00088 m,n = n,m
00089 xmax=max(abs(x0), abs(x1))
00090 if not integral_cache.has_key((m,n)) or integral_cache[(m,n)][0] < xmax:
00091
00092
00093 hermite_gauss(m,xmax)
00094 hermite_gauss(n,xmax)
00095 xm, xa1, ya1, y2a1 = hermite_cache[m]
00096 xm, xa2, ya2, y2a2 = hermite_cache[n]
00097
00098 stepcount=int(2.0*xmax/stepsize)
00099 if stepcount%2==0:
00100 stepcount=stepcount+1
00101 stepsize=2*xmax/(stepcount-1)
00102 xlist=Numeric.array(range(stepcount),Numeric.Float)*stepsize - xmax
00103 y=spline.splint(xa1, ya1, y2a1, xlist)*spline.splint(xa2, ya2, y2a2, xlist)
00104 hmn2=spline.spline(xlist, y)
00105 yint=Numeric.cumsum(y[0:-2:2]+y[2::2]+4.0*y[1::2])*(stepsize/3.0)
00106 yint=Numeric.concatenate( ( (0,), yint ))
00107 yi2=spline.spline(xlist[::2], yint)
00108 integral_cache[(m,n)]=(xmax, xlist[::2], yint, yi2, stepsize, xlist, y, hmn2)
00109
00110 xmax, xa, ya, y2a, stepjunk, xjunk, yjunk, hmn2junk=integral_cache[(m,n)]
00111 iv1, iv2=spline.splint(xa, ya, y2a, (x0, x1) )
00112 return iv2-iv1
00113
00114 def hermite_gauss_matrix_element(m, n, x0, x1, f, stepsize=0.01):
00115 "compute integral(h[m](x}*h[n](x)*exp(-x^2)*f(x),{x,x0,x1}) : f should be able to be evaluated with a vector x"
00116 if m>n:
00117 m,n = n,m
00118 xmax=max(abs(x0), abs(x1))
00119 if not integral_cache.has_key((m,n)) or integral_cache[(m,n)][0] < xmax:
00120 hermite_gauss_integral(m,n,x0,x1)
00121
00122 jxmax, jxa, jya, jy2a, jstepsize, xa, hmn, hmn2=integral_cache[(m,n)]
00123
00124 stepcount=int((x1-x0)/stepsize)
00125 if stepcount%2==0:
00126 stepcount=stepcount+1
00127 stepsize=(x1-x0)/(stepcount-1)
00128 xlist=Numeric.array(range(stepcount),Numeric.Float)*stepsize + x0
00129 y=spline.splint(xa, hmn, hmn2, xlist)*f(xlist)
00130 yint=Numeric.sum(y[0:-2:2]+y[2::2]+4.0*y[1::2])*(stepsize/3.0)
00131 return yint
00132
00133 if __name__=="__main__":
00134 print "\n***Start"
00135 for m in range(10):
00136 for n in range(10):
00137 print m,n,("%10.4f " % hermite_gauss_integral(m,n,-10., 10.)),
00138 print "%10.4f" % hermite_gauss_matrix_element(m,n,-.5, 0.5, lambda x: 1.0),
00139 print "%10.4f" % hermite_gauss_integral(m,n,-.5, 0.5)
00140
00141
00142
00143
00144
00145
00146