Source code for hamiltonians

## Copyright 2019-present The qocttools developing team
##
## This file is part of qocttools.
##
## qocttools is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## qocttools is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with qocttools.  If not, see <https://www.gnu.org/licenses/>.

"""This module holds the class that holds the Hamiltonian.


"""

import numpy as np
import qutip as qt

[docs] class hamiltonian: """A class to hold and manipulate the Hamiltonian and dissipation terms. The Hamiltonian should contain a static part, a list of possible perturbations, and also a list of dissipative terms for the Lindblad equation (which is not, of course, a proper term of the Hamiltonian) There are two options for the user to pass the Hamiltonian to qocttools: as a list of Qobj objects, or as a Qobj-valued user-defined function. 1. In the first case, the Hamiltonian has the form: .. math:: H(t) = H_0 + \sum_{i=1}^N f_i(t) V_i The pulses :math:`f_i(t)` are not described in the hamiltonian object. The user must then pass H0 and a list of perturbations V (it may also be just one). In addition, for open systems, the hamiltonian object should also contain the Lindblad operators, which should be supplied by the user as a list of Qobj objects. 2. In the second case, the user should supply Qobj-valued functions. In this case, the H0 function contains the full Hamiltonian, and depends on time and on the set of "pulses" :math:`f_i(t)`: .. math:: H_0 = H_0(t, f_1(t), \dots, f_N(t)) The user must then also supply, in the argument V, a list with the derivatives of :math:`H0` with respect to each :math:`f_i` argument: .. math:: V_i(t, f_1(t), \dots, f_N(t)) = \\frac{\partial H_o}{\partial f_i}(t, f_1(t), \dots, f_N(t)) The function H0 (and the functions in the V list) should have the following inteface: .. code-block:: python def H0(t, args): f = args["f"] # f[0], f[1], f[2], ..., f[N-1] are the time-dependent functions The arguments are a float t that means time, and a dictionary args with just one element with name "f", and whose value is a list of functions of time. Parameters ---------- H0 : Qobj or Qobj-valued function The qutip Qobj instance holding the static part of the Hamiltonian. V : Qobj or list of Qobj or Qobj-valued function or list of Qobj-valued functions. One or various Qobj instances holding external perturbations. A : Qobj or list of Qobj, default = None One or various Qobj instances holding the jump operators defining the Lindbladian. Attributes ---------- H0 : Qobj The qutip Qobj instance holding the static part of the Hamiltonian. V : list of Qobj One or various Qobj instances holding external perturbations. A : list of Qobj One or various Qobj instances holding the jump operators defining the Lindblad operator. """ def __init__(self, H0, V, A = None): if not isinstance(H0, qt.qobj.Qobj): self.function = True if isinstance(V, list): nfuncs = len(V) else: nfuncs = 1 args = { "f" : [lambda t : 0]*nfuncs } self.H0 = qt.QobjEvo(H0, args = args) if isinstance(V, list): self.V = [] for j in range(nfuncs): (self.V).append(qt.QobjEvo(V[j], args = args)) else: self.V = [qt.QobjEvo(V, args = args)] self.dim = self.H0.dims[0][0] else: self.function = False self.dim = H0.dims[0][0] self.H0 = H0.copy() if isinstance(V, list): self.V = [] for j in range(len(V)): (self.V).append(V[j].copy()) else: self.V = [V.copy()] self.A = A
[docs] def has_dissipative_terms(self): """Returns True if the dissipative terms are not None Returns ------- bool: True if the attribute holding the dissipative terms is not None, False otherwise. """ return (self.A is not None)
[docs] def toliouville(h, factor = 1.0): """ This function transforms a Hamiltonian, defined in Hilbert space, together with the set of Lindblad operators, to the corresponding Liouvillian in Liouville space. It is also returned as a hamiltonian object Parameters ---------- h : hamiltonian The input Hamiltonian, to be transformed. Returns ------- hamiltonian A hamiltonian object with the transformed Hamiltonian. """ dim = h.dim**2 v__ = [] l0__ = qt.Qobj( factor * qt.liouvillian(h.H0, h.A), dims = [[dim], [dim]] ) for j in range(len(h.V)): v__.append( factor * qt.Qobj(qt.liouvillian(h.V[j]), dims = [[dim], [dim]]) ) return hamiltonian(l0__, v__)