#!/usr/bin/env python # coding: utf-8 # # # # # Numerical Determination of Eigenenergies for an Asymmetric Potential # ## Examples - Quantum Mechanics #
# By Henning Goa Hugdal, Øystein Hiåsen and Peter Berg #
# Last edited: October 31st 2018 # ___ # In [*Numerical Determination of Eigeinenergies for the Harmonic Odcillator*](https://nbviewer.jupyter.org/urls/www.numfys.net/media/notebooks/numerical_determination_eigenvalues_harmonic_oscillator.ipynb), we showed how to numerically determine the eigenenergies of the harmonic oscillator potential. Using the fact that the potential was symmetric, and hence the wave functions symmetric or anti-symmetric, we could easily choose the correct boundary conditions for the wave function we were interested in. However, for an asymmetric potential we don't have any such information! All we know is that the eigenfunctions have to be square integrable and smooth. And that is actually enough information to solve this problem. # # Consider the following potential, # $$ V(x) = ax^4-b(x+c)^2+d, $$ # with $a=1$, $b=1.5$, $c=0.2$, and $d=1.17$. The potential is slightly asymmetrical, as seen in the plot below. # In[1]: get_ipython().run_line_magic('matplotlib', 'inline') from __future__ import division import numpy as np import matplotlib.pyplot as plt # Set common figure parameters: newparams = {'axes.labelsize': 14, 'axes.linewidth': 1, 'savefig.dpi': 300, 'lines.linewidth': 1.0, 'figure.figsize': (8, 3), 'figure.subplot.wspace': 0.4, 'ytick.labelsize': 10, 'xtick.labelsize': 10, 'ytick.major.pad': 5, 'xtick.major.pad': 5, 'legend.fontsize': 10, 'legend.frameon': False, 'legend.handlelength': 1.5} plt.rcParams.update(newparams) # In[2]: n = 1000 # number of points per unit on x-axis dx = 1.0/n p = 10.0 # which x-values to include linP = np.linspace(0,p*n-1, p*n, True) linM = np.linspace(-(p*n-1), 0, p*n, True) xP = linP/n # x-values in positive direction xM = linM/n # x-values in negative direction a = 1.0 b = 1.5 c = 0.2 d = 1.17 VP = a*xP**4 - b*(xP+c)**2 + d # potential for x>0 VM = a*xM**4 - b*(xM+c)**2 + d # potential for x<0 plt.figure() plt.plot(xM, VM, 'r', xP, VP, 'r') plt.grid() plt.ylim([-1, 10]) plt.xlim([-2, 2]) plt.title(r'The Potential Under Consideration') plt.xlabel(r'$x$') plt.ylabel(r'$V(x)$'); # Setting $\hbar = 1$, $m = 1$ for simplicity, the Schrödinger equation reads # $$\left[-\frac{1}{2}\frac{\rm d^2}{{\rm d}x^2} + V(x) \right]\psi(x) = E \psi(x), $$ # yielding the following equation for $\psi''(x)$, # $$\psi''(x) = 2[V(x)-E]\psi(x).$$ # Discretizing the $x$-axis and the wave function, and using the second-order central difference method, we get a formula for a function value $\psi_{i+1}$ based on two previous points, # $$\psi_{i+1} = 2\psi_i-\psi_{i-1}-2(\Delta x)^2\left[E-V(x) \right]\psi_i, $$ # where $\Delta x$ is the distance between two points $x_i$ and $x_{i+1}$ on the $x$-axis. For the first function value on each side of the origin we use # $$ \psi_1 = \psi_0 + \psi_0'\Delta x,$$ # where $\psi_0$ and $\psi_0'$ are the initial value at the origin for the wave function and the slope of the wave function respectively. # As mentioned, we have to find functions that are square integrable and smooth. Hence we will try the following procedure: # For a given energy, use the above equations to find wave functions for both positive and negative values of $x$ which are square integrable. To do this we need to define functions that find an initial value for the slope such that the wave functions go towards zero as $x \rightarrow \infty $, e.g. by using the bisection method. It is important to note that the criterion for the bisection method will vary depending on if the wave function approaches zero from above or below. Hence we need two different functions, and for simplicity we have also define seperate functions for positive and negative $x$-values. These four functions are defined below. # In[3]: def findSlopeP(Ein, acc): """Function for positive x, approaches zero from above. Takes energy and desired accuracy as imput. """ S1 = -30.0 # lower limit for slope S2 = 30.0 # upper limit for slope DeltaSP = 1.0 S = 0 # starting value for slope while DeltaSP > acc: for i in linP[0:-1]: if i == 0: f1[i+1] = f1[i] + dx*S else: f1[i+1] = -f1[i-1] + f1[i]*(2-dx**2*2*(Ein-VP[i])) if f1[i] < -20: # the wave function shoots off towards minus infinity, adjust slope S1 = S S = S1 + (S2-S1)/2 break elif f1[i] > 20: # the wave function shoots off towards plus infinity, adjust slope S2 = S S = S2 - (S2-S1)/2 break DeltaSP = S2-S1 # if DeltaSP is smaller than the given accuracy, the function returns the calculated slope return S def findSlopeM(Ein, acc): """Function for negative x, approaches zero from above. """ S1 = -30.0 S2 = 30.0 DeltaSM = 1.0 S = 0 while DeltaSM > acc: for i in linP[1:-1]: if i == 1: f2[-(i+1)] = f2[-i] + dx*S else: f2[-(i+1)] = -f2[-(i-1)] + f2[-i]*(2-dx**2*2*(Ein-VM[-i])) if f2[-i] <- 20: S1 = S S = S1 + (S2-S1)/2 break elif f2[-i] > 20: S2 = S S = S2 - (S2-S1)/2 break DeltaSM = (S2-S1) return S def findSlopeP2(Ein, acc): """Function for positive x, approaches zero from below. """ S1 = -30.0 S2 = 30.0 DeltaSP = 1.0 S = 0.0 while DeltaSP > acc: for i in linP[0:-1]: if i == 0: f1[i+1] = f1[i] + dx*S else: f1[i+1] = -f1[i-1] + f1[i]*(2-dx**2*2*(Ein-VP[i])) if f1[i] > 20: S1 = S S = S1 + (S2-S1)/2 break elif f1[i] < -20: S2 = S S = S2 - (S2-S1)/2 break DeltaSP = abs(S2-S1) return S def findSlopeM2(Ein, acc): """Function for negative x, approaches zero from below. """ S1 = -30.0 S2 = 30.0 DeltaSM = 1.0 S = 0.0 while DeltaSM > acc: for i in linP[1:-1]: if i == 1: f2[-(i+1)] = f2[-i] + dx*S else: f2[-(i+1)] = -f2[-(i-1)] + f2[-i]*(2-dx**2*2*(Ein-VM[-i])) if f2[-i] > 20: S1 = S S = S1 + (S2-S1)/2 break elif f2[-i] < -20: S2 = S S = S2 - (S2-S1)/2 break DeltaSM = abs(S2-S1) return S # We now need to look for values of the energy which give the same slope in both directions. Using the fact that the $n^{\rm th}$ excited state has $n-1$ nodes, we can determine which combinations of the above functions to use. Now all is set to start computing the eigenenergies. We start with the ground state energy, $E_0$. # ### Ground State # The ground state has zero nodes, hence we will use the functions where the wave function approaches zero from above, __findSlopeP__ and __findSlopeM__, beginning the search in an interval $0