#!/usr/bin/env python
"""Plot some Bessel functions of integer order, using Scipy and pylab"""
import scipy.special
import numpy as N
import scipy as S
import pylab as P
# shorthand
special = S.special
def jn_asym(n,x):
"""Asymptotic form of jn(x) for x>>n"""
return S.sqrt(2.0/S.pi/x)*S.cos(x-(n*S.pi/2.0+S.pi/4.0))
# build a range of values to plot in
x = N.linspace(0,30,400)
# Start by plotting the well-known j0 and j1
P.figure()
P.plot(x,special.j0(x),label='$J_0$')
P.plot(x,special.j1(x),label='$J_1$')
# Show a higher-order Bessel function
n = 5
P.plot(x,special.jn(n,x),label='$J_%s$' % n)
# and compute its asymptotic form (valid for x>>n, where n is the order). We
# must first find the valid range of x where at least x>n:
x_asym = S.compress(x>n,x)
P.plot(x_asym,jn_asym(n,x_asym),label='$J_%s$ (asymptotic)' % n)
# Finish off the plot
P.legend()
P.title('Bessel Functions')
# horizontal line at 0 to show x-axis, but after the legend
P.axhline(0)
# EXERCISE: redo the above, for the asymptotic range 0<x<<n. The asymptotic
# form in this regime is
# J(n,x) = (1/gamma(n+1))(x/2)^n
# Now, let's verify numerically the recursion relation
# J(n+1,x) = (2n/x)J(n,x)-J(n-1,x)
jn = special.jn # just a shorthand
# Be careful to check only for x!=0, to avoid divisions by zero
xp = S.compress(x>0.0,x) # positive x
# construct both sides of the recursion relation, these should be equal
j_np1 = jn(n+1,xp)
j_np1_rec = (2.0*n/xp)*jn(n,xp)-jn(n-1,xp)
# Now make a nice error plot of the difference, in a new figure
P.figure()
P.semilogy(xp,abs(j_np1-j_np1_rec),'r+-')
P.title('Error in recursion for $J_%s$' % n)
P.grid()
# Don't forget a show() call at the end of the script
P.show()