Source code for qutip.solver.correlation

__all__ = [
    'correlation_3op',
    'correlation_2op_1t', 'correlation_2op_2t', 'correlation_3op_1t',
    'correlation_3op_2t', 'coherence_function_g1', 'coherence_function_g2'
]

import numpy as np
import scipy.fftpack

from ..core import (
    Qobj, QobjEvo, liouvillian, spre, unstack_columns, stack_columns,
    tensor, expect, qeye_like, isket
)
from .mesolve import MESolver
from .mcsolve import MCSolver
from .brmesolve import BRSolver
from .heom.bofin_solvers import HEOMSolver

from .steadystate import steadystate
from ..ui.progressbar import progress_bars

# -----------------------------------------------------------------------------
# PUBLIC API
# -----------------------------------------------------------------------------

# low level correlation


[docs]def correlation_2op_1t(H, state0, taulist, c_ops, a_op, b_op, solver="me", reverse=False, args=None, options=None): r""" Calculate the two-operator one-time correlation function: :math:`\left<A(\tau)B(0)\right>` along one time axis using the quantum regression theorem and the evolution solver indicated by the `solver` parameter. Parameters ---------- H : :obj:`.Qobj`, :obj:`.QobjEvo` System Hamiltonian, may be time-dependent for solver choice of `me`. state0 : :obj:`.Qobj` Initial state density matrix :math:`\rho(t_0)` or state vector :math:`\psi(t_0)`. If 'state0' is 'None', then the steady state will be used as the initial state. The 'steady-state' is only implemented if ``c_ops`` are provided and the Hamiltonian is constant. taulist : array_like List of times for :math:`\tau`. taulist must be positive and contain the element `0`. c_ops : list of {:obj:`.Qobj`, :obj:`.QobjEvo`} List of collapse operators a_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator A. b_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator B. reverse : bool, default: False If ``True``, calculate :math:`\left<A(t)B(t+\tau)\right>` instead of :math:`\left<A(t+\tau)B(t)\right>`. solver : str {'me', 'es'}, default: 'me' Choice of solver, ``me`` for master-equation, and ``es`` for exponential series. ``es`` is equivalent to `me` with ``options={"method": "diag"}``. options : dict, optional Options for the solver. Returns ------- corr_vec : ndarray An array of correlation values for the times specified by ``taulist``. See Also -------- :func:`correlation_3op` : Similar function supporting various solver types. References ---------- See, Gardiner, Quantum Noise, Section 5.2. """ solver = _make_solver(H, c_ops, args, options, solver) if reverse: A_op, B_op, C_op = a_op, b_op, 1 else: A_op, B_op, C_op = 1, a_op, b_op if state0 is None: state0 = steadystate(H, c_ops) return correlation_3op(solver, state0, [0], taulist, A_op, B_op, C_op)[0]
[docs]def correlation_2op_2t(H, state0, tlist, taulist, c_ops, a_op, b_op, solver="me", reverse=False, args=None, options=None): r""" Calculate the two-operator two-time correlation function: :math:`\left<A(t+\tau)B(t)\right>` along two time axes using the quantum regression theorem and the evolution solver indicated by the ``solver`` parameter. Parameters ---------- H : :obj:`.Qobj`, :obj:`.QobjEvo` System Hamiltonian, may be time-dependent for solver choice of `me`. state0 : :obj:`.Qobj` Initial state density matrix :math:`\rho(t_0)` or state vector :math:`\psi(t_0)`. If 'state0' is 'None', then the steady state will be used as the initial state. The 'steady-state' is only implemented if ``c_ops`` are provided and the Hamiltonian is constant. tlist : array_like List of times for :math:`t`. tlist must be positive and contain the element `0`. When taking steady-steady correlations only one ``tlist`` value is necessary, i.e. when :math:`t \rightarrow \infty`. If ``tlist`` is ``None``, ``tlist=[0]`` is assumed. taulist : array_like List of times for :math:`\tau`. taulist must be positive and contain the element `0`. c_ops : list of {:obj:`.Qobj`, :obj:`.QobjEvo`} List of collapse operators a_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator A. b_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator B. reverse : bool, default: False If ``True``, calculate :math:`\left<A(t)B(t+\tau)\right>` instead of :math:`\left<A(t+\tau)B(t)\right>`. solver : str {'me', 'es'}, default: 'me' Choice of solver, ``me`` for master-equation, and ``es`` for exponential series. ``es`` is equivalent to `me` with ``options={"method": "diag"}``. options : dict, optional Options for the solver. Returns ------- corr_mat : ndarray An 2-dimensional array (matrix) of correlation values for the times specified by ``tlist`` (first index) and ``taulist`` (second index). See Also -------- :func:`correlation_3op` : Similar function supporting various solver types. References ---------- See, Gardiner, Quantum Noise, Section 5.2. """ solver = _make_solver(H, c_ops, args, options, solver) if tlist is None: tlist = [0] if state0 is None: state0 = steadystate(H, c_ops) if reverse: A_op, B_op, C_op = a_op, b_op, 1 else: A_op, B_op, C_op = 1, a_op, b_op return correlation_3op(solver, state0, tlist, taulist, A_op, B_op, C_op)
[docs]def correlation_3op_1t(H, state0, taulist, c_ops, a_op, b_op, c_op, solver="me", args=None, options=None): r""" Calculate the three-operator two-time correlation function: :math:`\left<A(0)B(\tau)C(0)\right>` along one time axis using the quantum regression theorem and the evolution solver indicated by the `solver` parameter. Note: it is not possibly to calculate a physically meaningful correlation of this form where :math:`\tau<0`. Parameters ---------- H : :obj:`.Qobj`, :obj:`.QobjEvo` System Hamiltonian, may be time-dependent for solver choice of ``me``. state0 : :obj:`.Qobj` Initial state density matrix :math:`\rho(t_0)` or state vector :math:`\psi(t_0)`. If 'state0' is 'None', then the steady state will be used as the initial state. The 'steady-state' is only implemented if ``c_ops`` are provided and the Hamiltonian is constant. taulist : array_like List of times for :math:`\tau`. taulist must be positive and contain the element `0`. c_ops : list of {:obj:`.Qobj`, :obj:`.QobjEvo`} List of collapse operators a_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator A. b_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator B. c_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator C. solver : str {'me', 'es'}, default: 'me' Choice of solver, ``me`` for master-equation, and ``es`` for exponential series. ``es`` is equivalent to `me` with ``options={"method": "diag"}``. options : dict, optional Options for the solver. Returns ------- corr_vec : array An array of correlation values for the times specified by ``taulist``. See Also -------- :func:`correlation_3op` : Similar function supporting various solver types. References ---------- See, Gardiner, Quantum Noise, Section 5.2. """ solver = _make_solver(H, c_ops, args, options, solver) if state0 is None: state0 = steadystate(H, c_ops) return correlation_3op(solver, state0, [0], taulist, a_op, b_op, c_op)[0]
[docs]def correlation_3op_2t(H, state0, tlist, taulist, c_ops, a_op, b_op, c_op, solver="me", args=None, options=None): r""" Calculate the three-operator two-time correlation function: :math:`\left<A(t)B(t+\tau)C(t)\right>` along two time axes using the quantum regression theorem and the evolution solver indicated by the `solver` parameter. Note: it is not possibly to calculate a physically meaningful correlation of this form where :math:`\tau<0`. Parameters ---------- H : :obj:`.Qobj`, :obj:`.QobjEvo` System Hamiltonian, may be time-dependent for solver choice of ``me``. state0 : :obj:`.Qobj` Initial state density matrix :math:`\rho(t_0)` or state vector :math:`\psi(t_0)`. If 'state0' is 'None', then the steady state will be used as the initial state. The 'steady-state' is only implemented if ``c_ops`` are provided and the Hamiltonian is constant. tlist : array_like List of times for :math:`t`. tlist must be positive and contain the element `0`. When taking steady-steady correlations only one tlist value is necessary, i.e. when :math:`t \rightarrow \infty`. If ``tlist`` is ``None``, ``tlist=[0]`` is assumed. taulist : array_like List of times for :math:`\tau`. taulist must be positive and contain the element `0`. c_ops : list of {:obj:`.Qobj`, :obj:`.QobjEvo`} List of collapse operators a_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator A. b_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator B. c_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator C. solver : str {'me', 'es'}, default: 'me' Choice of solver, ``me`` for master-equation, and ``es`` for exponential series. ``es`` is equivalent to `me` with ``options={"method": "diag"}``. options : dict, optional Options for the solver. Only used with ``me`` solver. Returns ------- corr_mat : array An 2-dimensional array (matrix) of correlation values for the times specified by ``tlist`` (first index) and ``taulist`` (second index). See Also -------- :func:`correlation_3op` : Similar function supporting various solver types. References ---------- See, Gardiner, Quantum Noise, Section 5.2. """ solver = _make_solver(H, c_ops, args, options, solver) if tlist is None: tlist = [0] if state0 is None: state0 = steadystate(H, c_ops) return correlation_3op(solver, state0, tlist, taulist, a_op, b_op, c_op)
# high level correlation
[docs]def coherence_function_g1( H, state0, taulist, c_ops, a_op, solver="me", args=None, options=None ): r""" Calculate the normalized first-order quantum coherence function: .. math:: g^{(1)}(\tau) = \frac{\langle A^\dagger(\tau)A(0)\rangle} {\sqrt{\langle A^\dagger(\tau)A(\tau)\rangle \langle A^\dagger(0)A(0)\rangle}} using the quantum regression theorem and the evolution solver indicated by the `solver` parameter. Parameters ---------- H : :obj:`.Qobj`, :obj:`.QobjEvo` System Hamiltonian, may be time-dependent for solver choice of ``me``. state0 : :obj:`.Qobj` Initial state density matrix :math:`\rho(t_0)` or state vector :math:`\psi(t_0)`. If 'state0' is 'None', then the steady state will be used as the initial state. The 'steady-state' is only implemented if ``c_ops`` are provided and the Hamiltonian is constant. taulist : array_like List of times for :math:`\tau`. taulist must be positive and contain the element `0`. c_ops : list of {:obj:`.Qobj`, :obj:`.QobjEvo`} List of collapse operators a_op : :obj:`.Qobj`, :obj:`.QobjEvo` Operator A. solver : str {'me', 'es'}, default: 'me' Choice of solver, ``me`` for master-equation, and ``es`` for exponential series. ``es`` is equivalent to `me` with ``options={"method": "diag"}``. args : dict, optional dictionary of parameters for time-dependent Hamiltonians options : dict, optional Options for the solver. Returns ------- g1, G1 : tuple The normalized and unnormalized second-order coherence function. """ solver = _make_solver(H, c_ops, args, options, solver) # first calculate the photon number if state0 is None: state0 = steadystate(H, c_ops) n = np.array([expect(state0, a_op.dag() * a_op)]) else: n = solver.run(state0, taulist, e_ops=[a_op.dag() * a_op]).expect[0] # calculate the correlation function G1 and normalize with n to obtain g1 G1 = correlation_3op(solver, state0, [0], taulist, None, a_op.dag(), a_op)[0] g1 = G1 / np.sqrt(n[0] * np.array(n))[0] return g1, G1
[docs]def coherence_function_g2(H, state0, taulist, c_ops, a_op, solver="me", args=None, options=None): r""" Calculate the normalized second-order quantum coherence function: .. math:: g^{(2)}(\tau) = \frac{\langle A^\dagger(0)A^\dagger(\tau)A(\tau)A(0)\rangle} {\langle A^\dagger(\tau)A(\tau)\rangle \langle A^\dagger(0)A(0)\rangle} using the quantum regression theorem and the evolution solver indicated by the `solver` parameter. Parameters ---------- H : :obj:`.Qobj`, :obj:`.QobjEvo` System Hamiltonian, may be time-dependent for solver choice of ``me``. state0 : :obj:`.Qobj` Initial state density matrix :math:`\rho(t_0)` or state vector :math:`\psi(t_0)`. If 'state0' is 'None', then the steady state will be used as the initial state. The 'steady-state' is only implemented if ``c_ops`` are provided and the Hamiltonian is constant. taulist : array_like List of times for :math:`\tau`. taulist must be positive and contain the element `0`. c_ops : list List of collapse operators, may be time-dependent for solver choice of ``me``. a_op : :obj:`.Qobj` Operator A. args : dict, optional Dictionary of arguments to be passed to solver. solver : str {'me', 'es'}, default: 'me' Choice of solver, ``me`` for master-equation, and ``es`` for exponential series. ``es`` is equivalent to ``me`` with ``options={"method": "diag"}``. options : dict, optional Options for the solver. Returns ------- g2, G2 : tuple The normalized and unnormalized second-order coherence function. """ solver = _make_solver(H, c_ops, args, options, solver) # first calculate the photon number if state0 is None: state0 = steadystate(H, c_ops) n = np.array([expect(state0, a_op.dag() * a_op)]) else: n = solver.run(state0, taulist, e_ops=[a_op.dag() * a_op]).expect[0] # calculate the correlation function G2 and normalize with n to obtain g2 G2 = correlation_3op(solver, state0, [0], taulist, a_op.dag(), a_op.dag() * a_op, a_op)[0] g2 = G2 / (n[0] * np.array(n)) return g2, G2
def _make_solver(H, c_ops, args, options, solver): H = QobjEvo(H, args=args) c_ops = [QobjEvo(c_op, args=args) for c_op in c_ops] if solver == "me": solver_instance = MESolver(H, c_ops, options=options) elif solver == "es": options = {"method": "diag"} solver_instance = MESolver(H, c_ops, options=options) elif solver == "mc": raise ValueError("MC solver for correlation has been removed") return solver_instance
[docs]def correlation_3op(solver, state0, tlist, taulist, A=None, B=None, C=None): r""" Calculate the three-operator two-time correlation function: :math:`\left<A(t)B(t+\tau)C(t)\right>`. from a open system :class:`.Solver`. Note: it is not possible to calculate a physically meaningful correlation where :math:`\tau<0`. Parameters ---------- solver : :class:`.MESolver`, :class:`.BRSolver` Qutip solver for an open system. state0 : :obj:`.Qobj` Initial state density matrix :math:`\rho(t_0)` or state vector :math:`\psi(t_0)`. tlist : array_like List of times for :math:`t`. tlist must be positive and contain the element `0`. taulist : array_like List of times for :math:`\tau`. taulist must be positive and contain the element `0`. A, B, C : :class:`.Qobj`, :class:`.QobjEvo`, optional, default=None Operators ``A``, ``B``, ``C`` from the equation ``<A(t)B(t+\tau)C(t)>`` in the Schrodinger picture. They do not need to be all provided. For exemple, if ``A`` is not provided, ``<B(t+\tau)C(t)>`` is computed. Returns ------- corr_mat : array An 2-dimensional array (matrix) of correlation values for the times specified by ``tlist`` (first index) and `taulist` (second index). If ``tlist`` is ``None``, then a 1-dimensional array of correlation values is returned instead. """ taulist = np.asarray(taulist) if isket(state0): state0 = state0.proj() A = QobjEvo(qeye_like(state0) if A in [None, 1] else A) B = QobjEvo(qeye_like(state0) if B in [None, 1] else B) C = QobjEvo(qeye_like(state0) if C in [None, 1] else C) if isinstance(solver, (MESolver, BRSolver)): out = _correlation_3op_dm(solver, state0, tlist, taulist, A, B, C) elif isinstance(solver, MCSolver): raise TypeError("Monte Carlo support for correlation was removed. " "Please, tell us on GitHub issues if you need it!") elif isinstance(solver, HEOMSolver): raise TypeError("HEOM is not supported by correlation. " "Please, tell us on GitHub issues if you need it!") else: raise TypeError("Only solvers able to evolve density matrices" " are supported.") return out
def _correlation_3op_dm(solver, state0, tlist, taulist, A, B, C): old_opt = solver.options.copy() try: # We don't want to modify the solver # TODO: Solver could have a ``with`` or ``copy``. solver.options["normalize_output"] = False solver.options["progress_bar"] = False progress_bar = progress_bars[old_opt['progress_bar']]( len(taulist) + 1, **old_opt['progress_kwargs'] ) rho_t = solver.run(state0, tlist).states corr_mat = np.zeros([np.size(tlist), np.size(taulist)], dtype=complex) progress_bar.update() for t_idx, rho in enumerate(rho_t): t = tlist[t_idx] corr_mat[t_idx, :] = solver.run( C(t) @ rho @ A(t), taulist + t, e_ops=B ).expect[0] progress_bar.update() progress_bar.finished() finally: solver.options = old_opt return corr_mat