def test_enr_thermal_dm2():
    "Excitation-number-restricted state space: thermal density operator (II)"
    dims, excitations = [3, 4, 5], 2

    n_vec = 0.1

    rho = enr_thermal_dm(dims, excitations, n_vec)

    rho_ref = tensor([thermal_dm(d, n_vec) for idx, d in enumerate(dims)])
    gonners = [idx for idx, state in enumerate(state_number_enumerate(dims))
               if sum(state) > excitations]
    rho_ref = rho_ref.eliminate_states(gonners)
    rho_ref = rho_ref / rho_ref.tr()

    assert_(abs((rho.data - rho_ref.data).data).max() < 1e-12)
Example #2
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