Skip to content

Commit 75f33c4

Browse files
authored
Fix keyword argument handling for SteadyStateODESolver (#537)
1 parent 15954c9 commit 75f33c4

File tree

2 files changed

+42
-25
lines changed

2 files changed

+42
-25
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased](https://github.com/qutip/QuantumToolbox.jl/tree/main)
99

1010
- Add support of `QobjEvo` for `steadystate` (ODE solver only). ([#536])
11+
- Changes to `SteadyStateODESolver`. ([#537])
12+
- Introduce the tolerances for `steadystate` terminate condition (two new fields: `terminate_reltol = 1e-5` and `terminate_abstol = 1e-7`)
13+
- Fix keyword argument handling for `SteadyStateODESolver` before passing to `mesolve`.
1114

1215
## [v0.34.1]
1316
Release date: 2025-08-23
@@ -304,3 +307,4 @@ Release date: 2024-11-13
304307
[#520]: https://github.com/qutip/QuantumToolbox.jl/issues/520
305308
[#531]: https://github.com/qutip/QuantumToolbox.jl/issues/531
306309
[#536]: https://github.com/qutip/QuantumToolbox.jl/issues/536
310+
[#537]: https://github.com/qutip/QuantumToolbox.jl/issues/537

src/steadystate.jl

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ end
4747
alg = Tsit5(),
4848
ψ0 = nothing,
4949
tmax = Inf,
50-
)
51-
52-
An ordinary differential equation (ODE) solver for solving [`steadystate`](@ref).
50+
terminate_reltol = 1e-5,
51+
terminate_abstol = 1e-7
52+
)
5353
54-
Solve the stationary state based on time evolution (ordinary differential equations; `OrdinaryDiffEq.jl`) with a given initial state.
54+
An ordinary differential equation (ODE) solver for solving [`steadystate`](@ref). It solves the stationary state based on [`mesolve`](@ref) with a termination condition.
5555
5656
The termination condition of the stationary state ``|\rho\rangle\rangle`` is that either the following condition is `true`:
5757
@@ -69,14 +69,26 @@ or
6969
- `alg::OrdinaryDiffEqAlgorithm=Tsit5()`: The algorithm to solve the ODE.
7070
- `ψ0::Union{Nothing,QuantumObject}=nothing`: The initial state of the system. If not specified, a random pure state will be generated.
7171
- `tmax::Real=Inf`: The final time step for the steady state problem.
72+
- `terminate_reltol` = The relative tolerance for stationary state terminate condition. Default to `1e-5`.
73+
- `terminate_abstol` = The absolute tolerance for stationary state terminate condition. Default to `1e-7`.
74+
75+
!!! warning "Tolerances for terminate condition"
76+
The terminate condition tolerances `terminate_reltol` and `terminate_abstol` should be larger than `reltol` and `abstol` of [`mesolve`](@ref), respectively.
7277
73-
For more details about the solvers, please refer to [`OrdinaryDiffEq.jl`](https://docs.sciml.ai/OrdinaryDiffEq/stable/).
78+
For more details about the solving `alg`orithms, please refer to [`OrdinaryDiffEq.jl`](https://docs.sciml.ai/OrdinaryDiffEq/stable/).
7479
"""
75-
Base.@kwdef struct SteadyStateODESolver{MT<:OrdinaryDiffEqAlgorithm,ST<:Union{Nothing,QuantumObject},T<:Real} <:
76-
SteadyStateSolver
80+
Base.@kwdef struct SteadyStateODESolver{
81+
MT<:OrdinaryDiffEqAlgorithm,
82+
ST<:Union{Nothing,QuantumObject},
83+
TT<:Real,
84+
RT<:Real,
85+
AT<:Real,
86+
} <: SteadyStateSolver
7787
alg::MT = Tsit5()
7888
ψ0::ST = nothing
79-
tmax::T = Inf
89+
tmax::TT = Inf
90+
terminate_reltol::RT = 10 * DEFAULT_ODE_SOLVER_OPTIONS.reltol
91+
terminate_abstol::AT = 10 * DEFAULT_ODE_SOLVER_OPTIONS.abstol
8092
end
8193

8294
@doc raw"""
@@ -200,27 +212,28 @@ function _steadystate(L::QuantumObject{SuperOperator}, solver::SteadyStateDirect
200212
end
201213

202214
function _steadystate(L::AbstractQuantumObject{SuperOperator}, solver::SteadyStateODESolver; kwargs...)
203-
tmax = solver.tmax
204-
205215
ψ0 = isnothing(solver.ψ0) ? rand_ket(L.dimensions) : solver.ψ0
206-
abstol = haskey(kwargs, :abstol) ? kwargs[:abstol] : DEFAULT_ODE_SOLVER_OPTIONS.abstol
207-
reltol = haskey(kwargs, :reltol) ? kwargs[:reltol] : DEFAULT_ODE_SOLVER_OPTIONS.reltol
208-
209216
ftype = _float_type(ψ0)
210-
_terminate_func = SteadyStateODECondition(similar(mat2vec(ket2dm(ψ0)).data))
211-
cb = TerminateSteadyState(abstol, reltol, _terminate_func)
212-
sol = mesolve(
213-
L,
214-
ψ0,
215-
[ftype(0), ftype(tmax)];
216-
alg = solver.alg,
217-
progress_bar = Val(false),
218-
save_everystep = false,
219-
saveat = ftype[],
220-
callback = cb,
221-
kwargs...,
217+
tlist = [ftype(0), ftype(solver.tmax)]
218+
219+
# overwrite some kwargs and throw warning message to tell the users that we are ignoring these settings
220+
haskey(kwargs, :progress_bar) && @warn "Ignore keyword argument 'progress_bar' for SteadyStateODESolver"
221+
haskey(kwargs, :save_everystep) && @warn "Ignore keyword argument 'save_everystep' for SteadyStateODESolver"
222+
haskey(kwargs, :saveat) && @warn "Ignore keyword argument 'saveat' for SteadyStateODESolver"
223+
kwargs2 = merge(
224+
NamedTuple(kwargs), # we convert to NamedTuple just in case if kwargs is empty
225+
(progress_bar = Val(false), save_everystep = false, saveat = ftype[]),
226+
)
227+
228+
# add terminate condition (callback)
229+
cb = TerminateSteadyState(
230+
solver.terminate_abstol,
231+
solver.terminate_reltol,
232+
SteadyStateODECondition(similar(mat2vec(ket2dm(ψ0)).data)),
222233
)
234+
kwargs3 = _merge_kwargs_with_callback(kwargs2, cb)
223235

236+
sol = mesolve(L, ψ0, tlist; kwargs3...)
224237
ρss = sol.states[end]
225238
return ρss
226239
end

0 commit comments

Comments
 (0)