Skip to content

dq.mepropagator

mepropagator(
    H: QArrayLike | TimeQArray,
    jump_ops: list[QArrayLike | TimeQArray],
    tsave: ArrayLike,
    *,
    solver: Solver = Expm(),
    gradient: Gradient | None = None,
    options: Options = Options()
) -> MEPropagatorResult

Compute the propagator of the Lindblad master equation.

This function computes the propagator \(\mathcal{U}(t)\) at time \(t\) of the Lindblad master equation (with \(\hbar=1\)) $$ \mathcal{U}(t) = \mathscr{T}\exp\left(\int_0^t\mathcal{L}(t')\dt'\right), $$ where \(\mathscr{T}\) is the time-ordering symbol and \(\mathcal{L}\) is the system's Liouvillian. The formula simplifies to \(\mathcal{U}(t)=e^{t\mathcal{L}}\) if the Liouvillian does not depend on time.

Warning

This function only supports constant or piecewise constant Hamiltonians and jump operators. Support for arbitrary time dependence will be added soon.

Parameters

  • H (qarray-like or time-qarray of shape (...H, n, n)) –

    Hamiltonian.

  • jump_ops (list of qarray-like or time-qarray, each of shape (...Lk, n, n)) –

    List of jump operators.

  • tsave (array-like of shape (ntsave,)) –

    Times at which the propagators are saved. The equation is solved from tsave[0] to tsave[-1], or from t0 to tsave[-1] if t0 is specified in options.

  • solver –

    Solver for the integration. Defaults to dq.solver.Expm (explicit matrix exponentiation), which is the only supported solver for now.

  • gradient –

    Algorithm used to compute the gradient. The default is solver-dependent, refer to the documentation of the chosen solver for more details.

  • options –

    Generic options (supported: save_propagators, cartesian_batching, t0, save_extra).

    Detailed options API
    dq.Options(
        save_propagators: bool = True,
        cartesian_batching: bool = True,
        t0: ScalarLike | None = None,
        save_extra: callable[[Array], PyTree] | None = None,
    )
    

    Parameters

    • save_propagators - If True, the propagator is saved at every time in tsave, otherwise only the final propagator is returned.
    • cartesian_batching - If True, batched arguments are treated as separated batch dimensions, otherwise the batching is performed over a single shared batched dimension.
    • t0 - Initial time. If None, defaults to the first time in tsave.
    • save_extra (function, optional) - A function with signature f(QArray) -> PyTree that takes a propagator as input and returns a PyTree. This can be used to save additional arbitrary data during the integration, accessible in result.extra.

Returns

dq.MEPropagatorResult object holding the result of the propagator computation. Use result.propagators to access the saved propagators.

Detailed result API
dq.MEPropagatorResult

Attributes

  • propagators (qarray of shape (..., nsave, n^2, n^2)) - Saved propagators with nsave = ntsave, or nsave = 1 if options.save_propagators=False.
  • final_propagator (qarray of shape (..., n^2, n^2)) - Saved final propagator.
  • extra (PyTree or None) - Extra data saved with save_extra() if specified in options.
  • infos (PyTree or None) - Solver-dependent information on the resolution.
  • tsave (array of shape (ntsave,)) - Times for which results were saved.
  • solver (Solver) - Solver used.
  • gradient (Gradient) - Gradient used.
  • options (Options) - Options used.

Advanced use-cases

Defining a time-dependent Hamiltonian or jump operator

If the Hamiltonian or the jump operators depend on time, they can be converted to time-qarrays using dq.pwc(), dq.modulated(), or dq.timecallable(). See the Time-dependent operators tutorial for more details.

Running multiple simulations concurrently

The Hamiltonian H and the jump operators jump_ops can be batched to compute multiple propagators concurrently. All other arguments are common to every batch. The resulting propagators are batched according to the leading dimensions of H and jump_ops. The behaviour depends on the value of the cartesian_batching option.

The results leading dimensions are

... = ...H, ...L0, ...L1, (...)
For example if:

  • H has shape (2, 3, n, n),
  • jump_ops = [L0, L1] has shape [(4, 5, n, n), (6, n, n)],

then result.propagators has shape (2, 3, 4, 5, 6, ntsave, n, n).

The results leading dimensions are

... = ...H = ...L0 = ...L1 = (...)  # (once broadcasted)
For example if:

  • H has shape (2, 3, n, n),
  • jump_ops = [L0, L1] has shape [(3, n, n), (2, 1, n, n)],

then result.propagators has shape (2, 3, ntsave, n, n).

See the Batching simulations tutorial for more details.