Skip to content

Commit

Permalink
Add spell check CI and fix typos (qutip#286)
Browse files Browse the repository at this point in the history
* add spell check CI

* fix version number

* fix version number

* add typo ignore

* fix typos

* minor changes
  • Loading branch information
ytdHuang authored and albertomercurio committed Nov 10, 2024
1 parent da322db commit 67cfbcc
Show file tree
Hide file tree
Showing 14 changed files with 77 additions and 62 deletions.
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

0 comments on commit 67cfbcc

Please sign in to comment.