# 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.