Professional Documents
Culture Documents
Computational Quantum Mechanics
Computational Quantum Mechanics
net/publication/351130364
CITATIONS READS
0 918
4 authors:
All content following this page was uploaded by Rithwik Ranganathan on 28 April 2021.
Using Scilab
i
About the Authors
1
Chapter 1
Initial value problems are ordinary differential equations where the initial conditions are
given. For example in a second order differential equation the value of the dependent vari-
able and its first derivative at the initial value of the independent variable is given.
1.1.1 Example 1
//Integrate the initial value problem
//y'+4y=x^2 y(0)=1
//x=[0, 0.03]
clc
y0=1;
x=0:0.01:5
function dy =f(x,y)
dy= x^2-4*y;
endfunction
sol=ode(y0,x(1),x,f);
disp(sol);
disp(x);
plot(x,sol,'kx');
xlabel('x','fontsize',3)
ylabel('y','fontsize',3)
title("Plot for ODE","fontsize",3)
legend("y(x)")
xgrid()
2
1.1.2 Example 2
//y"=-0.1y'-x
//y(0)=0 y'(0)=1
clc
x=0:0.05:2
y0=[0;1]
function dy=f(x,y)
dy(1)=y(2)
dy(2)=-0.1*y(2)-x
endfunction
sol=ode(y0,x(1),x,f);
disp(sol);
y=sol(1,:);
disp(y)
disp(y(2))
y_exact=100*x-5*x^2+990*(exp(-0.1*x)-1);
plot(x,y,'rx');
plot(x,y_exact,'b');
xlabel('x','fontsize',3)
ylabel('y','fontsize',3)
3
title("Plot for ODE","fontsize",3)
legend("Computational value of y","Analytical solution of y")
1.1.3 Example 3
//Integrate the problems from x=0 to 20
//(a) y"+0.5(y^2-1)+y=0 y(0)=1, y'(0)=0
//(b) y"=y*cos2x y(0)=0,y'(0)=1
//(a)
clc
x=0:0.1:20
y0=[0;1]
function dy=f(x,y)
dy(1)=y(2)
dy(2)=-y(1)-0.5*(y(1)^2-1)
endfunction
sol=ode(y0,0,x,f);
subplot(2,1,1)
plot(x,sol(1,:),'rx')
plot(x,sol(2,:),'kx')
xlabel('x','fontsize',3)
ylabel("y(x) and dy(x)/dx","fontsize",3)
4
title("Plot for ODE (a)","fontsize",3)
legend("y(x)","dy(x)/dx")
//(b)
x=0:0.1:20
y0=[0;1]
function dy=f(x,y)
dy(1)=y(2)
dy(2)=y(1)*cos(2*x)
endfunction
sol=ode(y0,x(1),x,f);
subplot(2,1,2)
plot(x,sol(1,:),'rx')
plot(x,sol(2,:),'kx')
xlabel('x','fontsize',3)
ylabel("y(x) and dy(x)/dx","fontsize",3)
title("Plot for ODE (b)","fontsize",3)
legend("y(x)","dy(x)/dx")
5
1.1.4 Example 4
//Find the root of x^3-10x^2+5=0 that lies in the interval of 0 to 1
//also plot the function
clc
n=100;
y=zeros(n)
x=0:0.01:1
root=zeros(2)
j=1;
function y=f(x)
y=x^3-10*x^2+5
endfunction
for i=1:length(x)
if((abs(f(x(i)))<0.1)&&(abs(f(x(i+1)))>=0.1))
root(j)=x(i);
j=j+1;
end
end
disp(root)
plot(x,f(x))
plot(root,f(root),'k.')
xlabel('x','fontsize',3)
ylabel('y(x)','fontsize',3)
legend('y(x)','roots of y(x) between 0 and 1 is '+string(root))
title('Plot of y(x) and its root ','fontsize',3)
6
1.1.5 Example 5
//A skydiver of mass m in a vertical free fall experiences an aerodynamic
//drag force CD*y'^2 where y is measured downward from the start of the fall.
//The differential equation describing the fall is y"=-g-CD/m*y^2
//Determine the time of a 500m fall
clc
g=9.8;
CD=0.2028;
m=80;
t=0:0.01:18
y0=[500;0]
function dy=f(x,y)
dy(1)=y(2)
dy(2)=-g+(CD*(y(2)*y(2)))/m
endfunction
sol=ode(y0,0,t,f)
y=sol(1,:)
dy=sol(2,:)
time=0;
for i=1:length(y)
7
if(abs(y(i))<0.1)
time=i
break
end
end
j=time*0.01
plot(t,y)
plot(t,dy,'r')
plot(t(time),y(time),'r.')
xlabel('time(s)','fontsize',3)
ylabel('height,y(m) and velocity,dy/dt(m/s)','fontsize',3)
title('Plot for body under drag force','fontsize',3)
legend('height of body','velocity of body','time of flight is '+string(j)+'s')
xgrid();
8
Chapter 2
Boundary value problems (BVPs) are second order differential equations whose solutions
at two values of the independent variable (boundaries) are given, instead of the values
of the dependent variable and its first derivative, as is given in an initial value problem.
Hence the name boundary value problem. This complicates the method to obtain a
solution of a BVP since the inbuilt functions in python, scipy or scilab are designed to
solve differential equations when the initial conditions are only given (There are however
higher level functions in scilab for solving BVPs).
Here we will discuss methods to solve BVPs using the inbuilt functions in scilab for
solving initial value problems. To do this we need to use a method, aptly called the
shooting method. The idea is to use the known solution of the BVP at one boundary and
an initial guess of its first derivative at that point and solve the ode to find the solution
at the other boundary. This value is then compared to the known solution of the BVP
at the other boundary. If it matches (you would be lucky, if it does) then you have got
the solution, else you have to go back and guess another value for the first derivative,
depending upon whether the solution at the second boundary undershot or overshot the
known boundary value. This will be repeated until your solution matches the boundary
value. This is akin to an archer trying to shoot an apple from a distant tree. Her first
try might fail, from which she will learn and change her aim the second time and again
till she succeeds. It also is similar to a gunner trying to shoot a cannon so that it hits
the target (see figure 2.1). The aim has to be adjusted by trial and error till the aim is
correct for hitting the target. This in essence is the shooting method of solving boundary
value problems.
To illustrate the shooting method of solving a BVP, let us consider the following boundary
value problem with the boundary values as given below
d2 y dy
+ + y = sin(3x) (2.1)
dx2 dx
y(0) = 1; (2.2)
y(5) = −1. (2.3)
9
Figure 2.1: Illustration of the shooting method. A cannon’s aim has to be adjusted by
trial and error till the aim is right to hit the target. Similarly in solving a BVP, the
first derivative of a second order ode has to be adjusted till the value is just right for the
solution to hit the correct value at the other boundary. The figure is taken from the book
[2].
To proceed with the solution using shooting method, first two guesses of the first derivative
of y have to be given. Moreover the two initial values of the first derivative have to be
such that one overshoots while the other undershoots the second boundary value. In
other words, the difference between the value of each of the two solutions at the second
boundary and the boundary value should be of opposite signs. This will ensure that the
correct value of the first derivative at the first boundary will definitely lie between these
two initial guesses and we can arrive at this value using the well known bisection method.
So this implementation of the shooting method uses the bisection method to arrive at the
correct value of the first derivative which will give the solution to our BVP. Once we have
the two initial guesses, we solve the ode with these first derivative guesses. Then we find
the middle value of this interval and solve the ode again taking this as the value of the
first derivative. Once the solution is known, we find the value at the second boundary
and take its difference with the actual boundary value. We then replace one of the initial
guesses of the first derivative with the middle value. That initial guess is replaced whose
solution at the second boundary differs from second boundary condition with the same
sign as the solution with the middle value as the first derivative guess. This is repeated
until the interval between the two guesses of the first derivative does not become smaller
than the accuracy we desire for the correct first derivative value. Once the interval has
become smaller we can solve the ode with the last middle value; this will give the solution
which will match the given boundary values within the decided accuracy.
2.0.1 Programme
The following code solves the BVP given in equation 2.3.
// Solve the 2nd order BVP defined by the ode d2y/dx2 + dy/dx + y = sin(3x)
// y(0) = 1 y(5) = -1
// using bisection method
10
alpha_1 = -1e4
alpha_2 = 1e7
tolerance = 1e-5
gap = abs(alpha_1 - alpha_2)
i = 1
while gap > tolerance
//disp("while")
y0 = [1;alpha_1]
solution = ode(y0,0,x,f)
y_b = solution(1,$)
difference_1 = y_b - (-1)
//disp('diff 1 is',difference_1)
y0 = [1;alpha_2]
solution = ode(y0,0,x,f)
y_b = solution(1,$)
difference_2 = y_b - (-1)
//disp('diff 2 is',difference_2)
if (difference_1*difference_2) > 0
disp("choose proper interval")
break
end
alpha_mid = (alpha_1+alpha_2)/2
y0 = [1;alpha_mid]
solution = ode(y0,0,x,f)
y_b = solution(1,$)
difference_mid = y_b - (-1)
//disp('diff mid is',difference_mid)
//disp(difference_1*difference_mid)
if difference_1*difference_mid < 0 then
alpha_2 = alpha_mid
//disp("lower")
else
alpha_1 = alpha_mid
//disp('upper')
end
gap = abs(alpha_1 - alpha_2)
disp('gap is',gap)
disp(i)
i = i + 1
//disp('alpha_mid is',alpha_mid)
end
y0= [1;alpha_mid]
final_solution = ode(y0,0,x,f)
y_final = final_solution(1,:)
plot(x,y_final)
plot([0,5],[-1,-1],'k')
11
7
−1
−2
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5
2.0.2 Output
The plot of the resulting solution is given in figure 2.2.
12
y0 =[1;alpha]
solution = ode(y0,0,x,f)
difference = solution(1,$)-(-1)
endfunction
alpha_optimum = fsolve(1,g)
y0 = [1;alpha_optimum]
final_sol = ode(y0,0,x,f)
plot(x,final_sol(1,:),'c')
plot([0,5],[-1,-1],'k')
d2 y dy
2
+ 5 + y = cos(x) (2.4)
dx dx
y(1) = 0.5; (2.5)
0
y (2) = −1.5. (2.6)
Another BVP problem defined in equation 2.6 can be solved using the code given below.
Note that the second boundary value specifies the first derivative at the second boundary.
The solution is plotted in figure 2.3.
/* SOLVE THE BOUNDARY VALUE PROBLEM (BVP) DESCRIBED BY THE ORDINARY
DIFFERENTIAL EQUATION D2Y/DX2 + 5(DY/DX) + Y = COS(X) */
// Y(1) = 0.5 Y'(2) = -1.5
function D_y = f(x,y)
D_y(1) = y(2)
D_y(2) = cos(x)-5*y(2)-y(1)
endfunction
x = linspace(1,2,100)
function difference = g(alpha)
y0 = [0.5;alpha]
solution = ode(y0,1,x,f)
difference = solution(2,$) - (-1.5)
endfunction
optimum_alpha = fsolve(0.5,g)
y0 = [0.5;optimum_alpha]
final_sol = ode(y0,1,x,f)
plot(x,final_sol(1,:))
//plot(x,final_sol(2,:))
plot([1,2],[7,7],'k')
xs2eps(0,'Plot_BVP_1')
13
10
0
1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2
14
Chapter 3
In this chapter, we will solve the Schrodinger equation for a finite potential well using the
shooting method. For a more detailed reading the user is referred to the book by Moruzzi
[3]
The finite well is given by (
0 if |x| <x0 ,
V = (3.1)
V0 if |x| > x0 .
The time independent Schrodinger equation for the finite well potential can be written
as
~2 d2 ψn (x)
− = En ψn (x), for |x| < x0 (3.2)
2m dx2
~2 d2 ψn (x)
− + V0 ψn (x) = Eψn (x), for |x| > x0 . (3.3)
2m dx2
The finite square well has bound states for En < V0 or Wn < 1. Since the wave function
ψn (ξ) is zero far away outside the finite well, hence the second order equations given by
equation 3.5 represents a boundary value problem.
We solve this with a slightly modified shooting method, where instead of finding the
appropriate initial condition (e.g. the first derivative at the initial point) which will give
the proper solution satisfying the boundary condition (i.e. ψ(ξ) disappears at |ξ| >> ξ0 ),
we find the values of energy or what is the same thing i.e. Wn which will lead to the
15
solutions to the boundary value problem. These energies are the energy eigenvalues Wn
(En ).
To do this, we use the fact that the solutions for energies other than the eigenvalues
diverge at large ξ i.e. far away from the boundaries of the finite well.
The algorithm for finding the wave-functions for the finite well is as follows:
1. We begin with an initial guess of the energy eigenvalue. Since energy is always
positive, we begin with Wn = 0.
2. The first eigenfunction will be even. So we set a variable which will count the
number of eigenvalues to zero. If the eigenfunction is even we choose ψ(ξ = 0) = 1
and dψ
dξ
(ξ = 0) = 0 and vice-versa if it is odd.
3. We begin a while loop which will search for the eigenvalues Wn in an incremental
manner as long as Wn < 1. The code firsts calculates the solution at the inital guess
of the eigenvalue. Then it finds the solution at a new energy value obtained by
adding the step in energy to the initial guess. It then checks whether they diverge
in opposite directions far away form the finite well boundary. This is repeated until
two values of energy are obtained for which the solutions diverge in opposite ways.
4. The two above values of energy bracket the energy which is our required eigenvalue
at which the solution does not diverge appreciably at large ξ. To find that we
start a while loop which calculates the midpoint of the above energy interval and
calculates the solution at this middle energy. It then compares how this solution
diverges at large ξ with the solutions for the energies of the endpoints of the interval.
The endpoint whose solution diverges in an opposite way to that for the midpoint
is chosen as the new interval along-with the midpoint. This is repeated until the
interval becomes smaller than a predetermined accuracy in energy.
5. Once the energy at which the solution does not diverge appreciably (eigenvalue)
has been found, we truncate the solution to a range of ξ for which we will plot the
solution (because even for the eigenvalue there is some divergence at large ξ). This
is our wave-function. But we normalize it by integrating square of the wave-function
and then dividing the unnormalized wave-function with the norm. We also scale
the wave-function by a suitable factor so that the different eigenfunctions are well
spaced out when we plot them. We also generate the wavefunctions for the negative
side of ξ using the proper symmetry conditions for even and odd functions.
3.0.1 Programme
The code for finding the eigenvalues and eigenfunctions is given below:
nPointsWell = 100 /*number of sampling points for the wavefunction
from x = 0 to x = xi0 */
nPoints = 500 /*number of sampling points for the wavefunction
from x = 0 to x = xiMax */
nPointsPlot = 200 /* number of sampling points for the wavefunction
from x = 0 to x = xiMaxPlot */
xi0 = 10 /*Half-width of the finite potential well in dimesionless
position variable x(x = $\epsilon$,see text) */
16
xiMax= (xi0*nPoints)/nPointsWell /*Highest x($\epsilon$) used for
calculation.*/
xiMaxPlot = (xi0*nPointsPlot)/nPointsWell /* Highest plotted
x($\epsilon$) value. */
EigvStep =0.05 /*Step size in the search for eigenvalues
()energy values for which there is a solution to the BVP or SE)
DeltaXi =xiMax/nPoints */
tolerance = 1.0e-12 /* the tolerance level of error in the
energy eigenvalue for which there is a solution */
s = ['r' 'g' 'b' 'c' 'm' 'y' 'k']/* string containing the keywords for
plotting each eigenfunction with a different colour */
17
the ends of which the solution diverges in opposite ways
(positive or negative) */
while 2 >0
E2 = E1 + EigvStep /* Finds a new energy value by
incrementing the initial energy value */
E = E2 // Increments E by step size to next value
psi = ode(y0,0,xi,f) /* Solves ode for new energy value
and earlier initial conditions */
psi_end2 = psi(1,$) /*Finds the value of the solution at the
end point xiMax */
if psi_end1*psi_end2 <0 /* compares the solution at the end
point for the last energy with that for the second last energy value*/
disp('break') /* breaks from the loop to search for the
interval without updating E1 */
break
end
E1 = E2 // updates the initial energy value to the last one
psi_end1 = psi_end2 /* updates the solution of initial energy
to the last one */
end
if E1 > 1 then /* If E1 has reached 1 then break from
loop of searching for energy intervals otherwise it will calculate
for one energy value higher than 1. */
break
end /* search for the energy value for which there is a solution
similar to the bisection method */
while abs(E1-E2)> tolerance /*checks that the energy interval
is less than the tolerance */
E_m = (E1+E2)/2 // finds the midvalue of the interval
E = E_m
psi = ode(y0,0,xi,f) // finds solution at midvalue
psi_end3 = psi(1,$) // finds solution at end point
if psi_end3*psi_end1 < 0 then /* compares the solution at
endpoint for midvalue of energy with that of the lower limit of the
interval */
E2 = E_m /* if it has changed sign, then
replaces the upper limit with the midpoint */
psi_end2 = psi_end3
elseif psi_end3*psi_end2 < 0 then // else does the reverse
E1 = E_m
psi_end1 = psi_end3
end
end
wavefunction = psi(1,:) /* calls the solution for the midpoint
which is eigenvalue as the wavefunction */
while length(xi) > nPointsPlot /* this loop truncates xi row matrix
so that its range is only till xiMaxPlot */
18
xi($) = []/* replaces with null element for columns higher
than xiMaxPlot */
wavefunction($) = [] /*replaces with null element for columns
higher than xiMaxPlot */
end
19
Eigenvalues and eigenfunctions of finite square well
1.2
1.1
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0
−20 −15 −10 −5 0 5 10 15 20
Figure 3.1: The eigenfunctions plotted as a function of ξ for a finite potential well with
ξ0 = 10. The eigenfunctions are displaced by the energy eigenvalue for clarity.
3.0.2 Output
The results of running the code is shown in figure 3.1
20
nPointsPlot = 200
xi0 = 10
xiMax= (xi0*nPoints)/nPointsWell
xiMaxPlot = (xi0*nPointsPlot)/nPointsWell
EigvStep =0.05
tolerance = 1.0e-12
s = ['r' 'g' 'b' 'c' 'm' 'y' 'k']
Delta_E = 1.0E-5
xi = linspace(0,xiMax,nPoints)
function Dy = f(xi,y,E)
if xi < xi0 then
Dy(1) = y(2)
Dy(2) = -E*y(1)
else
Dy(1) = y(2)
Dy(2) = (1-E)*y(1)
end
endfunction
n = 0
Eigen = []
E1 = 0.05 // Energy value from whgich search is to be started.
E = E1
// enters the loop to find the eigenvalues
if modulo(n,2) == 0 then
y0 = [1;0] // initial value y = 1 and y' = 0 for even states
else
y0 = [0;1] // initial value y = 0 and y' = 1 for odd states
end
psi = ode(y0,xi(1),xi,f)
psi_end1 = psi(1,$)
// this loop is to find the interval of energy values at the ends of
// which the solution diverges in opposite ways (positive or negative)
while 2 >0
E2 = E1 + EigvStep
E = E2
psi = ode(y0,0,xi,f)
psi_end2 = psi(1,$)
if psi_end1*psi_end2 <0
disp('break')
break
end
E1 = E2
psi_end1 = psi_end2
end
//search for the energy value for which there is a solution similar
//to the bisection method
21
while abs(E1-E2)> tolerance
E_m = (E1+E2)/2
E = E_m
psi = ode(y0,0,xi,f)
psi_end3 = psi(1,$)
if psi_end3*psi_end1 < 0 then
E2 = E_m
psi_end2 = psi_end3
elseif psi_end3*psi_end2 < 0 then
E1 = E_m
psi_end1 = psi_end3
end
end
wavefunction = psi(1,:)
E = E_m - Delta_E
psi_lower = ode(y0,0,xi,f)
E = E_m + Delta_E
psi_upper = ode(y0,0,xi,f)
plot(xi(1:nPointsPlot),psi(1,1:nPointsPlot),'go')
plot(xi(1:nPointsPlot),psi_lower(1,1:nPointsPlot),'r','LineWidth',4)
plot(xi(1:nPointsPlot),psi_upper(1,1:nPointsPlot),'b', 'LineWidth',2)
disp('psi_upper',psi_upper(1,$))
disp('psi_upper',psi_lower(1,$))
legend('$W_n$','$W_n - \Delta W$','$W_n + \Delta W$')
disp(Eigen)
22
1
0.8
0.6
0.4
0.2
−0.2
−0.4
−0.6
−0.8
−1
0 2 4 6 8 10 12 14 16 18 20
Figure 3.2: The solutions diverge for energies slightly lower or higher than the eigenvalue
at large ξ
23
Chapter 4
The harmonic oscillator problem can be solved similarly to the finite well method using
the shooting method and the fact that the eigenfunctions of harmonic oscillator decay to
zero far way from the centre of the potential at x = 0.
We start with the Schrodinger equation for the harmonic oscillator. The potential is given
as
V = 1/2mω 2 x2 (4.1)
and the Schrodinger equation as
~ 2 d2 ψ n 1
− 2
+ mω 2 x2 ψn = En ψn . (4.2)
2m dx 2
~ d2 ψn mωx2 2En
− 2
+ ψn = ψn . (4.3)
mω dx ~ ~ω
d2 ψn
− + ξ 2 ψn = 2Wn ψn (4.4)
dξ 2
d2 ψ n
= [ξ 2 − 2Wn ]ψn . (4.5)
dξ 2
We will use this equation to define the ode in our code. We can break the second order
differential equation in to a system of first order differential equation as follows
dψn
= χn (4.6)
dξ
dχn
= [ξ 2 − 2Wn ]ψn . (4.7)
dξ
24
4.0.1 Programme
The algortithm for finding the eigenvalues and eigenfunctions for the harmonic oscillator
are the same as that of finite well. One difference is that there is no upper limit to the
energy eigenvalue, so we need to set a limit on the number of eigenvalues to be calculated
for the harmonic oscillator. Below is the code for solving the Schrodinger equation for
the first seven eigenvalues and eigenfunctions of the harmonic oscillator.
nPoints = 500 // Total number of points in x used in the calculation
nPointsPlot = 200 // Number of points in x which are plotted
xiMax=10.0 /* The maxiumum value of $\xi$ used in the calculation.
It is assumed that the eigenfunctions will be almost zero at
$\xi_{max}$*/
xiMaxPlot = (xiMax*nPointsPlot)/nPoints // $xi$ upto which plotted
tolerance = 1.0e-12 // Size of error in eigenvalues.
nEigen = 7 // Number of eigenvalues to be found.
EigvStep = 0.005// Step size of energy while searching for eigenvalues
s = ['r' 'g' 'b' 'c' 'm' 'y' 'k'] // array of strings for plot colour
25
energy values, old and new, as the interval of energy
containing the required energy which is the eigenvalue. At
this energy the solution will not diverge at $\xi_{max}$ */
//disp('break')
break
end
psi_end1 = psi_end2 /* if two energy values with oppositely
diverging solutions has not been found, then replace old
energy with new energy and start over again by incrementing to
a third energy value */
E1 = E2
end
while abs(E1-E2)> tolerance /* do a while loop as long as energy
interval is not less than the desired accuracy in energy eigenvalue*/
E_m = (E1+E2)/2.0 // Find the midpoint of energy interval
E = E_m // Set the variable E to midpoint in energy
psi = ode(y0,0,xi,f) /*Solve ode for the energy value equal
to the midpoint in energy */
psi_end3 = psi(1,$) /* Store the solution for the midpoint in
energy interval at $\xi_{max}$ */
// mprintf("psi_end1 is %e \n",psi_end1)
// mprintf("psi_end2 is %e \n",psi_end2)
// mprintf("psi_end3 is %e \n",psi_end3)
if psi_end3*psi_end1 < 0 then /* Check which endpoint of the
energy interval has a solution diverging in opposite direction to the
solution at the midpoint energy. This endpoint along with the midpoint
will be the new interval of energy for repaeting the process*/
E2 = E_m /*psi_end2 = psi_end3 seems to be not required in
any three programs!!?*/
psi_end2 = psi_end3
elseif psi_end3*psi_end2 < 0 then
E1 = E_m //similarly here also!!?
psi_end1 = psi_end3
end
//mprintf("energy interval is %e \n",abs(E1-E2))
end
wavefunction = psi(1,:) /*Set wavefunction as the first row of the
solution for the energy midpoint which we take as the eignevalue
within the accuracy limits set by us*/
while length(xi) > nPointsPlot /* Truncate $xi$ and wavefunction to
within maximum $\xi$ to be plotted */
xi($) = []
wavefunction($) = []
end
Eigen($+1) = E_m /* Add the latest eigenvalue to the list
of eigenvalues */
E = E_m + EigvStep /* Set the new value of energy to last
eigenvalue plus step in eigenvalue search */
26
Norm_factor = sqrt(2*inttrap(xi,wavefunction**2)) /* integrate the
square of the wavefunction and take square root to find the norm*/
normalised_wf = wavefunction*0.4/Norm_factor /* Normalize the
wavefunctions by dividing by norm and scale by an appropriate
factor for clarity in plotting */
if modulo(n,2) == 0 then /* Generate the wavefunction for negative
$\xi$ by choosing suitable symmetry for even and off
wavefunctions*/
flip_wf = flipdim(normalised_wf,2)
flip_wf($)=[]
else
flip_wf = flipdim(-normalised_wf,2)
flip_wf($)=[]
end
total_wf = cat(2,flip_wf,normalised_wf)+ E_m /* combine the
positive and negative part of the wavefunctions and add the
corresponding eigenvalue to separate the wavefunctions
along the y axis */
flip_xi = flipdim(-xi,2) // flip the matrix $\xi$
flip_xi($) = [] /* Remove $xi = 0$ to avoid duplicate entries after
combining */
total_xi = cat(2,flip_xi,xi) // Combine -ve and +ve $\xi$
//disp(length(total_xi))
n = n + 1 // Increment the eigenvalue counter by 1
//disp(length(normalised_wf))
//disp(normalised_wf)
//disp('length of total_wf is',length(total_wf))
plot(total_xi,total_wf,s(n), 'linewidth',3) // Plot the wavefunction
plot([total_xi(1),total_xi($)],[E_m,E_m],'k')/* Plot horizontal
line at the eigenvalue */
end
disp(Eigen)
title("Eigenvalues and eigenfunctions of harmonic potential","fontsize", 5)
xlabel("$\xi = \sqrt\frac{\omega m}{\hbar}$", "fontsize",4)
ylabel("$W = E/\hbar$","fontsize",4)
y = 0.5*total_xi**2
plot(total_xi,y,'k')
xgrid(1,1)
xs2eps(0,'Plot_of_harmonic_potential') // saves plot as eps file
4.0.2 Output
The results are given in figure 4.1.
27
Eigenvalues and eigenfunctions of harmonic potential
8
0
−4 −3 −2 −1 0 1 2 3 4
Figure 4.1: First seven eigenfunctions and eigenvalues of the harmonic oscillator.
28
Diverging solutions of harmonic potential
1
0.8
0.6
0.4
0.2
−0.2
−0.4
−0.6
−0.8
−1
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6
Figure 4.2: Diverging solutions of the harmonic oscillator for energies deviating from the
eigenvalue.
29
xi = linspace(0,xiMax,nPoints)/* Generates a row matrix for $\xi$ to
be used in calculation*/
30
psi = ode(y0,0,xi,f) /*Solve ode for the energy value equal
to the midpoint in energy */
psi_end3 = psi(1,$) /* Store the solution for the midpoint in
energy interval at $\xi_{max}$ */
if psi_end3*psi_end1 < 0 then
/* Check which endpoint of the
energy interval has a solution diverging in opposite direction to the
solution at the midpoint energy. This endpoint along with the midpoint
will be the new interval of energy for repaeting the process*/
E2 = E_m /*psi_end2 = psi_end3 seems to be not required in
any three programs!!?*/
elseif psi_end3*psi_end2 < 0 then
E1 = E_m //similarly here also!!?
end
end
E = E_m - Delta_E
psi_lower = ode(y0,0,xi,f)
E = E_m + Delta_E
psi_upper = ode(y0,0,xi,f)
plot(xi(1:nPointsPlot),psi(1,1:nPointsPlot),'go') // plots the wavefunction
plot(xi(1:nPointsPlot),psi_lower(1,1:nPointsPlot),'r','LineWidth',4)
plot(xi(1:nPointsPlot),psi_upper(1,1:nPointsPlot),'b', 'LineWidth',2)
disp('psi_upper',psi_upper(1,$))
disp('psi_upper',psi_lower(1,$))
legend('$W_n$','$W_n - \Delta W$','$W_n + \Delta W$')
31
Chapter 5
In case of a central potential where the potential only depends on the radial distance from
origin, the three dimensional Schrodinger equation can be separated into a radial and an
angular part [4]. The radial equation then can be written as
d 2 dR 2mr2
(r ) − 2 [V (r) − E]R = l(l + 1)R. (5.1)
dr dr ~
This equation can be simplified by changing the variables to
To solve the Hydrogen atom problem, we replace the potential V(r) with the coulomb
potential
e2
V (r) = − (5.5)
4π0 r
and the radial equation becomes
~2 d2 u e2 ~2 l(l + 1)
− + [− + ]u = Eu. (5.6)
2m dr2 4π0 r 2m r2
This equation can be converted to one in terms of a dimensionless variable ξ by the
substitution r = aξ where a is a constant with dimension of length and whose significance
we will see below. With this substitution the radial equation becomes
~ 2 d2 u e2 ~2 l(l + 1)
− + [− + ]u = Eu. (5.7)
2ma2 dξ 2 4π0 aξ 2ma2 ξ 2
32
~2
Now, 2ma2
has the dimension of energy and if we divide throughout by it, we have
d2 u 2mae2 l(l + 1) E
− 2
+ [− 2
+ 2
]u = ~2 u. (5.8)
dξ 4π0 ~ ξ ξ 2ma2
d2 u 2mae2 l(l + 1)
− + [− + ]u = u. (5.9)
dξ 2 4π0 ~2 ξ ξ2
4π0 ~2
If we now choose a = me2
then the radial equation is simplified to a dimensionless form
d2 u 2 l(l + 1)
− + [− + ]u = u. (5.10)
dξ 2 ξ ξ2
4π0 ~2
The constant a = me2
is called the Bohr radius. is energy in Rydberg since 1Rydberg =
~2 2 2
2ma2
= m
( e ).
2~2 4π0
The radial equation is now in a dimensionless form ready to be solved
computationally.
We use a similar procedure of the shooting method which we have used in previous
chapters to solve the radial equation for the hydrogen atom. However, if we shoot from
the origin (r = 0), then the solutions diverge at large r even for the eigenvalues. This is
illustrated in figure 5.1 for the energy eigenvalue 1 = −1 and l = 0. Hence we shoot from
large r or what is the same thing, large ξ and try to find energies for which the solution
at origin is zero. This is shown in figure 5.2 for the energy eigenvalue 1 = −1 and l = 0.
We know that the eigenvalues of energy of the hydrogen atom, in units of Rydberg, go
like n = 1/n2 where n = 1, 2, 3, ... . So while shooting, we start from energy values less
than 1 , for example -1.2 and go to higher energy values. We also use a logarithmically
spaced mesh for ξ since the higher wavefunctions extend out to larger distances.
5.0.1 Programme
The code for finding the first seven states for the l = 0 case is given below. The centrifugal
term in equation 5.10 is then zero. The procedure is similar to the earlier shooting methods
used except for the differences pointed out in the preceding paragraphs. The explanation
for the code is given in the comments.
r = logspace(-10,2,600) /* defines a logarithmic grid for radial
coordinate, note r = 0 is not taken instead r is taken to be a
very small value*/
r_flip = flipdim(r,2) /*flip the r matrix so that the first element is
the largest r */
function D_u = f(r,u,E) /* defines the system of first order ode
for the radial Schrodinger equation*/
D_u(1) = u(2)
D_u(2) = (-E-2/r)*u(1)
endfunction
33
0.4
0.35
0.3
0.25
0.2
0.15
0.1
0.05
0
0 2 4 6 8 10 12 14 16 18 20
u_0 = [0;1e-5] /* takes an initial value for the wavefunction and its
derivative */
34
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
−0.1
0 10 20 30 40 50 60 70 80 90 100
35
if u_end1*u_end3<0 then /* choose the proper limit based on
whether the lower or upper energy limit has a solution diverging in
opposite direction to the solution at the middle energy */
E2 = E_mid
u_end2 = u_end3
else
E1 = E_mid
u_end1 = u_end3
end
end /* break from loop when the energy interval is less than
the tolerance */
disp("E_mid, the new eigenvalue is", E_mid)
Eigen_list($+1) = E_mid // stores the E_mid as eigenvalue
n_eigen = n_eigen + 1 // icrements the eigenfunction counter
E1 = E_mid + E_step /* changes E1 in line# 19 to new energy to
nudge it to next root */
u_wf = flipdim(u(1,:),2) /*flips the solution to get wavefunction
in increasing r*/
disp("length of u_wf", length(u_wf))
disp("length of r", length(r))
norm_factor = sqrt(inttrap(r,u_wf**2))// normalization constant
u_wf = u_wf/norm_factor // normalize the wavefunction
plot(r,u_wf**2,s(n_eigen-1),'linewidth',3) /*plot square of the
eigenfunctions */
end
plot([r(1),r($)],[0,0],'k') // plot horizontal line
xs2eps(0,'Plot_of_hydrogen_atom_radial_wavefunctions') /*generates a
eps file of the plot */
disp(Eigen_list)
5.0.2 Output
The plot of the first seven radial s-wavefunctions are given in figure 5.3.
36
0.6
0.55
0.5
0.45
0.4
0.35
0.3
0.25
0.2
0.15
0.1
0.05
0
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
Figure 5.3: First seven radial s-wavefunctions for the Hydrogen atom.
37
Chapter 6
We are now going to solve the s-wave (l = 0) radial Schrodinger equation for a particle
of mass m in the anharmonic oscillator potential
1 1
V (r) = kr2 + br3 (6.1)
2 3
Here k = 100 MeV/f m2 , m = 940 MeV/c2 , b = 10 MeV/f m3 and c~ = 197.3 MeV-fm.
Setting c = 1, the radial part of schrodinger equation becomes
~2 d2 ψn
1 2 1 3
− + kx + bx ψn = En ψn (6.2)
2m dr2 2 3
q
Further setting ξ = r mk~2 transforms the Schrodinger’s equation as
23 !
d2 ψn ~2 2 2b ~2
− 2 + ξ + ξ 3 ψn = Wn ψn . (6.3)
dξ mk 3k mk
2En
where Wn = k
38
Here’s why: if you have a force that causes a slight perturbation to a spring
system and this force is conservative then small oscillations about the mean
position can be described as:
∂V 1 ∂ 2V 1 ∂ 3V
V (r) = V (r0 )+( )|r=r0 (r−r0 )+ ( 2 )|r=r0 (r−r0 )2 + ( 3 )|r=r0 (r−r0 )3 +...
∂r 2! ∂r 3! ∂r
(6.4)
∂2V ∂3V
Now by setting ( ∂r2 )r=r0 = k(spring constant) and ( ∂r3 )r=r0 = b equation
6.4 becomes
1 1
V (r) = kx2 + bx3 .
2 6
The first derivative in equation 6.4 is zero as points of equilibrium tend to be
extremas. Below is the code for solving the anharmonic oscillator potential.
Figure 6.1 is the plot of the eigenfunctions of the anharmonic potential.
clc
nPoints = 500 //number of sampling points for the wavefunction
nPointsPlot = 200 // Number of points in x which are plotted
xiMax=10.0 //maximum value of x
xiMaxPlot = (xiMax*nPointsPlot)/nPoints//value of x upto which plotted
tolerance = 1.0e-12 //setting the tolerance for the values
nEigen = 7 //number of eigenstates plotted
EigvStep = 0.005 //step size for progression between eigenvalues
s = ['r' 'g' 'b' 'c' 'm' 'y' 'k']
xi = linspace(0,xiMax,nPoints) //defining x-axis points
m = 940 // mass of particle
k = 100 // spring constant
h =197.3 // Planck's constant
b = 10 // coefficient of cubic contribution
q1 = (h^2)/(m*k) //defining charecterstic scales
q2 = 2*m*b/(3*h.^2)
q3 = 2*m./h.^2
q4 = (2/3)*(b/k)*(h^2/(m*k))^(3/2)
function Dy = f(xi,y,E)//setting up the ODE for Schrodinger's equation
Dy(1) = y(2)
Dy(2) = (q1*xi*xi+q4*xi*xi*xi-E)*y(1)
endfunction
n = 0
Eigen = [] //defines empty array to store eigenvalues
E1 = 0 //initial guess W_n = 0
E = E1//Sets E to initial value chosen
39
while n < 7
if modulo(n,2) == 0
then
y0 = [1;0] // even solution
else
y0 = [0;1] // odd solution
end
psi = ode(y0,0,xi,f) //solving the ode given initial conditions
psi_end1 = psi(1,$) // value at xi_{max}
while 2 >0
E2 = E1 + EigvStep //finding the second eigenvalue
E = E2 //setting E in the ode equal to the 2nd eigenvalue
psi = ode(y0,0,xi,f) //solving the ode for 2nd energy
psi_end2 = psi(1,$) //xi_{max} for this eigenstate
if psi_end1*psi_end2 <0 /*incase there's a divergence break the loop
since we've obtained two different energy states*/
break
end
psi_end1 = psi_end2 /*if that's not the case then change your
eigenstate and repeat the process*/
E1 = E2
end
while abs(E1-E2)> tolerance /*Our two energy eigenvalues must differ
by not less than the set "tolerance value"*/
E_m = (E1+E2)/2.0 //find the midpoint of two energies
E = E_m //set the E parameter of ode equal to midpoint value
psi = ode(y0,0,xi,f) //solve the ode for midpoint value
psi_end3 = psi(1,$) //xi_{max} for this wavefunction
40
end
end
wavefunction = psi(1,:) //Wavefunction is the first row
while length(xi) > nPointsPlot //truncation of wavefunction
xi($) = []
wavefunction($) = []
end
Eigen($+1) = E_m //setting the eigenvalues equal to the E values
E = E_m + EigvStep
Norm_factor = sqrt(2*inttrap(xi,wavefunction**2))//norm
normalised_wf = wavefunction*0.4/Norm_factor // normalization
if modulo(n,2) == 0 then /*setting a symmetry for even and odd
wavefunctions*/
flip_wf = flipdim(normalised_wf,2) //even
flip_wf($)=[]
else
flip_wf = flipdim(-normalised_wf,2) //odd
flip_wf($)=[]
end
total_wf = cat(2,flip_wf,normalised_wf)+ E_m /*unification of even
and odd wavefunctions*/
flip_xi = flipdim(-xi,2)
flip_xi($) = []
total_xi = cat(2,flip_xi,xi) /*unification of $xi$ and $-xi$ and */
41
xset("font size",4)//sets the fontsize of text
xstring(-6,10, ' E7 = ' + string(Eigent(7)))/*displays the energy
eigenvalue against every eigenstate plot*/
xstring(-6,8, ' E6 = ' + string(Eigent(6)))
xstring(-6,6.5, ' E5 = ' + string(Eigent(5)))
xstring(-6,5, ' E4 = ' + string(Eigent(4)))
xstring(-6,3.5, ' E3 = ' + string(Eigent(3)))
xstring(-6,2, ' E2 = ' + string(Eigent(2)))
xstring(-6,0.5, ' E1 = ' + string(Eigent(1)))
42
Figure 6.1: Eigenfunctions and eigenvalues of the anharmonic oscillator potential. The
thick black solid line is the plot of the potential.
43
Chapter 7
44
~2
Now 2ma2 has the dimension of energy and if we divide throughout by it, we
have
d2 u
2 −ξ/α l(l + 1)
− 2+ − e + u = £u (7.6)
dξ ξ ξ2
2 2
where a = 4π 0~ ~
me2 is the Bohr Radius,£ is in Rydberg since 1 Rydberg = 2ma2 .
The radial equation is now in a dimensionless form ready to be solved com-
putationally. The following code was run to get the required output as shown
below. α = 2 was taken as the value parameter.
7.1.1 Programme
for l=0:1:1
scf(l)
r = logspace(-10,2,600)
r_flip = flipdim(r,2)
function D_u=f(r, u, E)
D_u(1) = u(2)
D_u(2) = ((-E-2/r)*exp(-r/2)+(l*(l+1)/r**2))*u(1)
endfunction
u_0 = [0;1e-5]
E_0 = -1.2
E_tol = 1.0e-12
E_step = 0.05
E1 = E_0
Eigen_list = []
n_eigen = 1
s=['red','maroon','magenta','purple','plum','violet','darkorchid','blue','cyan',
'turquoise','limegreen','forestgreen','green','yellow','orange','brown']
while n_eigen < 17
E = E1
u = ode(u_0,r_flip(1),r_flip,f)
u_end1 = u(1,$)
while 2>0
E2 = E1 + E_step
E = E2
u = ode(u_0,r_flip(1),r_flip,f)
u_end2 = u(1,$)
if u_end1*u_end2<0 then
break
end
E1 = E2
u_end1 = u_end2
end
while abs(E1-E2) > E_tol
E_mid = (E1+E2)/2
E = E_mid
u = ode(u_0,r_flip(1),r_flip,f)
u_end3 = u(1,$)
45
if u_end1*u_end3<0 then
E2 = E_mid
u_end2 = u_end3
else
E1 = E_mid
u_end1 = u_end3
end
end
Eigen_list($+1) = E_mid
n_eigen = n_eigen + 1
E1 = E_mid + E_step
u_wf = flipdim(u(1,:),2)
norm_factor = sqrt(inttrap(r,u_wf**2))
u_wf = u_wf/norm_factor
plot2d(r,u_wf**2,style=color(s(n_eigen-1)))
gca().font_size=4;
xstring((n_eigen-1)*6-6,.07+(l*.05)-(.002*n_eigen+(l*.005)),"${\textcolor{"+s(n_eigen-1)+
"}{\text{\epsilon_{"+string(n_eigen-1)+"}="+string(Eigen_list(n_eigen-1))+"}}$")
title("$Eigenfunctions\ at\ l\ ="+string(l)+"$", "fontsize", 5.5)
xlabel("$\xi = r\frac{me^2}{4\pi\epsilon_0\hbar^2}=\frac{r}{R_B}$", "fontsize",5)
ylabel("$Radial\ Part\ \psi(r)$","fontsize",5)
end
end
7.1.2 Output
46
Figure 7.2: Eigenfunctions of screened coulomb potential for l = 1 case.
47
y0 = [0;1]
end
psi = ode(y0,0,xi,f) // solve ode for initial value of E
psi_end1 = psi(1,$) // The value of solution at $\xi_{max}$
while 2 >0 //starts a while loop with a always true condition
E2 = E1 + EigvStep /*Increment to a new energy from the
initial value*/
E = E2 // Set variable E to the new value
psi = ode(y0,0,xi,f) // Solve ode for new E value
psi_end2 = psi(1,$) /*Store the value at $\xi_{max}$ of new
solution */
if psi_end1*psi_end2 <0 /* If the old and new solution diverge
in opposite directions, break from while loop with the two
energy values, old and new, as the interval of energy
13
containing the required energy which is the eigenvalue. At
this energy the solution will not diverge at $\xi_{max}$ */
//disp('break')
break
end
psi_end1 = psi_end2 /* if two energy values with oppositely
diverging solutions has not been found, then replace old
energy with new energy and start over again by incrementing to
a third energy value */
E1 = E2
end
while abs(E1-E2)> tolerance /* do a while loop as long as energy
interval is not less than the desired accuracy in energy eigenvalue*/
E_m = (E1+E2)/2.0 // Find the midpoint of energy interval
E = E_m // Set the variable E to midpoint in energy
psi = ode(y0,0,xi,f) /*Solve ode for the energy value equal
to the midpoint in energy */
psi_end3 = psi(1,$) /* Store the solution for the midpoint in
energy interval at $\xi_{max}$ */
// mprintf("psi_end1 is %e \n",psi_end1)
// mprintf("psi_end2 is %e \n",psi_end2)
// mprintf("psi_end3 is %e \n",psi_end3)
if psi_end3*psi_end1 < 0 then /* Check which endpoint of the
energy interval has a solution diverging in opposite direction to the
solution at the midpoint energy. This endpoint along with the midpoint
will be the new interval of energy for repaeting the process*/
E2 = E_m /*psi_end2 = psi_end3 seems to be not required in
any three programs!!?*/
psi_end2 = psi_end3
elseif psi_end3*psi_end2 < 0 then
E1 = E_m //similarly here also!!?
psi_end1 = psi_end3
end
//mprintf("energy interval is %e \n",abs(E1-E2))
end
wavefunction = psi(1,:) /*Set wavefunction as the first row of the
48
solution for the energy midpoint which we take as the eignevalue
within the accuracy limits set by us*/
while length(xi) > nPointsPlot /* Truncate $xi$ and wavefunction to
within maximum $\xi$ to be plotted */
xi($) = []
wavefunction($) = []
end
Eigen($+1) = E_m /* Add the latest eigenvalue to the list
of eigenvalues */
E = E_m + EigvStep /* Set the new value of energy to last
eigenvalue plus step in eigenvalue search */
Norm_factor = sqrt(2*inttrap(xi,wavefunction**2)) /* integrate the
14
square of the wavefunction and take square root to find the norm*/
normalised_wf = wavefunction*0.4/Norm_factor /* Normalize the
wavefunctions by dividing by norm and scale by an appropriate
factor for clarity in plotting */
if modulo(n,2) == 0 then /* Generate the wavefunction for negative
$\xi$ by choosing suitable symmetry for even and off
wavefunctions*/
flip_wf = flipdim(normalised_wf,2)
flip_wf($)=[]
else
flip_wf = flipdim(-normalised_wf,2)
flip_wf($)=[]
end
total_wf = cat(2,flip_wf,normalised_wf)+ E_m /* combine the
positive and negative part of the wavefunctions and add the
corresponding eigenvalue to separate the wavefunctions
along the y axis */
flip_xi = flipdim(-xi,2) // flip the matrix $\xi$
flip_xi($) = [] /* Remove $xi = 0$ to avoid duplicate entries after
combining */
total_xi = cat(2,flip_xi,xi) // Combine -ve and +ve $\xi$
//disp(length(total_xi))
n = n + 1 // Increment the eigenvalue counter by 1
plot2d(total_xi,total_wf,style=color(s(n)))
gca().children(1).children(1).thickness=3;
plot([total_xi(1),total_xi($)],[E_m,E_m],'k')/* Plot horizontal
line at the eigenvalue */
end
disp(Eigen)
gca().font_size=5;
title("$Eigenvalues\ \&\ Eigenfunctions\ of\ Double\ Well\ Potential\ V=\frac{\epsilon}{\delta^2}
xlabel("$\xi = \sqrt{\frac{\epsilon m}{\delta^2\hbar}(x^2-\delta)}\rightarrow$", "fontsize",5)
ylabel("$Energy\ E\rightarrow$","fontsize",5)
y = (1/4)*(total_xi**2-4)**2
plot(total_xi,y,'-.m', 'linewidth',2)
49
7.2.2 Output
50
Figure 7.4: Eigenfunctions of double well potential for l = 1 case.
51
Figure 7.6: Eigenfunctions of the double well potential.© Priyanshi Srivastava
52
Bibliography
[1] Jaan Kiusalaas. Numerical Methods in Engineering with Python 3. 3rd ed. Cambridge
University Press, 2013. doi: 10.1017/CBO9781139523899 (page 2).
[2] Q. Kong, T. Siauw, and A. Bayen. Python Programming and Numerical Methods:
A Guide for Engineers and Scientists. Elsevier Science, 2020. isbn: 9780128195505.
url: https://books.google.co.in/books?id=GWzqDwAAQBAJ (page 10).
[3] G. Moruzzi. Essential Python for the Physicist. Springer International Publishing,
2020. isbn: 9783030450267. url: https : / / books . google . co . in / books ? id =
mhZpzQEACAAJ (page 15).
[4] D.J. Griffiths and P.D.J. Griffiths. Introduction to Quantum Mechanics. Pearson in-
ternational edition. Pearson Prentice Hall, 2005. isbn: 9780131118928. url: https:
//books.google.co.in/books?id=z4fwAAAAMAAJ (pages 15, 29, 32).
53