Skip to content

Commit 5e108e1

Browse files
authored
Improve the construction of QobjEvo (#339)
1 parent 519a191 commit 5e108e1

File tree

4 files changed

+47
-7
lines changed

4 files changed

+47
-7
lines changed

CHANGELOG.md

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

88
## [Unreleased](https://github.com/qutip/QuantumToolbox.jl/tree/main)
99

10-
10+
- Improve the construction of `QobjEvo`. ([#338], [#339])
1111

1212
## [v0.23.1]
1313
Release date: 2024-12-06
@@ -53,3 +53,5 @@ Release date: 2024-11-13
5353
[#324]: https://github.com/qutip/QuantumToolbox.jl/issues/324
5454
[#330]: https://github.com/qutip/QuantumToolbox.jl/issues/330
5555
[#335]: https://github.com/qutip/QuantumToolbox.jl/issues/335
56+
[#338]: https://github.com/qutip/QuantumToolbox.jl/issues/338
57+
[#339]: https://github.com/qutip/QuantumToolbox.jl/issues/339

src/qobj/quantum_object_evo.jl

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,19 @@ function QuantumObjectEvolution(
180180
return QuantumObjectEvolution(data, type, dims)
181181
end
182182

183-
QuantumObjectEvolution(op::QuantumObject, f::Function; type::Union{Nothing,QuantumObjectType} = nothing) =
184-
QuantumObjectEvolution(((op, f),); type = type)
183+
# this is a extra method if user accidentally specify `QuantumObjectEvolution( (op, func) )` or `QuantumObjectEvolution( ((op, func)) )`
184+
QuantumObjectEvolution(
185+
op_func::Tuple{QuantumObject,Function},
186+
α::Union{Nothing,Number} = nothing;
187+
type::Union{Nothing,QuantumObjectType} = nothing,
188+
) = QuantumObjectEvolution((op_func,), α; type = type)
189+
190+
QuantumObjectEvolution(
191+
op::QuantumObject,
192+
f::Function,
193+
α::Union{Nothing,Number} = nothing;
194+
type::Union{Nothing,QuantumObjectType} = nothing,
195+
) = QuantumObjectEvolution(((op, f),), α; type = type)
185196

186197
function QuantumObjectEvolution(
187198
op::QuantumObject,
@@ -229,13 +240,15 @@ Parse the `op_func_list` and generate the data for the `QuantumObjectEvolution`
229240
N = length(op_func_list_types)
230241

231242
dims_expr = ()
243+
func_methods_expr = ()
232244
first_op = nothing
233245
data_expr = :(0)
234246
qobj_expr_const = :(0)
235247

236248
for i in 1:N
237249
op_func_type = op_func_list_types[i]
238250
if op_func_type <: Tuple
251+
# check the structure of the tuple
239252
length(op_func_type.parameters) == 2 || throw(ArgumentError("The tuple must have two elements."))
240253
op_type = op_func_type.parameters[1]
241254
func_type = op_func_type.parameters[2]
@@ -248,6 +261,7 @@ Parse the `op_func_list` and generate the data for the `QuantumObjectEvolution`
248261
op = :(op_func_list[$i][1])
249262
data_type = op_type.parameters[1]
250263
dims_expr = (dims_expr..., :($op.dims))
264+
func_methods_expr = (func_methods_expr..., :(methods(op_func_list[$i][2], [Any, Real]))) # [Any, Real] means each func must accept 2 arguments
251265
if i == 1
252266
first_op = :($op)
253267
end
@@ -267,10 +281,20 @@ Parse the `op_func_list` and generate the data for the `QuantumObjectEvolution`
267281
end
268282

269283
quote
284+
# check the dims of the operators
270285
dims = tuple($(dims_expr...))
271-
272286
allequal(dims) || throw(ArgumentError("The dimensions of the operators must be the same."))
273287

288+
# check if each func accepts 2 arguments
289+
func_methods = tuple($(func_methods_expr...))
290+
for f_method in func_methods
291+
length(f_method.ms) == 0 && throw(
292+
ArgumentError(
293+
"The following function must accept two arguments: `$(f_method.mt.name)(p, t)` with t<:Real",
294+
),
295+
)
296+
end
297+
274298
data_expr_const = $qobj_expr_const isa Integer ? $qobj_expr_const : _make_SciMLOperator($qobj_expr_const, α)
275299

276300
data_expr = data_expr_const + $data_expr

src/time_evolution/sesolve.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ export sesolveProblem, sesolve
22

33
_sesolve_make_U_QobjEvo(H::QuantumObjectEvolution{<:MatrixOperator}) =
44
QobjEvo(MatrixOperator(-1im * H.data.A), dims = H.dims, type = Operator)
5-
_sesolve_make_U_QobjEvo(H) = QobjEvo(H, -1im)
5+
_sesolve_make_U_QobjEvo(H::QuantumObject) = QobjEvo(MatrixOperator(-1im * H.data), dims = H.dims, type = Operator)
6+
_sesolve_make_U_QobjEvo(H::Union{QuantumObjectEvolution,Tuple}) = QobjEvo(H, -1im)
67

78
@doc raw"""
89
sesolveProblem(

test/core-test/quantum_objects_evo.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,24 @@
119119
"Quantum Object Evo.: type=SuperOperator dims=$L_dims size=$L_size ishermitian=$L_isherm isconstant=$L_isconst\n$datastring"
120120
end
121121

122-
@testset "Type Inference (QuantumObject)" begin
122+
@testset "Type Inference (QobjEvo)" begin
123+
N = 4
123124
for T in [ComplexF32, ComplexF64]
124-
N = 4
125125
a = MatrixOperator(rand(T, N, N))
126126
@inferred QobjEvo(a)
127127
for type in [Operator, SuperOperator]
128128
@inferred QobjEvo(a, type = type)
129129
end
130130
end
131131

132+
a = destroy(N)
133+
coef1(p, t) = exp(-t)
134+
coef2(p::Vector, t) = sin(p[1] * t)
135+
coef3(p::NamedTuple, t) = cos(p.ω * t)
136+
@inferred QobjEvo(a, coef1)
137+
@inferred QobjEvo((a', coef2))
138+
@inferred QobjEvo((a' * a, (a, coef1), (a', coef2), (a + a', coef3)))
139+
132140
@testset "Math Operation" begin
133141
a = QobjEvo(destroy(20))
134142
σx = QobjEvo(sigmax())
@@ -182,6 +190,7 @@
182190
@test isconstant(H_td) == false
183191
@test isconstant(QobjEvo(a)) == true
184192
@test isoper(H_td) == true
193+
@test QobjEvo(a, coef1) == QobjEvo((a, coef1))
185194

186195
# SuperOperator
187196
X = a * a'
@@ -205,7 +214,11 @@
205214
@test isconstant(L_td) == false
206215
@test issuper(L_td) == true
207216

217+
coef_wrong1(t) = nothing
218+
coef_wrong2(p, t::ComplexF64) = nothing
208219
@test_logs (:warn,) (:warn,) liouvillian(H_td * H_td) # warnings from lazy tensor
220+
@test_throws ArgumentError QobjEvo(a, coef_wrong1)
221+
@test_throws ArgumentError QobjEvo(a, coef_wrong2)
209222
@test_throws MethodError QobjEvo([[a, coef1], a' * a, [a', coef2]])
210223
@test_throws ArgumentError H_td(ρvec, p, t)
211224
@test_throws ArgumentError cache_operator(H_td, ρvec)

0 commit comments

Comments
 (0)