Skip to content

Commit 6ce4e9d

Browse files
Add more generic solver for steadystate_floquet
1 parent 210a78e commit 6ce4e9d

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

src/steadystate.jl

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export SteadyStateSolver,
55
SteadyStateLinearSolver,
66
SteadyStateODESolver,
77
SteadyStateFloquetSolver,
8-
SSFloquetLinearSystem,
8+
SSFloquetLinearSolve,
99
SSFloquetEffectiveLiouvillian
1010

1111
abstract type SteadyStateSolver end
@@ -58,7 +58,15 @@ Base.@kwdef struct SteadyStateODESolver{MT<:OrdinaryDiffEqAlgorithm} <: SteadySt
5858
alg::MT = Tsit5()
5959
end
6060

61-
struct SSFloquetLinearSystem <: SteadyStateFloquetSolver end
61+
Base.@kwdef struct SSFloquetLinearSolve{
62+
MT<:Union{SciMLLinearSolveAlgorithm,Nothing},
63+
PlT<:Union{Function,Nothing},
64+
PrT<:Union{Function,Nothing},
65+
} <: SteadyStateFloquetSolver
66+
alg::MT = KrylovJL_GMRES()
67+
Pl::PlT = nothing
68+
Pr::PrT = nothing
69+
end
6270
Base.@kwdef struct SSFloquetEffectiveLiouvillian{SSST<:SteadyStateSolver} <: SteadyStateFloquetSolver
6371
steadystate_solver::SSST = SteadyStateDirectSolver()
6472
end
@@ -255,7 +263,7 @@ end
255263
c_ops::Union{Nothing,AbstractVector,Tuple} = nothing;
256264
n_max::Integer = 2,
257265
tol::R = 1e-8,
258-
solver::FSolver = SSFloquetLinearSystem,
266+
solver::FSolver = SSFloquetLinearSolve,
259267
kwargs...,
260268
)
261269
@@ -265,11 +273,11 @@ Considering a monochromatic drive at frequency ``\omega_d``, we divide it into t
265273
`H_p` and `H_m`, where `H_p` oscillates
266274
as ``e^{i \omega t}`` and `H_m` oscillates as ``e^{-i \omega t}``.
267275
There are two solvers available for this function:
268-
- `SSFloquetLinearSystem`: Solves the linear system of equations.
276+
- `SSFloquetLinearSolve`: Solves the linear system of equations.
269277
- `SSFloquetEffectiveLiouvillian`: Solves the effective Liouvillian.
270278
For both cases, `n_max` is the number of Fourier components to consider, and `tol` is the tolerance for the solver.
271279
272-
In the case of `SSFloquetLinearSystem`, the full linear system is solved at once:
280+
In the case of `SSFloquetLinearSolve`, the full linear system is solved at once:
273281
274282
```math
275283
( \mathcal{L}_0 - i n \omega_d ) \hat{\rho}_n + \mathcal{L}_1 \hat{\rho}_{n-1} + \mathcal{L}_{-1} \hat{\rho}_{n+1} = 0
@@ -312,7 +320,7 @@ This will allow to simultaneously obtain all the ``\hat{\rho}_n``.
312320
In the case of `SSFloquetEffectiveLiouvillian`, instead, the effective Liouvillian is calculated using the matrix continued fraction method.
313321
314322
!!! note "different return"
315-
The two solvers returns different objects. The `SSFloquetLinearSystem` returns a list of [`QuantumObject`](@ref), containing the density matrices for each Fourier component (``\hat{\rho}_{-n}``, with ``n`` from ``0`` to ``n_\textrm{max}``), while the `SSFloquetEffectiveLiouvillian` returns only ``\hat{\rho}_0``.
323+
The two solvers returns different objects. The `SSFloquetLinearSolve` returns a list of [`QuantumObject`](@ref), containing the density matrices for each Fourier component (``\hat{\rho}_{-n}``, with ``n`` from ``0`` to ``n_\textrm{max}``), while the `SSFloquetEffectiveLiouvillian` returns only ``\hat{\rho}_0``.
316324
317325
## Arguments
318326
- `H_0::QuantumObject`: The Hamiltonian or the Liouvillian of the undriven system.
@@ -322,7 +330,7 @@ In the case of `SSFloquetEffectiveLiouvillian`, instead, the effective Liouvilli
322330
- `c_ops::Union{Nothing,AbstractVector} = nothing`: The optional collapse operators.
323331
- `n_max::Integer = 2`: The number of Fourier components to consider.
324332
- `tol::R = 1e-8`: The tolerance for the solver.
325-
- `solver::FSolver = SSFloquetLinearSystem`: The solver to use.
333+
- `solver::FSolver = SSFloquetLinearSolve`: The solver to use.
326334
- `kwargs...`: Additional keyword arguments to be passed to the solver.
327335
"""
328336
function steadystate_floquet(
@@ -333,7 +341,7 @@ function steadystate_floquet(
333341
c_ops::Union{Nothing,AbstractVector,Tuple} = nothing;
334342
n_max::Integer = 2,
335343
tol::R = 1e-8,
336-
solver::FSolver = SSFloquetLinearSystem(),
344+
solver::FSolver = SSFloquetLinearSolve(),
337345
kwargs...,
338346
) where {
339347
OpType1<:Union{OperatorQuantumObject,SuperOperatorQuantumObject},
@@ -353,7 +361,7 @@ function _steadystate_floquet(
353361
L_p::QuantumObject{SuperOperatorQuantumObject},
354362
L_m::QuantumObject{SuperOperatorQuantumObject},
355363
ωd::Number,
356-
solver::SSFloquetLinearSystem;
364+
solver::SSFloquetLinearSolve;
357365
n_max::Integer = 1,
358366
tol::R = 1e-8,
359367
kwargs...,
@@ -387,9 +395,18 @@ function _steadystate_floquet(
387395
v0 = zeros(T, n_fourier * N)
388396
v0[n_max*N+1] = weight
389397

390-
Pl = ilu(M, τ = 0.01)
398+
(haskey(kwargs, :Pl) || haskey(kwargs, :Pr)) && error("The use of preconditioners must be defined in the solver.")
399+
if !isnothing(solver.Pl)
400+
kwargs = merge((; kwargs...), (Pl = solver.Pl(M),))
401+
elseif isa(M, SparseMatrixCSC)
402+
kwargs = merge((; kwargs...), (Pl = ilu(M, τ = 0.01),))
403+
end
404+
!isnothing(solver.Pr) && (kwargs = merge((; kwargs...), (Pr = solver.Pr(M),)))
405+
!haskey(kwargs, :abstol) && (kwargs = merge((; kwargs...), (abstol = tol,)))
406+
!haskey(kwargs, :reltol) && (kwargs = merge((; kwargs...), (reltol = tol,)))
407+
391408
prob = LinearProblem(M, v0)
392-
ρtot = solve(prob, KrylovJL_GMRES(), Pl = Pl, abstol = tol, reltol = tol).u
409+
ρtot = solve(prob, solver.alg; kwargs...).u
393410

394411
offset1 = n_max * N
395412
offset2 = (n_max + 1) * N

test/core-test/steady_state.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@
6565
H_td = (H, (H_t, coeff))
6666

6767
sol_me = mesolve(H_td, psi0, t_l, c_ops, e_ops = e_ops, progress_bar = Val(false))
68-
ρ_ss1 = steadystate_floquet(H, -1im * 0.5 * H_t, 1im * 0.5 * H_t, 1, c_ops, solver = SSFloquetLinearSystem())[1]
68+
ρ_ss1 = steadystate_floquet(H, -1im * 0.5 * H_t, 1im * 0.5 * H_t, 1, c_ops, solver = SSFloquetLinearSolve())[1]
6969
ρ_ss2 =
7070
steadystate_floquet(H, -1im * 0.5 * H_t, 1im * 0.5 * H_t, 1, c_ops, solver = SSFloquetEffectiveLiouvillian())
7171

7272
@test abs(sum(sol_me.expect[1, end-100:end]) / 101 - expect(e_ops[1], ρ_ss1)) < 1e-3
7373
@test abs(sum(sol_me.expect[1, end-100:end]) / 101 - expect(e_ops[1], ρ_ss2)) < 1e-3
7474

7575
@testset "Type Inference (steadystate_floquet)" begin
76-
@inferred steadystate_floquet(H, -1im * 0.5 * H_t, 1im * 0.5 * H_t, 1, c_ops, solver = SSFloquetLinearSystem())
76+
@inferred steadystate_floquet(H, -1im * 0.5 * H_t, 1im * 0.5 * H_t, 1, c_ops, solver = SSFloquetLinearSolve())
7777
@inferred steadystate_floquet(
7878
H,
7979
-1im * 0.5 * H_t,

0 commit comments

Comments
 (0)