The Split-Operator Method (also called the Split-Step Method), was actually the primary method I used to solve the Schrödinger equation during my PhD. It is one of the simplest and fastest methods for this purpose and is widely used throughout modern quantum research in the area, in particular when dealing with the Non-linear Schrödinger Equation (NLSE):
which follows from the notation provided in the quantum systems chapter:
At its heart, the split-op method is nothing more than a pseudo-spectral differential equation solver... That is to say, it solves the Schrödinger equation with FFT's.
In fact, there is a large class of spectral and pseudo-spectral methods used to solve a number of different physical systems, and we'll definitely be covering those in the future.
As mentioned in the quantum systems section, we can represent a quantum wavefunction in momentum space, which is parameterized with the wavevector
If we assume a somewhat general solution to our quantum system:
and assume we are simulating our system by a series of small timesteps (
This accrues a small amount of error (
We can then address each part of this solution in chunks, first in position space, then in momentum space, then in position space again by using Fourier Transforms. Which looks something like this:
where
For the most part, that's it:
- Multiply the wavefunction in real space with the real-space operator.
- Flip to momentum space with a Fourier transform.
- Multiply the momentum-space wavefuntion by the momentum-space operator.
- Flip to position space with an inverse Fourier transform.
- Repeat 1-4 until satisfied.
If we guess that our initial wavefunction is gaussian-like and is slightly offset from the center or the trap, this should allow us to see our wavefunction "sloshing" back and forth in our trap, like so:
As a small concession, using this method enforces periodic boundary conditions, where the wavefunction will simply slide from one side of your simulation box to the other, but that's fine for most cases. In fact, for many cases (such as large-scale turbulence models) it's ideal.
That said, there is more to the story.
As we mentioned in the quantum systems section, many simulations of quantum systems desire to find the ground state of our system.
The split-operator method can be used for that too!
If we run this simulation in imaginary time, by simply setting
Luckily, the code in this case is pretty straightforward.
As a note before starting, we will be using normalized units in this simulation where
Regardless, we first need to set all the initial parameters, including the initial grids in real and momentum space:
{% method %} {% sample lang="jl" %} import:9-32, lang:"julia" {% sample lang="c" %} import:10-20, lang:"c_cpp" import:51-72, lang:"c_cpp" {% sample lang="py" %} import:11-30, lang:"python" {% endmethod %}
As a note, when we generate our grid in momentum space k
, we need to split the grid into two lines, one that is going from 0
to -kmax
and is then discontinuous and goes from kmax
to 0
.
This is simply because the FFT will naturally assume that the 0
in our grid is at the left side of the simulation, so we shift k-space to match this expectation.
Also, for this code we will be using notation to what we used above: opr.R
will be the real space operators and opr.K
will be the momentum space operators.
There is another boolean value here called im_time
, which is for imaginary time evolution.
Afterwards, we turn them into operators:
{% method %} {% sample lang="jl" %} import:34-60, lang:"julia" {% sample lang="c" %} import:22-28, lang:"c_cpp" import:74-95, lang:"c_cpp" {% sample lang="py" %} import:33-54, lang:"python" {% endmethod %}
Here, we use a standard harmonic potential for the atoms to sit in and a gaussian distribution for an initial guess for the probability distribution.
If we give either the trap or the atoms a slight offset (so the gaussian distribution of atoms does not quite rest at the bottom of the
The final step is to do the iteration, itself.
{% method %} {% sample lang="jl" %} import:63-109, lang:"julia" {% sample lang="c" %} import:97-145, lang:"c_cpp" {% sample lang="py" %} import:57-95, lang:"python" {% endmethod %}
And that's it.
There is something a bit odd about the simulation in imaginary time, though.
Basically, in imaginary time, we see an exponential decay of all the higher energy states, which means we are technically losing a large amount of our wavefunction density every timestep!
To solve this issue, we renormalize by enforcing that dx
, and then dividing each element in the wavefunction by the sqrt()
of that value.
The Split-Operator method is one of the most commonly used quantum simulation algorithms because of how straightforward it is to code and how quickly you can start really digging into the physics of the simulation results!
This example code is a simulation of a gaussian distribution of atoms slightly offset in a harmonic trap in imaginary time.
So long as the code is written appropriately, this means that the atoms should move towards the center of the trap and the energy should decay to
{% method %} {% sample lang="jl" %} import, lang:"julia" {% sample lang="c" %} import, lang:"c_cpp" {% sample lang="py" %} import:5-127, lang:"python" {% endmethod %}
<script> MathJax.Hub.Queue(["Typeset",MathJax.Hub]); </script>