Hide code cell content
import mmf_setup;mmf_setup.nbinit()
%matplotlib inline
import numpy as np, matplotlib.pyplot as plt

This cell adds /home/docs/checkouts/readthedocs.org/user_builds/physics-555-quantum-technologies/checkouts/latest/src to your path, and contains some definitions for equations and some CSS for styling the notebook. If things look a bit strange, please try the following:

  • Choose "Trust Notebook" from the "File" menu.
  • Re-execute this cell.
  • Reload the notebook.

Bound States in the 1D Schrödinger Equation#

Here we consider the problem of finding the energies \(E\) of bound states in a 1D potential:

\[\begin{gather*} -\frac{\hbar^2}{2m}\psi''(x) + V(x)\psi(x) = E\psi(x). \end{gather*}\]

To simplify the problem, let assume that the potential is zero \(V(\abs{x}>R) = 0\) for \(x\) outside of some region \(-R < x < R\). This excludes some interesting examples, but simplifies our analysis considerably.

We will also assume that \(V(x)\) is sufficiently smooth so that numerical integration techniques will converge if we choose a sufficiently small step size. If you want to deal with \(\delta\)-functions, then you must replace these with something smooth like gaussians and then take the limit of zero width after the computation.

Question#

Given some attractive potential \(V(x)\) with compact support, how can we determine the bound state energies?

  1. How can you quickly estimate the ground state energy \(E_0\)?

  2. How can you quickly use numerical techniques to refine this?

Do It!

Stop here and this about this. Can you come up a simple problem of this type, that you can quickly solve? Start with something easy, but think about how you might generalize your methods if someone gives you a similar problem in the future.

Hints:

Need hints for choosing a potential \(V(x)\)?

A finite finite square well potential is fairly simple:

\[\begin{gather*} V(x) = \begin{cases} V_0 & -R < x < R,\\ 0 & \text{otherwise}. \end{cases} \end{gather*}\]

You have probably solved this at some point by matching plane waves in the various regions. You may recall that determining the energies requires solving a transcendental equation, but this can be used to check results.

However, for this problem, the existence of such an analytic solution is not important. Instead, this potential is preferred because it will probably make integrals easy to do. Variations that are almost as easy include piecewise linear potentials and piecewise polynomial potentials. These can be used to mock up almost any potential, and so being able to quickly work with them can be very useful.

Another option might be a smooth potential like:

\[\begin{gather*} V(x) = V_0 e^{-x^2/2\sigma^2}. \end{gather*}\]

This has the advantage of having a nice simple mathematical form, but might lead to error functions when integrating, which could be problematic. Strictly speaking, such a potential does not have compact support, but we can take \(R \gtrapprox 9\sigma\) large enough that \(e^{-R^2/2\sigma^2} < 10^{-16}\) or so (machine precision in 64-bit double precision) which effectively behaves as a compact potential.

For testing purposes, there are also a large class of exactly solvable potential, like the Pöschl-Teller potential which have exact solutions. These might be a good start too, though the algebra is probably too complicated for work by hand. Numerically, they are a good choice.

Need hints for a method?

There are many options for estimating the energies:

  1. Variational Theorem: For the ground state, how about using the variational theorem?

    \[\begin{gather*} E_0 \leq \frac{\braket{\psi|\op{H}|\psi}}{\braket{\psi|\psi}}. \end{gather*}\]

    Getting estimates for some exited state energies is more difficult, but can be done in some cases (i.e. for the first excited state \(E_1\) if one has parity).

  2. Perturbation Theory: Another possibility is to write your potential as \(V(x) = V_0(x) + \lambda V_1(x)\) where you know the solution to \(V_0(x)\) and \(\lambda\) is small so that you can use perturbation theory. This will not work in all cases, but if you are free to choose the potential, then you can definitely choose an example where this will work.

  3. WKB/Semiclassical/Bohr-Sommerfeld: A third possibility is to use the WKB approximation or the Bohr-Sommerfeld quantization condition (with a Maslov correction of 1/2) for the classical action for a closed trajectory \(\bigl(x(t), p(t)\bigr)\) in classical phase space with approximate energy levels \(E = E_n\):

    \[\begin{gather*} \oint p\d{q} = (n + \tfrac{1}{2})\pi \hbar \end{gather*}\]

    If you can solve for the classical equations of motion, this is a good option.

Need hints for a trial wave-function?

If you are using the variational method, then you will need to be able to compute \(\braket{\psi|\op{H}|\psi}\). Integrals of polynomials are easy to do, so you might like to choose wavefunctions that are piecewise linear, quadratic, etc. If you want to do a better job, you might want to consider the asymptotic form of the wavefunction outside the region of support, but remember – the goal here is to quickly get an estimate, so keep it simple.

You might try something else like

\[\begin{gather*} \psi(x) \propto \abs{x-\tilde{R}}^\alpha. \end{gather*}\]

Here you could vary both \(\tilde{R} \approx R\) and \(\alpha\). (After working though with this, however, the expressions were not so simple, so I don’t think I would do this in the future.)

If you can use a computer to do the integrals, then you can use more complex forms.

If your potential is a gaussian, then perhaps a gaussian anzatz (with a polynomial prefactor) might be a good choice since the product of gaussians is a gaussian, and gaussian integrals are easy to do.

Need hints for integrals?

If you choose a potential and ansatz that requires gaussian integrals, then you likely need to compute integrals of the form

\[\begin{gather*} \int \d{x} x^n e^{-x^2/2\sigma^2}. \end{gather*}\]

Here are some hints about how to do this. It is worth being able to evaluate them quickly without references. A fundamental result is:

\[\begin{gather*} \int_{-\infty}^{\infty}\d{x} e^{-x^2} = \sqrt{\pi} \end{gather*}\]

which can be done by using the trick of computing the square of this integral, noting that the exponent becomes \(-x^2-y^2 = r^2\) and converting the integral to a 2D integral in cylindrical coordinates. This result might be worth memorizing.

Need more hints? Consider dimensional analysis? This should allow you to easily compute:

\[\begin{gather*} I(\sigma) = \int_{-\infty}^{\infty}\d{x} e^{-x^2/2\sigma^2} \end{gather*}\]

What about \(x^{n}\) where \(n\) is odd? Hint: Consider parity.

If you need a more general result, consider the derivatives

\[\begin{gather*} \diff[n]{I(\sigma)}{\sigma} \end{gather*}\]

and Feynman’s integration trick of taking the derivative under the integral.

Shooting#

There are many numerical techniques capable of solving the Schrödinger equation, but shooting is one of the easiest. The idea is to start with a guess for the wavefunction \(\psi(x_i)\) and its derivative \(\psi'(x_i)\) at some point \(x_i\), and then integrate forward to another point \(x_f\) trying match an appropriate boundary condition. Most numerical techniques require the differential equation to be specified as a first-order equation \(\vect{y}'(x) = f(x, \vect{y})\), so we use a vector \(\vect{y} = (\psi, \psi')\)

\[\begin{gather*} \diff{}{x}\overbrace{ \begin{pmatrix} \psi(x)\\ \psi'(x) \end{pmatrix} }^{\vect{y}(x)} = \overbrace{ \begin{pmatrix} \psi'(x)\\ \frac{2m}{\hbar^2}\Bigl(V(x) - E\Bigr)\psi(x) \end{pmatrix} }^{f(x,\vect{y}(x))}. \end{gather*}\]

This is pretty easy to implement, either by hand using Euler’s method or (better) Leapfrog integration, or using an adaptive routine like SciPy’s solve_ivp. The remaining challenges are:

  1. Choose an appropriate integration range \(x\in [x_i, x_f]\).

  2. Choose an appropriate initial state \(\vect{y}(x_i) = [\psi(x_i), \psi'(x_i)]\).

  3. Choose an appropriate boundary condition at \(x_f\) to “shoot for”.

Do It!

Try to answer find appropriate boundary conditions.

Hints:

Need hints for the range \(x_i < x < x_f\)?

Since our potential is compact on the domain \([-R, R]\), this might be an appropriate range. Depending on how you answer the other questions, you might need to expand this. How does the wavefunction behave outside the range of support? (I.e. what is it’s asymptotic form?) Can you use this asymptotic form to determine how large to make \(x_f = nR\) so that you get an accurate answer to some precision?

Don’t be discouraged if it is not immediately obvious what to do. I typically start with something reasonable, then play with it a bit to get an intuitive idea of what is happening. Once I have a good idea, I then revisit and refine my choice. Thus, I might first try \(x_f =2R\) or maybe \(x_f = 10R\). Later I will come back and make this more precise.

Need hints for the initial state \([\psi(x_i), \psi'(x_0)]\)?
  1. It seems like we need two conditions here, but the Schrödinger equation is linear. How does the solution change if we start with \([\alpha \psi(x_i), \alpha \psi'(x_i)]\) instead?

  2. Is there any point at which you could set one of \(\psi(x_i)=0\) or \(\psi'(x_i)=0\)? (For some potentials this will work very well, but for others might not be simple.)

Need hints for the shooting condition?

Why are the bound state energies \(E\) quantized? How must the wavefunction behave for large \(x\) if it represents a bound state? What happens if \(E\) is not one of the eigen-energies?

A Simple Numerical Solution#

Important

Do not work through this section until you have thought carefully about the problem and how you might try to solve. Ideally, you should try to solve it yourself, but if you are not very comfortable coding, then come here after you have thought about the math.

Let’s consider a the problem of a particle in the Pöschl-Teller potential:

\[\begin{gather*} V(x) = -\frac{n(n+1)\hbar^2}{2ma^2}\sech^2\frac{x}{a}, \end{gather*}\]

which has \(n\) bound states with energies

\[\begin{gather*} E_n = -\frac{n^2\hbar^2}{2ma^2}. \end{gather*}\]

We will use the Leapfrog integration scheme for a fixed step size.

# :tags: [hide-input, full-width]

hbar = m = a = 1.0
n = 2

V0 = hbar**2/2/m/a**2
ns = np.arange(1, n+1)
Es = -ns**2 * V0

def V(x, V0=V0, n=n):
    return -n*(n+1)*V0/np.cosh(np.asarray(x)/a)**2

dx = a/1000

xi = -10*a
xf = 10*a
Nsteps = int(np.ceil((xf-xi)/dx))

def shoot(E, xi=xi, xf=xf, Nsteps=Nsteps):
    """Return (xs, psis).
    
    Arguments
    ---------
    E : float
        Energy
    xi : float
        Initial point.
    xf : float
        Final point
    NSteps : int
        Number of steps.
    """
    dx = (xf-xi)/Nsteps

    # Initial ansatz... can be anything since the problem is linear
    psi = 0.1
    kappa = np.sqrt(-2*m*E)/hbar

    # Correct leapfrog initial guess using asymptotic form of wavefunction
    dpsi = kappa*psi*np.exp(kappa*dx/2)

    # Why does this work as well???
    #dpsi = 0

    x = xi
    xs = [xi]
    psis = [psi]
    for _n in range(Nsteps):
        ddpsi = 2*m*(V(x) - E)*psi/hbar**2
        dpsi += ddpsi * dx
        psi += dpsi * dx
        x += dx
        xs.append(x)
        psis.append(psi)

    xs, psis = map(np.asarray, (xs, psis))
    return xs, psis

fig, ax = plt.subplots()
xs = np.linspace(xi, xf, 200)
ax.plot(xs, V(xs), label="$V$")
V_min = np.min(V(xs))
for n, En in enumerate(Es):
    dE = 1.001
    xs, psis = shoot(E=En)
    max_psi = np.where(abs(V(xs)) > 0.1, abs(psis), 0).max()
    for E, ls in [(En/dE, ':'), (En, '-'),  (En*dE, '--')]:
        xs, psis = shoot(E=E)
        ax.plot(xs, E + psis*V0/max_psi, c=f"C{n}", ls =ls, 
                label=fr"$\psi$: $E={E/V0:.3f}V_0$")
    plt.axhline(En, ls='--', c='y')
    
ax.legend()
ax.set(xlabel="$x$", ylabel=r"$E + \psi(x)$", ylim=(1.1*V_min, 0.1*abs(V_min)));
../_images/dc73a790e9a2aad078162a2e81a0ec33c7439a8510cf232c8df8ced9d0d81051.png

To Ponder#

  • Notice that unless we tune the energy precisely, it diverges exponentially. Why?