Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
4a1dbd5
ssesolve problem
lgravina1997 Aug 28, 2024
42f4a21
Merge remote-tracking branch 'upstream/main' into SSE
lgravina1997 Aug 28, 2024
0515244
fix operator_sum
lgravina1997 Aug 28, 2024
eef4ce9
fixes
lgravina1997 Aug 28, 2024
7b43c7e
improved diffusion and added comments
lgravina1997 Aug 29, 2024
06cd067
ensemble problem
lgravina1997 Aug 29, 2024
3e344ca
Fix instabilities
albertomercurio Aug 29, 2024
90ad6a1
Improve WienerProcesses
albertomercurio Aug 29, 2024
e95ea5d
Fix type instabilities
albertomercurio Aug 30, 2024
34327c0
docs
lgravina1997 Aug 30, 2024
139c017
api
lgravina1997 Aug 31, 2024
5730f8c
update project
lgravina1997 Aug 31, 2024
a15e236
add tests
lgravina1997 Aug 31, 2024
5588ef2
fix TimeEvolutionSSESol
lgravina1997 Sep 1, 2024
c31c665
Fix white space
albertomercurio Sep 27, 2024
81885b4
[Docs] Basic Operations on Quantum Objects (#145)
ytdHuang Aug 31, 2024
fc5bb6b
Add Unitary Fund Badge
albertomercurio Sep 2, 2024
cbae37c
Improve ProgressBar thread safety (#212)
albertomercurio Sep 2, 2024
27263d2
Set Version v0.12.1
albertomercurio Sep 2, 2024
a0f6324
Update buildkite token (#214)
ytdHuang Sep 5, 2024
8039910
Normalize states for `mcsolve` solution (#213)
albertomercurio Sep 5, 2024
57e6e55
Improve c_ops handling (#216)
albertomercurio Sep 7, 2024
1f487d6
Change the type of `dims` for `QuantumObject` to `SVector` for type s…
albertomercurio Sep 8, 2024
70f5962
Drop `Julia v1.9` (#218)
ytdHuang Sep 8, 2024
8bf642c
fix typo for `versioninfo` (#220)
ytdHuang Sep 9, 2024
87495c0
Fix type instabilities for almost all functions (#221)
albertomercurio Sep 9, 2024
de271d5
bump version to `0.13.1`
ytdHuang Sep 10, 2024
6afd966
Add CUDA.allowscalar(false)
albertomercurio Sep 10, 2024
c2381fc
Avoid scalar indexing in runtests and fix buildkite pipeline (#222)
ytdHuang Sep 11, 2024
41a194c
update README
ytdHuang Sep 15, 2024
095eba4
extended methods for `expect` and `variance`
ytdHuang Sep 15, 2024
ae20ad7
add new section to docs
ytdHuang Sep 15, 2024
25140a6
format files
ytdHuang Sep 15, 2024
e895dc1
change section title in docs
ytdHuang Sep 15, 2024
ad6c2b0
extended methods for `tensor` and `kron`
ytdHuang Sep 15, 2024
a54a8f8
add new section to docs
ytdHuang Sep 15, 2024
b283ef5
add `hat` to all docs and make `fcreate` and `fdestroy` compat with `…
ytdHuang Sep 17, 2024
ac0e7c0
Fix `ptrace` (#225)
ytdHuang Sep 17, 2024
d7bc352
Change version to v0.14.0
albertomercurio Sep 17, 2024
30f9167
fix type conversion of `tlist` in time evolution
ytdHuang Sep 19, 2024
4625d35
fix typo
ytdHuang Sep 19, 2024
99dcb09
format files
ytdHuang Sep 19, 2024
18524a6
introduce inner function `_convert_u0`
ytdHuang Sep 19, 2024
78bfcbd
fix element type for `steadystate`
ytdHuang Sep 19, 2024
42543a7
add comments
ytdHuang Sep 19, 2024
c199e46
minor change
ytdHuang Sep 19, 2024
72f3974
re-organize runtests directory (#228)
ytdHuang Sep 19, 2024
108bdf9
handle type of `u0` with `sparse_to_dense`
ytdHuang Sep 19, 2024
e03b9d9
fix typo
ytdHuang Sep 19, 2024
1bae876
fix `rand_unitary` (#230)
ytdHuang Sep 22, 2024
1d0437a
fix CI config (#232)
ytdHuang Sep 22, 2024
08551b7
Add pipeline to run core and code quality tests under `Julia nightly`…
ytdHuang Sep 24, 2024
bc0074b
Introduce `Makefile` to make development more convenient (#234)
ytdHuang Sep 24, 2024
0827792
Automatically convert TimeDependentOperatorSum to liouvillian
albertomercurio Sep 26, 2024
e94dc3a
Change version to v0.14.1
albertomercurio Sep 27, 2024
de1babc
add command `all` to Makefile (#236)
ytdHuang Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.12.0"
[deps]
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def"
DiffEqNoiseProcess = "77a26b50-5914-5dd7-bc55-306e6241c503"
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
IncompleteLU = "40713840-3770-5561-ab4c-a76e7d0d7895"
Expand All @@ -18,6 +19,7 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0"

[weakdeps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
Expand Down
3 changes: 3 additions & 0 deletions src/QuantumToolbox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Reexport: @reexport
@reexport using LinearAlgebra
@reexport using SparseArrays
@reexport using OrdinaryDiffEq
@reexport using StochasticDiffEq
@reexport using LinearSolve

# other functions in LinearAlgebra
Expand All @@ -29,6 +30,7 @@ import Graphs: connected_components, DiGraph
import IncompleteLU: ilu
import LinearMaps: LinearMap
import OrdinaryDiffEq: OrdinaryDiffEqAlgorithm
import DiffEqNoiseProcess: RealWienerProcess, RealWienerProcess!
import Pkg
import Random
import SpecialFunctions: loggamma
Expand Down Expand Up @@ -60,6 +62,7 @@ include("time_evolution/mesolve.jl")
include("time_evolution/lr_mesolve.jl")
include("time_evolution/sesolve.jl")
include("time_evolution/mcsolve.jl")
include("time_evolution/ssesolve.jl")
include("time_evolution/time_evolution_dynamical.jl")

# Others
Expand Down
2 changes: 1 addition & 1 deletion src/qobj/operator_sum.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct OperatorSum{CT<:Vector{<:Number},OT<:AbstractVector} <: AbstractQuantumOb
mapreduce(x -> size(x) == size_1, &, operators) ||
throw(DimensionMismatch("All the operators must have the same dimensions."))
T = promote_type(
mapreduce(x -> eltype(x.data), promote_type, operators),
mapreduce(x -> eltype(x), promote_type, operators),
mapreduce(eltype, promote_type, coefficients),
)
coefficients2 = T.(coefficients)
Expand Down
4 changes: 2 additions & 2 deletions src/time_evolution/mcsolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function _mcsolve_output_func(sol, i)
return (sol, false)
end

function _mcsolve_generate_statistics(sol, i, times, states, expvals_all, jump_times, jump_which)
function _mcsolve_generate_statistics!(sol, i, times, states, expvals_all, jump_times, jump_which)
sol_i = sol[:, i]
!isempty(sol_i.prob.kwargs[:saveat]) ?
states[i] = [QuantumObject(sol_i.u[i], dims = sol_i.prob.p.Hdims) for i in 1:length(sol_i.u)] : nothing
Expand Down Expand Up @@ -524,7 +524,7 @@ function mcsolve(
jump_which = Vector{Vector{Int16}}(undef, length(sol))

foreach(
i -> _mcsolve_generate_statistics(sol, i, times, states, expvals_all, jump_times, jump_which),
i -> _mcsolve_generate_statistics!(sol, i, times, states, expvals_all, jump_times, jump_which),
eachindex(sol),
)
expvals = dropdims(sum(expvals_all, dims = 1), dims = 1) ./ length(sol)
Expand Down
219 changes: 219 additions & 0 deletions src/time_evolution/ssesolve.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
export ssesolveProblem, ssesolveEnsembleProblem, ssesolve

#TODO: Check if works in GPU
function _ssesolve_update_coefficients!(ψ, coefficients, c_ops)
_get_en = op -> real(dot(ψ, op, ψ)) #this is en/2: <Sn + Sn'>/2 = Re<Sn>
@. coefficients[2:end-1] = _get_en(c_ops) #coefficients of the OperatorSum: Σ Sn * en/2
coefficients[end] = -sum(x -> x^2, coefficients[2:end-1]) / 2 #this last coefficient is -Σen^2/8
return nothing
end

function ssesolve_drift!(du, u, p, t)
_ssesolve_update_coefficients!(u, p.K.coefficients, p.c_ops)

mul!(du, p.K, u)

return nothing
end

function ssesolve_diffusion!(du, u, p, t)
@inbounds en = @view(p.K.coefficients[2:end-1])

# du:(H,W). du_reshaped:(H*W,).
# H:Hilbert space dimension, W: number of c_ops
du_reshaped = reshape(du, :)
mul!(du_reshaped, p.D, u) #du[:,i] = D[i] * u

du .-= u .* reshape(en, 1, :) #du[:,i] -= en[i] * u

return nothing
end

function _ssesolve_prob_func(prob, i, repeat)
internal_params = prob.p

noise = RealWienerProcess!(prob.tspan[1], zeros(length(internal_params.c_ops)), zeros(length(internal_params.c_ops)), save_everystep = false)

prm = merge(
internal_params,
(
expvals = similar(internal_params.expvals),
progr = ProgressBar(size(internal_params.expvals, 2), enable = false),
),
)

return remake(prob, p = prm, noise = noise)
end

_ssesolve_output_func(sol, i) = (sol, false)

function _ssesolve_generate_statistics!(sol, i, states, expvals_all)
sol_i = sol[:, i]
!isempty(sol_i.prob.kwargs[:saveat]) ?
states[i] = [QuantumObject(sol_i.u[i], dims = sol_i.prob.p.Hdims) for i in 1:length(sol_i.u)] : nothing

copyto!(view(expvals_all, i, :, :), sol_i.prob.p.expvals)
return nothing
end

function ssesolveProblem(
H::QuantumObject{MT1,OperatorQuantumObject},
ψ0::QuantumObject{<:AbstractArray{T2},KetQuantumObject},
tlist::AbstractVector,
c_ops::Vector{QuantumObject{Tc,OperatorQuantumObject}} = QuantumObject{MT1,OperatorQuantumObject}[];
alg::StochasticDiffEq.StochasticDiffEqAlgorithm = EM(),
e_ops::Union{Nothing,AbstractVector} = nothing,
H_t::Union{Nothing,Function,TimeDependentOperatorSum} = nothing,
params::NamedTuple = NamedTuple(),
progress_bar::Union{Val,Bool} = Val(true),
kwargs...,
) where {MT1<:AbstractMatrix,T2,Tc<:AbstractMatrix}
H.dims != ψ0.dims && throw(DimensionMismatch("The two quantum objects are not of the same Hilbert dimension."))

haskey(kwargs, :save_idxs) &&
throw(ArgumentError("The keyword argument \"save_idxs\" is not supported in QuantumToolbox."))

!(H_t isa Nothing) && throw(ArgumentError("Time-dependent Hamiltonians are not currently supported in ssesolve."))

progress_bar_val = makeVal(progress_bar)

t_l = convert(Vector{Float64}, tlist) # Convert it into Float64 to avoid type instabilities for OrdinaryDiffEq.jl

ϕ0 = get_data(ψ0)

H_eff = get_data(H - T2(0.5im) * mapreduce(op -> op' * op, +, c_ops))
c_ops2 = get_data.(c_ops)

coefficients = [1.0, fill(0.0, length(c_ops) + 1)...]
operators = [-1im * H_eff, c_ops2..., I(prod(H.dims))]
K = OperatorSum(coefficients, operators)
_ssesolve_update_coefficients!(ϕ0, K.coefficients, c_ops2)

D = vcat(c_ops2...)

progr = ProgressBar(length(t_l), enable = getVal(progress_bar_val))

if e_ops isa Nothing
expvals = Array{ComplexF64}(undef, 0, length(t_l))
e_ops2 = MT1[]
is_empty_e_ops = true
else
expvals = Array{ComplexF64}(undef, length(e_ops), length(t_l))
e_ops2 = get_data.(e_ops)
is_empty_e_ops = isempty(e_ops)
end

p = (
K = K,
D = D,
e_ops = e_ops2,
c_ops = c_ops2,
expvals = expvals,
progr = progr,
Hdims = H.dims,
H_t = H_t,
is_empty_e_ops = is_empty_e_ops,
params...,
)

saveat = e_ops isa Nothing ? t_l : [t_l[end]]
default_values = (DEFAULT_SDE_SOLVER_OPTIONS..., saveat = saveat)
kwargs2 = merge(default_values, kwargs)
kwargs3 = _generate_sesolve_kwargs(e_ops, progress_bar_val, t_l, kwargs2)

tspan = (t_l[1], t_l[end])
noise = RealWienerProcess!(t_l[1], zeros(length(c_ops)), zeros(length(c_ops)), save_everystep = false)
noise_rate_prototype = similar(ϕ0, length(ϕ0), length(c_ops))
return SDEProblem{true}(
ssesolve_drift!,
ssesolve_diffusion!,
ϕ0,
tspan,
p;
noise_rate_prototype = noise_rate_prototype,
noise = noise,
kwargs3...,
)
end

function ssesolveEnsembleProblem(
H::QuantumObject{MT1,OperatorQuantumObject},
ψ0::QuantumObject{<:AbstractArray{T2},KetQuantumObject},
tlist::AbstractVector,
c_ops::Vector{QuantumObject{Tc,OperatorQuantumObject}} = QuantumObject{MT1,OperatorQuantumObject}[];
alg::StochasticDiffEq.StochasticDiffEqAlgorithm = EM(),
e_ops::Union{Nothing,AbstractVector} = nothing,
H_t::Union{Nothing,Function,TimeDependentOperatorSum} = nothing,
params::NamedTuple = NamedTuple(),
prob_func::Function = _ssesolve_prob_func,
output_func::Function = _ssesolve_output_func,
kwargs...,
) where {MT1<:AbstractMatrix,T2,Tc<:AbstractMatrix}
prob_sse = ssesolveProblem(H, ψ0, tlist, c_ops; alg = alg, e_ops = e_ops, H_t = H_t, params = params, kwargs...)

ensemble_prob = EnsembleProblem(prob_sse, prob_func = prob_func, output_func = output_func)

return ensemble_prob
end

function ssesolve(
H::QuantumObject{MT1,OperatorQuantumObject},
ψ0::QuantumObject{<:AbstractArray{T2},KetQuantumObject},
tlist::AbstractVector,
c_ops::Vector{QuantumObject{Tc,OperatorQuantumObject}} = QuantumObject{MT1,OperatorQuantumObject}[];
alg::StochasticDiffEq.StochasticDiffEqAlgorithm = EM(),
e_ops::Union{Nothing,AbstractVector} = nothing,
H_t::Union{Nothing,Function,TimeDependentOperatorSum} = nothing,
params::NamedTuple = NamedTuple(),
n_traj::Int = 1,
ensemble_method = EnsembleThreads(),
prob_func::Function = _ssesolve_prob_func,
output_func::Function = _ssesolve_output_func,
kwargs...,
) where {MT1<:AbstractMatrix,T2,Tc<:AbstractMatrix}
ens_prob = ssesolveEnsembleProblem(
H,
ψ0,
tlist,
c_ops;
alg = alg,
e_ops = e_ops,
H_t = H_t,
params = params,
prob_func = prob_func,
output_func = output_func,
kwargs...,
)

return ssesolve(ens_prob; alg = alg, n_traj = n_traj, ensemble_method = ensemble_method)
end

function ssesolve(
ens_prob::EnsembleProblem;
alg::StochasticDiffEq.StochasticDiffEqAlgorithm = EM(),
n_traj::Int = 1,
ensemble_method = EnsembleThreads(),
)
sol = solve(ens_prob, alg, ensemble_method, trajectories = n_traj)
_sol_1 = sol[:, 1]

expvals_all = Array{ComplexF64}(undef, length(sol), size(_sol_1.prob.p.expvals)...)
states =
isempty(_sol_1.prob.kwargs[:saveat]) ? fill(QuantumObject[], length(sol)) :
Vector{Vector{QuantumObject}}(undef, length(sol))

foreach(i -> _ssesolve_generate_statistics!(sol, i, states, expvals_all), eachindex(sol))
expvals = dropdims(sum(expvals_all, dims = 1), dims = 1) ./ length(sol)

return TimeEvolutionSSESol(
n_traj,
_sol_1.t,
states,
expvals,
expvals_all,
sol.converged,
_sol_1.alg,
_sol_1.prob.kwargs[:abstol],
_sol_1.prob.kwargs[:reltol],
)
end
32 changes: 32 additions & 0 deletions src/time_evolution/time_evolution.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export TimeEvolutionSol, TimeEvolutionMCSol
export liouvillian, liouvillian_floquet, liouvillian_generalized

const DEFAULT_ODE_SOLVER_OPTIONS = (abstol = 1e-8, reltol = 1e-6, save_everystep = false, save_end = true)
const DEFAULT_SDE_SOLVER_OPTIONS = (abstol = 1e-2, reltol = 1e-2, save_everystep = false, save_end = true)

@doc raw"""
struct TimeEvolutionSol
Expand Down Expand Up @@ -95,6 +96,37 @@ function Base.show(io::IO, sol::TimeEvolutionMCSol)
return nothing
end

struct TimeEvolutionSSESol{
TT<:Vector{<:Real},
TS<:AbstractVector,
TE<:Matrix{ComplexF64},
TEA<:Array{ComplexF64,3},
T<:Real,
}
n_traj::Int
times::TT
states::TS
expect::TE
expect_all::TEA
converged::Bool
alg::StochasticDiffEq.StochasticDiffEqAlgorithm
abstol::T
reltol::T
end

function Base.show(io::IO, sol::TimeEvolutionSSESol)
print(io, "Solution of quantum trajectories\n")
print(io, "(converged: $(sol.converged))\n")
print(io, "--------------------------------\n")
print(io, "num_trajectories = $(sol.n_traj)\n")
# print(io, "num_states = $(length(sol.states[1]))\n")
print(io, "num_expect = $(size(sol.expect, 1))\n")
print(io, "SDE alg.: $(sol.alg)\n")
print(io, "abstol = $(sol.abstol)\n")
print(io, "reltol = $(sol.reltol)\n")
return nothing
end

abstract type LindbladJumpCallbackType end

struct ContinuousLindbladJumpCallback <: LindbladJumpCallbackType
Expand Down