Exemple #1
0
def rcsolve(Hsys, psi0, tlist, e_ops, Q, wc, alpha, N, w_th, sparse=False,
            options=None):
    """
    Function to solve for an open quantum system using the
    reaction coordinate (RC) model.

    Parameters
    ----------
    Hsys: Qobj
        The system hamiltonian.
    psi0: Qobj
        Initial state of the system.
    tlist: List.
        Time over which system evolves.
    e_ops: list of :class:`qutip.Qobj` / callback function single
        Single operator or list of operators for which to evaluate
        expectation values.
    Q: Qobj
        The coupling between system and bath.
    wc: Float
        Cutoff frequency.
    alpha: Float
        Coupling strength.
    N: Integer
        Number of cavity fock states.
    w_th: Float
        Temperature.
    sparse: Boolean
        Optional argument to call the sparse eigenstates solver if needed.
    options : :class:`qutip.Options`
        With options for the solver.

    Returns
    -------
    output: Result
        System evolution.
    """
    if options is None:
        options = Options()

    dot_energy, dot_state = Hsys.eigenstates(sparse=sparse)
    deltaE = dot_energy[1] - dot_energy[0]
    if (w_th < deltaE/2):
        warnings.warn("Given w_th might not provide accurate results")
    gamma = deltaE / (2 * np.pi * wc)
    wa = 2 * np.pi * gamma * wc  # reaction coordinate frequency
    g = np.sqrt(np.pi * wa * alpha / 2.0)  # reaction coordinate coupling
    nb = (1 / (np.exp(wa/w_th) - 1))

    # Reaction coordinate hamiltonian/operators

    dimensions = dims(Q)
    a = tensor(destroy(N), qeye(dimensions[1]))
    unit = tensor(qeye(N), qeye(dimensions[1]))
    Nmax = N * dimensions[1][0]
    Q_exp = tensor(qeye(N), Q)
    Hsys_exp = tensor(qeye(N), Hsys)
    e_ops_exp = [tensor(qeye(N), kk) for kk in e_ops]

    na = a.dag() * a
    xa = a.dag() + a

    # decoupled Hamiltonian
    H0 = wa * a.dag() * a + Hsys_exp
    # interaction
    H1 = (g * (a.dag() + a) * Q_exp)
    H = H0 + H1
    L = 0
    PsipreEta = 0
    PsipreX = 0

    all_energy, all_state = H.eigenstates(sparse=sparse)
    Apre = spre((a + a.dag()))
    Apost = spost(a + a.dag())
    for j in range(Nmax):
        for k in range(Nmax):
            A = xa.matrix_element(all_state[j].dag(), all_state[k])
            delE = (all_energy[j] - all_energy[k])
            if abs(A) > 0.0:
                if abs(delE) > 0.0:
                    X = (0.5 * np.pi * gamma*(all_energy[j] - all_energy[k])
                         * (np.cosh((all_energy[j] - all_energy[k]) /
                            (2 * w_th))
                         / (np.sinh((all_energy[j] - all_energy[k]) /
                            (2 * w_th)))) * A)
                    eta = (0.5 * np.pi * gamma *
                           (all_energy[j] - all_energy[k]) * A)
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()
                    PsipreEta = PsipreEta + (eta * all_state[j]
                                             * all_state[k].dag())
                else:
                    X = 0.5 * np.pi * gamma * A * 2 * w_th
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()

    A = a + a.dag()
    L = ((-spre(A * PsipreX)) + (sprepost(A, PsipreX))
         + (sprepost(PsipreX, A)) + (-spost(PsipreX * A))
         + (spre(A * PsipreEta)) + (sprepost(A, PsipreEta))
         + (-sprepost(PsipreEta, A)) + (-spost(PsipreEta * A)))

    # Setup the operators and the Hamiltonian and the master equation
    # and solve for time steps in tlist
    rho0 = (tensor(thermal_dm(N, nb), psi0))
    output = mesolve(H, rho0, tlist, [L], e_ops_exp, options=options)

    return output
Exemple #2
0
def rcsolve(Hsys,
            psi0,
            tlist,
            e_ops,
            Q,
            wc,
            alpha,
            N,
            w_th,
            sparse=False,
            options=None):
    """
    Function to solve for an open quantum system using the
    reaction coordinate (RC) model.

    Parameters
    ----------
    Hsys: Qobj
        The system hamiltonian.
    psi0: Qobj
        Initial state of the system.
    tlist: List.
        Time over which system evolves.
    e_ops: list of :class:`qutip.Qobj` / callback function single
        Single operator or list of operators for which to evaluate
        expectation values.
    Q: Qobj
        The coupling between system and bath.
    wc: Float
        Cutoff frequency.
    alpha: Float
        Coupling strength.
    N: Integer
        Number of cavity fock states.
    w_th: Float
        Temperature.
    sparse: Boolean
        Optional argument to call the sparse eigenstates solver if needed.
    options : :class:`qutip.Options`
        With options for the solver.

    Returns
    -------
    output: Result
        System evolution.
    """
    if options is None:
        options = Options()

    dot_energy, dot_state = Hsys.eigenstates(sparse=sparse)
    deltaE = dot_energy[1] - dot_energy[0]
    if (w_th < deltaE / 2):
        warnings.warn("Given w_th might not provide accurate results")
    gamma = deltaE / (2 * np.pi * wc)
    wa = 2 * np.pi * gamma * wc  # reaction coordinate frequency
    g = np.sqrt(np.pi * wa * alpha / 2.0)  # reaction coordinate coupling
    nb = (1 / (np.exp(wa / w_th) - 1))

    # Reaction coordinate hamiltonian/operators

    dimensions = dims(Q)
    a = tensor(destroy(N), qeye(dimensions[1]))
    unit = tensor(qeye(N), qeye(dimensions[1]))
    Nmax = N * dimensions[1][0]
    Q_exp = tensor(qeye(N), Q)
    Hsys_exp = tensor(qeye(N), Hsys)
    e_ops_exp = [tensor(qeye(N), kk) for kk in e_ops]

    na = a.dag() * a
    xa = a.dag() + a

    # decoupled Hamiltonian
    H0 = wa * a.dag() * a + Hsys_exp
    # interaction
    H1 = (g * (a.dag() + a) * Q_exp)
    H = H0 + H1
    L = 0
    PsipreEta = 0
    PsipreX = 0

    all_energy, all_state = H.eigenstates(sparse=sparse)
    Apre = spre((a + a.dag()))
    Apost = spost(a + a.dag())
    for j in range(Nmax):
        for k in range(Nmax):
            A = xa.matrix_element(all_state[j].dag(), all_state[k])
            delE = (all_energy[j] - all_energy[k])
            if abs(A) > 0.0:
                if abs(delE) > 0.0:
                    X = (0.5 * np.pi * gamma *
                         (all_energy[j] - all_energy[k]) * (np.cosh(
                             (all_energy[j] - all_energy[k]) /
                             (2 * w_th)) / (np.sinh(
                                 (all_energy[j] - all_energy[k]) /
                                 (2 * w_th)))) * A)
                    eta = (0.5 * np.pi * gamma *
                           (all_energy[j] - all_energy[k]) * A)
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()
                    PsipreEta = PsipreEta + (eta * all_state[j] *
                                             all_state[k].dag())
                else:
                    X = 0.5 * np.pi * gamma * A * 2 * w_th
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()

    A = a + a.dag()
    L = ((-spre(A * PsipreX)) + (sprepost(A, PsipreX)) +
         (sprepost(PsipreX, A)) + (-spost(PsipreX * A)) +
         (spre(A * PsipreEta)) + (sprepost(A, PsipreEta)) +
         (-sprepost(PsipreEta, A)) + (-spost(PsipreEta * A)))

    # Setup the operators and the Hamiltonian and the master equation
    # and solve for time steps in tlist
    rho0 = (tensor(thermal_dm(N, nb), psi0))
    output = mesolve(H, rho0, tlist, [L], e_ops_exp, options=options)

    return output
Exemple #3
0
def hsolve(H, psi0, tlist, Q, gam, lam0, Nc, N, w_th, options=None):
    """
    Function to solve for an open quantum system using the
    hierarchy model.

    Parameters
    ----------
    H: Qobj
        The system hamiltonian.
    psi0: Qobj
        Initial state of the system.
    tlist: List.
        Time over which system evolves.
    Q: Qobj
        The coupling between system and bath.
    gam: Float
        Bath cutoff frequency.
    lam0: Float
        Coupling strength.
    Nc: Integer
        Cutoff parameter.
    N: Integer
        Number of matsubara terms.
    w_th: Float
        Temperature.
    options : :class:`qutip.Options`
        With options for the solver.

    Returns
    -------
    output: Result
        System evolution.
    """
    if options is None:
        options = Options()

    # Set up terms of the matsubara and tanimura boundaries

    # Parameters and hamiltonian
    hbar = 1.
    kb = 1.

    # Set by system
    dimensions = dims(H)
    Nsup = dimensions[0][0] * dimensions[0][0]
    unit = qeye(dimensions[0])

    # Ntot is the total number of ancillary elements in the hierarchy
    Ntot = int(round(factorial(Nc+N) / (factorial(Nc) * factorial(N))))
    c0 = (lam0 * gam * (_cot(gam * hbar / (2. * kb * w_th)) - (1j))) / hbar
    LD1 = (-2. * spre(Q) * spost(Q.dag()) + spre(Q.dag()*Q) + spost(Q.dag()*Q))
    pref = ((2. * lam0 * kb * w_th / (gam * hbar)) - 1j * lam0) / hbar
    gj = 2 * np.pi * kb * w_th / hbar
    L12 = -pref * LD1 + (c0 / gam) * LD1

    for i1 in range(1, N):
        num = (4 * lam0 * gam * kb * w_th * i1 * gj/((i1 * gj)**2 - gam**2))
        ci = num / (hbar**2)
        L12 = L12 + (ci / gj) * LD1

    # Setup liouvillian

    L = liouvillian(H, [L12])
    Ltot = L.data
    unit = sp.eye(Ntot,format='csr')
    Lbig = sp.kron(unit, Ltot)
    rho0big1 = np.zeros((Nsup * Ntot), dtype=complex)

    # Prepare initial state:

    rhotemp = mat2vec(np.array(psi0.full(), dtype=complex))

    for idx, element in enumerate(rhotemp):
        rho0big1[idx] = element[0]
    
    nstates, state2idx, idx2state = enr_state_dictionaries([Nc+1]*(N), Nc)
    for nlabelt in state_number_enumerate([Nc+1]*(N), Nc):
        nlabel = list(nlabelt)
        ntotalcheck = 0
        for ncheck in range(N):
            ntotalcheck = ntotalcheck + nlabel[ncheck]
        current_pos = int(round(state2idx[tuple(nlabel)]))
        Ltemp = sp.lil_matrix((Ntot, Ntot))
        Ltemp[current_pos, current_pos] = 1
        Ltemp.tocsr()
        Lbig = Lbig + sp.kron(Ltemp, (-nlabel[0] * gam * spre(unit).data))

        for kcount in range(1, N):
            counts = -nlabel[kcount] * kcount * gj * spre(unit).data
            Lbig = Lbig + sp.kron(Ltemp, counts)

        for kcount in range(N):
            if nlabel[kcount] >= 1:
                # find the position of the neighbour
                nlabeltemp = copy(nlabel)
                nlabel[kcount] = nlabel[kcount] - 1
                current_pos2 = int(round(state2idx[tuple(nlabel)]))
                Ltemp = sp.lil_matrix((Ntot, Ntot))
                Ltemp[current_pos, current_pos2] = 1
                Ltemp.tocsr()
                # renormalized version:
                ci = (4 * lam0 * gam * kb * w_th * kcount
                      * gj/((kcount * gj)**2 - gam**2)) / (hbar**2)
                if kcount == 0:
                    Lbig = Lbig + sp.kron(Ltemp, (-1j
                                          * (np.sqrt(nlabeltemp[kcount]
                                             / abs(c0)))
                                          * ((c0) * spre(Q).data
                                             - (np.conj(c0))
                                             * spost(Q).data)))
                if kcount > 0:
                    ci = (4 * lam0 * gam * kb * w_th * kcount
                          * gj/((kcount * gj)**2 - gam**2)) / (hbar**2)
                    Lbig = Lbig + sp.kron(Ltemp, (-1j
                                          * (np.sqrt(nlabeltemp[kcount]
                                             / abs(ci)))
                                          * ((ci) * spre(Q).data
                                             - (np.conj(ci))
                                             * spost(Q).data)))
                nlabel = copy(nlabeltemp)

        for kcount in range(N):
            if ntotalcheck <= (Nc-1):
                nlabeltemp = copy(nlabel)
                nlabel[kcount] = nlabel[kcount] + 1
                current_pos3 = int(round(state2idx[tuple(nlabel)]))
            if current_pos3 <= (Ntot):
                Ltemp = sp.lil_matrix((Ntot, Ntot))
                Ltemp[current_pos, current_pos3] = 1
                Ltemp.tocsr()
            # renormalized
                if kcount == 0:
                    Lbig = Lbig + sp.kron(Ltemp, -1j
                                          * (np.sqrt((nlabeltemp[kcount]+1)
                                             * abs(c0)))
                                          * (spre(Q) - spost(Q)).data)
                if kcount > 0:
                    ci = (4 * lam0 * gam * kb * w_th * kcount
                          * gj/((kcount * gj)**2 - gam**2)) / (hbar**2)
                    Lbig = Lbig + sp.kron(Ltemp, -1j
                                          * (np.sqrt((nlabeltemp[kcount]+1)
                                             * abs(ci)))
                                          * (spre(Q) - spost(Q)).data)
            nlabel = copy(nlabeltemp)

    output = []
    for element in rhotemp:
        output.append([])
    r = scipy.integrate.ode(cy_ode_rhs)
    Lbig2 = Lbig.tocsr()
    r.set_f_params(Lbig2.data, Lbig2.indices, Lbig2.indptr)
    r.set_integrator('zvode', method=options.method, order=options.order,
                     atol=options.atol, rtol=options.rtol,
                     nsteps=options.nsteps, first_step=options.first_step,
                     min_step=options.min_step, max_step=options.max_step)

    r.set_initial_value(rho0big1, tlist[0])
    dt = tlist[1] - tlist[0]

    for t_idx, t in enumerate(tlist):
        r.integrate(r.t + dt)
        for idx, element in enumerate(rhotemp):
            output[idx].append(r.y[idx])

    return output