def L_left_lindblad(H, PARAMS): I = qeye(PARAMS['N']) d_h = tensor(PARAMS['A_L'], I) J_leads = J_Lorentzian Lambda_up = lambda x : Lamdba_complex_rate(x, J_leads, PARAMS['mu_L'], PARAMS['T_L'], PARAMS['Gamma_L'], PARAMS['delta_L'], PARAMS['Omega_L'], type='p', real_only=True) Lambda_down = lambda x : Lamdba_complex_rate(x, J_leads, PARAMS['mu_L'], PARAMS['T_L'], PARAMS['Gamma_L'], PARAMS['delta_L'], PARAMS['Omega_L'], type='m', real_only=True) energies, states = H.eigenstates() L=0 for i in range(len(energies)): for j in range(len(energies)): eta_ij = energies[i] - energies[j] if (abs(eta_ij)>0):# take limit of rates going to zero d_h_ij = d_h.matrix_element(states[i].dag(), states[j]) d_h_ij_sq = d_h_ij*d_h_ij.conjugate() # real by construction if (abs(d_h_ij_sq)>0): # No need to do anything if the matrix element is zero IJ = states[i]*states[j].dag() JI = states[j]*states[i].dag() JJ = states[j]*states[j].dag() II = states[i]*states[i].dag() rate_up = Lambda_up(-eta_ij) # evaluated at positive freq diffs rate_down = Lambda_down(-eta_ij) print(rate_down) T1 = rate_up*spre(II)+rate_down*spre(JJ) T2 = rate_up.conjugate()*spost(II)+rate_down.conjugate()*spost(JJ) T3 = (rate_up*sprepost(JI, IJ)+rate_down*sprepost(IJ,JI)) L += d_h_ij_sq*(0.5*(T1 + T2) - T3) return -L
def L_nonsecular_old(H_vib, A, eps, Gamma, T, J, time_units='cm', silent=False): #Construct non-secular liouvillian ti = time.time() d = H_vib.shape[0] evals, evecs = H_vib.eigenstates() X1, X2, X3, X4 = 0, 0, 0, 0 for i in range(int(d)): for j in range(int(d)): eps_ij = abs(evals[i]-evals[j]) A_ij = A.matrix_element(evecs[i].dag(), evecs[j]) A_ji = (A.dag()).matrix_element(evecs[j].dag(), evecs[i]) Occ = Occupation(eps_ij, T, time_units) IJ = evecs[i]*evecs[j].dag() JI = evecs[j]*evecs[i].dag() # 0.5*np.pi*alpha*(N+1) if abs(A_ij)>0 or abs(A_ji)>0: r_up = 2*np.pi*J(eps_ij, Gamma, eps)*Occ r_down = 2*np.pi*J(eps_ij, Gamma, eps)*(Occ+1) X3+= r_down*A_ij*IJ X4+= r_up*A_ij*IJ X1+= r_up*A_ji*JI X2+= r_down*A_ji*JI L = spre(A*X1) -sprepost(X1,A)+spost(X2*A)-sprepost(A,X2) L+= spre(A.dag()*X3)-sprepost(X3, A.dag())+spost(X4*A.dag())-sprepost(A.dag(), X4) if not silent: print(("It took ", time.time()-ti, " seconds to build the Non-secular RWA Liouvillian")) return -0.5*L
def L_full_secular(H_vib, A, eps, Gamma, T, J, time_units='cm', silent=False): ''' Initially assuming that the vibronic eigenstructure has no degeneracy and the secular approximation has been made ''' ti = time.time() d = H_vib.shape[0] L = 0 eVals, eVecs = H_vib.eigenstates() A_dag = A.dag() terms = 0 for l in range(int(d)): for m in range(int(d)): for p in range(int(d)): for q in range(int(d)): secular_freq = (eVals[l] - eVals[m]) - (eVals[p] - eVals[q]) if abs(secular_freq) < 1E-10: terms += 1 A_lm = A.matrix_element(eVecs[l].dag(), eVecs[m]) A_lm_star = A_dag.matrix_element( eVecs[m].dag(), eVecs[l]) A_pq = A.matrix_element(eVecs[p].dag(), eVecs[q]) A_pq_star = A_dag.matrix_element( eVecs[q].dag(), eVecs[p]) coeff_1 = A_lm * A_pq_star coeff_2 = A_lm_star * A_pq eps_pq = abs(eVals[p] - eVals[q]) Occ = Occupation(eps_pq, T, time_units) r_up = np.pi * J(eps_pq, Gamma, eps) * Occ r_down = np.pi * J(eps_pq, Gamma, eps) * (Occ + 1) LM = eVecs[l] * eVecs[m].dag() ML = LM.dag() PQ = eVecs[p] * eVecs[q].dag() QP = PQ.dag() """ if abs(secular_freq) !=0: print (abs(secular_freq), r_up, A_lm, A_lm_star, A_pq, A_pq_star, r_down, l,m,p,q, m==q, l==p) """ if abs(r_up * coeff_1) > 0: L += r_up * coeff_1 * (spre(LM * QP) - sprepost(QP, LM)) if abs(r_up * coeff_2) > 0: L += r_up * coeff_2 * (spost(PQ * ML) - sprepost(ML, PQ)) if abs(r_down * coeff_1) > 0: L += r_down * coeff_1 * (spre(ML * PQ) - sprepost(PQ, ML)) if abs(r_down * coeff_2) > 0: L += r_down * coeff_2 * (spost(QP * LM) - sprepost(LM, QP)) if not silent: print(("It took ", time.time() - ti, " seconds to build the secular Liouvillian")) print(( "Secular approximation kept {:0.2f}% of total ME terms. \n".format( 100 * float(terms) / (d * d * d * d)))) return -L
def test_general_stochastic(): "Stochastic: general_stochastic" "Reproduce smesolve homodyne" tol = 0.025 N = 4 gamma = 0.25 ntraj = 20 nsubsteps = 50 a = destroy(N) H = [[a.dag() * a, f]] psi0 = coherent(N, 0.5) sc_ops = [np.sqrt(gamma) * a, np.sqrt(gamma) * a * 0.5] e_ops = [a.dag() * a, a + a.dag(), (-1j) * (a - a.dag())] L = liouvillian(QobjEvo([[a.dag() * a, f]], args={"a": 2}), c_ops=sc_ops) L.compile() sc_opsM = [QobjEvo(spre(op) + spost(op.dag())) for op in sc_ops] [op.compile() for op in sc_opsM] e_opsM = [spre(op) for op in e_ops] def d1(t, vec): return L.mul_vec(t, vec) def d2(t, vec): out = [] for op in sc_opsM: out.append(op.mul_vec(t, vec) - op.expect(t, vec) * vec) return np.stack(out) times = np.linspace(0, 0.5, 13) res_ref = mesolve(H, psi0, times, sc_ops, e_ops, args={"a": 2}) list_methods_tol = ['euler-maruyama', 'platen', 'explicit15'] for solver in list_methods_tol: res = general_stochastic(ket2dm(psi0), times, d1, d2, len_d2=2, e_ops=e_opsM, normalize=False, ntraj=ntraj, nsubsteps=nsubsteps, solver=solver) assert_( all([ np.mean(abs(res.expect[idx] - res_ref.expect[idx])) < tol for idx in range(len(e_ops)) ])) assert_(len(res.measurement) == ntraj)
def liouvillian_build(H_0, A, gamma, wRC, T_C): # Now this function has to construct the liouvillian so that it can be passed to mesolve H_0, A, Chi, Xi = RCME_operators(H_0, A, gamma, beta_f(T_C)) L = 0 L -= spre(A * Chi) L += sprepost(A, Chi) L += sprepost(Chi, A) L -= spost(Chi * A) L += spre(A * Xi) L += sprepost(A, Xi) L -= sprepost(Xi, A) L -= spost(Xi * A) return L, Chi + Xi
def _convert_superoperator_to_qutip(expr, full_space, mapping): if full_space != expr.space: all_spaces = full_space.local_factors own_space_index = all_spaces.index(expr.space) return qutip.tensor( *([qutip.qeye(s.dimension) for s in all_spaces[:own_space_index]] + convert_to_qutip(expr, expr.space, mapping=mapping) + [ qutip.qeye(s.dimension) for s in all_spaces[own_space_index + 1:] ])) if isinstance(expr, IdentitySuperOperator): return qutip.spre( qutip.tensor( *[qutip.qeye(s.dimension) for s in full_space.local_factors])) elif isinstance(expr, SuperOperatorPlus): return sum( (convert_to_qutip(op, full_space, mapping=mapping) for op in expr.operands), 0, ) elif isinstance(expr, SuperOperatorTimes): ops_qutip = [ convert_to_qutip(o, full_space, mapping=mapping) for o in expr.operands ] return reduce(lambda a, b: a * b, ops_qutip, 1) elif isinstance(expr, ScalarTimesSuperOperator): return complex(expr.coeff) * convert_to_qutip( expr.term, full_space, mapping=mapping) elif isinstance(expr, SPre): return qutip.spre( convert_to_qutip(expr.operands[0], full_space, mapping)) elif isinstance(expr, SPost): return qutip.spost( convert_to_qutip(expr.operands[0], full_space, mapping)) elif isinstance(expr, SuperOperatorTimesOperator): sop, op = expr.operands return convert_to_qutip(sop, full_space, mapping=mapping) * convert_to_qutip( op, full_space, mapping=mapping) elif isinstance(expr, ZeroSuperOperator): return qutip.spre( convert_to_qutip(ZeroOperator, full_space, mapping=mapping)) else: raise ValueError("Cannot convert '%s' of type %s" % (str(expr), type(expr)))
def test_terminator(self, combine): Q = sigmaz() op = -2 * spre(Q) * spost(Q.dag()) + spre(Q.dag() * Q) + spost( Q.dag() * Q) bath = DrudeLorentzPadeBath( Q=Q, lam=0.025, T=1 / 0.95, Nk=1, gamma=0.05, combine=combine, ) delta, terminator = bath.terminator() assert np.abs(delta - (0.0 / 4.0)) < 1e-8 assert isequal(terminator, -(0.0 / 4.0) * op, tol=1e-8)
def test_sprepost(self): U1 = rand_unitary(3) U2 = rand_unitary(3) S1 = spre(U1) * spost(U2) S2 = sprepost(U1, U2) assert_(S1 == S2)
def L_vib_lindblad(H_vib, A, eps, Gamma, T, J, time_units='cm', silent=False): ''' Initially assuming that the vibronic eigenstructure has no degeneracy and the secular approximation has been made ''' ti = time.time() d = H_vib.shape[0] ti = time.time() L = 0 eig = H_vib.eigenstates() eVals = eig[0] eVecs = eig[1] # come out like kets l = 0 occs = [] for i in range(int(d)): l = 0 for j in range(int(d)): t_0 = time.time( ) # initial time reference for tracking slow calculations lam_ij = A.matrix_element(eVecs[i].dag(), eVecs[j]) #lam_mn = (A.dag()).matrix_element(eVecs[n].dag(), eVecs[m]) lam_ij_sq = lam_ij * lam_ij.conjugate() # real by construction eps_ij = abs(eVals[i] - eVals[j]) if abs(lam_ij_sq) > 0: IJ = eVecs[i] * eVecs[j].dag() JI = eVecs[j] * eVecs[i].dag() JJ = eVecs[j] * eVecs[j].dag() II = eVecs[i] * eVecs[i].dag() Occ = Occupation(eps_ij, T, time_units) r_up = 2 * np.pi * J(eps_ij, Gamma, eps) * Occ r_down = 2 * np.pi * J(eps_ij, Gamma, eps) * (Occ + 1) T1 = r_up * spre(II) + r_down * spre(JJ) T2 = r_up.conjugate() * spost(II) + r_down.conjugate() * spost( JJ) T3 = (r_up * sprepost(JI, IJ) + r_down * sprepost(IJ, JI)) L += lam_ij_sq * (0.5 * (T1 + T2) - T3) l += 1 if not silent: print(("It took ", time.time() - ti, " seconds to build the vibronic Lindblad Liouvillian")) return -L
def test_general_stochastic(): "Stochastic: general_stochastic" "Reproduce smesolve homodyne" tol = 0.025 N = 4 gamma = 0.25 ntraj = 20 nsubsteps = 50 a = destroy(N) H = [[a.dag() * a,f]] psi0 = coherent(N, 0.5) sc_ops = [np.sqrt(gamma) * a, np.sqrt(gamma) * a * 0.5] e_ops = [a.dag() * a, a + a.dag(), (-1j)*(a - a.dag())] L = liouvillian(QobjEvo([[a.dag() * a,f]], args={"a":2}), c_ops = sc_ops) L.compile() sc_opsM = [QobjEvo(spre(op) + spost(op.dag())) for op in sc_ops] [op.compile() for op in sc_opsM] e_opsM = [spre(op) for op in e_ops] def d1(t, vec): return L.mul_vec(t,vec) def d2(t, vec): out = [] for op in sc_opsM: out.append(op.mul_vec(t,vec)-op.expect(t,vec)*vec) return np.stack(out) times = np.linspace(0, 0.5, 13) res_ref = mesolve(H, psi0, times, sc_ops, e_ops, args={"a":2}) list_methods_tol = ['euler-maruyama', 'platen', 'explicit15'] for solver in list_methods_tol: res = general_stochastic(ket2dm(psi0),times,d1,d2,len_d2=2, e_ops=e_opsM, normalize=False, ntraj=ntraj, nsubsteps=nsubsteps, solver=solver) assert_(all([np.mean(abs(res.expect[idx] - res_ref.expect[idx])) < tol for idx in range(len(e_ops))])) assert_(len(res.measurement) == ntraj)
def L_EM_lindblad(splitting, col_em, Gamma, T, J, time_units='cm', silent=False): # col_em is collapse operator ti = time.time() L = 0 EMnb = Occupation(splitting, T, time_units) L += 2 * np.pi * J(splitting, Gamma, splitting) * (EMnb + 1) * ( sprepost(col_em, col_em.dag()) - 0.5 * (spre(col_em.dag() * col_em) + spost(col_em.dag() * col_em))) L += 2 * np.pi * J(splitting, Gamma, splitting) * EMnb * ( sprepost(col_em.dag(), col_em) - 0.5 * (spre(col_em * col_em.dag()) + spost(col_em * col_em.dag()))) if not silent: print(("It took ", time.time() - ti, " seconds to build the electronic-Lindblad Liouvillian")) return L
def testOperatorUnitaryTransform(self): """ Superoperator: Unitary transformation with operators and superoperators """ N = 3 rho = rand_dm(N) U = rand_unitary(N) rho1 = U * rho * U.dag() rho2_vec = spre(U) * spost(U.dag()) * operator_to_vector(rho) rho2 = vector_to_operator(rho2_vec) assert_((rho1 - rho2).norm() < 1e-8)
def testOperatorSpreAppl(self): """ Superoperator: apply operator and superoperator from left (spre) """ N = 3 rho = rand_dm(N) U = rand_unitary(N) rho1 = U * rho rho2_vec = spre(U) * operator_to_vector(rho) rho2 = vector_to_operator(rho2_vec) assert_((rho1 - rho2).norm() < 1e-8)
def _spectrum_pi(H, wlist, c_ops, a_op, b_op, use_pinv=False): """ Internal function for calculating the spectrum of the correlation function :math:`\left<A(\\tau)B(0)\\right>`. """ #print issuper(H) L = H if issuper(H) else liouvillian(H, c_ops) tr_mat = tensor([qeye(n) for n in L.dims[0][0]]) N = prod(L.dims[0][0]) A = L.full() b = spre(b_op).full() a = spre(a_op).full() tr_vec = transpose(mat2vec(tr_mat.full())) rho_ss = steadystate(L) rho = transpose(mat2vec(rho_ss.full())) I = identity(N * N) P = kron(transpose(rho), tr_vec) Q = I - P spectrum = zeros(len(wlist)) for idx, w in enumerate(wlist): if use_pinv: MMR = pinv(-1.0j * w * I + A) else: MMR = dot(Q, solve(-1.0j * w * I + A, Q)) s = dot(tr_vec, dot(a, dot(MMR, dot(b, transpose(rho))))) spectrum[idx] = -2 * real(s[0, 0]) return spectrum
def test_qpt_snot(): "quantum process tomography for snot gate" U_psi = snot() U_rho = spre(U_psi) * spost(U_psi.dag()) N = 1 op_basis = [[qeye(2), sigmax(), 1j * sigmay(), sigmaz()] for i in range(N)] # op_label = [["i", "x", "y", "z"] for i in range(N)] chi1 = qpt(U_rho, op_basis) chi2 = np.zeros((2 ** (2 * N), 2 ** (2 * N)), dtype=complex) chi2[1, 1] = chi2[1, 3] = chi2[3, 1] = chi2[3, 3] = 0.5 assert_(norm(chi2 - chi1) < 1e-8)
def test_qpt_snot(): "quantum process tomography for snot gate" U_psi = snot() U_rho = spre(U_psi) * spost(U_psi.dag()) N = 1 op_basis = [[qeye(2), sigmax(), 1j * sigmay(), sigmaz()] for i in range(N)] # op_label = [["i", "x", "y", "z"] for i in range(N)] chi1 = qpt(U_rho, op_basis) chi2 = np.zeros((2**(2 * N), 2**(2 * N)), dtype=complex) chi2[1, 1] = chi2[1, 3] = chi2[3, 1] = chi2[3, 3] = 0.5 assert_(norm(chi2 - chi1) < 1e-8)
def liouvillian_build_new(H_0, A, gamma, wRC, T_C): # Now this function has to construct the liouvillian so that it can be passed to mesolve H_0, A, Chi, Xi = RCME_operators(H_0, A, gamma, beta_f(T_C)) Z = Chi + Xi Z_dag = Z.dag() L = 0 #L+=spre(A*Z_dag) #L-=sprepost(A, Z) #L-=sprepost(Z_dag, A) #L+=spost(Z_dag*A) L -= spre(A * Z_dag) L += sprepost(A, Z) L += sprepost(Z_dag, A) L -= spost(Z * A) print("new L built") return L, Z
def liouvillian(self): """Build the total Liouvillian using the Dicke basis. Returns ------- liouv: :class: qutip.Qobj The Liouvillian matrix for the system. """ lindblad = self.lindbladian() if self.hamiltonian is None: liouv = lindblad else: hamiltonian = self.hamiltonian hamiltonian_superoperator = - 1j * \ spre(hamiltonian) + 1j * spost(hamiltonian) liouv = lindblad + hamiltonian_superoperator return liouv
def liouvillian(self): """Build the total Liouvillian in the Dicke basis. Returns ------- liouv: :class: qutip.Qobj The Liouvillian matrix for the system. """ lindblad = self.lindbladian() if self.hamiltonian is None: liouv = lindblad else: hamiltonian = self.hamiltonian hamiltonian_superoperator = - 1j * \ spre(hamiltonian) + 1j * spost(hamiltonian) liouv = lindblad + hamiltonian_superoperator return liouv
def generator(k,H,L1,L2): """ Create the generator for the cascaded chain of k system copies """ # create bare operators id = qt.qeye(H.dims[0][0]) Id = qt.spre(id)*qt.spost(id) Hlist = [] L1list = [] L2list = [] for l in range(1,k+1): h = H l1 = L1 l2 = L2 for i in range(1,l): h = qt.tensor(h,id) l1 = qt.tensor(l1,id) l2 = qt.tensor(l2,id) for i in range(l+1,k+1): h = qt.tensor(id,h) l1 = qt.tensor(id,l1) l2 = qt.tensor(id,l2) Hlist.append(h) L1list.append(l1) L2list.append(l2) # create Lindbladian L = qt.Qobj() H0 = 0.5*Hlist[0] L0 = L2list[0] #L0 = 0.*L2list[0] L += qt.liouvillian(H0,[L0]) E0 = Id for l in range(k-1): E0 = qt.composite(Id,E0) Hl = 0.5*(Hlist[l]+Hlist[l+1]+1j*(L1list[l].dag()*L2list[l+1] -L2list[l+1].dag()*L1list[l])) Ll = L1list[l] + L2list[l+1] L += qt.liouvillian(Hl,[Ll]) Hk = 0.5*Hlist[k-1] Hk = 0.5*Hlist[k-1] Lk = L1list[k-1] L += qt.liouvillian(Hk,[Lk]) E0.dims = L.dims return L,E0
def L_wc_analytic(detuning=0., Rabi=0, alpha=0., w0=0., Gamma=0., T=0., tol=1e-7): energies, states = exciton_states(detuning, Rabi) dark_proj = states[0] * states[0].dag() bright_proj = states[1] * states[1].dag() ct_p = states[1] * states[0].dag() ct_m = states[0] * states[1].dag() cross_term = (ct_p + ct_m) epsilon = -detuning V = Rabi / 2 eta = sqrt(epsilon**2 + 4 * V**2) # Bath 1 (only one bath) G = (lambda x: (DecayRate(x, beta_f(T), _J_underdamped, Gamma, w0, imag_part=True, alpha=alpha, tol=tol))) G_0 = G(0.) G_p = G(eta) G_m = G(-eta) site_1 = (0.5 / eta) * ((eta + epsilon) * bright_proj + (eta - epsilon) * dark_proj + 2 * V * cross_term) Z_1 = (0.5 / eta) * (G_0 * ((eta + epsilon) * bright_proj + (eta - epsilon) * dark_proj) + 2 * V * (ct_p * G_p + ct_m * G_m)) L = -qt.spre(site_1 * Z_1) + qt.sprepost(Z_1, site_1) L += -qt.spost(Z_1.dag() * site_1) + qt.sprepost(site_1, Z_1.dag()) return L
def L_non_rwa(H_vib, A, w_0, Gamma, T_EM, J, principal=False, silent=False, alpha=0., tol=1e-5): ti = time.time() beta = beta_f(T_EM) eVals, eVecs = H_vib.eigenstates() #J=J_minimal # J_minimal(omega, Gamma, omega_0) d_dim = len(eVals) G = 0 for i in range(d_dim): for j in range(d_dim): eta = eVals[i] - eVals[j] s = eVecs[i] * (eVecs[j].dag()) #print A.matrix_element(eVecs[i].dag(), eVecs[j]) overlap = A.matrix_element(eVecs[i].dag(), eVecs[j]) s *= A.matrix_element(eVecs[i].dag(), eVecs[j]) s *= DecayRate(eta, beta, J, Gamma, w_0, imag_part=principal, alpha=alpha, tol=tol) G += s G_dag = G.dag() # Initialise liouvilliian L = qt.spre(A * G) - qt.sprepost(G, A) L += qt.spost(G_dag * A) - qt.sprepost(A, G_dag) if not silent: print(("Calculating non-RWA Liouvilliian took {} seconds.".format( time.time() - ti))) return -L
def liouvillian(epsilon, delta, J, T): L = 0 # Initialise liouvilliian Z = 0 # initialise operator Z #beta = 1 /(T* 0.695) beta = 7.683/T eta = np.sqrt(epsilon**2 + delta**2) # Here I define the eigenstates of the H_s H = qt.Qobj([[-epsilon/2., delta/2],[delta/2, epsilon/2.]]) eVecs = H.eigenstates()[1] psi_p = (1/np.sqrt(2*eta))*(np.sqrt(eta-epsilon)*qt.basis(2,0) + np.sqrt(eta+epsilon)*qt.basis(2,1)) psi_m = (-1/np.sqrt(2*eta))*(np.sqrt(eta+epsilon)*qt.basis(2,0) - np.sqrt(eta-epsilon)*qt.basis(2,1)) #print H.eigenstates() # Jake's eigenvectors #psi_p = (1/np.sqrt(2*eta))*(np.sqrt(eta+epsilon)*qt.basis(2,0) - np.sqrt(eta-epsilon)*qt.basis(2,1)) #psi_m = (1/np.sqrt(2*eta))*(np.sqrt(eta-epsilon)*qt.basis(2,0) + np.sqrt(eta+epsilon)*qt.basis(2,1)) sigma_z = (1/eta)*(epsilon*(psi_p*psi_p.dag()-psi_m*psi_m.dag()) + delta*(psi_p*psi_m.dag() + psi_m*psi_p.dag())) Z = (1/eta)*(epsilon*(psi_p*psi_p.dag()-psi_m*psi_m.dag() )*Gamma(0, beta, J) + delta*(Gamma(eta, beta, J)*psi_p*psi_m.dag() + Gamma(-eta,beta, J)*psi_m*psi_p.dag())) L += qt.spre(sigma_z*Z) - qt.sprepost(Z, sigma_z) L += qt.spost(Z.dag()*sigma_z) - qt.sprepost(sigma_z, Z.dag()) return -L
def secular_term(state_j, state_k): jk = state_j*state_k.dag() kj = jk.dag() jj = state_j*state_j.dag() return 2*sprepost(kj, jk) - (spre(jj) + spost(jj))
a=destroy(N) adag=a.dag() It= qeye(N) tm = diag(sqrt(range(1, N)),1) # Lowering operator for the transmon. print tm print a #tdiag = sparse(diag(0:2:2*(Nt-1))); % Operator for dephasing. #tdiag = Qobj(diag(range(0, N))) # Diagonal matrix for the transmon. #tdiag_l = kron(It,tdiag) # tdiag operator multiplying rho from the left. tm_l = spre(a) #kron(It, a) # tm operator multiplying rho from the left. #print #print tm_l[1] #print #print kron(eye(N), tm)[1] #raise Exception c_op_list = [] rate = gamma * (1 + N_gamma) c_op_list.append(sqrt(rate) * a) # decay operators Lindblad_tm = rate*(kron(a.conj(),a) - 0.5*kron(It,adag*a) -
def commutator_term1(O1, O2): # [O1, O2*rho] return spre(O1*O2)-sprepost(O2, O1)
def _to_qutip(self, full_space): return qutip.spre(self.operands[0].to_qutip(full_space))
def ttmsolve(dynmaps, rho0, times, e_ops=[], learningtimes=None, tensors=None, **kwargs): """ Solve time-evolution using the Transfer Tensor Method, based on a set of precomputed dynamical maps. Parameters ---------- dynmaps : list of :class:`qutip.Qobj` List of precomputed dynamical maps (superoperators), or a callback function that returns the superoperator at a given time. rho0 : :class:`qutip.Qobj` Initial density matrix or state vector (ket). times : array_like list of times :math:`t_n` at which to compute :math:`\\rho(t_n)`. Must be uniformily spaced. e_ops : list of :class:`qutip.Qobj` / callback function single operator or list of operators for which to evaluate expectation values. learningtimes : array_like list of times :math:`t_k` for which we have knowledge of the dynamical maps :math:`E(t_k)`. tensors : array_like optional list of precomputed tensors :math:`T_k` kwargs : dictionary Optional keyword arguments. See :class:`qutip.nonmarkov.ttm.TTMSolverOptions`. Returns ------- output: :class:`qutip.solver.Result` An instance of the class :class:`qutip.solver.Result`. """ opt = TTMSolverOptions(dynmaps=dynmaps, times=times, learningtimes=learningtimes, **kwargs) diff = None if isket(rho0): rho0 = ket2dm(rho0) output = Result() e_sops_data = [] if callable(e_ops): n_expt_op = 0 expt_callback = True else: try: tmp = e_ops[:] del tmp n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states opt.store_states = True for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(len(times))) else: output.expect.append(np.zeros(len(times), dtype=complex)) except TypeError: raise TypeError("Argument 'e_ops' should be a callable or" + "list-like.") if tensors is None: tensors, diff = _generatetensors(dynmaps, learningtimes, opt=opt) if rho0.isoper: # vectorize density matrix rho0vec = operator_to_vector(rho0) else: # rho0 might be a super in which case we should not vectorize rho0vec = rho0 K = len(tensors) states = [rho0vec] for n in range(1, len(times)): states.append(None) for k in range(n): if n-k < K: states[-1] += tensors[n-k]*states[k] for i, r in enumerate(states): if opt.store_states or expt_callback: if r.type == 'operator-ket': states[i] = vector_to_operator(r) else: states[i] = r if expt_callback: # use callback method e_ops(times[i], states[i]) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 0) else: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 1) output.solver = "ttmsolve" output.times = times output.ttmconvergence = diff if opt.store_states: output.states = states return output
def ttmsolve(dynmaps, rho0, times, e_ops=[], learningtimes=None, tensors=None, **kwargs): """ Solve time-evolution using the Transfer Tensor Method, based on a set of precomputed dynamical maps. Parameters ---------- dynmaps : list of :class:`qutip.Qobj` List of precomputed dynamical maps (superoperators), or a callback function that returns the superoperator at a given time. rho0 : :class:`qutip.Qobj` Initial density matrix or state vector (ket). times : array_like list of times :math:`t_n` at which to compute :math:`\\rho(t_n)`. Must be uniformily spaced. e_ops : list of :class:`qutip.Qobj` / callback function single operator or list of operators for which to evaluate expectation values. learningtimes : array_like list of times :math:`t_k` for which we have knowledge of the dynamical maps :math:`E(t_k)`. tensors : array_like optional list of precomputed tensors :math:`T_k` kwargs : dictionary Optional keyword arguments. See :class:`qutip.nonmarkov.ttm.TTMSolverOptions`. Returns ------- output: :class:`qutip.solver.Result` An instance of the class :class:`qutip.solver.Result`. """ opt = TTMSolverOptions(dynmaps=dynmaps, times=times, learningtimes=learningtimes, **kwargs) diff = None if isket(rho0): rho0 = ket2dm(rho0) output = Result() e_sops_data = [] if callable(e_ops): n_expt_op = 0 expt_callback = True else: try: tmp = e_ops[:] del tmp n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states opt.store_states = True for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(len(times))) else: output.expect.append(np.zeros(len(times), dtype=complex)) except TypeError: raise TypeError("Argument 'e_ops' should be a callable or" + "list-like.") if tensors is None: tensors, diff = _generatetensors(dynmaps, learningtimes, opt=opt) rho0vec = operator_to_vector(rho0) K = len(tensors) states = [rho0vec] for n in range(1, len(times)): states.append(None) for k in range(n): if n-k < K: states[-1] += tensors[n-k]*states[k] for i, r in enumerate(states): if opt.store_states or expt_callback: if r.type == 'operator-ket': states[i] = vector_to_operator(r) else: states[i] = r if expt_callback: # use callback method e_ops(times[i], states[i]) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 0) else: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 1) output.solver = "ttmsolve" output.times = times output.ttmconvergence = diff if opt.store_states: output.states = states return output
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
N_gamma = 1/(exp(wd/T)-1)# % Thermal population of the transmon phonon bath around wd. print N_gamma N = 5 # number of basis states to consider phi_arr=linspace(0.2, 0.35, 51) Ej_arr=linspace(10078, 17960, 51) w0_arr=linspace(4211, 5622, 301) a = destroy(N) adag=a.dag() #Qobj(diag(range(0, 2*N, 2))) #dephasing operator, tdiag print spre(a) #tm_l = kron(Itot,tm); tm operator multiplying rho from the left. p = -1.0j*(adag - a) # "P" operator. print p print spre(p) #p_l = kron(Itot,p) % "P" operator multiplying rho from the left. print spost(p) #p_r = kron(transpose(p),Itot) % "P" operator multiplying rho from the right. #It= qeye(N) c_op_list = [] rate = gamma * (1 + N_gamma)
def test_spre_td(self): "Superoperator: spre, time-dependent" assert_(spre(self.t1)(.5) == spre(self.t1(.5)))
def _to_qutip(self, full_space): return qutip.spre(qutip.tensor(*[qutip.qeye(s.dimension) for s in full_space.local_factors()]))
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
#w12_vec(i) = wT_vec(3)- wT_vec(2); #w23_vec(i) = wT_vec(4)- wT_vec(3); #w34_vec(i) = wT_vec(5)- wT_vec(4); H = make_H(0.2, 190, 4000.0) print H L = liouvillian(H, c_op_list) print L tr_mat = tensor([qeye(n) for n in L.dims[0][0]]) print tr_mat tr_vec = transpose(mat2vec(tr_mat.full())) print tr_vec N = prod(L.dims[0][0]) print N A = L.full() a_sup = spre(a).full() b_sup = spre(p).full() D, U = eig(A) print "D", D I = identity(N * N) w = 3.0 MMR1 = pinv(-1.0j * w * I + A) print A * MMR1 * inv(A) print U * MMR1 * inv(U) #raise Exception #A.expm() #MMR1 = pinv(1.0j * w * I + diag(D))
N_gamma = 1 / (exp(wd / T) - 1 ) # % Thermal population of the transmon phonon bath around wd. print N_gamma N = 5 # number of basis states to consider phi_arr = linspace(0.2, 0.35, 51) Ej_arr = linspace(10078, 17960, 51) w0_arr = linspace(4211, 5622, 301) a = destroy(N) adag = a.dag() #Qobj(diag(range(0, 2*N, 2))) #dephasing operator, tdiag print spre( a) #tm_l = kron(Itot,tm); tm operator multiplying rho from the left. p = -1.0j * (adag - a) # "P" operator. print p print spre( p) #p_l = kron(Itot,p) % "P" operator multiplying rho from the left. print spost( p ) #p_r = kron(transpose(p),Itot) % "P" operator multiplying rho from the right. #It= qeye(N) c_op_list = []
def find_expect(phi=0.1, Omega_vec=3.0, wd=wd, use_pinv=True): Ej = (phi**2) / ( 8 * Ec ) #Ejmax*absolute(cos(pi*phi)) #; % Josephson energy as function of Phi. wTvec = -Ej + sqrt(8.0 * Ej * Ec) * (nvec + 0.5) + Ecvec #wdvec=nvec*sqrt(8.0*Ej*Ec) #wdvec=nvec*wd wT = wTvec - wdvec transmon_levels = Qobj(diag(wT[range(N)])) H = transmon_levels + Omega_vec #- 0.5j*(Omega_true*adag - conj(Omega_true)*a) L = liouvillian( H, c_op_list) #ends at same thing as L = H_comm + Lindblad_tm ; rho_ss = steadystate(L) #same as rho_ss_c but that's in column vector form tr_mat = tensor([qeye(n) for n in L.dims[0][0]]) #N = prod(L.dims[0][0]) A = L.full() #D, U= L.eigenstates() #print D.shape, D #print diag(D) b = spre(p).full() - spost(p).full() a2 = spre(a).full() tr_vec = transpose(mat2vec(tr_mat.full())) rho = transpose(mat2vec(rho_ss.full())) I = identity(N * N) P = kron(transpose(rho), tr_vec) Q = I - P #wp=4.9 #w=-(wp-wd) spectrum = zeros(len(wlist2), dtype=complex) for idx, w in enumerate(wlist2): if use_pinv: MMR = pinv(-1.0j * w * I + A) #eig(MMR)[0] is equiv to Dint else: MMR = dot(Q, solve(-1.0j * w * I + A, Q)) #print diag(1.0/(1j*(wp-wd)*ones(N**2)+D)) #Dint = diag(1./(1i*(wp-wd)*diag(eye(dim^2)) + diag(D))) #print 1.0/(1j*(wp-wd)*ones(N**2)+D) #Dint = diag(1./(1i*(wp-wd)*diag(eye(dim^2)) + diag(D))) #U2=squeeze([u.full() for u in U]).transpose() #Dint=eig(MMR)[0] #print "MMR", eig(MMR)[1] #print "Umult", U2*Dint*inv(U2) s = dot(tr_vec, dot(a2, dot(MMR, dot(b, transpose(rho))))) #spectrum[idx] = -2 * real(s[0, 0]) spectrum[idx] = 1j * s[0][0] #matches Chi_temp result #(1/theta_steps) return spectrum #final_state = steadystate(H, c_op_list) #print H.shape #print dir(H) #U,D = eig(H.full()) #print D #Uinv = Qobj(inv(D)) #U=Qobj(D) # Doing the chi integral (gives the susceptibility) #Dint = 1.0/(1.0j*(wp-wd)) #Qobj(1.0/(1.0j*(wp-wd)*diag(qeye(N**2))))# + diag(D)))) #Hint = H.expm() #U*H*Uinv #Chi_temp(i,j) += (1.0/theta_steps)*1j*trace(reshape(tm_l*Lint*(p_l - p_r)*rho_ss_c,dim,dim)) #exp1=correlation_2op_1t(H, None, wlist2, c_op_list, a, p, solver="es") #exp2=correlation_2op_1t(H, None, wlist2, c_op_list, p, a, solver="es", reverse=True) #exp1=correlation_2op_1t(H, None, wlist2, c_op_list, a, p_l-p_r, solver="es") #exp1=correlation_ss(H, wlist2, c_op_list, a, p) #exp2=correlation_ss(H, wlist2, c_op_list, p, a, reverse=True) exp1 = spectrum(H, wlist2, c_op_list, a, p, solver="pi", use_pinv=False) exp2 = spectrum(H, wlist2, c_op_list, p, a, solver="pi", use_pinv=False) return exp1 - exp2 return expect(a, final_state) #tm_l
Ej=1.0 wd=4.8 Omega=3.0 #print qeye(N) #print help(qeye) a=destroy(N) #equivalent to tm adag=a.dag() #print a #print a.dag() #equivalent to tp print Qobj(diag(range(0, 2*N, 2))) #dephasing operator, tdiag #print help(diag) print spre(a) #tm_l = kron(Itot,tm); p = -1.0j*(adag - a) # "P" operator. print p print spre(p) #p_l = kron(Itot,p) % "P" operator multiplying rho from the left. print spost(p) #p_r = kron(transpose(p),Itot) % "P" operator multiplying rho from the right. N_gamma=0.0 gamma=0.01 rate = gamma c_op_list=[sqrt(rate) * a,] # decay operators
import qutip as qt import cascade gamma = 1.0 # coupling strength to reservoir phi = 1.*np.pi # phase shift in fb loop eps = 2.0*np.pi*gamma # eps/2 = Rabi frequency delta = 0. # detuning # time delay tau = np.pi/(eps) print 'tau =',tau dim_S = 2 Id = qt.spre(qt.qeye(dim_S))*qt.spost(qt.qeye(dim_S)) # Hamiltonian and jump operators H_S = delta*qt.sigmap()*qt.sigmam() + eps*(qt.sigmam()+qt.sigmap()) L1 = sp.sqrt(gamma)*qt.sigmam() L2 = sp.exp(1j*phi)*L1 # initial state rho0 = qt.ket2dm(qt.basis(2,0)) # times to evaluate rho(t) tlist=np.arange(0.0001,2*tau,0.01) def run(rho0=rho0,tau=tau,tlist=tlist): # run feedback simulation opts = qt.Options()
def outfieldpropagator(self, blist, tlist, tau, c1=None, c2=None, notrace=False): r""" Compute propagator for computing output field expectation values <O_n(tn)...O_2(t2)O_1(t1)> for times t1,t2,... and O_i = I, b_out, b_out^\dagger, b_loop, b_loop^\dagger Parameters ---------- blist : array_like List of integers specifying the field operators: 0: I (nothing) 1: b_out 2: b_out^\dagger 3: b_loop 4: b_loop^\dagger tlist : array_like list of corresponding times t1,..,tn at which to evaluate the field operators tau : float time-delay c1 : :class:`qutip.Qobj` system collapse operator that couples to the in-loop field in question (only needs to be specified if self.L1 has more than one element) c2 : :class:`qutip.Qobj` system collapse operator that couples to the output field in question (only needs to be specified if self.L2 has more than one element) notrace : bool {False} If this optional is set to True, a propagator is returned for a cascade of k systems, where :math:`(k-1) tau < t < k tau`. If set to False (default), a generalized partial trace is performed and a propagator for a single system is returned. Returns ------- : :class:`qutip.Qobj` time-propagator for computing field correlation function """ if c1 is None and len(self.L1) == 1: c1 = self.L1[0] else: raise ValueError('Argument c1 has to be specified when more than' + 'one collapse operator couples to the feedback' + 'loop.') if c2 is None and len(self.L2) == 1: c2 = self.L2[0] else: raise ValueError('Argument c1 has to be specified when more than' + 'one collapse operator couples to the feedback' + 'loop.') klist = [] slist = [] for t in tlist: klist.append(int(t/tau)+1) slist.append(t-(klist[-1]-1)*tau) kmax = max(klist) zipped = sorted(zip(slist, klist, blist)) slist = [s for (s, k, b) in zipped] klist = [k for (s, k, b) in zipped] blist = [b for (s, k, b) in zipped] G1, E0 = _generator(kmax, self.H_S, self.L1, self.L2, self.S_matrix, self.c_ops_markov) sprev = 0. E = E0 for i, s in enumerate(slist): E = _integrate(G1, E, sprev, s, integrator=self.integrator, parallel=self.parallel, opt=self.options) if klist[i] == 1: l1 = 0.*qt.Qobj() else: l1 = _localop(c1, klist[i]-1, kmax) l2 = _localop(c2, klist[i], kmax) if blist[i] == 0: superop = self.Id elif blist[i] == 1: superop = qt.spre(l1+l2) elif blist[i] == 2: superop = qt.spost(l1.dag()+l2.dag()) elif blist[i] == 3: superop = qt.spre(l1) elif blist[i] == 4: superop = qt.spost(l1.dag()) else: raise ValueError('Allowed values in blist are 0, 1, 2, 3 ' + 'and 4.') superop.dims = E.dims E = superop*E sprev = s E = _integrate(G1, E, slist[-1], tau, integrator=self.integrator, parallel=self.parallel, opt=self.options) E.dims = E0.dims if not notrace: E = _genptrace(E, kmax) return E
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
def _to_qutip(self, full_space): return qutip.spre(ZeroOperator.to_qutip(full_space))
def find_expect(phi=0.1, Omega_vec=3.0, wd=wd, use_pinv=True): Ej = (phi**2)/(8*Ec) #Ejmax*absolute(cos(pi*phi)) #; % Josephson energy as function of Phi. wTvec = -Ej + sqrt(8.0*Ej*Ec)*(nvec+0.5)+Ecvec #wdvec=nvec*sqrt(8.0*Ej*Ec) #wdvec=nvec*wd wT = wTvec-wdvec transmon_levels = Qobj(diag(wT[range(N)])) H=transmon_levels +Omega_vec #- 0.5j*(Omega_true*adag - conj(Omega_true)*a) L=liouvillian(H, c_op_list) #ends at same thing as L = H_comm + Lindblad_tm ; rho_ss = steadystate(L) #same as rho_ss_c but that's in column vector form tr_mat = tensor([qeye(n) for n in L.dims[0][0]]) #N = prod(L.dims[0][0]) A = L.full() #D, U= L.eigenstates() #print D.shape, D #print diag(D) b = spre(p).full()-spost(p).full() a2 = spre(a).full() tr_vec = transpose(mat2vec(tr_mat.full())) rho = transpose(mat2vec(rho_ss.full())) I = identity(N * N) P = kron(transpose(rho), tr_vec) Q = I - P #wp=4.9 #w=-(wp-wd) spectrum = zeros(len(wlist2), dtype=complex) for idx, w in enumerate(wlist2): if use_pinv: MMR = pinv(-1.0j * w * I + A) #eig(MMR)[0] is equiv to Dint else: MMR = dot(Q, solve(-1.0j * w * I + A, Q)) #print diag(1.0/(1j*(wp-wd)*ones(N**2)+D)) #Dint = diag(1./(1i*(wp-wd)*diag(eye(dim^2)) + diag(D))) #print 1.0/(1j*(wp-wd)*ones(N**2)+D) #Dint = diag(1./(1i*(wp-wd)*diag(eye(dim^2)) + diag(D))) #U2=squeeze([u.full() for u in U]).transpose() #Dint=eig(MMR)[0] #print "MMR", eig(MMR)[1] #print "Umult", U2*Dint*inv(U2) s = dot(tr_vec, dot(a2, dot(MMR, dot(b, transpose(rho))))) #spectrum[idx] = -2 * real(s[0, 0]) spectrum[idx]=1j*s[0][0] #matches Chi_temp result #(1/theta_steps) return spectrum #final_state = steadystate(H, c_op_list) #print H.shape #print dir(H) #U,D = eig(H.full()) #print D #Uinv = Qobj(inv(D)) #U=Qobj(D) # Doing the chi integral (gives the susceptibility) #Dint = 1.0/(1.0j*(wp-wd)) #Qobj(1.0/(1.0j*(wp-wd)*diag(qeye(N**2))))# + diag(D)))) #Hint = H.expm() #U*H*Uinv #Chi_temp(i,j) += (1.0/theta_steps)*1j*trace(reshape(tm_l*Lint*(p_l - p_r)*rho_ss_c,dim,dim)) #exp1=correlation_2op_1t(H, None, wlist2, c_op_list, a, p, solver="es") #exp2=correlation_2op_1t(H, None, wlist2, c_op_list, p, a, solver="es", reverse=True) #exp1=correlation_2op_1t(H, None, wlist2, c_op_list, a, p_l-p_r, solver="es") #exp1=correlation_ss(H, wlist2, c_op_list, a, p) #exp2=correlation_ss(H, wlist2, c_op_list, p, a, reverse=True) exp1=spectrum(H, wlist2, c_op_list, a, p, solver="pi", use_pinv=False) exp2=spectrum(H, wlist2, c_op_list, p, a, solver="pi", use_pinv=False) return exp1-exp2 return expect( a, final_state) #tm_l
def outfieldpropagator(self, blist, tlist, tau, c1=None, c2=None, notrace=False): """ Compute propagator for computing output field expectation values <O_n(tn)...O_2(t2)O_1(t1)> for times t1,t2,... and O_i = I, b_out, b_out^\dagger, b_loop, b_loop^\dagger Parameters ---------- blist : array_like List of integers specifying the field operators: 0: I (nothing) 1: b_out 2: b_out^\dagger 3: b_loop 4: b_loop^\dagger tlist : array_like list of corresponding times t1,..,tn at which to evaluate the field operators tau : float time-delay c1 : :class:`qutip.Qobj` system collapse operator that couples to the in-loop field in question (only needs to be specified if self.L1 has more than one element) c2 : :class:`qutip.Qobj` system collapse operator that couples to the output field in question (only needs to be specified if self.L2 has more than one element) notrace : bool {False} If this optional is set to True, a propagator is returned for a cascade of k systems, where :math:`(k-1) tau < t < k tau`. If set to False (default), a generalized partial trace is performed and a propagator for a single system is returned. Returns ------- : :class:`qutip.Qobj` time-propagator for computing field correlation function """ if c1 is None and len(self.L1) == 1: c1 = self.L1[0] else: raise ValueError('Argument c1 has to be specified when more than' + 'one collapse operator couples to the feedback' + 'loop.') if c2 is None and len(self.L2) == 1: c2 = self.L2[0] else: raise ValueError('Argument c1 has to be specified when more than' + 'one collapse operator couples to the feedback' + 'loop.') klist = [] slist = [] for t in tlist: klist.append(int(t/tau)+1) slist.append(t-(klist[-1]-1)*tau) kmax = max(klist) zipped = sorted(zip(slist, klist, blist)) slist = [s for (s, k, b) in zipped] klist = [k for (s, k, b) in zipped] blist = [b for (s, k, b) in zipped] G1, E0 = _generator(kmax, self.H_S, self.L1, self.L2, self.S_matrix, self.c_ops_markov) sprev = 0. E = E0 for i, s in enumerate(slist): E = _integrate(G1, E, sprev, s, integrator=self.integrator, parallel=self.parallel, opt=self.options) if klist[i] == 1: l1 = 0.*qt.Qobj() else: l1 = _localop(c1, klist[i]-1, kmax) l2 = _localop(c2, klist[i], kmax) if blist[i] == 0: superop = self.Id elif blist[i] == 1: superop = qt.spre(l1+l2) elif blist[i] == 2: superop = qt.spost(l1.dag()+l2.dag()) elif blist[i] == 3: superop = qt.spre(l1) elif blist[i] == 4: superop = qt.spost(l1.dag()) else: raise ValueError('Allowed values in blist are 0, 1, 2, 3 ' + 'and 4.') superop.dims = E.dims E = superop*E sprev = s E = _integrate(G1, E, slist[-1], tau, integrator=self.integrator, parallel=self.parallel, opt=self.options) E.dims = E0.dims if not notrace: E = _genptrace(E, kmax) return E
def lin_construct(O): Od = O.dag() L = 2. * spre(O) * spost(Od) - spre(Od * O) - spost(Od * O) return L