Skip to content

Commit 5e1707d

Browse files
authored
Store both times and times_states in time evolution solutions (#506)
1 parent 3057e3e commit 5e1707d

File tree

18 files changed

+105
-63
lines changed

18 files changed

+105
-63
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
- Implement `EnrSpace` and corresponding functionality. ([#500])
1111
- Check for orthogonality breakdown in `Lanczos` solver for `spectrum`. ([#501])
12+
- Store both `times` and `times_states` in time evolution solutions. ([#506], [#504])
1213
- Fix errors in `Julia v1.12`. ([#507])
1314

1415
## [v0.32.1]
@@ -259,4 +260,6 @@ Release date: 2024-11-13
259260
[#494]: https://github.com/qutip/QuantumToolbox.jl/issues/494
260261
[#500]: https://github.com/qutip/QuantumToolbox.jl/issues/500
261262
[#501]: https://github.com/qutip/QuantumToolbox.jl/issues/501
263+
[#504]: https://github.com/qutip/QuantumToolbox.jl/issues/504
264+
[#506]: https://github.com/qutip/QuantumToolbox.jl/issues/506
262265
[#507]: https://github.com/qutip/QuantumToolbox.jl/issues/507

docs/src/users_guide/time_evolution/mcsolve.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ CairoMakie.enable_only_mime!(MIME"image/svg+xml"())
5959
```
6060

6161
```@example mcsolve
62-
times = LinRange(0.0, 10.0, 200)
62+
tlist = LinRange(0.0, 10.0, 200)
6363
6464
ψ0 = tensor(fock(2, 0), fock(10, 8))
6565
a = tensor(qeye(2), destroy(10))
@@ -69,7 +69,7 @@ H = 2 * π * a' * a + 2 * π * σm' * σm + 2 * π * 0.25 * (σm * a' + σm' * a
6969
c_ops = [sqrt(0.1) * a]
7070
e_ops = [a' * a, σm' * σm]
7171
72-
sol_500 = mcsolve(H, ψ0, times, c_ops, e_ops=e_ops)
72+
sol_500 = mcsolve(H, ψ0, tlist, c_ops, e_ops=e_ops)
7373
7474
# plot by CairoMakie.jl
7575
fig = Figure(size = (500, 350))
@@ -78,8 +78,8 @@ ax = Axis(fig[1, 1],
7878
ylabel = "Expectation values",
7979
title = "Monte Carlo time evolution (500 trajectories)",
8080
)
81-
lines!(ax, times, real(sol_500.expect[1,:]), label = "cavity photon number", linestyle = :solid)
82-
lines!(ax, times, real(sol_500.expect[2,:]), label = "atom excitation probability", linestyle = :dash)
81+
lines!(ax, tlist, real(sol_500.expect[1,:]), label = "cavity photon number", linestyle = :solid)
82+
lines!(ax, tlist, real(sol_500.expect[2,:]), label = "atom excitation probability", linestyle = :dash)
8383
8484
axislegend(ax, position = :rt)
8585
@@ -93,9 +93,9 @@ We can also change the number of trajectories (`ntraj`). This can be used to exp
9393
```@example mcsolve
9494
e_ops = [a' * a]
9595
96-
sol_1 = mcsolve(H, ψ0, times, c_ops, e_ops=e_ops, ntraj = 1)
97-
sol_10 = mcsolve(H, ψ0, times, c_ops, e_ops=e_ops, ntraj = 10)
98-
sol_100 = mcsolve(H, ψ0, times, c_ops, e_ops=e_ops, ntraj = 100)
96+
sol_1 = mcsolve(H, ψ0, tlist, c_ops, e_ops=e_ops, ntraj = 1)
97+
sol_10 = mcsolve(H, ψ0, tlist, c_ops, e_ops=e_ops, ntraj = 10)
98+
sol_100 = mcsolve(H, ψ0, tlist, c_ops, e_ops=e_ops, ntraj = 100)
9999
100100
# plot by CairoMakie.jl
101101
fig = Figure(size = (500, 350))
@@ -104,9 +104,9 @@ ax = Axis(fig[1, 1],
104104
ylabel = "Expectation values",
105105
title = "Monte Carlo time evolution",
106106
)
107-
lines!(ax, times, real(sol_1.expect[1,:]), label = "1 trajectory", linestyle = :dashdot)
108-
lines!(ax, times, real(sol_10.expect[1,:]), label = "10 trajectories", linestyle = :dash)
109-
lines!(ax, times, real(sol_100.expect[1,:]), label = "100 trajectories", linestyle = :solid)
107+
lines!(ax, tlist, real(sol_1.expect[1,:]), label = "1 trajectory", linestyle = :dashdot)
108+
lines!(ax, tlist, real(sol_10.expect[1,:]), label = "10 trajectories", linestyle = :dash)
109+
lines!(ax, tlist, real(sol_100.expect[1,:]), label = "100 trajectories", linestyle = :solid)
110110
111111
axislegend(ax, position = :rt)
112112
@@ -126,8 +126,8 @@ Monte Carlo evolutions often need hundreds of trajectories to obtain sufficient
126126
See the [documentation of `DifferentialEquations.jl`](https://docs.sciml.ai/DiffEqDocs/stable/features/ensemble/) for more details. Also, see Julia's documentation for more details about multithreading and adding more processes.
127127

128128
```julia
129-
sol_serial = mcsolve(H, ψ0, times, c_ops, e_ops=e_ops, ensemblealg=EnsembleSerial())
130-
sol_parallel = mcsolve(H, ψ0, times, c_ops, e_ops=e_ops, ensemblealg=EnsembleThreads());
129+
sol_serial = mcsolve(H, ψ0, tlist, c_ops, e_ops=e_ops, ensemblealg=EnsembleSerial())
130+
sol_parallel = mcsolve(H, ψ0, tlist, c_ops, e_ops=e_ops, ensemblealg=EnsembleThreads());
131131
```
132132

133133
!!! tip "Parallelization on a Cluster"

docs/src/users_guide/time_evolution/mesolve.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,14 @@ sol = mesolve(H, ψ0, tlist, c_ops, e_ops = [sigmaz(), sigmay()])
128128
We can therefore plot the expectation values:
129129

130130
```@example mesolve
131-
times = sol.times
132131
expt_z = real(sol.expect[1,:])
133132
expt_y = real(sol.expect[2,:])
134133
135134
# plot by CairoMakie.jl
136135
fig = Figure(size = (500, 350))
137136
ax = Axis(fig[1, 1], xlabel = "Time", ylabel = "Expectation values")
138-
lines!(ax, times, expt_z, label = L"\langle\hat{\sigma}_z\rangle", linestyle = :solid)
139-
lines!(ax, times, expt_y, label = L"\langle\hat{\sigma}_y\rangle", linestyle = :dash)
137+
lines!(ax, tlist, expt_z, label = L"\langle\hat{\sigma}_z\rangle", linestyle = :solid)
138+
lines!(ax, tlist, expt_y, label = L"\langle\hat{\sigma}_y\rangle", linestyle = :dash)
140139
141140
axislegend(ax, position = :rt)
142141
@@ -210,17 +209,15 @@ tlist = LinRange(0.0, 10.0, 200)
210209
L = liouvillian(H_a + H_c + H_I, c_ops)
211210
sol = mesolve(L, ψ0, tlist, e_ops=[σm' * σm, a' * a])
212211
213-
times = sol.times
214-
215212
# expectation value of Number operator
216213
N_atom = real(sol.expect[1,:])
217214
N_cavity = real(sol.expect[2,:])
218215
219216
# plot by CairoMakie.jl
220217
fig = Figure(size = (500, 350))
221218
ax = Axis(fig[1, 1], xlabel = "Time", ylabel = "Expectation values")
222-
lines!(ax, times, N_atom, label = "atom excitation probability", linestyle = :solid)
223-
lines!(ax, times, N_cavity, label = "cavity photon number", linestyle = :dash)
219+
lines!(ax, tlist, N_atom, label = "atom excitation probability", linestyle = :solid)
220+
lines!(ax, tlist, N_cavity, label = "cavity photon number", linestyle = :dash)
224221
225222
axislegend(ax, position = :rt)
226223

docs/src/users_guide/time_evolution/sesolve.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ sol = sesolve(H, ψ0, tlist, e_ops = [sigmaz(), sigmay()])
5959
Here, we call [`sesolve`](@ref) directly instead of pre-defining [`sesolveProblem`](@ref) first (as shown previously).
6060

6161
```@example sesolve
62-
times = sol.times
63-
print(size(times))
62+
println(size(sol.times)) # time points corresponds to stored expectation values
63+
println(size(sol.times_states)) # time points corresponds to stored states
6464
```
6565

6666
```@example sesolve
@@ -77,8 +77,8 @@ expt_y = real(expt[2,:])
7777
# plot by CairoMakie.jl
7878
fig = Figure(size = (500, 350))
7979
ax = Axis(fig[1, 1], xlabel = "Time", ylabel = "Expectation values")
80-
lines!(ax, times, expt_z, label = L"\langle\hat{\sigma}_z\rangle", linestyle = :solid)
81-
lines!(ax, times, expt_y, label = L"\langle\hat{\sigma}_y\rangle", linestyle = :dash)
80+
lines!(ax, tlist, expt_z, label = L"\langle\hat{\sigma}_z\rangle", linestyle = :solid)
81+
lines!(ax, tlist, expt_y, label = L"\langle\hat{\sigma}_y\rangle", linestyle = :dash)
8282
8383
axislegend(ax, position = :rb)
8484
@@ -91,6 +91,9 @@ If the keyword argument `e_ops` is not specified (or given as an empty `Vector`)
9191
tlist = [0, 10]
9292
sol = sesolve(H, ψ0, tlist) # or specify: e_ops = []
9393
94+
println(size(sol.times))
95+
println(size(sol.times_states))
96+
9497
sol.states
9598
```
9699

@@ -104,9 +107,11 @@ sol = sesolve(H, ψ0, tlist, e_ops = [sigmay()], saveat = tlist)
104107
```
105108

106109
```@example sesolve
110+
println(size(sol.times))
107111
sol.expect
108112
```
109113

110114
```@example sesolve
115+
println(size(sol.times_states))
111116
sol.states
112117
```

docs/src/users_guide/time_evolution/solution.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ CairoMakie.enable_only_mime!(MIME"image/svg+xml"())
1212

1313
| **Fields (Attributes)** | **Description** |
1414
|:------------------------|:----------------|
15-
| `sol.times` | The time list of the evolution. |
16-
| `sol.states` | The list of result states. |
15+
| `sol.times` | The list of time points at which the expectation values are calculated during the evolution. |
16+
| `sol.times_states` | The list of time points at which the states are stored during the evolution. |
17+
| `sol.states` | The list of result states corresponding to each time point in `sol.times_states`. |
1718
| `sol.expect` | The expectation values corresponding to each time point in `sol.times`. |
1819
| `sol.alg` | The algorithm which is used during the solving process. |
1920
| `sol.abstol` | The absolute tolerance which is used during the solving process. |
@@ -54,7 +55,7 @@ nothing # hide
5455

5556
Recall that `Julia` uses `Fortran`-style indexing that begins with one (i.e., `[1,:]` represents the 1-st observable, where `:` represents all values corresponding to `tlist`).
5657

57-
Together with the array of times at which these expectation values are calculated:
58+
Together with the list of time points at which these expectation values are calculated:
5859

5960
```@example TE-solution
6061
times = sol.times
@@ -83,6 +84,13 @@ State vectors, or density matrices, are accessed in a similar manner:
8384
sol.states
8485
```
8586

87+
Together with the list of time points at which these states are stored:
88+
89+
```@example TE-solution
90+
times = sol.times_states
91+
nothing # hide
92+
```
93+
8694
Here, the solution contains only one (final) state. Because the `states` will be saved depend on the keyword argument `saveat` in `kwargs`. If `e_ops` is empty, the default value of `saveat=tlist` (saving the states corresponding to `tlist`), otherwise, `saveat=[tlist[end]]` (only save the final state). One can also specify `e_ops` and `saveat` separately.
8795

8896
Some other solvers can have other output.

src/correlations.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ end
1919
C::QuantumObject;
2020
kwargs...)
2121
22-
Returns the two-times correlation function of three operators ``\hat{A}``, ``\hat{B}`` and ``\hat{C}``: ``\left\langle \hat{A}(t) \hat{B}(t + \tau) \hat{C}(t) \right\rangle`` for a given initial state ``|\psi_0\rangle``.
22+
Returns the two-time correlation function of three operators ``\hat{A}``, ``\hat{B}`` and ``\hat{C}``: ``\left\langle \hat{A}(t) \hat{B}(t + \tau) \hat{C}(t) \right\rangle`` for a given initial state ``|\psi_0\rangle``.
2323
2424
If the initial state `ψ0` is given as `nothing`, then the [`steadystate`](@ref) will be used as the initial state. Note that this is only implemented if `H` is constant ([`QuantumObject`](@ref)).
2525
"""
@@ -96,7 +96,7 @@ end
9696
reverse::Bool=false,
9797
kwargs...)
9898
99-
Returns the two-times correlation function of two operators ``\hat{A}`` and ``\hat{B}`` : ``\left\langle \hat{A}(t + \tau) \hat{B}(t) \right\rangle`` for a given initial state ``|\psi_0\rangle``.
99+
Returns the two-time correlation function of two operators ``\hat{A}`` and ``\hat{B}`` : ``\left\langle \hat{A}(t + \tau) \hat{B}(t) \right\rangle`` for a given initial state ``|\psi_0\rangle``.
100100
101101
If the initial state `ψ0` is given as `nothing`, then the [`steadystate`](@ref) will be used as the initial state. Note that this is only implemented if `H` is constant ([`QuantumObject`](@ref)).
102102

src/spectrum.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ end
313313
Calculate the power spectrum corresponding to a two-time correlation function using fast Fourier transform (FFT).
314314
315315
# Parameters
316-
- `tlist::AbstractVector`: List of times at which the two-time correlation function is given.
316+
- `tlist::AbstractVector`: List of time points at which the two-time correlation function is given.
317317
- `corr::AbstractVector`: List of two-time correlations corresponding to the given time point in `tlist`.
318318
- `inverse::Bool`: Whether to use the inverse Fourier transform or not. Default to `false`.
319319

src/time_evolution/brmesolve.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ Solves for the dynamics of a system using the Bloch-Redfield master equation, gi
158158
159159
- `H`: The system Hamiltonian. Must be an [`Operator`](@ref)
160160
- `ψ0`: Initial state of the system $|\psi(0)\rangle$. It can be either a [`Ket`](@ref), [`Operator`](@ref) or [`OperatorKet`](@ref).
161-
- `tlist`: List of times at which to save either the state or the expectation values of the system.
161+
- `tlist`: List of time points at which to save either the state or the expectation values of the system.
162162
- `a_ops`: Nested list with each element is a `Tuple` of operator-function pairs `(a_op, spectra)`, and the coupling [`Operator`](@ref) `a_op` must be hermitian with corresponding `spectra` being a `Function` of transition energy
163163
- `c_ops`: List of collapse operators corresponding to Lindblad dissipators
164164
- `sec_cutoff`: Cutoff for secular approximation. Use `-1` if secular approximation is not used when evaluating bath-coupling terms.

src/time_evolution/lr_mesolve.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ A structure storing the results and some information from solving low-rank maste
77
88
# Fields (Attributes)
99
10-
- `times::AbstractVector`: The time list of the evolution.
11-
- `states::Vector{QuantumObject}`: The list of result states.
10+
- `times::AbstractVector`: The list of time points at which the expectation values are calculated during the evolution.
11+
- `times_states::AbstractVector`: The list of time points at which the states are stored during the evolution.
12+
- `states::Vector{QuantumObject}`: The list of result states corresponding to each time point in `times_states`.
1213
- `expect::Matrix`: The expectation values corresponding to each time point in `times`.
13-
- `fexpect::Matrix`: The function values at each time point.
14+
- `fexpect::Matrix`: The function values corresponding to each time point in `times`.
1415
- `retcode`: The return code from the solver.
1516
- `alg`: The algorithm which is used during the solving process.
1617
- `abstol::Real`: The absolute tolerance which is used during the solving process.
@@ -19,7 +20,8 @@ A structure storing the results and some information from solving low-rank maste
1920
- `B::Vector{QuantumObject}`: The `B` matrix of the low-rank algorithm at each time point.
2021
"""
2122
struct TimeEvolutionLRSol{
22-
TT<:AbstractVector{<:Real},
23+
TT1<:AbstractVector{<:Real},
24+
TT2<:AbstractVector{<:Real},
2325
TS<:AbstractVector,
2426
TE<:Matrix{ComplexF64},
2527
RetT<:Enum,
@@ -29,7 +31,8 @@ struct TimeEvolutionLRSol{
2931
TSZB<:AbstractVector,
3032
TM<:Vector{<:Integer},
3133
}
32-
times::TT
34+
times::TT1
35+
times_states::TT2
3336
states::TS
3437
expect::TE
3538
fexpect::TE
@@ -549,6 +552,7 @@ function lr_mesolve(prob::ODEProblem; kwargs...)
549552
ρt = map(x -> Qobj(x[1] * x[2] * x[1]', type = Operator(), dims = prob.p.Hdims), zip(zt, Bt))
550553

551554
return TimeEvolutionLRSol(
555+
prob.p.times,
552556
sol.t,
553557
ρt,
554558
prob.p.expvals,

src/time_evolution/mcsolve.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ If the environmental measurements register a quantum jump, the wave function und
8989
9090
- `H`: Hamiltonian of the system ``\hat{H}``. It can be either a [`QuantumObject`](@ref), a [`QuantumObjectEvolution`](@ref), or a `Tuple` of operator-function pairs.
9191
- `ψ0`: Initial state of the system ``|\psi(0)\rangle``.
92-
- `tlist`: List of times at which to save either the state or the expectation values of the system.
92+
- `tlist`: List of time points at which to save either the state or the expectation values of the system.
9393
- `c_ops`: List of collapse operators ``\{\hat{C}_n\}_n``. It can be either a `Vector` or a `Tuple`.
9494
- `e_ops`: List of operators for which to calculate expectation values. It can be either a `Vector` or a `Tuple`.
9595
- `params`: Parameters to pass to the solver. This argument is usually expressed as a `NamedTuple` or `AbstractVector` of parameters. For more advanced usage, any custom struct can be used.
@@ -195,7 +195,7 @@ If the environmental measurements register a quantum jump, the wave function und
195195
196196
- `H`: Hamiltonian of the system ``\hat{H}``. It can be either a [`QuantumObject`](@ref), a [`QuantumObjectEvolution`](@ref), or a `Tuple` of operator-function pairs.
197197
- `ψ0`: Initial state of the system ``|\psi(0)\rangle``.
198-
- `tlist`: List of times at which to save either the state or the expectation values of the system.
198+
- `tlist`: List of time points at which to save either the state or the expectation values of the system.
199199
- `c_ops`: List of collapse operators ``\{\hat{C}_n\}_n``. It can be either a `Vector` or a `Tuple`.
200200
- `e_ops`: List of operators for which to calculate expectation values. It can be either a `Vector` or a `Tuple`.
201201
- `params`: Parameters to pass to the solver. This argument is usually expressed as a `NamedTuple` or `AbstractVector` of parameters. For more advanced usage, any custom struct can be used.
@@ -320,7 +320,7 @@ If the environmental measurements register a quantum jump, the wave function und
320320
321321
- `H`: Hamiltonian of the system ``\hat{H}``. It can be either a [`QuantumObject`](@ref), a [`QuantumObjectEvolution`](@ref), or a `Tuple` of operator-function pairs.
322322
- `ψ0`: Initial state of the system ``|\psi(0)\rangle``.
323-
- `tlist`: List of times at which to save either the state or the expectation values of the system.
323+
- `tlist`: List of time points at which to save either the state or the expectation values of the system.
324324
- `c_ops`: List of collapse operators ``\{\hat{C}_n\}_n``. It can be either a `Vector` or a `Tuple`.
325325
- `alg`: The algorithm to use for the ODE solver. Default to `Tsit5()`.
326326
- `e_ops`: List of operators for which to calculate expectation values. It can be either a `Vector` or a `Tuple`.
@@ -412,6 +412,7 @@ function mcsolve(
412412
return TimeEvolutionMCSol(
413413
ntraj,
414414
ens_prob_mc.times,
415+
_sol_1.t,
415416
states,
416417
expvals,
417418
expvals, # This is average_expect

0 commit comments

Comments
 (0)