|
1 | 1 | export mcsolveProblem, mcsolveEnsembleProblem, mcsolve |
2 | 2 | export ContinuousLindbladJumpCallback, DiscreteLindbladJumpCallback |
3 | 3 |
|
4 | | -const jump_times_which_init_size = 200 |
5 | | - |
6 | | -function _save_func_mcsolve(integrator, e_ops, is_empty_e_ops) |
7 | | - expvals = integrator.p.expvals |
8 | | - progr = integrator.p.progr |
9 | | - cache_mc = integrator.p.mcsolve_params.cache_mc |
10 | | - if !is_empty_e_ops |
11 | | - copyto!(cache_mc, integrator.u) |
12 | | - normalize!(cache_mc) |
13 | | - ψ = cache_mc |
14 | | - _expect = op -> dot(ψ, get_data(op), ψ) |
15 | | - @. expvals[:, progr.counter[]+1] = _expect(e_ops) |
16 | | - end |
17 | | - next!(progr) |
18 | | - u_modified!(integrator, false) |
19 | | - return nothing |
20 | | -end |
21 | | - |
22 | | -function LindbladJumpAffect!(integrator, c_ops, c_ops_herm) |
23 | | - params = integrator.p |
24 | | - cache_mc = params.mcsolve_params.cache_mc |
25 | | - weights_mc = params.mcsolve_params.weights_mc |
26 | | - cumsum_weights_mc = params.mcsolve_params.cumsum_weights_mc |
27 | | - random_n = params.mcsolve_params.random_n |
28 | | - jump_times = params.mcsolve_params.jump_times |
29 | | - jump_which = params.mcsolve_params.jump_which |
30 | | - jump_times_which_idx = params.mcsolve_params.jump_times_which_idx |
31 | | - traj_rng = params.mcsolve_params.traj_rng |
32 | | - ψ = integrator.u |
33 | | - |
34 | | - @inbounds for i in eachindex(weights_mc) |
35 | | - weights_mc[i] = real(dot(ψ, c_ops_herm[i], ψ)) |
36 | | - end |
37 | | - cumsum!(cumsum_weights_mc, weights_mc) |
38 | | - r = rand(traj_rng) * sum(real, weights_mc) |
39 | | - collapse_idx = getindex(1:length(weights_mc), findfirst(x -> real(x) > r, cumsum_weights_mc)) |
40 | | - mul!(cache_mc, c_ops[collapse_idx], ψ) |
41 | | - normalize!(cache_mc) |
42 | | - copyto!(integrator.u, cache_mc) |
43 | | - |
44 | | - @inbounds random_n[1] = rand(traj_rng) |
45 | | - |
46 | | - @inbounds idx = round(Int, real(jump_times_which_idx[1])) |
47 | | - @inbounds jump_times[idx] = integrator.t |
48 | | - @inbounds jump_which[idx] = collapse_idx |
49 | | - @inbounds jump_times_which_idx[1] += 1 |
50 | | - @inbounds if real(jump_times_which_idx[1]) > length(jump_times) |
51 | | - resize!(jump_times, length(jump_times) + jump_times_which_init_size) |
52 | | - resize!(jump_which, length(jump_which) + jump_times_which_init_size) |
53 | | - end |
54 | | -end |
55 | | - |
56 | | -_mcsolve_continuous_condition(u, t, integrator) = |
57 | | - @inbounds real(integrator.p.mcsolve_params.random_n[1]) - real(dot(u, u)) |
58 | | - |
59 | | -_mcsolve_discrete_condition(u, t, integrator) = |
60 | | - @inbounds real(dot(u, u)) < real(integrator.p.mcsolve_params.random_n[1]) |
61 | | - |
62 | 4 | function _mcsolve_prob_func(prob, i, repeat, global_rng, seeds) |
63 | 5 | params = prob.p |
64 | 6 |
|
@@ -144,40 +86,6 @@ function _normalize_state!(u, dims, normalize_states) |
144 | 86 | return QuantumObject(u, type = Ket, dims = dims) |
145 | 87 | end |
146 | 88 |
|
147 | | -function _generate_mcsolve_kwargs(e_ops, tlist, c_ops, jump_callback, kwargs) |
148 | | - c_ops_data = get_data.(c_ops) |
149 | | - c_ops_herm_data = map(op -> op' * op, c_ops_data) |
150 | | - |
151 | | - _affect = integrator -> LindbladJumpAffect!(integrator, c_ops_data, c_ops_herm_data) |
152 | | - |
153 | | - if jump_callback isa DiscreteLindbladJumpCallback |
154 | | - cb1 = DiscreteCallback(_mcsolve_discrete_condition, _affect, save_positions = (false, false)) |
155 | | - else |
156 | | - cb1 = ContinuousCallback( |
157 | | - _mcsolve_continuous_condition, |
158 | | - _affect, |
159 | | - nothing, |
160 | | - interp_points = jump_callback.interp_points, |
161 | | - save_positions = (false, false), |
162 | | - ) |
163 | | - end |
164 | | - |
165 | | - if e_ops isa Nothing |
166 | | - kwargs2 = |
167 | | - haskey(kwargs, :callback) ? merge(kwargs, (callback = CallbackSet(cb1, kwargs.callback),)) : |
168 | | - merge(kwargs, (callback = cb1,)) |
169 | | - return kwargs2 |
170 | | - else |
171 | | - is_empty_e_ops = isempty(e_ops) |
172 | | - f = integrator -> _save_func_mcsolve(integrator, e_ops, is_empty_e_ops) |
173 | | - cb2 = PresetTimeCallback(tlist, f, save_positions = (false, false)) |
174 | | - kwargs2 = |
175 | | - haskey(kwargs, :callback) ? merge(kwargs, (callback = CallbackSet(cb1, cb2, kwargs.callback),)) : |
176 | | - merge(kwargs, (callback = CallbackSet(cb1, cb2),)) |
177 | | - return kwargs2 |
178 | | - end |
179 | | -end |
180 | | - |
181 | 89 | function _mcsolve_make_Heff_QobjEvo(H::QuantumObject, c_ops) |
182 | 90 | c_ops isa Nothing && return QobjEvo(H) |
183 | 91 | return QobjEvo(H - 1im * mapreduce(op -> op' * op, +, c_ops) / 2) |
@@ -302,8 +210,8 @@ function mcsolveProblem( |
302 | 210 | weights_mc = similar(ψ0.data, T, length(c_ops)) # It should be a Float64 Vector, but we have to keep the same type for all the parameters due to SciMLStructures.jl |
303 | 211 | cumsum_weights_mc = similar(weights_mc) |
304 | 212 |
|
305 | | - jump_times = similar(ψ0.data, T, jump_times_which_init_size) |
306 | | - jump_which = similar(ψ0.data, T, jump_times_which_init_size) |
| 213 | + jump_times = similar(ψ0.data, T, JUMP_TIMES_WHICH_INIT_SIZE) |
| 214 | + jump_which = similar(ψ0.data, T, JUMP_TIMES_WHICH_INIT_SIZE) |
307 | 215 | jump_times_which_idx = T[1] # We could use a Ref, but we have to keep the same type for all the parameters due to SciMLStructures.jl |
308 | 216 |
|
309 | 217 | random_n = similar(ψ0.data, T, 1) # We could use a Ref, but we have to keep the same type for all the parameters due to SciMLStructures.jl. |
@@ -439,7 +347,7 @@ function mcsolveEnsembleProblem( |
439 | 347 | ) |
440 | 348 |
|
441 | 349 | ensemble_prob = TimeEvolutionProblem( |
442 | | - EnsembleProblem(prob_mc.prob, prob_func = _prob_func, output_func = _output_func[1], safetycopy = true), |
| 350 | + EnsembleProblem(prob_mc.prob, prob_func = _prob_func, output_func = _output_func[1], safetycopy = false), |
443 | 351 | prob_mc.times, |
444 | 352 | prob_mc.dims, |
445 | 353 | (progr = _output_func[2], channel = _output_func[3]), |
|
0 commit comments