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
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()
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],
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)
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
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, \
# 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([[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))
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
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)
# 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'