def initialize_from_rdm(self, rho): rho = rho.copy() if self.is_secular: if self.is_verbose: print "\n--- Using the secular approximation" ident = np.identity(self.ham.nsite) self.Omega = -1j*np.einsum('ij,ik,jl->ijkl', self.ham.omega_diff, ident, ident) self.Omega = utils.to_liouville(self.Omega) self.R, self.K = None, None if self.method == 'Redfield': self.diffeq_type = 'TCL' self.make_redfield_tensor(np.inf) self.R = self._redfield_wrapper elif self.method == 'TCL2': self.diffeq_type = 'TCL' self.make_redfield_tensor(0.0) self.R = self._tcl_wrapper self.tensor_is_changing = True elif self.method == 'TC2': self.diffeq_type = 'TC' self.K = self._tc_wrapper self.make_redfield_tensor(0.0) self.tensor_is_changing = True return rho
def setup(self): if self.is_secular: if self.is_verbose: print "\n--- Using the secular approximation" ident = np.identity(self.ham.nsite) self.Omega = -1j*np.einsum('ij,ik,jl->ijkl', self.ham.omega_diff, ident, ident) self.Omega = utils.to_liouville(self.Omega) self.R, self.K = None, None if self.method == 'Redfield': self.diffeq_type = 'TCL' self.make_redfield_tensor(np.inf) self.R = self._redfield_wrapper elif self.method == 'TCL2': self.diffeq_type = 'TCL' self.make_redfield_tensor(0.0) self.R = self._tcl_wrapper self.tensor_is_changing = True elif self.method == 'TC2': self.diffeq_type = 'TC' self.K = self._tc_wrapper self.make_redfield_tensor(0.0) self.tensor_is_changing = True else: # Should never get here due to assertion above. pass
def propagate_full(self, rho_0, t_init, t_final, dt, markov_tol=1e-3, markov_time=np.inf, is_verbose=False): self.markov_tol = markov_tol self.markov_time = markov_time times = np.arange(t_init, t_final, dt) rho_eig = self.ham.site2eig(rho_0) integrator = Integrator(self.diffeq_type, dt, Omega=self.Omega, R=self.R, K=self.K) if self.method == 'TCL2': if not hasattr(self, 'redfield_tensor_n'): self.precompute_redfield_tensor(t_init, t_final, dt) elif len(self.redfield_tensor_n) < int((t_final - t_init) / dt): self.precompute_redfield_tensor(t_init, t_final, dt) if self.method == 'TC2': self.precompute_redfield_tensor(t_init, t_final, dt) #self.precompute_redfield_tensor_finegrid(t_init, t_final, dt, # integrator) integrator.set_initial_value(utils.to_liouville(rho_eig), t_init) rhos_site = [] for time in times: # Retrieve data from integrator rho_eig = utils.from_liouville(integrator.y) # Collect results rho_site = self.ham.eig2site(rho_eig) rhos_site.append(rho_site) # Propagate one timestep integrator.integrate() if is_verbose: print("\n--- Finished performing RDM dynamics") return times, rhos_site
def pack(self, rho, q, p): yt = np.concatenate((utils.to_liouville(rho), q.flatten(), p.flatten())) return yt
def make_redfield_tensor(self, t): """Make and store the Redfield-like tensor, only at time t. Parameters ---------- t : float The time at which the Redfield-like tensor is to be calculated. """ ns = self.ham.nsite gamma_plus = np.zeros((ns,ns,ns,ns), dtype=np.complex_) gamma_minus = np.zeros((ns,ns,ns,ns), dtype=np.complex_) for a in range(self.ham.nbath): if self.method in ['TC2', 'TCL2']: bath_corr_t = self.ham.sd[a].bath_corr(t) Ga = self.ham.site2eig( self.ham.sysbath[a] ) theta_plus_a = np.zeros((ns,ns), dtype=np.complex_) for i in range(ns): for j in range(ns): omega_ij = self.ham.omega_diff[i,j] if self.method in ['TC2', 'TCL2']: theta_plus_a[i,j] = np.exp(-1j*omega_ij*t)*bath_corr_t else: # Note, our C(w) has \int e^{+iwt}. theta_plus_a[i,j] = self.ham.sd[a].bath_corr_ft(-omega_ij,t) theta_minus_a = theta_plus_a.conj().transpose() gamma_plus += np.einsum('lj,ik,ik->ljik', Ga, Ga, theta_plus_a) gamma_minus += np.einsum('lj,ik,lj->ljik', Ga, Ga, theta_minus_a) gamma_plus /= const.hbar**2 gamma_minus /= const.hbar**2 ident = np.identity(ns) self.redfield_tensor = ( gamma_plus.transpose(2,1,3,0) + gamma_minus.transpose(2,1,3,0) - np.einsum('lj,irrk->ijkl', ident, gamma_plus) - np.einsum('ik,lrrj->ijkl', ident, gamma_minus) ) if self.method == 'TC2': for i in range(ns): for j in range(ns): for k in range(ns): for l in range(ns): omega_kl = self.ham.omega_diff[k,l] self.redfield_tensor[i,j,k,l] *= np.exp(-1j*omega_kl*t) if self.is_secular: for i in range(ns): for j in range(ns): for k in range(ns): for l in range(ns): if abs(self.ham.omega_diff[i,j] -self.ham.omega_diff[k,l]) > 1e-6: self.redfield_tensor[i,j,k,l] = 0.0 if ns == 2 and self.method == "Redfield": if self.is_verbose: print "\n--- The Redfield tensor" print self.redfield_tensor print "\n--- Checking detailed balance" for i in range(ns): for j in range(i+1,ns): print "R[%d,%d,%d,%d]/R[%d,%d,%d,%d] = %0.10lf =? %0.10lf"%( i,i,j,j,j,j,i,i, np.real( self.redfield_tensor[i,i,j,j] / self.redfield_tensor[j,j,i,i] ), np.exp(-(self.ham.evals[i]-self.ham.evals[j]) / const.kT) ) self.redfield_tensor = utils.to_liouville(self.redfield_tensor)
def pack(self, rho, q, p): yt = np.concatenate( (utils.to_liouville(rho), q.flatten(), p.flatten())) return yt
def propagate(self, rho_0, t_init, t_final, dt, markov_tol = 1e-3, markov_time = np.inf, is_verbose=True): """Propagate the RDM according to Redfield-like dynamics. Parameters ---------- rho_0 : np.array The initial RDM. t_init : float The initial time. t_final : float The final time. dt : float The timestep. markov_tol : float The relative tolerance at which to decide that the memory tensor has stopped changing (and henceforth Markovian). markov_time : float The hard-coded time to stop re-calculating the memory tensor. is_verbose : bool Flag to indicate verbose printing. Returns ------- times : list of floats The times at which the RDM has been calculated. rhos_site : list of np.arrays The RDM at each time in the site basis. rhos_eig : list of np.arrays The RDM at each time in the system eigen-basis. """ self.markov_tol = markov_tol self.markov_time = markov_time times = np.arange(t_init, t_final, dt) rho_site = rho_0.copy() rho_eig = self.ham.site2eig(rho_site) integrator = Integrator(self.diffeq_type, dt, Omega=self.Omega, R=self.R, K=self.K) if self.method in ['TCL2', 'TC2']: self.precompute_redfield_tensor(t_init, t_final, dt) #self.precompute_redfield_tensor_finegrid(t_init, t_final, dt, # integrator) integrator.set_initial_value(utils.to_liouville(rho_eig), t_init) rhos_site = [] rhos_eig = [] for time in times: # Retrieve data from integrator rho_eig = utils.from_liouville(integrator.y) # Collect results rho_site = self.ham.eig2site(rho_eig) rhos_site.append(rho_site) rhos_eig.append(rho_eig) # Propagate one timestep integrator.integrate() if is_verbose: print "\n--- Finished performing RDM dynamics" return times, rhos_site, rhos_eig