Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge from main branch #55

Merged
merged 15 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
12 changes: 8 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ on:
push:
branches:
- 'main'
paths-ignore:
- 'docs/**'
pull_request:
branches:
- 'main'
paths-ignore:
- 'docs/**'
types:
- opened
- reopened
Expand Down Expand Up @@ -38,7 +42,7 @@ jobs:
- Core
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v1
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
Expand All @@ -52,6 +56,6 @@ jobs:
directories: src
- uses: codecov/codecov-action@v4
with:
verbose: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
if: ${{ !github.event.pull_request.draft }}
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v1
- uses: julia-actions/setup-julia@v2
with:
version: '1'
- uses: julia-actions/julia-buildpkg@v1
Expand Down
6 changes: 2 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,19 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"

[compat]
DiffEqCallbacks = "2.24, <3.2.0"
DiffEqCallbacks = "2.24, <3.2.0, >=3.5.0"
FFTW = "1.5"
Graphs = "1.7.4"
IncompleteLU = "0.2"
LinearMaps = "3"
LinearSolve = "2"
OrdinaryDiffEq = "6.30"
Reexport = "1"
SafeTestsets = "0.1"
SpecialFunctions = "2.2"
julia = "1.7"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"

[targets]
test = ["Test", "SafeTestsets"]
test = ["Test"]
1 change: 1 addition & 0 deletions src/QuantumToolbox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ include("spin_lattice.jl")
include("arnoldi.jl")
include("eigsolve.jl")
include("negativity.jl")
include("progress_bar.jl")

export QuantumObject, Qobj, BraQuantumObject, KetQuantumObject, OperatorQuantumObject, SuperOperatorQuantumObject, TimeEvolutionSol
export isket, isbra, isoper, issuper, ket2dm
Expand Down
52 changes: 52 additions & 0 deletions src/progress_bar.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export ProgressBar

struct ProgressBar{CT,T1<:Integer, T2<:Real}
counter::CT
max_counts::T1
enable::Bool
bar_width::T1
start_time::T2
lock::ReentrantLock
end

function ProgressBar(max_counts; enable=true, bar_width=30)
return ProgressBar(Ref{Int64}(0), max_counts, enable, bar_width, time(), ReentrantLock())
end

function next!(p::ProgressBar)

lock(p.lock)

p.counter[] += 1

!p.enable && return

counter = p.counter[]
max_counts = p.max_counts
bar_width = p.bar_width
start_time = p.start_time

percentage = counter / max_counts
percentage_100 = lpad(round(100 * percentage, digits=1), 5, " ")
progress = floor(Int, bar_width * percentage)

# Calculate the elapsed time in seconds
elapsed_time = floor(Int, time() - start_time)
# Convert the elapsed time into a string in hours, minutes and seconds
elapsed_time_str = string(elapsed_time ÷ 3600, "h ", lpad((elapsed_time % 3600) ÷ 60, 2, "0"), "m ", lpad(elapsed_time % 60, 2, "0"), "s")

# Calculate the estimated time of arrival
eta = floor(Int, elapsed_time ÷ counter * (max_counts - counter))
# convert eta into a string in hours, minutes and seconds
eta_str = string(eta ÷ 3600, "h ", lpad((eta % 3600) ÷ 60, 2, "0"), "m ", lpad(eta % 60, 2, "0"), "s")

# Construct the progress bar string
bar = "[" * repeat("=", progress) * repeat(" ", bar_width - progress) * "]"

print("\rProgress: $bar $percentage_100% --- Elapsed Time: $elapsed_time_str (ETA: $eta_str)")
flush(stdout)

unlock(p.lock)

p.counter[] >= p.max_counts ? print("\n") : nothing
end
73 changes: 52 additions & 21 deletions src/quantum_object.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,62 @@ mutable struct QuantumObject{MT<:AbstractArray,ObjType<:QuantumObjectType} <: Ab
dims::Vector{Int}
end

function QuantumObject(A::AbstractVector{T}; type::Type{ObjType}=KetQuantumObject, dims=nothing) where
{T,ObjType<:Union{BraQuantumObject,KetQuantumObject}}

dims === nothing ? dims = [length(A)] : nothing
prod(dims) != length(A) && throw(DimensionMismatch("The dims parameter does not fit the dimension of the Vector."))
# if !(norm(A) ≈ 1)
# @warn "The norm of the input data is not one."
# end
ObjType <: KetQuantumObject ? QuantumObject(A, type, dims) : QuantumObject(transpose(A), type, dims)
end

function QuantumObject(A::AbstractMatrix{T}; type::Type{ObjType}=OperatorQuantumObject, dims=nothing) where
{T,ObjType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}}
function QuantumObject(A::AbstractArray{T, N}; type::Type{ObjType}=Nothing, dims=nothing) where {T,N,ObjType<:Union{Nothing,QuantumObjectType}}

n = checksquare(A)
if type <: SuperOperatorQuantumObject
sqrt(n) - isqrt(n) != 0 ? throw(DomainError(n, "The dimension of the matrix is not compatible with the SuperOperator type")) : nothing
dims === nothing ? dims = [isqrt(n)] : nothing
prod(dims) != isqrt(n) && throw(DimensionMismatch("The dims parameter does not fit the dimension of the Matrix."))
# only accept 1D- and 2D-array
if N == 1
Size = (length(A), 1)
else
dims === nothing ? dims = [n] : nothing
prod(dims) != n && throw(DimensionMismatch("The dims parameter does not fit the dimension of the Matrix."))
Size = size(A)
N > 2 ? throw(DomainError(Size, "The dimension of the array is not compatible with Quantum Object")) : nothing
end

# decide QuantumObjectType from the size of A
if type == Nothing
if Size[1] == Size[2]
type = OperatorQuantumObject
elseif Size[2] == 1
type = KetQuantumObject
elseif Size[1] == 1
type = BraQuantumObject
else
throw(DomainError(Size, "The dimension of the array is not compatible with Quantum Object"))
end
end

# decide dims from the size of A and the given type
if dims === nothing
if (type <: KetQuantumObject) || (type <: OperatorQuantumObject)
dims = [Size[1]]
elseif type <: SuperOperatorQuantumObject
dims = [isqrt(Size[1])]
elseif type <: BraQuantumObject
dims = [Size[2]]
end
end

QuantumObject(A, type, dims)
_check_QuantumObject(type, prod(dims), Size[1], Size[2])
return QuantumObject(A, type, dims)
end

function _check_QuantumObject(type::Type{KetQuantumObject}, prod_dims::Int, m::Int, n::Int)
(n != 1) ? throw(DomainError((m, n), "The dimension of the array is not compatible with Ket type")) : nothing
prod_dims != m ? throw(DimensionMismatch("The dims parameter does not fit the dimension of the Array.")) : nothing
end

function _check_QuantumObject(type::Type{BraQuantumObject}, prod_dims::Int, m::Int, n::Int)
(m != 1) ? throw(DomainError((m, n), "The dimension of the array is not compatible with Bra type")) : nothing
prod_dims != n ? throw(DimensionMismatch("The dims parameter does not fit the dimension of the Array.")) : nothing
end

function _check_QuantumObject(type::Type{OperatorQuantumObject}, prod_dims::Int, m::Int, n::Int)
(m != n) ? throw(DomainError((m, n), "The dimension of the array is not compatible with Operator type")) : nothing
prod_dims != m ? throw(DimensionMismatch("The dims parameter does not fit the dimension of the Array.")) : nothing
end

function _check_QuantumObject(type::Type{SuperOperatorQuantumObject}, prod_dims::Int, m::Int, n::Int)
(m != n) ? throw(DomainError((m, n), "The dimension of the array is not compatible with SuperOperator type")) : nothing
prod_dims != sqrt(m) ? throw(DimensionMismatch("The dims parameter does not fit the dimension of the Array.")) : nothing
end

function QuantumObject(A::QuantumObject{<:AbstractArray}; type::Type{ObjType}=A.type, dims=A.dims) where
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 @@ -63,7 +63,7 @@ function _mcsolve_prob_func(prob, i, repeat)

prm = merge(internal_params, (expvals = similar(internal_params.expvals),
cache_mc = similar(internal_params.cache_mc), weights_mc = similar(internal_params.weights_mc),
cumsum_weights_mc = similar(internal_params.weights_mc), random_n = Ref(rand()), progr_mc = ODEProgress(0), jump_times_which_idx = Ref(1),
cumsum_weights_mc = similar(internal_params.weights_mc), random_n = Ref(rand()), progr_mc = ProgressBar(size(internal_params.expvals, 2), enable=false), jump_times_which_idx = Ref(1),
jump_times = similar(internal_params.jump_times), jump_which = similar(internal_params.jump_which)))

remake(prob, p=prm)
Expand Down Expand Up @@ -149,7 +149,7 @@ function mcsolveProblem(H::QuantumObject{MT1,OperatorQuantumObject},

params2 = (expvals = expvals, e_ops_mc = e_ops2,
is_empty_e_ops_mc = isempty(e_ops),
progr_mc = ODEProgress(0), seeds = seeds,
progr_mc = ProgressBar(length(t_l), enable=false), seeds = seeds,
random_n = Ref(rand()), c_ops = get_data.(c_ops), cache_mc = cache_mc,
weights_mc = weights_mc, cumsum_weights_mc = cumsum_weights_mc,
jump_times = jump_times, jump_which = jump_which,
Expand Down
10 changes: 8 additions & 2 deletions src/time_evolution/mesolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ end
e_ops::AbstractVector=[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...)

Generates the ODEProblem for the master equation time evolution of an open quantum system.
Expand All @@ -47,6 +48,7 @@ Generates the ODEProblem for the master equation time evolution of an open quant
- `e_ops::AbstractVector=[]`: The list of the operators for which the expectation values are calculated.
- `H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing`: The time-dependent Hamiltonian or Liouvillian.
- `params::NamedTuple=NamedTuple()`: The parameters of the time evolution.
- `progress_bar::Bool=true`: Whether to show the progress bar.
- `kwargs...`: The keyword arguments for the ODEProblem.

# Returns
Expand All @@ -60,6 +62,7 @@ function mesolveProblem(H::QuantumObject{MT1,HOpType},
e_ops::Vector{QuantumObject{Te, OperatorQuantumObject}}=QuantumObject{MT1, OperatorQuantumObject}[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...) where {MT1<:AbstractMatrix,T2,Tc<:AbstractMatrix,Te<:AbstractMatrix,
HOpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject},
StateOpType<:Union{KetQuantumObject,OperatorQuantumObject},
Expand All @@ -72,7 +75,7 @@ function mesolveProblem(H::QuantumObject{MT1,HOpType},
ρ0 = mat2vec(ket2dm(ψ0).data)
L = liouvillian(H, c_ops).data

progr = ODEProgress(0)
progr = ProgressBar(length(t_l), enable=progress_bar)
expvals = Array{ComplexF64}(undef, length(e_ops), length(t_l))
e_ops2 = @. mat2vec(adjoint(get_data(e_ops)))

Expand Down Expand Up @@ -105,6 +108,7 @@ end
e_ops::AbstractVector=[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...)

Time evolution of an open quantum system using master equation.
Expand All @@ -118,6 +122,7 @@ Time evolution of an open quantum system using master equation.
- `e_ops::AbstractVector`: List of operators for which to calculate expectation values.
- `H_t::Union{Nothing,Function,TimeDependentOperatorSum}`: Time-dependent part of the Hamiltonian.
- `params::NamedTuple`: Named Tuple of parameters to pass to the solver.
- `progress_bar::Bool`: Whether to show the progress bar.
- `kwargs...`: Additional keyword arguments to pass to the solver.

# Returns
Expand All @@ -131,13 +136,14 @@ function mesolve(H::QuantumObject{MT1,HOpType},
e_ops::Vector{QuantumObject{Te, OperatorQuantumObject}}=QuantumObject{MT1, OperatorQuantumObject}[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...) where {MT1<:AbstractMatrix,T2,Tc<:AbstractMatrix,Te<:AbstractMatrix,
HOpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject},
StateOpType<:Union{KetQuantumObject,OperatorQuantumObject},
COpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}}

prob = mesolveProblem(H, ψ0, t_l, c_ops; alg=alg, e_ops=e_ops,
H_t=H_t, params=params, kwargs...)
H_t=H_t, params=params, progress_bar=progress_bar, kwargs...)

return mesolve(prob, alg; kwargs...)
end
Expand Down
10 changes: 8 additions & 2 deletions src/time_evolution/sesolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ end
e_ops::AbstractVector=[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...)

Generates the ODEProblem for the Schrödinger time evolution of a quantum system.
Expand All @@ -44,6 +45,7 @@ Generates the ODEProblem for the Schrödinger time evolution of a quantum system
- `e_ops::AbstractVector`: The list of operators to be evaluated during the evolution.
- `H_t::Union{Nothing,Function,TimeDependentOperatorSum}`: The time-dependent Hamiltonian of the system. If `nothing`, the Hamiltonian is time-independent.
- `params::NamedTuple`: The parameters of the system.
- `progress_bar::Bool`: Whether to show the progress bar.
- `kwargs...`: The keyword arguments passed to the `ODEProblem` constructor.

# Returns
Expand All @@ -56,6 +58,7 @@ function sesolveProblem(H::QuantumObject{MT1,OperatorQuantumObject},
e_ops::Vector{QuantumObject{MT2, OperatorQuantumObject}}=QuantumObject{MT1, OperatorQuantumObject}[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...) where {MT1<:AbstractMatrix,T2,MT2<:AbstractMatrix}

H.dims != ψ0.dims && throw(ErrorException("The two operators don't have the same Hilbert dimension."))
Expand All @@ -65,7 +68,7 @@ function sesolveProblem(H::QuantumObject{MT1,OperatorQuantumObject},
ϕ0 = get_data(ψ0)
U = -1im * get_data(H)

progr = ODEProgress(0)
progr = ProgressBar(length(t_l), enable=progress_bar)
expvals = Array{ComplexF64}(undef, length(e_ops), length(t_l))
e_ops2 = get_data.(e_ops)

Expand Down Expand Up @@ -98,6 +101,7 @@ end
e_ops::AbstractVector=[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...)

Time evolution of a closed quantum system using the Schrödinger equation.
Expand All @@ -110,6 +114,7 @@ Time evolution of a closed quantum system using the Schrödinger equation.
- `e_ops::AbstractVector`: List of operators for which to calculate expectation values.
- `H_t::Union{Nothing,Function,TimeDependentOperatorSum}`: Time-dependent part of the Hamiltonian.
- `params::NamedTuple`: Dictionary of parameters to pass to the solver.
- `progress_bar::Bool`: Whether to show the progress bar.
- `kwargs...`: Additional keyword arguments to pass to the solver.

- Returns
Expand All @@ -122,10 +127,11 @@ function sesolve(H::QuantumObject{MT1,OperatorQuantumObject},
e_ops::Vector{QuantumObject{MT2, OperatorQuantumObject}}=QuantumObject{MT1, OperatorQuantumObject}[],
H_t::Union{Nothing,Function,TimeDependentOperatorSum}=nothing,
params::NamedTuple=NamedTuple(),
progress_bar::Bool=true,
kwargs...) where {MT1<:AbstractMatrix,T2,MT2<:AbstractMatrix}

prob = sesolveProblem(H, ψ0, t_l; alg=alg, e_ops=e_ops,
H_t=H_t, params=params, kwargs...)
H_t=H_t, params=params, progress_bar=progress_bar, kwargs...)

return sesolve(prob, alg; kwargs...)
end
Expand Down
16 changes: 0 additions & 16 deletions src/time_evolution/time_evolution.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,6 @@ end

LiouvillianDirectSolver(;tol=1e-16) = LiouvillianDirectSolver(tol)

# It is needed to keep track of the index for saving the expectation values
mutable struct ODEProgress{T<:Integer}
counter::T
# max_counts::T
# start_time::T2
end

function next!(p::ODEProgress)
p.counter += 1
# prog = round(100 * p.counter / p.max_counts, digits=2)
# eta = round((time() - p.start_time) / p.counter * (p.max_counts - p.counter), digits=2)
# # convert eta into a string in hours, minutes and seconds
# eta_str = string(round(Int, eta / 3600), "h ", round(Int, (eta % 3600) / 60), "m ", round(Int, eta % 60), "s")
# print("\rProgress: $prog% --- ETA: $eta_str")
end

abstract type LindbladJumpCallbackType end

struct ContinuousLindbladJumpCallback <: LindbladJumpCallbackType
Expand Down
2 changes: 1 addition & 1 deletion src/time_evolution/time_evolution_dynamical.jl
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ function _dsf_mcsolve_prob_func(prob, i, repeat)
prm = merge(internal_params, (U = copy(internal_params.U), e_ops_mc = copy(internal_params.e_ops_mc),
c_ops = copy(internal_params.c_ops), expvals = similar(internal_params.expvals),
cache_mc = similar(internal_params.cache_mc), weights_mc = similar(internal_params.weights_mc),
cumsum_weights_mc = similar(internal_params.weights_mc), random_n = Ref(rand()), progr_mc = ODEProgress(0), jump_times_which_idx = Ref(1),
cumsum_weights_mc = similar(internal_params.weights_mc), random_n = Ref(rand()), progr_mc = ProgressBar(size(internal_params.expvals, 2), enable=false), jump_times_which_idx = Ref(1),
jump_times = similar(internal_params.jump_times), jump_which = similar(internal_params.jump_which),
αt_list = copy(internal_params.αt_list), dsf_cache1 = similar(internal_params.dsf_cache1),
dsf_cache2 = similar(internal_params.dsf_cache2), expv_cache = copy(internal_params.expv_cache),
Expand Down
Loading
Loading