Skip to content

Commit 8283c71

Browse files
committed
introduce PseudoInverse<:SpectrumSolver
1 parent 6ab7a09 commit 8283c71

File tree

4 files changed

+55
-4
lines changed

4 files changed

+55
-4
lines changed

benchmarks/correlations_and_spectrum.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ function benchmark_correlations_and_spectrum!(SUITE)
1111
ω_l = range(0, 3, length = 1000)
1212
t_l = range(0, 333 * π, length = 1000)
1313

14+
PI_solver = PseudoInverse()
15+
1416
function _calculate_fft_spectrum(H, tlist, c_ops, A, B)
1517
corr = correlation_2op_1t(H, nothing, tlist, c_ops, A, B; progress_bar = Val(false))
1618
ωlist, spec = spectrum_correlation_fft(tlist, corr)
@@ -23,5 +25,8 @@ function benchmark_correlations_and_spectrum!(SUITE)
2325
SUITE["Correlations and Spectrum"]["Spectrum"]["Exponential Series"] =
2426
@benchmarkable spectrum($H, $ω_l, $c_ops, $(a'), $a)
2527

28+
SUITE["Correlations and Spectrum"]["Spectrum"]["Pseudo Inverse"] =
29+
@benchmarkable spectrum($H, $ω_l, $c_ops, $(a'), $a, solver = $PI_solver)
30+
2631
return nothing
2732
end

docs/src/resources/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ correlation_2op_1t
235235
spectrum_correlation_fft
236236
spectrum
237237
ExponentialSeries
238+
PseudoInverse
238239
```
239240

240241
## [Metrics](@id doc-API:Metrics)

src/spectrum.jl

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export spectrum, spectrum_correlation_fft
2-
export SpectrumSolver, ExponentialSeries#, PseudoInverse
2+
export SpectrumSolver, ExponentialSeries, PseudoInverse
33

44
abstract type SpectrumSolver end
55

@@ -15,6 +15,17 @@ end
1515

1616
ExponentialSeries(; tol = 1e-14, calc_steadystate = false) = ExponentialSeries(tol, calc_steadystate)
1717

18+
@doc raw"""
19+
PseudoInverse(; alg::SciMLLinearSolveAlgorithm = KrylovJL_GMRES())
20+
21+
A solver which solves [`spectrum`](@ref) by finding the inverse of Liouvillian [`SuperOperator`](@ref) using the `alg`orithms given in [`LinearSolve.jl`](https://docs.sciml.ai/LinearSolve/stable/).
22+
"""
23+
struct PseudoInverse{MT<:SciMLLinearSolveAlgorithm} <: SpectrumSolver
24+
alg::MT
25+
end
26+
27+
PseudoInverse(; alg::SciMLLinearSolveAlgorithm = KrylovJL_GMRES()) = PseudoInverse(alg)
28+
1829
@doc raw"""
1930
spectrum(H::QuantumObject,
2031
ωlist::AbstractVector,
@@ -32,6 +43,7 @@ S(\omega) = \int_{-\infty}^\infty \lim_{t \rightarrow \infty} \left\langle \hat{
3243
3344
See also the following list for `SpectrumSolver` docstrings:
3445
- [`ExponentialSeries`](@ref)
46+
- [`PseudoInverse`](@ref)
3547
"""
3648
function spectrum(
3749
H::QuantumObject{MT1,HOpType},
@@ -91,18 +103,47 @@ function _spectrum(
91103
return spec
92104
end
93105

94-
#= function _spectrum(
106+
function _spectrum(
95107
L::QuantumObject{<:AbstractArray{T1},SuperOperatorQuantumObject},
96108
ωlist::AbstractVector,
97109
A::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject},
98110
B::QuantumObject{<:AbstractArray{T3},OperatorQuantumObject},
99111
solver::PseudoInverse;
100112
kwargs...,
101113
) where {T1,T2,T3}
102-
allequal((L.dims, A.dims, B.dims)) || throw(DimensionMismatch("The quantum objects are not of the same Hilbert dimension."))
114+
allequal((L.dims, A.dims, B.dims)) ||
115+
throw(DimensionMismatch("The quantum objects are not of the same Hilbert dimension."))
116+
117+
ωList = convert(Vector{_FType(L)}, ωlist) # Convert it to support GPUs and avoid type instabilities
118+
Length = length(ωList)
119+
spec = Vector{_FType(L)}(undef, Length)
120+
121+
# calculate vectorized steadystate, multiply by operator B on the left (spre)
122+
ρss = mat2vec(steadystate(L))
123+
b = (spre(B) * ρss).data
124+
125+
# multiply by operator A on the left (spre) and then perform trace operation
126+
D = prod(L.dims)
127+
_tr = SparseVector(D^2, [1 + n * (D + 1) for n in 0:(D-1)], ones(_CType(L), D)) # same as vec(system_identity_matrix)
128+
_tr_A = transpose(_tr) * spre(A).data
129+
130+
cache = nothing
131+
I_cache = I(D^2)
132+
for (idx, ω) in enumerate(ωList)
133+
if idx == 1
134+
cache = init(LinearProblem(L.data - 1im * ω * I_cache, b), solver.alg, kwargs...)
135+
sol = solve!(cache)
136+
else
137+
cache.A = L.data - 1im * ω * I_cache
138+
sol = solve!(cache)
139+
end
140+
141+
# trace over the Hilbert space of system (expectation value)
142+
spec[idx] = -2 * real(dot(_tr_A, sol.u))
143+
end
103144

104145
return spec
105-
end =#
146+
end
106147

107148
@doc raw"""
108149
spectrum_correlation_fft(tlist, corr; inverse=false)

test/core-test/correlations_and_spectrum.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,25 @@
99

1010
ω_l2 = range(0, 3, length = 1000)
1111
spec2 = spectrum(H, ω_l2, c_ops, a', a)
12+
spec3 = spectrum(H, ω_l2, c_ops, a', a; solver = PseudoInverse())
1213

1314
spec1 = spec1 ./ maximum(spec1)
1415
spec2 = spec2 ./ maximum(spec2)
16+
spec3 = spec3 ./ maximum(spec3)
1517

1618
test_func1 = maximum(real.(spec1)) * (0.1 / 2)^2 ./ ((ω_l1 .- 1) .^ 2 .+ (0.1 / 2)^2)
1719
test_func2 = maximum(real.(spec2)) * (0.1 / 2)^2 ./ ((ω_l2 .- 1) .^ 2 .+ (0.1 / 2)^2)
1820
idxs1 = test_func1 .> 0.05
1921
idxs2 = test_func2 .> 0.05
2022
@test sum(abs2.(spec1[idxs1] .- test_func1[idxs1])) / sum(abs2.(test_func1[idxs1])) < 0.01
2123
@test sum(abs2.(spec2[idxs2] .- test_func2[idxs2])) / sum(abs2.(test_func2[idxs2])) < 0.01
24+
@test all(spec2 .≈ spec3)
2225

2326
@testset "Type Inference spectrum" begin
2427
@inferred correlation_2op_1t(H, nothing, t_l, c_ops, a', a; progress_bar = Val(false))
2528
@inferred spectrum_correlation_fft(t_l, corr)
2629
@inferred spectrum(H, ω_l2, c_ops, a', a)
30+
@inferred spectrum(H, ω_l2, c_ops, a', a; solver = PseudoInverse())
2731
end
2832

2933
@test_throws ErrorException FFTCorrelation()

0 commit comments

Comments
 (0)