Two-time Correlation Functions
Introduction
With the QuantumToolbox.jl time-evolution function mesolve, a state vector (Ket) or density matrix (Operator) can be evolved from an initial state at
where
To calculate two-time correlation functions on the form
] to write
We therefore first calculate mesolve with mesolve to calculate
Note that if the initial state is the steady state, then
which is independent of
QuantumToolbox.jl provides a family of functions that assists in the process of calculating two-time correlation functions. The available functions and their usage is shown in the table below.
| Function call | Correlation function |
|---|---|
correlation_2op_2t | |
correlation_2op_1t | |
correlation_3op_1t | |
correlation_3op_2t |
The most common used case is to calculate the two time correlation function correlation_2op_1t.
Steadystate correlation function
The following code demonstrates how to calculate the
tlist = LinRange(0, 10, 200)
a = destroy(10)
x = a' + a
H = a' * a
# if the initial state is specified as `nothing`, the steady state will be calculated and used as the initial state.
corr1 = correlation_2op_1t(H, nothing, tlist, [sqrt(0.5) * a], x, x)
corr2 = correlation_2op_1t(H, nothing, tlist, [sqrt(1.0) * a], x, x)
corr3 = correlation_2op_1t(H, nothing, tlist, [sqrt(2.0) * a], x, x)
# plot by CairoMakie.jl
fig = Figure(size = (500, 350))
ax = Axis(fig[1, 1], xlabel = L"Time $t$", ylabel = L"\langle \hat{x}(t) \hat{x}(0) \rangle")
lines!(ax, tlist, real(corr1), label = L"\gamma = 0.5", linestyle = :solid)
lines!(ax, tlist, real(corr2), label = L"\gamma = 1.0", linestyle = :dash)
lines!(ax, tlist, real(corr3), label = L"\gamma = 2.0", linestyle = :dashdot)
axislegend(ax, position = :rt)
figEmission spectrum
Given a correlation function
In QuantumToolbox.jl, we can calculate spectrum, which provides several solvers to perform the Fourier transform semi-analytically, or we can use the function spectrum_correlation_fft to numerically calculate the fast Fourier transform (FFT) of a given correlation data.
The following example demonstrates how these methods can be used to obtain the emission (
N = 4 # number of cavity fock states
ωc = 1.0 * 2 * π # cavity frequency
ωa = 1.0 * 2 * π # atom frequency
g = 0.1 * 2 * π # coupling strength
κ = 0.75 # cavity dissipation rate
γ = 0.25 # atom dissipation rate
# Jaynes-Cummings Hamiltonian
a = tensor(destroy(N), qeye(2))
sm = tensor(qeye(N), destroy(2))
H = ωc * a' * a + ωa * sm' * sm + g * (a' * sm + a * sm')
# collapse operators
n_th = 0.25
c_ops = [
sqrt(κ * (1 + n_th)) * a,
sqrt(κ * n_th) * a',
sqrt(γ) * sm,
];
# calculate the correlation function using mesolve, and then FFT to obtain the spectrum.
# Here we need to make sure to evaluate the correlation function for a sufficient long time and
# sufficiently high sampling rate so that FFT captures all the features in the resulting spectrum.
tlist = LinRange(0, 100, 5000)
corr = correlation_2op_1t(H, nothing, tlist, c_ops, a', a; progress_bar = Val(false))
ωlist1, spec1 = spectrum_correlation_fft(tlist, corr)
# calculate the power spectrum using spectrum
# using Exponential Series (default) method
ωlist2 = LinRange(0.25, 1.75, 200) * 2 * π
spec2 = spectrum(H, ωlist2, c_ops, a', a; solver = ExponentialSeries())
# calculate the power spectrum using spectrum
# using Pseudo-Inverse method
spec3 = spectrum(H, ωlist2, c_ops, a', a; solver = PseudoInverse())
# plot by CairoMakie.jl
fig = Figure(size = (500, 350))
ax = Axis(fig[1, 1], title = "Vacuum Rabi splitting", xlabel = "Frequency", ylabel = "Emission power spectrum")
lines!(ax, ωlist1 / (2 * π), spec1, label = "mesolve + FFT", linestyle = :solid)
lines!(ax, ωlist2 / (2 * π), spec2, label = "Exponential Series", linestyle = :dash)
lines!(ax, ωlist2 / (2 * π), spec3, label = "Pseudo-Inverse", linestyle = :dashdot)
xlims!(ax, ωlist2[1] / (2 * π), ωlist2[end] / (2 * π))
axislegend(ax, position = :rt)
figNon-steadystate correlation function
More generally, we can also calculate correlation functions of the kind QuantumToolbox.jl, we can evaluate such correlation functions using the function correlation_2op_2t. The default behavior of this function is to return a matrix with the correlations as a function of the two time coordinates (
t1_list = LinRange(0, 10.0, 200)
t2_list = LinRange(0, 10.0, 200)
N = 10
a = destroy(N)
x = a' + a
H = a' * a
c_ops = [sqrt(0.25) * a]
α = 2.5
ρ0 = coherent_dm(N, α)
corr = correlation_2op_2t(H, ρ0, t1_list, t2_list, c_ops, x, x; progress_bar = Val(false))
# plot by CairoMakie.jl
fig = Figure(size = (500, 400))
ax = Axis(fig[1, 1], title = L"\langle \hat{x}(t_1 + t_2) \hat{x}(t_1) \rangle", xlabel = L"Time $t_1$", ylabel = L"Time $t_2$")
heatmap!(ax, t1_list, t2_list, real(corr))
figExample: first-order optical coherence function
This example demonstrates how to calculate a correlation function on the form
For a coherent state
τlist = LinRange(0, 10, 200)
# Hamiltonian
N = 15
a = destroy(N)
H = 2 * π * a' * a
# collapse operator
G1 = 0.75
n_th = 2.00 # bath temperature in terms of excitation number
c_ops = [
sqrt(G1 * (1 + n_th)) * a,
sqrt(G1 * n_th) * a'
]
# start with a coherent state of α = 2.0
ρ0 = coherent_dm(N, 2.0)
# first calculate the occupation number as a function of time
n = mesolve(H, ρ0, τlist, c_ops, e_ops = [a' * a], progress_bar = Val(false)).expect[1,:]
n0 = n[1] # occupation number at τ = 0
# calculate the correlation function G1 and normalize with n to obtain g1
g1 = correlation_2op_1t(H, ρ0, τlist, c_ops, a', a, progress_bar = Val(false))
g1 = g1 ./ sqrt.(n .* n0)
# plot by CairoMakie.jl
fig = Figure(size = (500, 350))
ax = Axis(fig[1, 1], title = "Decay of a coherent state to an incoherent (thermal) state", xlabel = L"Time $\tau$")
lines!(ax, τlist, real(g1), label = L"g^{(1)}(\tau)", linestyle = :solid)
lines!(ax, τlist, real(n), label = L"n(\tau)", linestyle = :dash)
axislegend(ax, position = :rt)
figExample: second-order optical coherence function
The second-order optical coherence function, with time-delay
For a coherent state
To calculate this type of correlation function with QuantumToolbox.jl, we can use correlation_3op_1t, which computes a correlation function on the form
The following code calculates and plots
τlist = LinRange(0, 25, 200)
# Hamiltonian
N = 25
a = destroy(N)
H = 2 * π * a' * a
κ = 0.25
n_th = 2.0 # bath temperature in terms of excitation number
c_ops = [
sqrt(κ * (1 + n_th)) * a,
sqrt(κ * n_th) * a'
]
cases = [
Dict("state" => coherent_dm(N, sqrt(2)), "label" => "coherent state", "lstyle" => :solid),
Dict("state" => thermal_dm(N, 2), "label" => "thermal state", "lstyle" => :dash),
Dict("state" => fock_dm(N, 2), "label" => "Fock state", "lstyle" => :dashdot),
]
# plot by CairoMakie.jl
fig = Figure(size = (500, 350))
ax = Axis(fig[1, 1], xlabel = L"Time $\tau$", ylabel = L"g^{(2)}(\tau)")
for case in cases
ρ0 = case["state"]
# calculate the occupation number at τ = 0
n0 = expect(a' * a, ρ0)
# calculate the correlation function g2
g2 = correlation_3op_1t(H, ρ0, τlist, c_ops, a', a' * a, a, progress_bar = Val(false))
g2 = g2 ./ n0^2
lines!(ax, τlist, real(g2), label = case["label"], linestyle = case["lstyle"])
end
axislegend(ax, position = :rt)
fig