Schrödinger Equation Solver
Unitary evolution
The dynamics of a closed (pure) quantum system is governed by the Schrödinger equation
where
where
The Schrödinger equation, which governs the time-evolution of closed quantum systems, is defined by its Hamiltonian and state vector. In the previous sections, Manipulating States and Operators and Tensor Products and Partial Traces, we showed how Hamiltonians and state vectors are constructed in QuantumToolbox.jl
. Given a Hamiltonian, we can calculate the unitary (non-dissipative) time-evolution of an arbitrary initial state vector QuantumToolbox
time evolution problem sesolveProblem
or directly call the function sesolve
. It evolves the state vector e_ops
at each given time points, using an ordinary differential equation solver provided by the powerful julia package DifferentialEquation.jl
.
Example: Spin dynamics
For example, the time evolution of a quantum spin-
H = 2 * π * 0.1 * sigmax()
ψ0 = basis(2, 0) # spin-up
tlist = LinRange(0.0, 10.0, 20)
prob = sesolveProblem(H, ψ0, tlist, e_ops = [sigmaz()])
sol = sesolve(prob)
Solution of time evolution
(return code: Success)
--------------------------
num_states = 1
num_expect = 1
ODE alg.: OrdinaryDiffEqTsit5.Tsit5{typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!), Static.False}(OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, static(false))
abstol = 1.0e-8
reltol = 1.0e-6
Note
Here, we generate the time evolution problem by sesolveProblem
first and then put it into the function sesolve
. One can also directly call sesolve
, which we also demonstrates in below.
The function returns TimeEvolutionSol
, as described in the previous section Time Evolution Solutions. The attribute expect
in sol
ution is a list of expectation values for the operator(s) that are passed to the e_ops
keyword argument.
sol.expect
1×20 Matrix{ComplexF64}:
1.0+0.0im 0.789141+0.0im 0.245485+0.0im … 0.789141+0.0im 1.0+0.0im
Passing multiple operators to e_ops
as a Vector
results in the expectation values for each operators at each time points.
tlist = LinRange(0.0, 10.0, 100)
sol = sesolve(H, ψ0, tlist, e_ops = [sigmaz(), sigmay()])
Solution of time evolution
(return code: Success)
--------------------------
num_states = 1
num_expect = 2
ODE alg.: OrdinaryDiffEqTsit5.Tsit5{typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!), Static.False}(OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, static(false))
abstol = 1.0e-8
reltol = 1.0e-6
Note
Here, we call sesolve
directly instead of pre-defining sesolveProblem
first (as shown previously).
times = sol.times
print(size(times))
(100,)
expt = sol.expect
print(size(expt))
(2, 100)
We can therefore plot the expectation values:
expt_z = real(expt[1,:])
expt_y = real(expt[2,:])
# plot by CairoMakie.jl
fig = Figure(size = (500, 350))
ax = Axis(fig[1, 1], xlabel = "Time", ylabel = "Expectation values")
lines!(ax, times, expt_z, label = L"\langle\hat{\sigma}_z\rangle", linestyle = :solid)
lines!(ax, times, expt_y, label = L"\langle\hat{\sigma}_y\rangle", linestyle = :dash)
axislegend(ax, position = :rb)
fig
If the keyword argument e_ops
is not specified (or given as an empty Vector
), the sesolve
and functions return a TimeEvolutionSol
that contains a list of state vectors which corresponds to the time points specified in tlist
:
tlist = [0, 10]
sol = sesolve(H, ψ0, tlist) # or specify: e_ops = []
sol.states
2-element Vector{QuantumObject{KetQuantumObject, Dimensions{1, Tuple{Space}}, Vector{ComplexF64}}}:
Quantum Object: type=Ket dims=[2] size=(2,)
2-element Vector{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
Quantum Object: type=Ket dims=[2] size=(2,)
2-element Vector{ComplexF64}:
0.9999999543220187 + 0.0im
0.0 - 5.6377384923229734e-8im
This is because the states
will be saved depend on the keyword argument saveat
in kwargs
. If e_ops
is empty, the default value of saveat=tlist
(saving the states corresponding to tlist
), otherwise, saveat=[tlist[end]]
(only save the final state).
One can also specify e_ops
and saveat
separately:
tlist = [0, 5, 10]
sol = sesolve(H, ψ0, tlist, e_ops = [sigmay()], saveat = tlist)
Solution of time evolution
(return code: Success)
--------------------------
num_states = 3
num_expect = 1
ODE alg.: OrdinaryDiffEqTsit5.Tsit5{typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!), Static.False}(OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, static(false))
abstol = 1.0e-8
reltol = 1.0e-6
sol.expect
1×3 Matrix{ComplexF64}:
0.0+0.0im -7.18972e-8+0.0im -1.12755e-7+0.0im
sol.states
3-element Vector{QuantumObject{KetQuantumObject, Dimensions{1, Tuple{Space}}, Vector{ComplexF64}}}:
Quantum Object: type=Ket dims=[2] size=(2,)
2-element Vector{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0im
Quantum Object: type=Ket dims=[2] size=(2,)
2-element Vector{ComplexF64}:
-0.9999999984043708 + 0.0im
0.0 + 3.594862168420766e-8im
Quantum Object: type=Ket dims=[2] size=(2,)
2-element Vector{ComplexF64}:
0.9999999543220187 + 0.0im
0.0 - 5.6377384923229734e-8im