Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
571abc9
made most of the changes. Look at testing.ipynb ##Testing Solver Exte…
Gavin-Rockwood Nov 30, 2025
9665194
Added operator support. Look at testing.ipynb ##Testing Solver Extens…
Gavin-Rockwood Nov 30, 2025
0e6036a
Merge branch 'qutip:main' into Adding-Operator-Support-to-TimeEvoluti…
Gavin-Rockwood Nov 30, 2025
01baa16
updated testing.ipynb
Gavin-Rockwood Nov 30, 2025
e575f7d
added to_dense call to sesolve_map to ensure all initial states are d…
Gavin-Rockwood Nov 30, 2025
71842a7
fixed .gitignore and removed testing.ipynb
Gavin-Rockwood Dec 2, 2025
41e8216
Merge branch 'qutip:main' into Adding-Operator-Support-to-TimeEvoluti…
Gavin-Rockwood Dec 2, 2025
5a354fe
Updated the state type variable to ST and made the other changes disc…
Gavin-Rockwood Dec 2, 2025
d8d26a3
fixed a bug with smesolve!
Gavin-Rockwood Dec 2, 2025
db3422e
Updated ssesolve, smesolve and mcsolve to be minimal changes along wi…
Gavin-Rockwood Dec 9, 2025
01a205c
Updated ssesolve, smesolve and mcsolve to be minmial working changes.
Gavin-Rockwood Dec 9, 2025
aa176c5
Modified the docs and added a new `vec2mat(A::AbstractMatrix) = x` to…
Gavin-Rockwood Dec 9, 2025
8bc6422
updated docs, changelog, propagators.jl test and a few other small th…
Gavin-Rockwood Dec 11, 2025
cae7ac6
fixed a few docs and updated .gitignore.
Gavin-Rockwood Dec 11, 2025
8a3dd42
Ran the `make format` and `make test`. All core tests pass.
Gavin-Rockwood Dec 11, 2025
ab828b5
ard make changelog and fixed PR comments.
Gavin-Rockwood Dec 12, 2025
ab3074d
Update src/time_evolution/mesolve.jl
Gavin-Rockwood Dec 13, 2025
8f3307d
Update src/time_evolution/mesolve.jl
Gavin-Rockwood Dec 13, 2025
c76cca2
Update src/time_evolution/time_evolution.jl
Gavin-Rockwood Dec 13, 2025
29f85dc
fixed mesolve checks for passing to sesolve.
Gavin-Rockwood Dec 13, 2025
04b37e1
made a change to make the code-quality test happy.
Gavin-Rockwood Dec 18, 2025
faed0b7
updated with better fix.
Gavin-Rockwood Dec 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ Manifest.toml
benchmarks/benchmarks_output.json

.ipynb_checkpoints
*.ipynb
.devcontainer/*
*.ipynb
5 changes: 5 additions & 0 deletions src/qobj/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,12 @@ Converts a sparse QuantumObject to a dense QuantumObject.
to_dense(A::QuantumObject) = QuantumObject(to_dense(A.data), A.type, A.dimensions)
to_dense(A::MT) where {MT<:AbstractSparseArray} = Array(A)
to_dense(A::MT) where {MT<:AbstractArray} = A
to_dense(A::Diagonal) = diagm(A.diag)

to_dense(::Type{T}, A::AbstractSparseArray) where {T<:Number} = Array{T}(A)
to_dense(::Type{T1}, A::AbstractArray{T2}) where {T1<:Number,T2<:Number} = Array{T1}(A)
to_dense(::Type{T}, A::AbstractArray{T}) where {T<:Number} = A
to_dense(::Type{T}, A::Diagonal{T}) where {T<:Number} = diagm(A.diag)

function to_dense(::Type{M}) where {M<:Union{Diagonal,SparseMatrixCSC}}
T = M
Expand Down Expand Up @@ -257,6 +259,9 @@ function vec2mat(A::AbstractVector)
newsize = isqrt(length(A))
return reshape(A, newsize, newsize)
end
function vec2mat(A::AbstractMatrix)
return A
end

@doc raw"""
vec2mat(A::QuantumObject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct LindbladJump{
T2,
RNGType<:AbstractRNG,
RandT,
CT<:AbstractVector,
CT<:AbstractArray,
WT<:AbstractVector,
JTT<:AbstractVector,
JWT<:AbstractVector,
Expand Down
3 changes: 2 additions & 1 deletion src/time_evolution/mcsolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ function mcsolveEnsembleProblem(
ensemble_prob = TimeEvolutionProblem(
EnsembleProblem(prob_mc.prob, prob_func = _prob_func, output_func = _output_func[1], safetycopy = false),
prob_mc.times,
prob_mc.states_type,
prob_mc.dimensions,
(progr = _output_func[2], channel = _output_func[3]),
)
Expand Down Expand Up @@ -435,4 +436,4 @@ function mcsolve(
kwargs.abstol,
kwargs.reltol,
)
end
end
57 changes: 32 additions & 25 deletions src/time_evolution/mesolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ _mesolve_make_L_QobjEvo(H::Union{QuantumObjectEvolution,Tuple}, c_ops) = liouvil
_mesolve_make_L_QobjEvo(H::Nothing, c_ops::Nothing) = throw(ArgumentError("Both H and
c_ops are Nothing. You are probably running the wrong function."))

function _gen_mesolve_solution(sol, times, dimensions, isoperket::Val)
if getVal(isoperket)
ρt = map(ϕ -> QuantumObject(ϕ, type = OperatorKet(), dims = dimensions), sol.u)
function _gen_mesolve_solution(sol, prob::TimeEvolutionProblem{ST}) where {ST<:Union{Operator,OperatorKet,SuperOperator}}
if prob.states_type isa Operator
ρt = map(ϕ -> QuantumObject(vec2mat(ϕ), type = prob.states_type, dims = prob.dimensions), sol.u)
else
ρt = map(ϕ -> QuantumObject(vec2mat(ϕ), type = Operator(), dims = dimensions), sol.u)
ρt = map(ϕ -> QuantumObject(ϕ, type = prob.states_type, dims = prob.dimensions), sol.u)
end

kwargs = NamedTuple(sol.prob.kwargs) # Convert to NamedTuple for Zygote.jl compatibility

return TimeEvolutionSol(
times,
prob.times,
sol.t,
ρt,
_get_expvals(sol, SaveFuncMESolve),
Expand Down Expand Up @@ -66,6 +66,7 @@ where

# Notes

- The initial state can also be [`SuperOperator`](@ref) (such as a super-identity). This is useful for simulating many density matrices simultaneously or calculating process matrices. Currently must be Square.
- 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). You can also specify `e_ops` and `saveat` separately.
- If `H` is an [`Operator`](@ref), `ψ0` is a [`Ket`](@ref) and `c_ops` is `Nothing`, the function will call [`sesolveProblem`](@ref) instead.
Expand All @@ -86,8 +87,8 @@ function mesolveProblem(
progress_bar::Union{Val,Bool} = Val(true),
inplace::Union{Val,Bool} = Val(true),
kwargs...,
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet}}
(isoper(H) && isket(ψ0) && isnothing(c_ops)) && return sesolveProblem(
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet,SuperOperator}}
(isoper(H) && (isket(ψ0) || isoper(ψ0)) && isnothing(c_ops)) && return sesolveProblem(
H,
ψ0,
tlist;
Expand All @@ -106,12 +107,17 @@ function mesolveProblem(
L_evo = _mesolve_make_L_QobjEvo(H, c_ops)
check_dimensions(L_evo, ψ0)

T = Base.promote_eltype(L_evo, ψ0)
ρ0 = if isoperket(ψ0) # Convert it to dense vector with complex element type
to_dense(_complex_float_type(T), copy(ψ0.data))
# Convert to dense vector with complex element type

T = _complex_float_type(Base.promote_eltype(L_evo, ψ0))
if isoperket(ψ0) || issuper(ψ0)
ρ0 = to_dense(T, copy(ψ0.data))
states_type = ψ0.type
else
to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
ρ0 = to_dense(T, mat2vec(ket2dm(ψ0).data))
states_type = Operator()
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you change this into

Suggested change
if isoperket(ψ0) || issuper(ψ0)
ρ0 = to_dense(T, copy(ψ0.data))
states_type = ψ0.type
else
to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
ρ0 = to_dense(T, mat2vec(ket2dm(ψ0).data))
states_type = Operator()
end
ρ0, states_type = if isoperket(ψ0) || issuper(ψ0)
to_dense(T, copy(ψ0.data)), ψ0.type
else
to_dense(T, mat2vec(ket2dm(ψ0).data)), Operator()
end

It might fix the issue of JET.jl


L = cache_operator(L_evo.data, ρ0)

kwargs2 = _merge_saveat(tlist, e_ops, DEFAULT_ODE_SOLVER_OPTIONS; kwargs...)
Expand All @@ -122,7 +128,7 @@ function mesolveProblem(

prob = ODEProblem{getVal(inplace),FullSpecialize}(L, ρ0, tspan, params; kwargs4...)

return TimeEvolutionProblem(prob, tlist, L_evo.dimensions, (isoperket = Val(isoperket(ψ0)),))
return TimeEvolutionProblem(prob, tlist, states_type, L_evo.dimensions)
end

@doc raw"""
Expand Down Expand Up @@ -154,7 +160,7 @@ where
# Arguments

- `H`: Hamiltonian of the system ``\hat{H}``. It can be either a [`QuantumObject`](@ref), a [`QuantumObjectEvolution`](@ref), or a `Tuple` of operator-function pairs.
- `ψ0`: Initial state of the system ``|\psi(0)\rangle``. It can be either a [`Ket`](@ref), [`Operator`](@ref) or [`OperatorKet`](@ref).
- `ψ0`: Initial state of the system ``|\psi(0)\rangle``. It can be either a [`Ket`](@ref), [`Operator`](@ref), [`OperatorKet`](@ref) or [`SuperOperator`](@ref).
- `tlist`: List of time points at which to save either the state or the expectation values of the system.
- `c_ops`: List of collapse operators ``\{\hat{C}_n\}_n``. It can be either a `Vector` or a `Tuple`.
- `alg`: The algorithm for the ODE solver. The default value is `DP5()`.
Expand Down Expand Up @@ -188,8 +194,8 @@ function mesolve(
progress_bar::Union{Val,Bool} = Val(true),
inplace::Union{Val,Bool} = Val(true),
kwargs...,
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet}}
(isoper(H) && isket(ψ0) && isnothing(c_ops)) && return sesolve(
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet,SuperOperator}}
(isoper(H) && (isket(ψ0) || isoper(ψ0)) && isnothing(c_ops)) && return sesolve(
H,
ψ0,
tlist;
Expand Down Expand Up @@ -230,7 +236,7 @@ end
function mesolve(prob::TimeEvolutionProblem, alg::AbstractODEAlgorithm = DP5(); kwargs...)
sol = solve(prob.prob, alg; kwargs...)

return _gen_mesolve_solution(sol, prob.times, prob.dimensions, prob.kwargs.isoperket)
return _gen_mesolve_solution(sol, prob)
end

@doc raw"""
Expand Down Expand Up @@ -278,6 +284,7 @@ for each combination in the ensemble.

# Notes

- The initial state can also be [`SuperOperator`](@ref) (such as a super-identity). This is useful for simulating many density matrices simultaneously or calculating process matrices. Currently must be Square.
- The function returns an array of solutions with dimensions matching the Cartesian product of initial states and parameter sets.
- If `ψ0` is a vector of `m` states and `params = (p1, p2, ...)` where `p1` has length `n1`, `p2` has length `n2`, etc., the output will be of size `(m, n1, n2, ...)`.
- If `H` is an [`Operator`](@ref), `ψ0` is a [`Ket`](@ref) and `c_ops` is `Nothing`, the function will call [`sesolve_map`](@ref) instead.
Expand All @@ -298,8 +305,8 @@ function mesolve_map(
params::Union{NullParameters,Tuple} = NullParameters(),
progress_bar::Union{Val,Bool} = Val(true),
kwargs...,
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet}}
(isoper(H) && all(isket, ψ0) && isnothing(c_ops)) && return sesolve_map(
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet,SuperOperator}}
(isoper(H) && (all(isket, ψ0) || all(isoper, ψ0)) && isnothing(c_ops)) && return sesolve_map(
H,
ψ0,
tlist;
Expand All @@ -315,7 +322,7 @@ function mesolve_map(
# Convert to appropriate format based on state type
ψ0_iter = map(ψ0) do state
T = _complex_float_type(eltype(state))
if isoperket(state)
if isoperket(state) || issuper(state)
to_dense(T, copy(state.data))
else
to_dense(T, mat2vec(ket2dm(state).data))
Expand Down Expand Up @@ -347,7 +354,7 @@ mesolve_map(
tlist::AbstractVector,
c_ops::Union{Nothing,AbstractVector,Tuple} = nothing;
kwargs...,
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet}} =
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator,OperatorKet,SuperOperator}} =
mesolve_map(H, [ψ0], tlist, c_ops; kwargs...)

# this method is for advanced usage
Expand All @@ -357,14 +364,14 @@ mesolve_map(
#
# Return: An array of TimeEvolutionSol objects with the size same as the given iter.
function mesolve_map(
prob::TimeEvolutionProblem{<:ODEProblem},
prob::TimeEvolutionProblem{StateOpType, <:AbstractDimensions, <:ODEProblem},
iter::AbstractArray,
alg::AbstractODEAlgorithm = DP5(),
ensemblealg::EnsembleAlgorithm = EnsembleThreads();
prob_func::Union{Function,Nothing} = nothing,
output_func::Union{Tuple,Nothing} = nothing,
progress_bar::Union{Val,Bool} = Val(true),
)
) where {StateOpType<:Union{Ket,Operator,OperatorKet,SuperOperator}}
# generate ensemble problem
ntraj = length(iter)
_prob_func = isnothing(prob_func) ? (prob, i, repeat) -> _se_me_map_prob_func(prob, i, repeat, iter) : prob_func
Expand All @@ -380,14 +387,14 @@ function mesolve_map(
ens_prob = TimeEvolutionProblem(
EnsembleProblem(prob.prob, prob_func = _prob_func, output_func = _output_func[1], safetycopy = false),
prob.times,
prob.states_type,
prob.dimensions,
(progr = _output_func[2], channel = _output_func[3], isoperket = prob.kwargs.isoperket),
(progr = _output_func[2], channel = _output_func[3]),
)

sol = _ensemble_dispatch_solve(ens_prob, alg, ensemblealg, ntraj)

# handle solution and make it become an Array of TimeEvolutionSol
sol_vec =
[_gen_mesolve_solution(sol[:, i], prob.times, prob.dimensions, prob.kwargs.isoperket) for i in eachindex(sol)] # map is type unstable
sol_vec = [_gen_mesolve_solution(sol[:, i], prob) for i in eachindex(sol)] # map is type unstable
return reshape(sol_vec, size(iter))
end
46 changes: 28 additions & 18 deletions src/time_evolution/sesolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ export sesolveProblem, sesolve, sesolve_map

_sesolve_make_U_QobjEvo(H) = -1im * QuantumObjectEvolution(H, type = Operator())

function _gen_sesolve_solution(sol, times, dimensions)
ψt = map(ϕ -> QuantumObject(ϕ, type = Ket(), dims = dimensions), sol.u)
function _gen_sesolve_solution(sol, prob::TimeEvolutionProblem{ST}) where {ST<:Union{Ket,Operator}}
ψt = map(ϕ -> QuantumObject(ϕ, type = prob.states_type, dims = prob.dimensions), sol.u)

kwargs = NamedTuple(sol.prob.kwargs) # Convert to NamedTuple for Zygote.jl compatibility

return TimeEvolutionSol(
times,
prob.times,
sol.t,
ψt,
_get_expvals(sol, SaveFuncSESolve),
Expand Down Expand Up @@ -50,6 +50,7 @@ Generate the ODEProblem for the Schrödinger time evolution of a quantum system:

# Notes

- Initial state can also be [`Operator`](@ref)s where each column represents a state vector, such as the Identity operator. This can be used, for example, to calculate the propagator.
- 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). You can also specify `e_ops` and `saveat` separately.
- The default tolerances in `kwargs` are given as `reltol=1e-6` and `abstol=1e-8`.
Expand All @@ -61,18 +62,19 @@ Generate the ODEProblem for the Schrödinger time evolution of a quantum system:
"""
function sesolveProblem(
H::Union{AbstractQuantumObject{Operator},Tuple},
ψ0::QuantumObject{Ket},
ψ0::QuantumObject{ST},
tlist::AbstractVector;
e_ops::Union{Nothing,AbstractVector,Tuple} = nothing,
params = NullParameters(),
progress_bar::Union{Val,Bool} = Val(true),
inplace::Union{Val,Bool} = Val(true),
kwargs...,
)
) where {ST<:Union{Ket,Operator}}
haskey(kwargs, :save_idxs) &&
throw(ArgumentError("The keyword argument \"save_idxs\" is not supported in QuantumToolbox."))

tlist = _check_tlist(tlist, _float_type(ψ0))
states_type = ψ0.type

H_evo = _sesolve_make_U_QobjEvo(H) # Multiply by -i
isoper(H_evo) || throw(ArgumentError("The Hamiltonian must be an Operator."))
Expand All @@ -90,7 +92,7 @@ function sesolveProblem(

prob = ODEProblem{getVal(inplace),FullSpecialize}(U, ψ0, tspan, params; kwargs4...)

return TimeEvolutionProblem(prob, tlist, H_evo.dimensions)
return TimeEvolutionProblem(prob, tlist, states_type, H_evo.dimensions)
end

@doc raw"""
Expand All @@ -115,7 +117,7 @@ Time evolution of a closed quantum system using the Schrödinger equation:
# Arguments

- `H`: Hamiltonian of the system ``\hat{H}``. It can be either a [`QuantumObject`](@ref), a [`QuantumObjectEvolution`](@ref), or a `Tuple` of operator-function pairs.
- `ψ0`: Initial state of the system ``|\psi(0)\rangle``.
- `ψ0`: Initial state of the system ``|\psi(0)\rangle``. It can be either a [`Ket`](@ref) or a [`Operator`](@ref).
- `tlist`: List of time points at which to save either the state or the expectation values of the system.
- `alg`: The algorithm for the ODE solver. The default is `Vern7(lazy=false)`.
- `e_ops`: List of operators for which to calculate expectation values. It can be either a `Vector` or a `Tuple`.
Expand All @@ -138,15 +140,15 @@ Time evolution of a closed quantum system using the Schrödinger equation:
"""
function sesolve(
H::Union{AbstractQuantumObject{Operator},Tuple},
ψ0::QuantumObject{Ket},
ψ0::QuantumObject{ST},
tlist::AbstractVector;
alg::AbstractODEAlgorithm = Vern7(lazy = false),
e_ops::Union{Nothing,AbstractVector,Tuple} = nothing,
params = NullParameters(),
progress_bar::Union{Val,Bool} = Val(true),
inplace::Union{Val,Bool} = Val(true),
kwargs...,
)
) where {ST<:Union{Ket,Operator}}

# Move sensealg argument to solve for Enzyme.jl support.
# TODO: Remove it when https://github.com/SciML/SciMLSensitivity.jl/issues/1225 is fixed.
Expand Down Expand Up @@ -175,7 +177,7 @@ end
function sesolve(prob::TimeEvolutionProblem, alg::AbstractODEAlgorithm = Vern7(lazy = false); kwargs...)
sol = solve(prob.prob, alg; kwargs...)

return _gen_sesolve_solution(sol, prob.times, prob.dimensions)
return _gen_sesolve_solution(sol, prob)
end

@doc raw"""
Expand Down Expand Up @@ -225,17 +227,20 @@ for each combination in the ensemble.
"""
function sesolve_map(
H::Union{AbstractQuantumObject{Operator},Tuple},
ψ0::AbstractVector{<:QuantumObject{Ket}},
ψ0::AbstractVector{<:QuantumObject{ST}},
tlist::AbstractVector;
alg::AbstractODEAlgorithm = Vern7(lazy = false),
ensemblealg::EnsembleAlgorithm = EnsembleThreads(),
e_ops::Union{Nothing,AbstractVector,Tuple} = nothing,
params::Union{NullParameters,Tuple} = NullParameters(),
progress_bar::Union{Val,Bool} = Val(true),
kwargs...,
)
) where {ST<:Union{Ket,Operator}}
# mapping initial states and parameters
ψ0_iter = map(get_data, ψ0)

ψ0 = map(to_dense, ψ0) # Convert all initial states to dense vectors

ψ0_iter = map(state -> to_dense(_complex_float_type(eltype(state)), copy(state.data)), ψ0)
if params isa NullParameters
iter = collect(Iterators.product(ψ0_iter, [params])) |> vec # convert nx1 Matrix into Vector
else
Expand All @@ -255,8 +260,12 @@ function sesolve_map(

return sesolve_map(prob, iter, alg, ensemblealg; progress_bar = progress_bar)
end
sesolve_map(H::Union{AbstractQuantumObject{Operator},Tuple}, ψ0::QuantumObject{Ket}, tlist::AbstractVector; kwargs...) =
sesolve_map(H, [ψ0], tlist; kwargs...)
sesolve_map(
H::Union{AbstractQuantumObject{Operator},Tuple},
ψ0::QuantumObject{ST},
tlist::AbstractVector;
kwargs...,
) where {ST<:Union{Ket,Operator}} = sesolve_map(H, [ψ0], tlist; kwargs...)

# this method is for advanced usage
# User can define their own iterator structure, prob_func and output_func
Expand All @@ -265,14 +274,14 @@ sesolve_map(H::Union{AbstractQuantumObject{Operator},Tuple}, ψ0::QuantumObject{
#
# Return: An array of TimeEvolutionSol objects with the size same as the given iter.
function sesolve_map(
prob::TimeEvolutionProblem{<:ODEProblem},
prob::TimeEvolutionProblem{ST, <:AbstractDimensions, <:ODEProblem},
iter::AbstractArray,
alg::AbstractODEAlgorithm = Vern7(lazy = false),
ensemblealg::EnsembleAlgorithm = EnsembleThreads();
prob_func::Union{Function,Nothing} = nothing,
output_func::Union{Tuple,Nothing} = nothing,
progress_bar::Union{Val,Bool} = Val(true),
)
) where {ST<:Union{Ket,Operator}}
# generate ensemble problem
ntraj = length(iter)
_prob_func = isnothing(prob_func) ? (prob, i, repeat) -> _se_me_map_prob_func(prob, i, repeat, iter) : prob_func
Expand All @@ -288,13 +297,14 @@ function sesolve_map(
ens_prob = TimeEvolutionProblem(
EnsembleProblem(prob.prob, prob_func = _prob_func, output_func = _output_func[1], safetycopy = false),
prob.times,
prob.states_type,
prob.dimensions,
(progr = _output_func[2], channel = _output_func[3]),
)

sol = _ensemble_dispatch_solve(ens_prob, alg, ensemblealg, ntraj)

# handle solution and make it become an Array of TimeEvolutionSol
sol_vec = [_gen_sesolve_solution(sol[:, i], prob.times, prob.dimensions) for i in eachindex(sol)] # map is type unstable
sol_vec = [_gen_sesolve_solution(sol[:, i], prob) for i in eachindex(sol)] # map is type unstable
return reshape(sol_vec, size(iter))
end
Loading