Roberto Di Remigio, Luca Frediani
In this assignment we require you to look at some one-dimensional quantum systems and leverage the knowledge of Python acquired during the seminars. Many of the tasks can also be achieved with pen-and-paper derivations, but we encourage to use Python as much as possible. Remember that:
numpy, scipy, matplotlib and sympy are very rich modules, with extensive online documentation that you are encouraged to search throughThe eigenfunctions for the hydrogen-like atoms can be expressed as the product of a radial and angular part: \begin{equation} \psi_{nlm}(r, \theta, \phi) = R_{nl}(r)Y_{l}^{m}(\theta, \phi) \end{equation} These eigenfunctions are expressed in spherical polar coordinates. $r$ is the distance between the electron and the nucleus, $\theta$ is the polar angle and $\phi$ the azimuthal angle.
The general form of the radial function is: \begin{equation} R_{nl} (r) = \sqrt {{\left ( \frac{2 Z}{n a_{\mu}} \right ) }^3\frac{(n-l-1)!}{2n[(n+l)!]} } e^{- Z r / {n a_{\mu}}} \left ( \frac{2 Z r}{n a_{\mu}} \right )^{l} L_{n-l-1}^{2l+1} \left ( \frac{2 Z r}{n a_{\mu}} \right ) \end{equation} where:
scipy has a module for special functions Check there if you can find a function for the generalized Laguerre polynomialsNow that we have looked at the radial part of hydrogen-like atoms wavefunctions, we can have a closer look at their angular part. The angular part is expressed in terms of spherical harmonics: \begin{equation} Y_l^m(\theta, \phi) = (-1)^{(m+|m|)/2}\sqrt{\frac{(2l+1)(l-|m|)!}{4\pi(l+|m|)!}}P_l^{|m|}(\cos\theta)\mathrm{e}^{\mathrm{i}m\phi} \end{equation} where $P_l^{|m|}(\cos\theta)$ are associated Legendre polynomials.
scipy already has the definition of the spherical harmonics
In [8]:
%matplotlib inline
from __future__ import division
import scipy as sci
import scipy.special as sp
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm, colors
l = 0 # degree
m = 0 # order
PHI, THETA = np.mgrid[0:2*np.pi:200j, 0:np.pi:100j] # arrays of angular variables
## Plotting the module
Ylm_abs = np.abs(sp.sph_harm(m, l, PHI, THETA)) # Array with the absolute values of Ylm
# Now we convert to cartesian coordinates for the 3D representation
X_abs = Ylm_abs * np.sin(THETA) * np.cos(PHI)
Y_abs = Ylm_abs * np.sin(THETA) * np.sin(PHI)
Z_abs = Ylm_abs * np.cos(THETA)
N_abs = Ylm_abs/Ylm_abs.max() # Normalize R for the plot colors to cover the entire range of colormap.
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'), figsize=(12,10))
im = ax.plot_surface(X_abs, Y_abs, Z_abs, rstride=1, cstride=1, facecolors=cm.jet(N_abs))
ax.set_title(r'$|Y^0_0|$', fontsize=20)
m = cm.ScalarMappable(cmap=cm.jet)
m.set_array(Ylm_abs) # Assign the unnormalized data array to the mappable
# so that the scale corresponds to the values of Ylm_abs
fig.colorbar(m, shrink=0.8);
In [14]:
%matplotlib inline
from __future__ import division
import scipy as sci
import scipy.special as sp
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm, colors
l = 1 # degree
m = 0 # order
PHI, THETA = np.mgrid[0:2*np.pi:200j, 0:np.pi:100j] # arrays of angular variables
## Plotting the real part
Ylm_real = sp.sph_harm(m, l, PHI, THETA).real # array with the real values of Ylm
X_real = Ylm_real * np.sin(THETA) * np.cos(PHI)
Y_real = Ylm_real * np.sin(THETA) * np.sin(PHI)
Z_real = Ylm_real * np.cos(THETA)
# As Ylm_real has negative values, we'll use an instance of Normalize
# see http://stackoverflow.com/questions/25023075/normalizing-colormap-used-by-facecolors-in-matplotlib
norm = colors.Normalize()
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'), figsize=(14,10))
m = cm.ScalarMappable(cmap=cm.jet)
ax.plot_surface(X_real, Y_real, Z_real, rstride=1, cstride=1, facecolors=cm.jet(norm(Ylm_real)))
ax.set_title('$\Re(Y^0_0)$', fontsize=20)
m.set_array(Ylm_real)
fig.colorbar(m, shrink=0.8);
In [12]:
%matplotlib inline
from __future__ import division
import scipy as sci
import scipy.special as sp
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm, colors
l = 0 # degree
m = 0 # order
PHI, THETA = np.mgrid[0:2*np.pi:200j, 0:np.pi:100j] # arrays of angular variables
## Plotting the imaginary part
Ylm_imag = sp.sph_harm(m, l, PHI, THETA).imag # array with the imaginary values of Ylm
X_imag = Ylm_imag * np.sin(THETA) * np.cos(PHI)
Y_imag = Ylm_imag * np.sin(THETA) * np.sin(PHI)
Z_imag = Ylm_imag * np.cos(THETA)
# As Ylm_imag has negative values, we'll use an instance of Normalize
# see http://stackoverflow.com/questions/25023075/normalizing-colormap-used-by-facecolors-in-matplotlib
norm = colors.Normalize()
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'), figsize=(14,10))
m = cm.ScalarMappable(cmap=cm.jet)
ax.plot_surface(X_imag, Y_imag, Z_imag, rstride=1, cstride=1, facecolors=cm.jet(norm(Ylm_imag)))
ax.set_title('$\Im(Y^0_0)$', fontsize=20)
m.set_array(Ylm_imag)
fig.colorbar(m, shrink=0.8);
In the lectures and seminars we have considered potential wells with infinite barries, i.e. cases where the quantum particle is confined inside a finite space and cannot escape. More interesting systems are those where the particle is confined within a well, with finite barriers:
Using finite differences, solve the quantum mechanical problem for the finite potential well. You should prepare a table with the first 5 eigenvalues, plot the first 5 eigenvectors and corresponding probability distributions.
Hint: Avoid full diagonalization of $\mathbf{H}$
This can be done by using sparse matrix operations as provided by scipy. You can then ask for the $k$ lowest eigenvectors and eigenvalues. The general function to use is scipy.sparse.linalg.eigs. For symmetric matrices it's preferable to use scipy.sparse.linalg.eigsh
Read the documentation to understand how to use these functions
Can this model be used as a crude approximation to the harmonic oscillator potential? Why? If yes, how would you compare the results from the two models? Hint: Think about the turning points of the harmonic oscillator
What happens when the energy is higher that $V_0$?
Another interesting potential is the semi-infinite potential well:
In [25]:
import numpy as np
from scipy.sparse import linalg as la
import matplotlib.pyplot as plt
%matplotlib inline
def finite_well(x, L):
V_0 = 100.0
V = 0.0
if np.abs(x) <= L:
V = V_0
return V
def finite_difference_Hamiltonian(grid, potential):
""" Return finite difference Hamiltonian using a centered, three-point stencil
grid -- equispaced grid
potential -- potential function in the Hamiltonian
"""
N = grid.size
h = grid[1] - grid[0]
hamiltonian = np.zeros((N, N))
for i in range(N):
hamiltonian[i, i] = 1.0 / (h**2) + potential(grid[i])
for j in range(N):
if (j == i+1) or (j == i-1):
hamiltonian[i, j] = -1.0/(2.0 * h**2)
return hamiltonian
# Discretization set up
L = 1.0
N = 1000
grid = np.linspace(-L -1.0, L + 1.0, N)
H = np.zeros((N, N))
H = finite_difference_Hamiltonian(grid, (lambda x : finite_well(x, L)))
E, psi = la.eigsh(H, k=5, which='SM')
plt.plot(grid, psi[:, 0])
Out[25]:
In [ ]: