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

Add spell check CI and fix typos #286

Merged
merged 6 commits into from
Nov 5, 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
13 changes: 13 additions & 0 deletions .github/workflows/SpellCheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Spell Check

on: [pull_request]

jobs:
typos-check:
name: Spell Check with Typos
runs-on: ubuntu-latest
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v4
- name: Check spelling
uses: crate-ci/[email protected]
2 changes: 2 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[default.extend-words]
ket = "ket"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ QuantumToolbox.jl is equipped with a robust set of features:

- **Quantum State and Operator Manipulation:** Easily handle quantum states and operators with a rich set of tools, with the same functionalities as QuTiP.
- **Dynamical Evolution:** Advanced solvers for time evolution of quantum systems, thanks to the powerful [DifferentialEquations.jl](https://github.com/SciML/DifferentialEquations.jl) package.
- **GPU Computing:** Leverage GPU resources for high-performance computing. For example, you run the master equation direclty on the GPU with the same syntax as the CPU case.
- **GPU Computing:** Leverage GPU resources for high-performance computing. For example, you run the master equation directly on the GPU with the same syntax as the CPU case.
- **Distributed Computing:** Distribute the computation over multiple nodes (e.g., a cluster). For example, you can run hundreds of quantum trajectories in parallel on a cluster, with, again, the same syntax as the simple case.
- **Easy Extension:** Easily extend the package, taking advantage of the Julia language features, like multiple dispatch and metaprogramming.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ QuantumToolbox.jl is equipped with a robust set of features:

- **Quantum State and Operator Manipulation:** Easily handle quantum states and operators with a rich set of tools, with the same functionalities as QuTiP.
- **Dynamical Evolution:** Advanced solvers for time evolution of quantum systems, thanks to the powerful [DifferentialEquations.jl](https://github.com/SciML/DifferentialEquations.jl) package.
- **GPU Computing:** Leverage GPU resources for high-performance computing. For example, you run the master equation direclty on the GPU with the same syntax as the CPU case.
- **GPU Computing:** Leverage GPU resources for high-performance computing. For example, you run the master equation directly on the GPU with the same syntax as the CPU case.
- **Distributed Computing:** Distribute the computation over multiple nodes (e.g., a cluster). For example, you can run undreds of quantum trajectories in parallel on a cluster, with, again, the same syntax as the simple case.
- **Easy Extension:** Easily extend the package, taking advantage of the Julia language features, like multiple dispatch and metaprogramming.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorials/lowrank.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# [Low rank master equation](@id doc-tutor:Low-rank-master-equation)

In this tutorial, we will show how to solve the master equation using the low-rank method. For a detailed explaination of the method, we recommend to read the article [gravina2024adaptive](@cite).
In this tutorial, we will show how to solve the master equation using the low-rank method. For a detailed explanation of the method, we recommend to read the article [gravina2024adaptive](@cite).

As a test, we will consider the dissipative Ising model with a transverse field. The Hamiltonian is given by

Expand Down
2 changes: 1 addition & 1 deletion docs/src/users_guide/states_and_operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ We can also create superpositions of states:
ket = normalize(basis(5, 0) + basis(5, 1))
```

where we have used the `normalize` function again to normalize the state. Apply the number opeartor again:
where we have used the `normalize` function again to normalize the state. Apply the number operator again:

```@example states_and_operators
n * ket
Expand Down
2 changes: 1 addition & 1 deletion src/linear_maps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ A **linear map** is a transformation `L` that satisfies:
L(cu) = cL(u)
```

It is typically represented as a matrix with dimensions given by `size`, and this abtract type helps to define this map when the matrix is not explicitly available.
It is typically represented as a matrix with dimensions given by `size`, and this abstract type helps to define this map when the matrix is not explicitly available.

## Methods

Expand Down
72 changes: 36 additions & 36 deletions src/qobj/arithmetic_and_attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -511,17 +511,17 @@ Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=true
function ptrace(QO::QuantumObject{<:AbstractArray,KetQuantumObject}, sel::Union{AbstractVector{Int},Tuple})
_non_static_array_warning("sel", sel)

ns = length(sel)
if ns == 0 # return full trace for empty sel
n_s = length(sel)
if n_s == 0 # return full trace for empty sel
return tr(ket2dm(QO))
else
nd = length(QO.dims)
n_d = length(QO.dims)

(any(>(nd), sel) || any(<(1), sel)) && throw(
ArgumentError("Invalid indices in `sel`: $(sel), the given QuantumObject only have $(nd) sub-systems"),
(any(>(n_d), sel) || any(<(1), sel)) && throw(
ArgumentError("Invalid indices in `sel`: $(sel), the given QuantumObject only have $(n_d) sub-systems"),
)
(ns != length(unique(sel))) && throw(ArgumentError("Duplicate selection indices in `sel`: $(sel)"))
(nd == 1) && return ket2dm(QO) # ptrace should always return Operator
(n_s != length(unique(sel))) && throw(ArgumentError("Duplicate selection indices in `sel`: $(sel)"))
(n_d == 1) && return ket2dm(QO) # ptrace should always return Operator
end

_sort_sel = sort(SVector{length(sel),Int}(sel))
Expand All @@ -534,17 +534,17 @@ ptrace(QO::QuantumObject{<:AbstractArray,BraQuantumObject}, sel::Union{AbstractV
function ptrace(QO::QuantumObject{<:AbstractArray,OperatorQuantumObject}, sel::Union{AbstractVector{Int},Tuple})
_non_static_array_warning("sel", sel)

ns = length(sel)
if ns == 0 # return full trace for empty sel
n_s = length(sel)
if n_s == 0 # return full trace for empty sel
return tr(QO)
else
nd = length(QO.dims)
n_d = length(QO.dims)

(any(>(nd), sel) || any(<(1), sel)) && throw(
ArgumentError("Invalid indices in `sel`: $(sel), the given QuantumObject only have $(nd) sub-systems"),
(any(>(n_d), sel) || any(<(1), sel)) && throw(
ArgumentError("Invalid indices in `sel`: $(sel), the given QuantumObject only have $(n_d) sub-systems"),
)
(ns != length(unique(sel))) && throw(ArgumentError("Duplicate selection indices in `sel`: $(sel)"))
(nd == 1) && return QO
(n_s != length(unique(sel))) && throw(ArgumentError("Duplicate selection indices in `sel`: $(sel)"))
(n_d == 1) && return QO
end

_sort_sel = sort(SVector{length(sel),Int}(sel))
Expand All @@ -554,61 +554,61 @@ end
ptrace(QO::QuantumObject, sel::Int) = ptrace(QO, SVector(sel))

function _ptrace_ket(QO::AbstractArray, dims::Union{SVector,MVector}, sel)
nd = length(dims)
n_d = length(dims)

nd == 1 && return QO, dims
n_d == 1 && return QO, dims

qtrace = filter(i -> i ∉ sel, 1:nd)
qtrace = filter(i -> i ∉ sel, 1:n_d)
dkeep = dims[sel]
dtrace = dims[qtrace]
nt = length(dtrace)
n_t = length(dtrace)

# Concatenate qtrace and sel without losing the length information
# Tuple(qtrace..., sel...)
qtrace_sel = ntuple(Val(nd)) do i
if i <= nt
qtrace_sel = ntuple(Val(n_d)) do i
if i <= n_t
@inbounds qtrace[i]
else
@inbounds sel[i-nt]
@inbounds sel[i-n_t]
end
end

vmat = reshape(QO, reverse(dims)...)
topermute = reverse(nd + 1 .- qtrace_sel)
topermute = reverse(n_d + 1 .- qtrace_sel)
vmat = permutedims(vmat, topermute) # TODO: use PermutedDimsArray when Julia v1.11.0 is released
vmat = reshape(vmat, prod(dkeep), prod(dtrace))

return vmat * vmat', dkeep
end

function _ptrace_oper(QO::AbstractArray, dims::Union{SVector,MVector}, sel)
nd = length(dims)
n_d = length(dims)

nd == 1 && return QO, dims
n_d == 1 && return QO, dims

qtrace = filter(i -> i ∉ sel, 1:nd)
qtrace = filter(i -> i ∉ sel, 1:n_d)
dkeep = dims[sel]
dtrace = dims[qtrace]
nk = length(dkeep)
nt = length(dtrace)
_2_nt = 2 * nt
n_k = length(dkeep)
n_t = length(dtrace)
_2_n_t = 2 * n_t

# Concatenate qtrace and sel without losing the length information
# Tuple(qtrace..., sel...)
qtrace_sel = ntuple(Val(2 * nd)) do i
if i <= nt
qtrace_sel = ntuple(Val(2 * n_d)) do i
if i <= n_t
@inbounds qtrace[i]
elseif i <= _2_nt
@inbounds qtrace[i-nt] + nd
elseif i <= _2_nt + nk
@inbounds sel[i-_2_nt]
elseif i <= _2_n_t
@inbounds qtrace[i-n_t] + n_d
elseif i <= _2_n_t + n_k
@inbounds sel[i-_2_n_t]
else
@inbounds sel[i-_2_nt-nk] + nd
@inbounds sel[i-_2_n_t-n_k] + n_d
end
end

ρmat = reshape(QO, reverse(vcat(dims, dims))...)
topermute = reverse(2 * nd + 1 .- qtrace_sel)
topermute = reverse(2 * n_d + 1 .- qtrace_sel)
ρmat = permutedims(ρmat, topermute) # TODO: use PermutedDimsArray when Julia v1.11.0 is released
ρmat = reshape(ρmat, prod(dkeep), prod(dkeep), prod(dtrace), prod(dtrace))
res = map(tr, eachslice(ρmat, dims = (1, 2)))
Expand Down
2 changes: 1 addition & 1 deletion src/qobj/boolean_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,6 @@ SciMLOperators.iscached(A::AbstractQuantumObject) = iscached(A.data)
@doc raw"""
SciMLOperators.isconstant(A::AbstractQuantumObject)

Test whether the [`AbstractQuantumObject`](@ref) `A` is constant in time. For a [`QuantumObject`](@ref), this function returns `true`, while for a [`QuantumObjectEvolution`](@ref), this function returns `true` if the operator is contant in time.
Test whether the [`AbstractQuantumObject`](@ref) `A` is constant in time. For a [`QuantumObject`](@ref), this function returns `true`, while for a [`QuantumObjectEvolution`](@ref), this function returns `true` if the operator is constant in time.
"""
SciMLOperators.isconstant(A::AbstractQuantumObject) = isconstant(A.data)
2 changes: 1 addition & 1 deletion src/qobj/superoperators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function _sprepost(A, B) # for any other input types
end

## if input is AbstractSciMLOperator
## some of them are optimzed to speed things up
## some of them are optimized to speed things up
## the rest of the SciMLOperators will just use lazy tensor (and prompt a warning)
_spre(A::MatrixOperator, Id::AbstractMatrix) = MatrixOperator(_spre(A.A, Id))
_spre(A::ScaledOperator, Id::AbstractMatrix) = ScaledOperator(A.λ, _spre(A.L, Id))
Expand Down
12 changes: 6 additions & 6 deletions src/steadystate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ function _steadystate(
idx_range = collect(1:N)
rows = _get_dense_similar(L_tmp, N)
cols = _get_dense_similar(L_tmp, N)
datas = _get_dense_similar(L_tmp, N)
vals = _get_dense_similar(L_tmp, N)
fill!(rows, 1)
copyto!(cols, N .* (idx_range .- 1) .+ idx_range)
fill!(datas, weight)
Tn = sparse(rows, cols, datas, N^2, N^2)
fill!(vals, weight)
Tn = sparse(rows, cols, vals, N^2, N^2)
L_tmp = L_tmp + Tn

(haskey(kwargs, :Pl) || haskey(kwargs, :Pr)) && error("The use of preconditioners must be defined in the solver.")
Expand Down Expand Up @@ -160,11 +160,11 @@ function _steadystate(
idx_range = collect(1:N)
rows = _get_dense_similar(L_tmp, N)
cols = _get_dense_similar(L_tmp, N)
datas = _get_dense_similar(L_tmp, N)
vals = _get_dense_similar(L_tmp, N)
fill!(rows, 1)
copyto!(cols, N .* (idx_range .- 1) .+ idx_range)
fill!(datas, weight)
Tn = sparse(rows, cols, datas, N^2, N^2)
fill!(vals, weight)
Tn = sparse(rows, cols, vals, N^2, N^2)
L_tmp = L_tmp + Tn

ρss_vec = L_tmp \ v0 # This is still not supported on GPU, yet
Expand Down
6 changes: 3 additions & 3 deletions src/time_evolution/mcsolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ function LindbladJumpAffect!(integrator)
end
cumsum!(cumsum_weights_mc, weights_mc)
r = rand(traj_rng) * sum(weights_mc)
collaps_idx = getindex(1:length(weights_mc), findfirst(>(r), cumsum_weights_mc))
mul!(cache_mc, c_ops[collaps_idx], ψ)
collapse_idx = getindex(1:length(weights_mc), findfirst(>(r), cumsum_weights_mc))
mul!(cache_mc, c_ops[collapse_idx], ψ)
normalize!(cache_mc)
copyto!(integrator.u, cache_mc)

random_n[] = rand(traj_rng)
jump_times[internal_params.jump_times_which_idx[]] = integrator.t
jump_which[internal_params.jump_times_which_idx[]] = collaps_idx
jump_which[internal_params.jump_times_which_idx[]] = collapse_idx
internal_params.jump_times_which_idx[] += 1
if internal_params.jump_times_which_idx[] > length(jump_times)
resize!(jump_times, length(jump_times) + internal_params.jump_times_which_init_size)
Expand Down
8 changes: 4 additions & 4 deletions src/time_evolution/ssesolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ export ssesolveProblem, ssesolveEnsembleProblem, ssesolve

A struct to represent the diffusion operator. This is used to perform the diffusion process on N different Wiener processes.
=#
struct DiffusionOperator{T,OT<:Tuple{Vararg{AbstractSciMLOperator}}} <: AbstractSciMLOperator{T}
ops::OT
function DiffusionOperator(ops::OT) where {OT}
struct DiffusionOperator{T,OpType<:Tuple{Vararg{AbstractSciMLOperator}}} <: AbstractSciMLOperator{T}
ops::OpType
function DiffusionOperator(ops::OpType) where {OpType}
T = mapreduce(eltype, promote_type, ops)
return new{T,OT}(ops)
return new{T,OpType}(ops)
end
end

Expand Down
12 changes: 6 additions & 6 deletions src/time_evolution/time_evolution_dynamical.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ function _reduce_dims(
sel,
reduce,
) where {T,N,DT<:Integer}
nd = length(dims)
n_d = length(dims)
dims_new = zero(dims)
dims_new[sel] .= reduce
@. dims_new = dims - dims_new

if nd == 1
if n_d == 1
ρmat = similar(QO, dims_new[1], dims_new[1])
copyto!(ρmat, view(QO, 1:dims_new[1], 1:dims_new[1]))
else
Expand All @@ -32,12 +32,12 @@ function _increase_dims(
sel,
increase,
) where {T,N,DT<:Integer}
nd = length(dims)
n_d = length(dims)
dims_new = MVector(zero(dims)) # Mutable SVector
dims_new[sel] .= increase
@. dims_new = dims + dims_new

if nd == 1
if n_d == 1
ρmat = similar(QO, dims_new[1], dims_new[1])
fill!(selectdim(ρmat, 1, dims[1]+1:dims_new[1]), 0)
fill!(selectdim(ρmat, 2, dims[1]+1:dims_new[1]), 0)
Expand All @@ -46,8 +46,8 @@ function _increase_dims(
ρmat2 = similar(QO, reverse(vcat(dims_new, dims_new))...)
ρmat = reshape(QO, reverse(vcat(dims, dims))...)
for i in eachindex(sel)
fill!(selectdim(ρmat2, nd - sel[i] + 1, dims[sel[i]]+1:dims_new[sel[i]]), 0)
fill!(selectdim(ρmat2, 2 * nd - sel[i] + 1, dims[sel[i]]+1:dims_new[sel[i]]), 0)
fill!(selectdim(ρmat2, n_d - sel[i] + 1, dims[sel[i]]+1:dims_new[sel[i]]), 0)
fill!(selectdim(ρmat2, 2 * n_d - sel[i] + 1, dims[sel[i]]+1:dims_new[sel[i]]), 0)
end
copyto!(view(ρmat2, reverse!(repeat([1:n for n in dims], 2))...), ρmat)
ρmat = reshape(ρmat2, prod(dims_new), prod(dims_new))
Expand Down
Loading