Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
 def pack(self, rho, q, p):
     yt = np.concatenate((utils.to_liouville(rho), 
                          q.flatten(), p.flatten())) 
     return yt
Esempio n. 5
0
    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)
Esempio n. 6
0
 def pack(self, rho, q, p):
     yt = np.concatenate(
         (utils.to_liouville(rho), q.flatten(), p.flatten()))
     return yt
Esempio n. 7
0
    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)
Esempio n. 8
0
    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