1212(f:: SaveFuncSESolve )(integrator) = _save_func_sesolve (integrator, f. e_ops, f. is_empty_e_ops)
1313(f:: SaveFuncSESolve{Nothing} )(integrator) = _save_func_sesolve (integrator)
1414
15+ # #
16+
1517# When e_ops is Nothing
1618function _save_func_sesolve (integrator)
1719 next! (integrator. p. progr)
@@ -25,15 +27,15 @@ function _save_func_sesolve(integrator, e_ops, is_empty_e_ops)
2527 progr = integrator. p. progr
2628 if ! is_empty_e_ops
2729 ψ = integrator. u
28- _expect = op -> dot (ψ, get_data (op) , ψ)
30+ _expect = op -> dot (ψ, op , ψ)
2931 @. expvals[:, progr. counter[]+ 1 ] = _expect (e_ops)
3032 end
3133 return _save_func_sesolve (integrator)
3234end
3335
3436function _generate_sesolve_callback (e_ops, tlist)
3537 is_empty_e_ops = e_ops isa Nothing ? true : isempty (e_ops)
36- _save_affect! = SaveFuncSESolve (e_ops, is_empty_e_ops)
38+ _save_affect! = SaveFuncSESolve (get_data .( e_ops) , is_empty_e_ops)
3739 return PresetTimeCallback (tlist, _save_affect!, save_positions = (false , false ))
3840end
3941
4648
4749(f:: SaveFuncMCSolve )(integrator) = _save_func_mcsolve (integrator, f. e_ops, f. is_empty_e_ops)
4850
49- struct LindbladJumpAffect! {T1,T2}
51+ struct LindbladJump {T1,T2}
5052 c_ops:: T1
5153 c_ops_herm:: T2
5254end
5355
54- (f:: LindbladJumpAffect! )(integrator) = _lindblad_jump_affect! (integrator, f. c_ops, f. c_ops_herm)
56+ (f:: LindbladJump )(integrator) = _lindblad_jump_affect! (integrator, f. c_ops, f. c_ops_herm)
5557
5658# #
5759
@@ -63,7 +65,7 @@ function _save_func_mcsolve(integrator, e_ops, is_empty_e_ops)
6365 copyto! (cache_mc, integrator. u)
6466 normalize! (cache_mc)
6567 ψ = cache_mc
66- _expect = op -> dot (ψ, get_data (op) , ψ)
68+ _expect = op -> dot (ψ, op , ψ)
6769 @. expvals[:, progr. counter[]+ 1 ] = _expect (e_ops)
6870 end
6971 next! (progr)
@@ -75,7 +77,7 @@ function _generate_mcsolve_kwargs(e_ops, tlist, c_ops, jump_callback, kwargs)
7577 c_ops_data = get_data .(c_ops)
7678 c_ops_herm_data = map (op -> op' * op, c_ops_data)
7779
78- _affect! = LindbladJumpAffect! (c_ops_data, c_ops_herm_data)
80+ _affect! = LindbladJump (c_ops_data, c_ops_herm_data)
7981
8082 if jump_callback isa DiscreteLindbladJumpCallback
8183 cb1 = DiscreteCallback (_mcsolve_discrete_condition, _affect!, save_positions = (false , false ))
@@ -96,8 +98,8 @@ function _generate_mcsolve_kwargs(e_ops, tlist, c_ops, jump_callback, kwargs)
9698 return kwargs2
9799 else
98100 is_empty_e_ops = isempty (e_ops)
99- _save_affect! = SaveFuncMCSolve (e_ops, is_empty_e_ops)
100- cb2 = PresetTimeCallback (tlist, _save_affect!, save_positions = (false , false ))
101+ _save_affect! = SaveFuncMCSolve (get_data .( e_ops) , is_empty_e_ops)
102+ cb2 = _PresetTimeCallback (tlist, _save_affect!, save_positions = (false , false ))
101103 kwargs2 =
102104 haskey (kwargs, :callback ) ? merge (kwargs, (callback = CallbackSet (cb1, cb2, kwargs. callback),)) :
103105 merge (kwargs, (callback = CallbackSet (cb1, cb2),))
@@ -146,3 +148,74 @@ _mcsolve_continuous_condition(u, t, integrator) =
146148
147149_mcsolve_discrete_condition (u, t, integrator) =
148150 @inbounds real (dot (u, u)) < real (integrator. p. mcsolve_params. random_n[1 ])
151+
152+ #=
153+ With this function we extract the c_ops and c_ops_herm from the LindbladJump `affect!` function of the callback of the integrator.
154+ This callback can be a DiscreteLindbladJumpCallback or a ContinuousLindbladJumpCallback.
155+ =#
156+ function _mcsolve_get_c_ops (integrator:: AbstractODEIntegrator )
157+ cb_set = integrator. opts. callback # This is supposed to be a CallbackSet
158+ (cb_set isa CallbackSet) || throw (ArgumentError (" The callback must be a CallbackSet." ))
159+ cb = isempty (cb_set. continuous_callbacks) ? cb_set. discrete_callback[1 ] : cb_set. continuous_callbacks[1 ]
160+ return cb. affect!. c_ops, cb. affect!. c_ops_herm
161+ end
162+
163+ #=
164+ With this function we extract the e_ops from the SaveFuncMCSolve `affect!` function of the callback of the integrator.
165+ This callback can only be a PresetTimeCallback (DiscreteCallback).
166+ =#
167+ function _mcsolve_get_e_ops (integrator:: AbstractODEIntegrator )
168+ cb_set = integrator. opts. callback # This is supposed to be a CallbackSet
169+ (cb_set isa CallbackSet) || throw (ArgumentError (" The callback must be a CallbackSet." ))
170+ cb = length (cb_set. continuous_callbacks) > 0 ? cb_set. discrete_callbacks[1 ] : cb_set. discrete_callbacks[2 ]
171+ return cb. affect!. e_ops
172+ end
173+
174+ # # Temporary function to avoid errors. Waiting for the PR In DiffEqCallbacks.jl to be merged.
175+
176+ import SciMLBase: INITIALIZE_DEFAULT, add_tstop!
177+
178+ function _PresetTimeCallback (
179+ tstops,
180+ user_affect!;
181+ initialize = INITIALIZE_DEFAULT,
182+ filter_tstops = true ,
183+ sort_inplace = false ,
184+ kwargs... ,
185+ )
186+ if ! (tstops isa AbstractVector) && ! (tstops isa Number)
187+ throw (ArgumentError (" tstops must either be a number or a Vector. Was $tstops " ))
188+ end
189+
190+ tstops = tstops isa Number ? [tstops] : (sort_inplace ? sort! (tstops) : sort (tstops))
191+
192+ condition = let
193+ function (u, t, integrator)
194+ if hasproperty (integrator, :dt )
195+ insorted (t, tstops) && (integrator. t - integrator. dt) != integrator. t
196+ else
197+ insorted (t, tstops)
198+ end
199+ end
200+ end
201+
202+ # Initialization: first call to `f` should be *before* any time steps have been taken:
203+ initialize_preset = function (c, u, t, integrator)
204+ initialize (c, u, t, integrator)
205+
206+ if filter_tstops
207+ tdir = integrator. tdir
208+ tspan = integrator. sol. prob. tspan
209+ _tstops = tstops[@. tdir * tspan[1 ] < tdir * tstops < tdir * tspan[2 ]]
210+ else
211+ _tstops = tstops
212+ end
213+ for tstop in _tstops
214+ add_tstop! (integrator, tstop)
215+ end
216+ if t ∈ tstops
217+ user_affect! (integrator)
218+ end
219+ end
220+ return DiscreteCallback (condition, user_affect!; initialize = initialize_preset, kwargs... )
221+ end
0 commit comments