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_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_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 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 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 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 testOperatorSpostAppl(self): """ Superoperator: apply operator and superoperator from right (spost) """ N = 3 rho = rand_dm(N) U = rand_unitary(N) rho1 = rho * U rho2_vec = spost(U) * operator_to_vector(rho) rho2 = vector_to_operator(rho2_vec) assert_((rho1 - rho2).norm() < 1e-8)
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 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 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 _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 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 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_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 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 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_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
# -*- coding: utf-8 -*- """ Created on Wed Aug 1 07:15:05 2018 @author: huang For qubits, a particularly useful way to visualize superoperators is to plot them in the Pauli basis, such that Sμ,ν=⟨⟨σμ|S[σν]⟩⟩. Because the Pauli basis is Hermitian, Sμ,ν is a real number for all Hermitian-preserving superoperators S, allowing us to plot the elements of S as a Hinton diagram. In such diagrams, positive elements are indicated by white squares, and negative elements by black squares. The size of each element is indicated by the size of the corresponding square. For instance, let S[ρ]=σxρσ†xS[ρ]=σxρσx†. We can quickly see this by noting that the Y and Z elements of the Hinton diagram for S are negative: """ import qutip as qt qt.settings.colorblind_safe = True import matplotlib.pyplot as plt plt.rcParams['savefig.transparent'] = True X = qt.sigmax() S = qt.spre(X) * qt.spost(X.dag()) print(S) qt.hinton(S)
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
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))
# Excitation (at T>0). #Lindblad_deph = 0.5*gamma_phi*(kron(conj(tdiag),tdiag) -... # 0.5*kron(Itot,ctranspose(tdiag)*tdiag) -... # 0.5*kron(transpose(tdiag)*conj(tdiag),Itot)); # Dephasing. p = -1.0j*(adag - a) # "P" operator. #p_l = kron(It,p) # % "P" operator multiplying rho from the left. #p_r = kron(transpose(p),It) # "P" operator multiplying rho from the right. #print p_l.shape p_l=spre(p)#.full() p_r=spost(p)#.full() print p_l.shape #raise Exception p_l_m_p_r=p_l-p_r #tm_l=spre(a).full() nvec=arange(N) Ecvec=-Ec*(6.0*nvec**2+6.0*nvec+3.0)/12.0 Omega_op=[0.5*Omega*(a*exp(-1.0j*theta)+adag*exp(1.0j*theta)) for theta in [0.0]] tr_mat = tensor(qeye(N)) #N = np.prod(L.dims[0][0]) tr_vec = transpose(mat2vec(tr_mat.full()))
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.spost(self.operands[0].to_qutip(full_space))
def test_spost_td(self): "Superoperator: spre, time-dependent" assert_(spost(self.t1)(.5) == spost(self.t1(.5)))
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 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
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
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Wed Aug 1 07:06:18 2018 @author: huang """ import qutip as qt import numpy as np X = qt.sigmax() S = qt.spre(X) * qt.spost(X.dag()) # Represents conjugation by X. print(X) print(S) S2 = qt.to_super(X) print(S2) # type of S is super # Check if S is completely positive print(S.iscp)
def lin_construct(O): Od = O.dag() L = 2. * spre(O) * spost(Od) - spre(Od * O) - spost(Od * O) return L
#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 nvec=arange(N) wdvec=nvec*wd Ecvec=-Ec*(6.0*nvec**2+6.0*nvec+3.0)/12.0 wTvec = -Ej + sqrt(8.0*Ej*Ec)*(nvec+0.5)+Ecvec #wdvec=nvec*sqrt(8.0*Ej*Ec) #wdvec=nvec*wd
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) c_op_list.append(sqrt(rate) * a) # decay operators rate = gamma * N_gamma c_op_list.append(sqrt(rate) * adag) # excitation operators # Excitation (at T>0).
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 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 commutator_term2(O1, O2): # [rho*O1, O2] return spost(O1*O2)-sprepost(O2, O1)