Operators

Operator Definitions

quantized defines a set of commonly used quantum mechanical operators. These can be used to find the solution to the schroedinger equation, or to simply find the expectation value of an operator for a given state.

In [1]:
import numpy as np
np.set_printoptions(precision=4, suppress=True)

from quantized.basis import HarmonicOscillator
from quantized import operators as op

All operators are defined such that Operator()(state_1, state_2) is equal to $\langle {state}_1 | \hat{O} | {state}_2 \rangle$

Overlap

The most commonly used operator is the overlap operator. By default, the overlap operator will work on one dimensional functions and will integrate over $-\infty$ to $+\infty$. Since the harmonic oscillators are also functions, we can simply use the overlap operator to find the overlap of the harmonic oscillators.

In [2]:
ho = HarmonicOscillator(center=0.0, n=0)
op.Overlap()(ho, ho)
Out[2]:
1.0

As expected, the overlap of a normalized harmonic oscillator wavefunction with itself is exactly 1. As a sanity check, we can find the overlap of two different harmonic oscillators. One for n=1 and another for n=0. If we programmed correctly, this should be 0, since the wave functions are orthogonal.

In [3]:
ho1 = HarmonicOscillator(center=0.0, n=1)

op.Overlap()(ho, ho1)
Out[3]:
0.0

By now you might be wondering why the op.Overlap() syntax has us using an empty parenthesis. This is because we are free to supply the range of integration to our overlap function:

In [4]:
op.Overlap(lower_limit=-1.0, upper_limit=0.0)(ho, ho)
Out[4]:
0.42135039647485745

We will use this facility later to find the overlaps in each spatial region. For now, we can simply use Overlap() which will default to all space in one dimension. There are other operators that are defined similarly.

Kinetic Energy

We can evaluate the kinetic energy integral of our harmonic oscillator ground state:

In [5]:
op.Kinetic()(ho, ho)
Out[5]:
0.24999999999999933

Potential Energy

And we can evaluate the potential energy operator. The potential operator is a bit more unique. We can pass any function of one variable to the op.Potential to use for our potential operator. Let's try it out by using the potential for the harmonic oscillator.

In [6]:
op.Potential(ho.potential)(ho, ho)
Out[6]:
0.2500000000000006

Hamiltonian

Observant readers will notice that the kinetic + potential energy operators, when evaluated on the ground state harmonic oscillator, give us the ground state energy of the harmonic oscillator. In a similar fashion to the potential operator, the Hamiltonian operator also takes in any function of one variable to use as the potential.

In [7]:
op.Hamiltonian(ho.potential)(ho, ho)
Out[7]:
0.49999999999999994

Matrix Representation


As mentioned above, calling the operator on a pair of basis functions is equivalent to evaluating $\langle {state}_1 | \hat{O} | {state}_2 \rangle$. It is common practice to convert the operator into a matrix form, by evaluating the operator on all pairwise combinations of some chosen basis set. All operators support this via the following syntax:

In [8]:
basis = [HarmonicOscillator(center=0.0, n=i) for i in range(3)]
S = op.Overlap().matrix(basis)
S
Out[8]:
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
In [9]:
V = op.Potential(ho.potential).matrix(basis)
V
Out[9]:
array([[0.25  , 0.    , 0.3536],
       [0.    , 0.75  , 0.    ],
       [0.3536, 0.    , 1.25  ]])
In [10]:
T = op.Kinetic().matrix(basis)
T
Out[10]:
array([[ 0.25  ,  0.    , -0.3536],
       [ 0.    ,  0.75  ,  0.    ],
       [-0.3536,  0.    ,  1.25  ]])
In [11]:
H = op.Hamiltonian(ho.potential).matrix(basis)
H
Out[11]:
array([[0.5, 0. , 0. ],
       [0. , 1.5, 0. ],
       [0. , 0. , 2.5]])

Observe here that the Hamiltonian matrix is diagonal in the basis of harmonic oscillator wave functions. The diagonal elements are the energy levels of the harmonic oscillator.

Equivalence of Kinetic, Hamiltonian and Potential


As a sanity check, we can evaluate that the hamiltonian matrix is the sum of the potential energy matrix and the kinetic energy matrix.

In [12]:
H - (T + V)
Out[12]:
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

Overlap Matrix over portions of Space


In the probability analysis, we are often doing integrals over a subset of all space. In this operator formulation, it becomes very simple to do this

In [13]:
s1 = op.Overlap(-np.inf, 0).matrix(basis)
s1
Out[13]:
array([[ 0.5   , -0.3989,  0.    ],
       [-0.3989,  0.5   , -0.2821],
       [ 0.    , -0.2821,  0.5   ]])
In [14]:
s2 = op.Overlap(0, np.inf).matrix(basis)
s2
Out[14]:
array([[0.5   , 0.3989, 0.    ],
       [0.3989, 0.5   , 0.2821],
       [0.    , 0.2821, 0.5   ]])

Here we've calculated what I've been calling the partial overlap matrix. s1 represents the overlap matrix for negative values of x, and s2 represents the overlap matrix for positive x. They should add up to the total overlap matrix:

In [15]:
S - s1 - s2
Out[15]:
array([[ 0.,  0., -0.],
       [ 0., -0.,  0.],
       [-0.,  0.,  0.]])

And they do!