def calculate_HEOM(reorg_energy):
    print reorg_energy
    system_hamiltonian = np.array([[100., 20.], [20., 0]])
    cutoff_freq = 53.
    temperature = 300.
    hs = HierarchySolver(system_hamiltonian, environment(reorg_energy, beta, K), beta, N=trunc_level)
    hs.init_system_dm = init_state
    HEOM_history, time = hs.calculate_time_evolution(time_step, duration)
    return HEOM_history
class DQDHEOMModelSparse():
    
    def __init__(self, Gamma_L, Gamma_R, bias, T_c, environment=[], beta=1., K=0, tc=True, trunc_level=5, \
                 dissipator_test=False):
        
        self.system_dimension = 3
        
        self.bias = bias
        self.T_c = T_c
        
        self.Gamma_L = Gamma_L
        self.Gamma_R = Gamma_R
        
        self.jump_operators = np.array([np.array([[0, 0, 0],
                                                  [1., 0, 0],
                                                  [0, 0, 0]]), np.array([[0, 0, 1.],
                                                                         [0, 0, 0],
                                                                         [0, 0, 0]])])
        self.jump_rates = np.array([self.Gamma_L, self.Gamma_R])
        
        self.beta = beta
        self.environment = environment
        
        self.filter = False
        
        self.K = K
        self.tc = tc
        self.heom_solver = HierarchySolver(self.system_hamiltonian(), self.environment, \
                                           self.beta, self.jump_operators, self.jump_rates, N=trunc_level,\
                                           num_matsubara_freqs=self.K, temperature_correction=self.tc, \
                                           dissipator_test=dissipator_test)
        self.truncation_level = trunc_level
        #self.heom_solver.truncation_level = self.truncation_level
        
        self.dv_pops = np.zeros(self.system_dimension**2 * self.heom_solver.number_density_matrices())
        self.dv_pops[:self.system_dimension**2] = np.array([1., 0, 0, 0, 1., 0, 0, 0, 1.])
        
    def system_hamiltonian(self):
        return np.array([[0, 0, 0],
                         [0, self.bias/2., self.T_c],
                         [0, self.T_c, -self.bias/2.]])

    def heom_matrix(self):
        self.heom_solver = HierarchySolver(self.system_hamiltonian(), self.environment, \
                                           self.beta, self.jump_operators, self.jump_rates, N=self.truncation_level, \
                                           num_matsubara_freqs=self.K, temperature_correction=self.tc)
        #self.heom_solver.truncation_level = self.truncation_level
        return sp.csr_matrix(self.heom_solver.construct_hierarchy_matrix_super_fast())

    def jump_matrix(self):
        if not self.filter:
            heom_dim = self.heom_solver.number_density_matrices() * self.heom_solver.system_dimension**2
        else:
            heom_dim = self.heom_solver.num_dms * self.heom_solver.system_dimension**2
        LJ = sp.lil_matrix((heom_dim, heom_dim), dtype='complex128')
        LJ[0,8] = self.Gamma_R
        return LJ
Example #3
0
def calculate_HEOM(reorg_energy):
    system_hamiltonian = np.array([[100., 20.], [20., 0]])
    cutoff_freq = 53.
    temperature = 300.
    init_state = np.array([[1., 0], [0, 0]])
    
    time_step = 0.00005
    duration = 5.

    hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, temperature)
    HEOM_history, time = hs.hierarchy_time_evolution(init_state, 18, time_step, duration)
    return HEOM_history
def calculate_HEOM(reorg_energy):
    print reorg_energy
    system_hamiltonian = np.array([[100., 20.], [20., 0]])
    cutoff_freq = 53.
    temperature = 300.
    hs = HierarchySolver(system_hamiltonian,
                         environment(reorg_energy, beta, K),
                         beta,
                         N=trunc_level)
    hs.init_system_dm = init_state
    HEOM_history, time = hs.calculate_time_evolution(time_step, duration)
    return HEOM_history
def HEOM_calculation(hamiltonian):
    reorg_energy = 100.
    cutoff_freq = 53.
    temperature = 300.
    init_state = np.array([[1., 0], [0, 0]])
    
    duration = 5.
    time_step = 0.00005
    
    hs = HierarchySolver(hamiltonian, reorg_energy, cutoff_freq, temperature)
    HEOM_history, time = hs.hierarchy_time_evolution(init_state, 18, time_step, duration)
    return HEOM_history
class SRLHEOMModel():
    
    def __init__(self):
        self.hamiltonian = np.array([[100.,8.],[8.,0]])
        self.jump_operators = np.array([np.array([[0, 0],[1., 0]]), np.array([[0, 1.],[0, 0]])])
        self.Gamma_L = 1.
        self.Gamma_R = 1.#e-4
        self.jump_rates = np.array([self.Gamma_L, self.Gamma_R])
        
        self.dt = 1.e4
        
        self.hs = HierarchySolver(self.hamiltonian, 35., 40., temperature=300., jump_operators=self.jump_operators, jump_rates=self.jump_rates)
        self.hs.truncation_level = 4
        self.hm = self.hs.construct_hierarchy_matrix_super_fast().tolil()
        #print self.hm.todense()
        
        self.init_ss_vector = spla.eigs(self.hm.tocsc(), k=1, sigma=0, which='LM', maxiter=1000)[1]

    def hm_chi(self, chi):
        new_hm = self.hm.copy()
#         sys_dim = self.hs.system_dimension
#         for i in range(self.hs.number_density_matrices()):
#             print  'i = ' + str(i*sys_dim**2)
#             print 'j = ' + str((i+1)*sys_dim**2 - 1)
#             new_hm[i*sys_dim**2,(i+1)*sys_dim**2 - 1] *= np.exp(chi)
        new_hm[0,3] *= np.exp(chi)
        return new_hm
    
    # define cumulant generating function
    def cumulant_generating_function(self, chi):
        W = self.hm_chi(chi).tocsc()
        ss = spla.eigs(W, k=1, sigma=0, which='LM', maxiter=1000, v0=self.init_ss_vector)[1]
        #ss = spla.svds(W, k=1, which='SM', maxiter=10000, v0=self.init_ss_vector)[0]
        ss /= np.trace(self.hs.extract_system_density_matrix(ss))
        dv_pops = np.zeros(4 * self.hs.number_density_matrices())
        dv_pops[:4] = np.array([1., 0, 0, 1.])
        #ss = utils.stationary_state_svd(W.todense(), dv_pops)
        return np.log(dv_pops.dot(spla.expm(W.multiply(self.dt)).dot(ss)))
    
    def zero_frequency_noise(self):
        CGF_dd = ndt.Derivative(self.cumulant_generating_function, n=2, method='central')
        return CGF_dd(0)[0] / self.dt

    def mean(self):
        ss = spla.eigs(self.hm_chi(0).tocsc(), k=1, sigma=0, which='LM', v0=self.init_ss_vector)[1]
        #ss = spla.svds(self.hm_chi(0).tocsc(), k=1, which='SM', maxiter=10000, v0=self.init_ss_vector)[0]
        ss = self.hs.extract_system_density_matrix(ss)
        ss /= np.trace(ss)
        return self.Gamma_R * ss[1,1]
    
    def fano_factor(self):
        return self.zero_frequency_noise() / self.mean()
def HEOM_calculation(hamiltonian):
    reorg_energy = 100.
    cutoff_freq = 53.
    temperature = 300.
    init_state = np.array([[1., 0], [0, 0]])

    duration = 5.
    time_step = 0.00005

    hs = HierarchySolver(hamiltonian, reorg_energy, cutoff_freq, temperature)
    HEOM_history, time = hs.hierarchy_time_evolution(init_state, 18, time_step,
                                                     duration)
    return HEOM_history
 def __init__(self, Gamma_L, Gamma_R, bias, T_c, environment=[], beta=1., K=0, tc=True, trunc_level=5, \
              dissipator_test=False):
     
     self.system_dimension = 3
     
     self.bias = bias
     self.T_c = T_c
     
     self.Gamma_L = Gamma_L
     self.Gamma_R = Gamma_R
     
     self.jump_operators = np.array([np.array([[0, 0, 0],
                                               [1., 0, 0],
                                               [0, 0, 0]]), np.array([[0, 0, 1.],
                                                                      [0, 0, 0],
                                                                      [0, 0, 0]])])
     self.jump_rates = np.array([self.Gamma_L, self.Gamma_R])
     
     self.beta = beta
     self.environment = environment
     
     self.filter = False
     
     self.K = K
     self.tc = tc
     self.heom_solver = HierarchySolver(self.system_hamiltonian(), self.environment, \
                                        self.beta, self.jump_operators, self.jump_rates, N=trunc_level,\
                                        num_matsubara_freqs=self.K, temperature_correction=self.tc, \
                                        dissipator_test=dissipator_test)
     self.truncation_level = trunc_level
     #self.heom_solver.truncation_level = self.truncation_level
     
     self.dv_pops = np.zeros(self.system_dimension**2 * self.heom_solver.number_density_matrices())
     self.dv_pops[:self.system_dimension**2] = np.array([1., 0, 0, 0, 1., 0, 0, 0, 1.])
Example #9
0
    def construct_heom_matrix(self):

        if not self.no_mode:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.v * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.c * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)), (), ()]
        else:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ), (), ()]


        jump_operators = [self.excitation_op(), self.deexcitation_op(), \
                          self.forward_secondary_CT_op(), self.backward_secondary_CT_op(), \
                          self.drain_lead_op(), self.source_lead_op()]

        jump_rates = np.array([self.gamma_ex, self.gamma_deex, self.forward_secondary_CT, self.backward_secondary_CT, \
                      self.Gamma_R, self.Gamma_L])

        self.solver = HierarchySolver(self.el_hamiltonian(), environment=env, beta=self.beta, \
                                 jump_operators=jump_operators, jump_rates=jump_rates, \
                                 N=self.N, num_matsubara_freqs=self.K, temperature_correction=True)

        return self.solver.construct_hierarchy_matrix_super_fast()
 def __init__(self):
     self.hamiltonian = np.array([[100.,8.],[8.,0]])
     self.jump_operators = np.array([np.array([[0, 0],[1., 0]]), np.array([[0, 1.],[0, 0]])])
     self.Gamma_L = 1.
     self.Gamma_R = 1.#e-4
     self.jump_rates = np.array([self.Gamma_L, self.Gamma_R])
     
     self.dt = 1.e4
     
     self.hs = HierarchySolver(self.hamiltonian, 35., 40., temperature=300., jump_operators=self.jump_operators, jump_rates=self.jump_rates)
     self.hs.truncation_level = 4
     self.hm = self.hs.construct_hierarchy_matrix_super_fast().tolil()
     #print self.hm.todense()
     
     self.init_ss_vector = spla.eigs(self.hm.tocsc(), k=1, sigma=0, which='LM', maxiter=1000)[1]
Example #11
0
class PhotocellModel(object):
    def __init__(self,
                 delta_E,
                 J,
                 drude_reorg_energy,
                 drude_cutoff,
                 mode_freq,
                 mode_S,
                 mode_damping,
                 CT_scaling,
                 temperature=300.,
                 N=6,
                 K=0,
                 v=1.,
                 no_mode=False):
        '''
            Parameters...
            delta_E: unshifted electronic energy splitting in site basis
            J: electronic coupling 
            drude_reorg_energy: reorg energy due to Drude bath
            drude_cutoff: relaxation parameter of the Drude bath
            mode_freq: frequency of the mode
            mode_S: Huang-Rhys factor of the mode
            mode_damping: damping constant for the mode
            CT_scaling: the scaling parameter for the CT state reorg energy
            temperature
            N: number of tiers to use with HEOM
            K: number of Matsubara terms to use in correlation function expansion with HEOM
            v: the scaling parameter for the excited state reorg energy
            no_mode: whether to include the mode in the spectral density or not
        '''

        self.el_dim = 5  # the dimension of the electronic system

        self.delta_E = delta_E  # 100.
        self.J = J  # 5.

        #evals,evecs = np.linalg.eig(H)

        self.T = temperature  # 300. # temperature in Kelvin
        self.beta = 1. / (utils.KELVIN_TO_WAVENUMS * self.T
                          )  # the inverse temperature in wavenums

        self.drude_reorg_energy = drude_reorg_energy  # 35.
        self.drude_cutoff = drude_cutoff  # 40.

        self.no_mode = no_mode
        self.mode_freq = mode_freq  # 342.
        self.mode_S = mode_S  # 0.0438
        self.mode_damping = mode_damping  # 10.
        self.mode_reorg_energy = self.mode_freq * self.mode_S

        self.total_reorg_energy = (
            self.drude_reorg_energy + self.mode_reorg_energy
        ) if not self.no_mode else self.drude_reorg_energy

        self.v = v  # scaling of site 1 reorg energy (in case we want to vary it too)
        self.c = CT_scaling  # scaling of CT state reorg energy

        self.N = N  # truncation level
        self.K = K  # num Matsubara terms
        '''
        Where did I take the following parameters from?
        '''
        self.n_ex = 6000  # number of photons in the 'hot' bath
        self.gamma = 1.e-2  # bare transition rate between ground and excited states
        self.gamma_ex = self.gamma * self.n_ex  # rate from ground to excited state
        self.gamma_deex = self.gamma * (self.n_ex + 1.
                                        )  # rate from excited to ground state

        self.secondary_CT_energy_gap = 300.
        self.bare_secondary_CT = 1.  #0.0025 # rate from CT1 to CT2
        self.n_c = utils.planck_distribution(self.secondary_CT_energy_gap,
                                             self.T)
        self.forward_secondary_CT = (self.n_c + 1) * self.bare_secondary_CT
        self.backward_secondary_CT = self.n_c * self.bare_secondary_CT

        self.Gamma_L = 1.  # 0.025 # the rate from left lead to populate ground state
        self.Gamma_R = 1.  # rate from CT2 state to right lead

        # set up environment depending on no_mode
        if not self.no_mode:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.v * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.c * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)), (), ()]
        else:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ), (), ()]

        # I think this dummy solver is set up so we can get info about the size of hierarchy
        # etc using methods from HierarchySolver before actually creating the hierarchy matrix
        self.dummy_solver = HierarchySolver(self.el_hamiltonian(),
                                            env,
                                            self.beta,
                                            N=self.N,
                                            num_matsubara_freqs=self.K)

    def el_hamiltonian(self):
        '''
        The electronic Hamiltonian. We can ignore the energies of ground, CT2 and
        empty states as there is no coherent evolution between them. We take into
        account the relative energies through the incoherent rates instead. 
        '''
        H = np.zeros((self.el_dim, self.el_dim))
        H[1:3, 1:3] = np.array([[self.delta_E / 2., self.J],
                                [self.J, -self.delta_E / 2.]]) + np.diag([
                                    self.v * self.total_reorg_energy,
                                    self.c * self.total_reorg_energy
                                ])
        return H

    def excitation_op(self):
        '''
        Operator to take the system from ground state to site 1 (excited state)
        transformed to the electronic eigenstate basis.
        '''
        op = np.zeros((self.el_dim, self.el_dim))
        op[1, 0] = 1.  # eigenstate basis

        evals, evecs = np.linalg.eig(self.el_hamiltonian()[1:3, 1:3])
        transform = np.eye(self.el_dim, dtype='complex128')
        transform[1:3, 1:3] = evecs

        return np.dot(transform.T, np.dot(op, transform))

    def deexcitation_op(self):
        '''
        Operator to take the system from site 1 (excited state) to ground state
        transformed to the electronic eigenstate basis.
        '''
        op = np.zeros((self.el_dim, self.el_dim))
        op[0, 1] = 1.  # eigenstate basis

        evals, evecs = np.linalg.eig(self.el_hamiltonian()[1:3, 1:3])
        transform = np.eye(self.el_dim, dtype='complex128')
        transform[1:3, 1:3] = evecs

        return np.dot(transform.T, np.dot(op, transform))

    def forward_secondary_CT_op(self):
        op = np.zeros((self.el_dim, self.el_dim))
        op[3, 2] = 1.
        return op

    def backward_secondary_CT_op(self):
        op = np.zeros((self.el_dim, self.el_dim))
        op[2, 3] = 1.
        return op

    def drain_lead_op(self):
        op = np.zeros((self.el_dim, self.el_dim))
        op[4, 3] = 1.
        return op

    def source_lead_op(self):
        op = np.zeros((self.el_dim, self.el_dim))
        op[0, 4] = 1.
        return op

    def construct_heom_matrix(self):

        if not self.no_mode:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.v * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.c * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)), (), ()]
        else:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ), (), ()]


        jump_operators = [self.excitation_op(), self.deexcitation_op(), \
                          self.forward_secondary_CT_op(), self.backward_secondary_CT_op(), \
                          self.drain_lead_op(), self.source_lead_op()]

        jump_rates = np.array([self.gamma_ex, self.gamma_deex, self.forward_secondary_CT, self.backward_secondary_CT, \
                      self.Gamma_R, self.Gamma_L])

        self.solver = HierarchySolver(self.el_hamiltonian(), environment=env, beta=self.beta, \
                                 jump_operators=jump_operators, jump_rates=jump_rates, \
                                 N=self.N, num_matsubara_freqs=self.K, temperature_correction=True)

        return self.solver.construct_hierarchy_matrix_super_fast()

    def jump_matrix(self):
        dim = self.dummy_solver.M_dimension()
        jop = sp.csr_matrix((dim, dim))
        jop[:self.el_dim**2, :self.el_dim**2] = self.Gamma_R * np.kron(
            self.drain_lead_op(), self.drain_lead_op())
        return jop

    def dv_pops(self):
        dv_pops = np.zeros(self.dummy_solver.system_dimension**2 *
                           self.dummy_solver.number_density_matrices())
        dv_pops[:self.dummy_solver.system_dimension**2] = np.eye(
            self.dummy_solver.system_dimension).flatten()
        return dv_pops

    def update_Gamma_R(self, Gamma_R):
        self.Gamma_R = Gamma_R
        self.solver.jump_rates[-2] = Gamma_R
                              [1., 0, 0],
                              [0, 0, 0]]), np.array([[0, 0, 1.],
                                                     [0, 0, 0],
                                                     [0, 0, 0]])])
jump_rates = np.array([0.1, 0.0025])

K = 4
environment = []
if mode_params: # assuming that there is a single identical mode on each site 
    environment = [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K), UBOscillator(mode_params[0][0], mode_params[0][1], mode_params[0][2], beta, K=K)), \
                   (OBOscillator(reorg_energy, cutoff_freq, beta, K=K), UBOscillator(mode_params[0][0], mode_params[0][1], mode_params[0][2], beta, K=K))]
else:
    environment = [(),
                   (OBOscillator(reorg_energy, cutoff_freq, beta, K=K),),
                   (OBOscillator(reorg_energy, cutoff_freq, beta, K=K),)]
hs = HierarchySolver(system_hamiltonian, environment, beta, jump_ops, jump_rates, num_matsubara_freqs=K, temperature_correction=True)
hs.truncation_level = 7

hm = hs.construct_hierarchy_matrix_super_fast()
print 'hierarchy matrix shape: ' + str(hm.shape)
print hs.dm_per_tier()

np.savez('DQD_heom_matrix_N7_K4.npz', hm=hm)

import scipy.sparse.linalg as spla
np.set_printoptions(precision=6, linewidth=150, suppress=True)
v0 = np.zeros(hm.shape[0])
v0[0] = 1./3
v0[4] = 1./3
v0[8] = 1./3
evals,evec = spla.eigs(hm.tocsc(), k=1, sigma=0, which='LM', v0=v0)#, ncv=100)
beta = 1. / (utils.KELVIN_TO_WAVENUMS * temperature)
init_state = np.array([[1., 0], [0, 0]])

trunc_level = 30
K = 0

#hs = HierarchySolver(system_hamiltonian, 1., cutoff_freq, temperature)


def environment(reorg_energy, beta, K):
    return [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K),), \
            (OBOscillator(reorg_energy, cutoff_freq, beta, K=K),)]


hs = HierarchySolver(system_hamiltonian,
                     environment(1., beta, K),
                     beta,
                     N=trunc_level)


# error function for least squares fit
def residuals(p, y, pops1, pops2):
    k12, k21 = p
    return y - (-k12 * pops1 + k21 * pops2)


def fit_func(t, k01, k10):
    time_propagator = np.zeros((2, 2))
    time_propagator[0, 0] = -k01
    time_propagator[0, 1] = k10
    time_propagator[1, 1] = -k10
    time_propagator[1, 0] = k01
Example #14
0
CT2_empty_rate = 25.e-3 * utils.EV_TO_WAVENUMS
empty_ground_rate = 25.e-3 * utils.EV_TO_WAVENUMS
# jump_rates = np.array([excitation_rate, deexcitation_rate, chl_CT1_rate, CT1_chl_rate, \
#                        phe_CT1_rate, CT1_phe_rate, CT1_CT2_rate, CT2_CT1_rate, CT2_empty_rate, empty_ground_rate])

jump_rates = np.array([excitation_rate, deexcitation_rate])
for i in range(6):
    jump_rates = np.append(jump_rates, [forward_exciton_CT_rates[i], backward_exciton_CT_rates[i]])
#jump_rates[2:] *= 0.1
jump_rates = np.append(jump_rates, [CT1_CT2_rate, CT2_CT1_rate, CT2_empty_rate, empty_ground_rate])

single_mode_params = []#[(342., 342.*0.4, 100.)]

#print jump_rates
#jump_rates = np.zeros(18)
hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, temperature, jump_operators=jump_operators, jump_rates=jump_rates, underdamped_mode_params=single_mode_params)
hs.truncation_level = 6
init_state = np.zeros((10, 10))
init_state[0,0] = 1.
init_state = np.dot(site_exciton_transform, np.dot(init_state, site_exciton_transform.T))
hs.init_system_dm = init_state
dm_history, time = hs.calculate_time_evolution(0.01, 5.)
# transform back to exciton basis
exciton_dm_history = np.zeros((dm_history.shape[0], dm_history.shape[1], dm_history.shape[2]))
for i,dm in enumerate(dm_history):
    exciton_dm_history[i] = np.dot(site_exciton_transform.T, np.dot(dm, site_exciton_transform))
np.savez('../../data/PSIIRC_HEOM_incoherent_rates_slow_jump_rates_data.npz', exciton_dm_history=exciton_dm_history, \
                            time=time, reorg_energy=reorg_energy, cutoff_freq=cutoff_freq, temperature=temperature, \
                            site_exciton_transform=site_exciton_transform, jump_rates=jump_rates)

# np.savez('../../data/PSIIRC_HEOM_incoherent_rates_mode_data.npz', exciton_dm_history=exciton_dm_history, \
'''Ed's params'''
electronic_coupling = 92.
system_hamiltonian = np.array([[1042., electronic_coupling], [electronic_coupling, 0]])
reorg_energy = 110.
cutoff_freq = 100. #53.08
temperature = 300. # Kelvin
beta = 1. / (utils.KELVIN_TO_WAVENUMS * temperature)

fig,ax1 = plt.subplots()

mode_params = []
    
K = 0
environment = [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K),),
               (OBOscillator(reorg_energy, cutoff_freq, beta, K=K),)]
hs = HierarchySolver(system_hamiltonian, environment, beta, num_matsubara_freqs=K, temperature_correction=True)
hs.truncation_level = 12

print 'Calculating time evolution...'
start = tutils.getTime()

init_state = np.array([[0,0],[0,1.]])
init_state = np.dot(hs.system_evectors.T, np.dot(init_state, hs.system_evectors))
hs.init_system_dm = init_state
dm_history, time = hs.calculate_time_evolution(time_step, duration)
exciton_dm_history = hs.transform_to_exciton_basis(dm_history)

end = tutils.getTime()
print 'Calculation took ' + str(tutils.duration(end, start))

# convert time in inverse wavenums to picoseconds
Example #16
0
# site-CT couplings
couplings = np.array([[0,150.,-42.,-55.,-6.,17.,0,0],
                     [0,0,-56.,-36.,20.,-2.,0,0],
                     [0,0,0,7.,46.,-4.,70.,0],
                     [0,0,0,0,-5.,37.,0,0],
                     [0,0,0,0,0,-3.,70.,0],
                     [0,0,0,0,0,0,0,0],
                     [0,0,0,0,0,0,0,40.],
                     [0,0,0,0,0,0,0,0]])
system_hamiltonian = np.diag(average_site_CT_energies) + couplings + couplings.T
system_hamiltonian = system_hamiltonian[:6,:6]
reorg_energy = 35.
cutoff_freq = 300.
temperature = 300.
mode_params = []#[(342., 342.*0.4, 100.)]
hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, temperature, underdamped_mode_params=mode_params)

init_state = np.zeros(system_hamiltonian.shape)
init_state[0,0] = 1. # exciton basis
init_state = np.dot(hs.system_evectors, np.dot(init_state, hs.system_evectors.T)) # transform to site basis for HEOM calculation

#dm_history, time = hs.converged_time_evolution(init_state, 6, 6, time_step, duration)
hs.init_system_dm = init_state
hs.truncation_level = 8
dm_history, time = hs.calculate_time_evolution(time_step, duration)
exciton_dm_history = hs.transform_to_exciton_basis(dm_history)

end_time = tutils.getTime()
print 'Calculation took ' + str(tutils.duration(end_time, start_time))

# print 'Calculating steady state...'
system_hamiltonian = np.array([[100., electronic_coupling],
                               [electronic_coupling, 0]])
reorg_energy = 100.
cutoff_freq = 53.08
temperature = 300.  # Kelvin
beta = 1. / (utils.KELVIN_TO_WAVENUMS * temperature)
mode_params = []  #[(200., 0.25, 10.)]
init_state = np.array([[1., 0], [0, 0]])

K_values = range(4)

dm_histories = np.zeros((len(K_values) + 1, duration / time_step + 1, 2, 2),
                        dtype='complex128')

for i in K_values:
    hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, beta, underdamped_mode_params=mode_params, \
                        num_matsubara_freqs=i, temperature_correction=True)

    print 'Calculating for K = ' + str(i)
    start = tutils.getTime()

    hs.init_system_dm = init_state
    hs.truncation_level = 9
    dm_history, time = hs.calculate_time_evolution(time_step, duration)
    dm_histories[i] = dm_history

    end = tutils.getTime()
    print 'Calculation took ' + str(tutils.duration(end, start))
'''Now calculate for K = 0 but include temperature correction'''
hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, beta, underdamped_mode_params=mode_params, \
                        num_matsubara_freqs=0, temperature_correction=True)
 def heom_matrix(self):
     self.heom_solver = HierarchySolver(self.system_hamiltonian(), self.environment, \
                                        self.beta, self.jump_operators, self.jump_rates, N=self.truncation_level, \
                                        num_matsubara_freqs=self.K, temperature_correction=self.tc)
     #self.heom_solver.truncation_level = self.truncation_level
     return sp.csr_matrix(self.heom_solver.construct_hierarchy_matrix_super_fast())
#     print 'Started calculating HEOM dynamics for reorg_energy = ' + str(reorg_energy) + 'cm-1 at ' + str(tutils.getTime())
#     hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, temperature)
#     init_state = np.zeros(system_hamiltonian.shape)
#     init_state[0,0] = 1. # exciton basis
#     init_state = np.dot(hs.system_evectors, np.dot(init_state, hs.system_evectors.T)) # transform to site basis for HEOM calculation
#     dm_history, time = hs.converged_time_evolution(init_state, truncation_level, truncation_level, time_step, duration)
#     exciton_dm_history = hs.transform_to_exciton_basis(dm_history)
#     np.savez('../../data/PSIIRC_HEOM_dynamics_reorg_energy_'+str(int(reorg_energy))+'_wavenums.npz', exciton_dm_history=exciton_dm_history, \
#                                             time=time, init_state=init_state, reorg_energy=reorg_energy, cutoff_freq=cutoff_freq, temperature=temperature, \
#                                             system_hamiltonian=system_hamiltonian)
    
# try different cutoff freqs
reorg_energy = 35.
cutoff_freq_values = [40., 70., 100.]
temperature = 300.

for cutoff_freq in cutoff_freq_values:
    print 'Started calculating HEOM dynamics for cutoff_freq = ' + str(cutoff_freq) + 'cm-1 at ' + str(tutils.getTime())
    hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, temperature)
    init_state = np.zeros(system_hamiltonian.shape)
    init_state[0,0] = 1. # exciton basis
    init_state = np.dot(hs.system_evectors, np.dot(init_state, hs.system_evectors.T)) # transform to site basis for HEOM calculation
    dm_history, time = hs.converged_time_evolution(init_state, truncation_level, truncation_level, time_step, duration)
    exciton_dm_history = hs.transform_to_exciton_basis(dm_history)
    np.savez('../../data/PSIIRC_HEOM_dynamics_cutoff_freq_'+str(int(cutoff_freq))+'_wavenums.npz', exciton_dm_history=exciton_dm_history, \
                                            time=time, init_state=init_state, reorg_energy=reorg_energy, cutoff_freq=cutoff_freq, temperature=temperature, \
                                            system_hamiltonian=system_hamiltonian)

print 'Calculations finished'

#     init_state = np.dot(hs.system_evectors, np.dot(init_state, hs.system_evectors.T)) # transform to site basis for HEOM calculation
#     dm_history, time = hs.converged_time_evolution(init_state, truncation_level, truncation_level, time_step, duration)
#     exciton_dm_history = hs.transform_to_exciton_basis(dm_history)
#     np.savez('../../data/PSIIRC_HEOM_dynamics_reorg_energy_'+str(int(reorg_energy))+'_wavenums.npz', exciton_dm_history=exciton_dm_history, \
#                                             time=time, init_state=init_state, reorg_energy=reorg_energy, cutoff_freq=cutoff_freq, temperature=temperature, \
#                                             system_hamiltonian=system_hamiltonian)

# try different cutoff freqs
reorg_energy = 35.
cutoff_freq_values = [40., 70., 100.]
temperature = 300.

for cutoff_freq in cutoff_freq_values:
    print 'Started calculating HEOM dynamics for cutoff_freq = ' + str(
        cutoff_freq) + 'cm-1 at ' + str(tutils.getTime())
    hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq,
                         temperature)
    init_state = np.zeros(system_hamiltonian.shape)
    init_state[0, 0] = 1.  # exciton basis
    init_state = np.dot(hs.system_evectors,
                        np.dot(init_state, hs.system_evectors.T)
                        )  # transform to site basis for HEOM calculation
    dm_history, time = hs.converged_time_evolution(init_state,
                                                   truncation_level,
                                                   truncation_level, time_step,
                                                   duration)
    exciton_dm_history = hs.transform_to_exciton_basis(dm_history)
    np.savez('../../data/PSIIRC_HEOM_dynamics_cutoff_freq_'+str(int(cutoff_freq))+'_wavenums.npz', exciton_dm_history=exciton_dm_history, \
                                            time=time, init_state=init_state, reorg_energy=reorg_energy, cutoff_freq=cutoff_freq, temperature=temperature, \
                                            system_hamiltonian=system_hamiltonian)

print 'Calculations finished'
Example #21
0
jump_operators[3] = np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0],
                              [0, 0, 1., 0]])
# CT2 backward
jump_operators[4] = np.array([[0, 0, 0, 0], [0, 0, 0, 1.], [0, 0, 0, 0],
                              [0, 0, 0, 0]])
# CT2 forward
jump_operators[5] = np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0],
                              [0, 1., 0, 0]])
# irreversible transfer to ground state
jump_operators[6] = np.array([[0, 0, 0, 1.], [0, 0, 0, 0], [0, 0, 0, 0],
                              [0, 0, 0, 0]])
jump_rates = np.array([1., 1.1, 2., 2.1, 0.8, 0.82, 0.2])

hs = HierarchySolver(system_hamiltonian,
                     reorg_energy,
                     cutoff_freq,
                     temperature,
                     jump_operators=jump_operators,
                     jump_rates=jump_rates)

# start_time = tutils.getTime()
# print 'Calculating steady state...'
# steady_state = hs.calculate_steady_state(6,6)
# print steady_state
#
# end_time = tutils.getTime()
# print 'Calculation took ' + str(tutils.duration(end_time, start_time))

start_time = tutils.getTime()
print 'Calculating time evolution...'
dm_history, time = hs.hierarchy_time_evolution(np.array([[0, 0, 0, 0],
                                                         [0, 1., 0, 0],
                              [0, 0, 0, 1.],
                              [0, 0, 0, 0],
                              [0, 0, 0, 0]])
# CT2 forward
jump_operators[5] = np.array([[0, 0, 0, 0],
                              [0, 0, 0, 0],
                              [0, 0, 0, 0],
                              [0, 1., 0, 0]])
# irreversible transfer to ground state
jump_operators[6] = np.array([[0, 0, 0, 1.],
                              [0, 0, 0, 0],
                              [0, 0, 0, 0],
                              [0, 0, 0, 0]])
jump_rates = np.array([1., 1.1, 2., 2.1, 0.8, 0.82, 0.2])

hs = HierarchySolver(system_hamiltonian, reorg_energy, cutoff_freq, temperature, jump_operators=jump_operators, jump_rates=jump_rates)

# start_time = tutils.getTime()
# print 'Calculating steady state...'
# steady_state = hs.calculate_steady_state(6,6)
# print steady_state
#  
# end_time = tutils.getTime()
# print 'Calculation took ' + str(tutils.duration(end_time, start_time))

start_time = tutils.getTime()
print 'Calculating time evolution...'
dm_history,time = hs.hierarchy_time_evolution(np.array([[0, 0, 0, 0],[0, 1., 0, 0],[0, 0, 0, 0],[0, 0, 0, 0]]), 8, 8, 0.005, 15., sparse=True)
end_time = tutils.getTime()
print 'Calculation took ' + str(tutils.duration(end_time, start_time))
print time.shape
Example #23
0
    np.array([[0, 0, 1.], [0, 0, 0], [0, 0, 0]])
])
jump_rates = np.array([0.1, 0.0025])

K = 4
environment = []
if mode_params:  # assuming that there is a single identical mode on each site
    environment = [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K), UBOscillator(mode_params[0][0], mode_params[0][1], mode_params[0][2], beta, K=K)), \
                   (OBOscillator(reorg_energy, cutoff_freq, beta, K=K), UBOscillator(mode_params[0][0], mode_params[0][1], mode_params[0][2], beta, K=K))]
else:
    environment = [(), (OBOscillator(reorg_energy, cutoff_freq, beta, K=K), ),
                   (OBOscillator(reorg_energy, cutoff_freq, beta, K=K), )]
hs = HierarchySolver(system_hamiltonian,
                     environment,
                     beta,
                     jump_ops,
                     jump_rates,
                     num_matsubara_freqs=K,
                     temperature_correction=True)
hs.truncation_level = 7

hm = hs.construct_hierarchy_matrix_super_fast()
print 'hierarchy matrix shape: ' + str(hm.shape)
print hs.dm_per_tier()

np.savez('DQD_heom_matrix_N7_K4.npz', hm=hm)

import scipy.sparse.linalg as spla
np.set_printoptions(precision=6, linewidth=150, suppress=True)
v0 = np.zeros(hm.shape[0])
v0[0] = 1. / 3
Example #24
0
    def __init__(self,
                 delta_E,
                 J,
                 drude_reorg_energy,
                 drude_cutoff,
                 mode_freq,
                 mode_S,
                 mode_damping,
                 CT_scaling,
                 temperature=300.,
                 N=6,
                 K=0,
                 v=1.,
                 no_mode=False):
        '''
            Parameters...
            delta_E: unshifted electronic energy splitting in site basis
            J: electronic coupling 
            drude_reorg_energy: reorg energy due to Drude bath
            drude_cutoff: relaxation parameter of the Drude bath
            mode_freq: frequency of the mode
            mode_S: Huang-Rhys factor of the mode
            mode_damping: damping constant for the mode
            CT_scaling: the scaling parameter for the CT state reorg energy
            temperature
            N: number of tiers to use with HEOM
            K: number of Matsubara terms to use in correlation function expansion with HEOM
            v: the scaling parameter for the excited state reorg energy
            no_mode: whether to include the mode in the spectral density or not
        '''

        self.el_dim = 5  # the dimension of the electronic system

        self.delta_E = delta_E  # 100.
        self.J = J  # 5.

        #evals,evecs = np.linalg.eig(H)

        self.T = temperature  # 300. # temperature in Kelvin
        self.beta = 1. / (utils.KELVIN_TO_WAVENUMS * self.T
                          )  # the inverse temperature in wavenums

        self.drude_reorg_energy = drude_reorg_energy  # 35.
        self.drude_cutoff = drude_cutoff  # 40.

        self.no_mode = no_mode
        self.mode_freq = mode_freq  # 342.
        self.mode_S = mode_S  # 0.0438
        self.mode_damping = mode_damping  # 10.
        self.mode_reorg_energy = self.mode_freq * self.mode_S

        self.total_reorg_energy = (
            self.drude_reorg_energy + self.mode_reorg_energy
        ) if not self.no_mode else self.drude_reorg_energy

        self.v = v  # scaling of site 1 reorg energy (in case we want to vary it too)
        self.c = CT_scaling  # scaling of CT state reorg energy

        self.N = N  # truncation level
        self.K = K  # num Matsubara terms
        '''
        Where did I take the following parameters from?
        '''
        self.n_ex = 6000  # number of photons in the 'hot' bath
        self.gamma = 1.e-2  # bare transition rate between ground and excited states
        self.gamma_ex = self.gamma * self.n_ex  # rate from ground to excited state
        self.gamma_deex = self.gamma * (self.n_ex + 1.
                                        )  # rate from excited to ground state

        self.secondary_CT_energy_gap = 300.
        self.bare_secondary_CT = 1.  #0.0025 # rate from CT1 to CT2
        self.n_c = utils.planck_distribution(self.secondary_CT_energy_gap,
                                             self.T)
        self.forward_secondary_CT = (self.n_c + 1) * self.bare_secondary_CT
        self.backward_secondary_CT = self.n_c * self.bare_secondary_CT

        self.Gamma_L = 1.  # 0.025 # the rate from left lead to populate ground state
        self.Gamma_R = 1.  # rate from CT2 state to right lead

        # set up environment depending on no_mode
        if not self.no_mode:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.v * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K),
                    UBOscillator(self.mode_freq,
                                 self.c * self.mode_S,
                                 self.mode_damping,
                                 beta=self.beta,
                                 K=self.K)), (), ()]
        else:
            env = [(),
                   (OBOscillator(self.v * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ),
                   (OBOscillator(self.c * self.drude_reorg_energy,
                                 self.drude_cutoff,
                                 beta=self.beta,
                                 K=self.K), ), (), ()]

        # I think this dummy solver is set up so we can get info about the size of hierarchy
        # etc using methods from HierarchySolver before actually creating the hierarchy matrix
        self.dummy_solver = HierarchySolver(self.el_hamiltonian(),
                                            env,
                                            self.beta,
                                            N=self.N,
                                            num_matsubara_freqs=self.K)
Example #25
0
# system_hamiltonian = np.array([[1042., electronic_coupling], [electronic_coupling, 0]])
# reorg_energy = 110.
# cutoff_freq = 100. #53.08
# temperature = 300. # Kelvin
# beta = 1. / (utils.KELVIN_TO_WAVENUMS * temperature)
# mode_params = [] #[(1111., 0.0578, 50.)]

K = 0
environment = []
if mode_params: # assuming that there is a single identical mode on each site 
    environment = [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K), UBOscillator(mode_params[0][0], mode_params[0][1], mode_params[0][2], beta, K=K)), \
                   (OBOscillator(reorg_energy, cutoff_freq, beta, K=K), UBOscillator(mode_params[0][0], mode_params[0][1], mode_params[0][2], beta, K=K))]
else:
    environment = [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K),),
                   (OBOscillator(reorg_energy, cutoff_freq, beta, K=K),)]
hs = HierarchySolver(system_hamiltonian, environment, beta, num_matsubara_freqs=K, temperature_correction=False)
#hs = HierarchySolverNonRenorm(system_hamiltonian, environment, beta, num_matsubara_freqs=K, temperature_correction=False)
hs.truncation_level = 30

print 'Calculating time evolution...'
start = tutils.getTime()

init_state = np.array([[1.,0],[0,0]])
#init_state = np.dot(hs.system_evectors.T, np.dot(init_state, hs.system_evectors))
hs.init_system_dm = init_state
dm_history, time = hs.calculate_time_evolution(time_step, duration)
#exciton_dm_history = hs.transform_to_exciton_basis(dm_history)

end = tutils.getTime()
print 'Calculation took ' + str(tutils.duration(end, start))
                               [electronic_coupling, 0]])
reorg_energy = 110.
cutoff_freq = 100.  #53.08
temperature = 300.  # Kelvin
beta = 1. / (utils.KELVIN_TO_WAVENUMS * temperature)

fig, ax1 = plt.subplots()

mode_params = []

K = 0
environment = [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K), ),
               (OBOscillator(reorg_energy, cutoff_freq, beta, K=K), )]
hs = HierarchySolver(system_hamiltonian,
                     environment,
                     beta,
                     num_matsubara_freqs=K,
                     temperature_correction=True)
hs.truncation_level = 12

print 'Calculating time evolution...'
start = tutils.getTime()

init_state = np.array([[0, 0], [0, 1.]])
init_state = np.dot(hs.system_evectors.T, np.dot(init_state,
                                                 hs.system_evectors))
hs.init_system_dm = init_state
dm_history, time = hs.calculate_time_evolution(time_step, duration)
exciton_dm_history = hs.transform_to_exciton_basis(dm_history)

end = tutils.getTime()
mode_params = []  # [(200., 0.25, 10.)]

"""Ed's PE545 params"""
# electronic_coupling = 92.
# system_hamiltonian = np.array([[1042., electronic_coupling], [electronic_coupling, 0]])
# reorg_energy = 100.
# cutoff_freq = 140. #53.08
# temperature = 300. # Kelvin
# beta = 1. / (utils.KELVIN_TO_WAVENUMS * temperature)
# mode_params = [] #[(1111., 0.0578, 10.)]

hs = HierarchySolver(
    system_hamiltonian,
    reorg_energy,
    cutoff_freq,
    beta,
    underdamped_mode_params=mode_params,
    num_matsubara_freqs=1,
    temperature_correction=True,
    sites_to_couple=np.array([1, 1]),
)

hs.truncation_level = 11
print hs.system_dimension ** 2 * hs.number_density_matrices()

print "Calculating time evolution..."
start = tutils.getTime()

init_state = np.array([[1.0, 0], [0, 0]])
# init_state = np.dot(hs.system_evectors.T, np.dot(init_state, hs.system_evectors))
# print init_state
system_hamiltonian = np.array([[100., 20.], [20., 0]])
cutoff_freq = 53.08
temperature = 300.
beta = 1. / (utils.KELVIN_TO_WAVENUMS * temperature)
init_state = np.array([[1., 0], [0, 0]])

trunc_level = 30
K = 0

#hs = HierarchySolver(system_hamiltonian, 1., cutoff_freq, temperature)

def environment(reorg_energy, beta, K):
    return [(OBOscillator(reorg_energy, cutoff_freq, beta, K=K),), \
            (OBOscillator(reorg_energy, cutoff_freq, beta, K=K),)]

hs = HierarchySolver(system_hamiltonian, environment(1., beta, K), beta, N=trunc_level)

# error function for least squares fit
def residuals(p, y, pops1, pops2):
        k12, k21 = p
        return y - (-k12*pops1 + k21*pops2)
    
def fit_func(t, k01, k10):
    time_propagator = np.zeros((2,2))
    time_propagator[0,0] = -k01
    time_propagator[0,1] = k10
    time_propagator[1,1] = -k10
    time_propagator[1,0] = k01
    time_step = t[1] - t[0]
    dynamics = te.liouvillian_time_evolution(np.array([1,0]), time_propagator, t[-1], time_step, wave_nums=False)
    return dynamics[:,0]