Stochastic semi-classical systems
In addition to the stochastic Schrödinger and master equations, an implementation for semi-classical systems that are subject to noise is also available. In general, the functions stochastic.schroedinger_semiclassical
and stochastic.master_semiclassical
are written to handle time-dependent semi-classical problems including stochastic processes of any kind. From the point of view of syntax, they are very similar to the semi-classical implementations (see Semi-classical systems)
Semi-classical stochastic Schrödinger equation
To solve semi-classical problems, the functions fquantum(t, psi, u)
and fclassical(t, psi, u, du)
need to be passed to the solver. Here, psi
is the quantum part of a semiclassical.State
, u
its classical part and du
the derivative of the classical part. Now, in order to solve a semi-classical equation that is subject to noise, one (or both) of two optional functions needs to be passed to stochastic.schroedinger_semiclassical
. The corresponding keyword arguments are fstoch_quantum
and fstoch_classical
that are of the same form as fquantum
and fclassical
, respectively.
function fstoch_q_schroedinger(t, psi, u)
# Calculate time-dependent stuff
Hs
end
function fstoch_c_schroedinger!(du, u, psi, t)
# Calculate classical stochastic stuff
du[1] = -u[2] # some example
du[2] = u[1]
end
# Quantum noise
stochastic.schroedinger_semiclassical(tspan, ψ0, fquantum_schroedinger, fclassical_schroedinger!;
fstoch_quantum=fstoch_q_schroedinger, dt=dt)
# Classical noise
stochastic.schroedinger_semiclassical(tspan, ψ0, fquantum_schroedinger, fclassical_schroedinger!;
fstoch_classical=fstoch_c_schroedinger!, dt=dt)
Note, that here ψ0
needs to be a semiclassical.State
. If one of the functions is omitted, then the semi-classical problem is solved where noise is only present in the quantum or classical part, respectively. Once again, it is possible to avoid initial calculation of the function fquantum_stoch
to obtain the length of Hs
by defining noise_processes
. This number has to be equal to the length of Hs
. If fstoch_classical
is given then you can set this by passing the noise_prototype_classical
keyword (see below). Note, that this argument becomes necessary when working on combinations of quantum and classical noise, or in cases of non-diagonal classical noise.
Semi-classical stochastic master equation
Implementing a semi-classical stochastic master equation works similarly to above. The output of the functions needs to be altered in order to return the operators needed for the Lindblad and stochastic superoperator, respectively.
function fstoch_q_master(t, psi, u)
# Calculate time-dependent stuff
C, Cdagger
end
function fstoch_c_master!(du, u, psi, t)
# Calculate classical stochastic stuff
du[1] = -u[2] # some example
du[2] = u[1]
end
# Quantum noise
stochastic.master_semiclassical(tspan, ρ0, fquantum_master, fclassical_master!;
fstoch_quantum=fstoch_q_master, dt=dt)
# Classical noise
stochastic.master_semiclassical(tspan, ρ0, fquantum_master, fclassical_master!;
fstoch_classical=fstoch_c_master!, dt=dt)
Note, that the operators returned by fstoch_q_master
are cast in the form of a stochastic superoperator in the stochastic master equation. Again, if one of the functions is omitted, the semi-classical time evolution is calculated where noise is only present in the part for which the respective function is defined.
If this is to combined with classical noise, some extra options are necessary.
Combinations of quantum and (non-diagonal) classical noise
While the above discussed examples work fine for problems with quantum noise or classical noise, one needs to be careful when working with combinations of the two. For combinations of quantum and classical noise, we need to set the keyword argument noise_prototype_classical
. This is essentially the same option as they keyword noise_rate_prototype
in the StochasticDiffEq package, which is needed to treat non-diagonal noise. It is important to note, that even if the quantum noise is diagonal (i.e. there is only one noise operator) and also the classical noise is diagonal, the combined problem corresponds to non-diagonal noise. This means, that the classical increment du
in the stochastic classical function is a two-dimensional array. The noise_prototype_classical
carries the information for the shape of this array.
For example, consider a stochastic Schrödinger equation with a single noise term in the Hamiltonian and diagonal classical noise. This can be implemented by
function fstoch_q_diagonal(t, psi, u)
Hs # This is a vector containing a single operator
end
function fstoch_c_diagonal!(du, u, psi, t)
# Same example as before, but du is now an array
du[1,1] = -u[2]
du[2,2] = u[1]
end
stochastic.schroedinger_semiclassical(tspan, ψ0, fquantum_schroedinger, fclassical_schroedinger!;
fstoch_quantum=fstoch_q_diagonal, fstoch_classical=fstoch_c_diagonal!,
noise_prototype_classical=zeros(ComplexF64, 2, 2), dt=dt)
Note, how we need to index the diagonal of the array du
in order to treat to obtain a diagonal classical noise problem.
Non-diagonal classical noise can be treated in the same way, e.g.
function fstoch_c_nondiag!(du, u, psi, t)
# Non-diagonal noise
du[1,1] = -u[2]
du[1,2] = 0.1u[1]
du[2,2] = u[1]
du[2,1] = -0.1u[2]
du[2,3] = u[2]
end
stochastic.schroedinger_semiclassical(tspan, ψ0, fquantum_schroedinger, fclassical_schroedinger!; dt=dt,
fstoch_classical=fstoch_c_nondiag!, noise_prototype_classical=zeros(ComplexF64, 2, 3))
Note, that the above can be combined with the quantum noise function from before (without any further changes) by passing the corresponding function. The entire discussion above can be used in the same fashion for stochastic master equations.
For details on non-diagonal noise, please refer to the DifferentialEquations documentation.