Beispiel #1
0
def generalised_forster_rate(hamiltonian, cluster1_dim, cluster2_dim, total_site_reorg_energies, site_cutoff_freqs, site_lbfs, time, temperature, high_energy_modes=None):
    sys_dim = cluster1_dim+cluster2_dim
    cluster1_hamiltonian = hamiltonian[:cluster1_dim, :cluster1_dim]# - np.diag(site_reorg_energies[:cluster1_dim])
    cluster2_hamiltonian = hamiltonian[cluster1_dim:, cluster1_dim:]# - np.diag(site_reorg_energies[cluster1_dim:])
    
    # diagonalise individual clusters
    cluster1_evals, cluster1_evecs = utils.sorted_eig(cluster1_hamiltonian)
    cluster2_evals, cluster2_evecs = utils.sorted_eig(cluster2_hamiltonian)
    
    # calculate inter-cluster exciton couplings
    couplings = hamiltonian[:cluster1_dim,cluster1_dim:]
    couplings_matrix = np.dot(cluster1_evecs.conj(), np.dot(couplings, cluster2_evecs.T))
    
    # construct partially diagonalised Hamiltonian
    exciton_hamiltonian = np.asarray(np.bmat([[np.diag(cluster1_evals), couplings_matrix], [couplings_matrix.conj().T, np.diag(cluster2_evals)]]))
    
    # calculate exciton reorg energies
    cluster1_exciton_reorg_energies = np.array([exciton_reorg_energy(cluster1_evecs[i], total_site_reorg_energies[:cluster1_dim]) for i in range(cluster1_dim)])
    cluster2_exciton_reorg_energies = np.array([exciton_reorg_energy(cluster2_evecs[i], total_site_reorg_energies[cluster1_dim:]) for i in range(cluster2_dim)])
    
    # calculate exciton line broadening functions
    cluster1_lbfs = np.array([exciton_lbf(cluster1_evecs[i], site_lbfs[:cluster1_dim]) for i in range(cluster1_dim)])
    cluster2_lbfs = np.array([exciton_lbf(cluster2_evecs[i], site_lbfs[cluster1_dim:]) for i in range(cluster2_dim)])
    
    # calculate lifetimes
    OBO_reorg_energies = total_site_reorg_energies - np.sum([s[0]*s[1] for s in high_energy_modes])
    cluster1_lifetimes = exciton_lifetimes(cluster1_hamiltonian, OBO_reorg_energies[:cluster1_dim], site_cutoff_freqs[:cluster1_dim], temperature, high_energy_modes=high_energy_modes)
    cluster2_lifetimes = exciton_lifetimes(cluster2_hamiltonian, OBO_reorg_energies[cluster1_dim:], site_cutoff_freqs[cluster1_dim:], temperature, high_energy_modes=high_energy_modes)
    
    bare_cluster1_evals = cluster1_evals - cluster1_exciton_reorg_energies
    bare_cluster2_evals = cluster2_evals - cluster2_exciton_reorg_energies
    
    # calculate individual Forster rates
    forster_rates = np.zeros((cluster1_dim, cluster2_dim))
    for i in range(cluster1_dim):
        for j in range(cluster2_dim):
            cluster1_state = np.zeros(sys_dim)
            cluster1_state[i] = 1.
            cluster2_state = np.zeros(sys_dim)
            cluster2_state[cluster1_dim+j] = 1.
            forster_rates[i,j] = forster_rate(bare_cluster1_evals[i], bare_cluster2_evals[j], cluster1_exciton_reorg_energies[i], \
                                                  cluster2_exciton_reorg_energies[j], cluster1_lbfs[i], cluster2_lbfs[j], cluster1_lifetimes[i], cluster2_lifetimes[j], \
                                                  cluster1_state, cluster2_state, exciton_hamiltonian, time)
    
    # calculate generalised Forster rate
    B800_thermal_state = utils.general_thermal_state(np.diag(cluster1_evals), temperature)
    result = np.dot(np.diag(B800_thermal_state), np.sum(forster_rates, axis=1))
    return result
Beispiel #2
0
def exciton_relaxation_rates(site_hamiltonian, E_reorg, cutoff_freq, spectral_density, temperature, high_energy_params=None):
    # calculate sorted exciton energies and eigenvectors
    evals, evecs = utils.sorted_eig(site_hamiltonian)
    rates = np.zeros((site_hamiltonian.shape[0], site_hamiltonian.shape[1]))
    
    for i in range(evals.size):
        for j in range(evals.size):
            E_i = evals[i]
            E_j = evals[j]
            w = E_j - E_i
            rates[i,j] = Gamma(w, cutoff_freq, spectral_density, E_reorg, temperature, evecs[i], evecs[j], high_energy_params) if w != 0 else 0
            
    return rates
Beispiel #3
0
def redfield_tensor_identical_drude(site_hamiltonian, reorg_energy, cutoff_freq, temperature):
    
    system_dimension = site_hamiltonian.shape[0]
    evalues,evectors = utils.sorted_eig(site_hamiltonian) # may need to get bare exciton energies here
    #evalues,evectors = np.linalg.eig(site_hamiltonian)
    
    # site_correlation function in frequency space for Drude-Lorentz spectral density
    def site_correlation_function(freq):
        if freq != 0 :
            return overdamped_BO_spectral_density(np.abs(freq), reorg_energy, cutoff_freq) * np.abs(utils.planck_distribution(freq, temperature))
        else:
            return 0
    
    # construct system part of system-bath coupling operators (single diagonal elements for this simple case)
    site_bath_coupling_matrices = np.zeros((system_dimension, system_dimension, system_dimension))
    for i in range(system_dimension):
        site_bath_coupling_matrices[i,i,i] = 1.
    
    # construct pairs of indices to iterate over when constructing the tensor
    from itertools import product
    indices = [(i,j) for i,j in product(range(system_dimension), range(system_dimension))]
        
    def Gamma(a, b, c, d):
        return np.real(np.sum([np.dot(evectors[a], np.dot(site_bath_coupling_matrices[n], evectors[b])) \
                                * np.dot(evectors[c], np.dot(site_bath_coupling_matrices[n], evectors[d])) for n in range(system_dimension)]) \
                                * site_correlation_function(evalues[c]-evalues[d]))
        
    def tensor_element(a, b, c, d):
        element = 0
        if a == c:
            for e in range(system_dimension):
                element += Gamma(b, e, e, d)
        if b == d:
            for e in range(system_dimension):
                element += Gamma(a, e, e ,c)
        element -= Gamma(c, a, b, d) + Gamma(d, b, a, c)
        return element
    
    result = np.zeros((system_dimension**2, system_dimension**2))
    for i,ab in enumerate(indices):
        for j,cd in enumerate(indices):
            result[i,j] = tensor_element(ab[0], ab[1], cd[0], cd[1])
    
    return result
Beispiel #4
0
def MRT_rate_PE545(site_hamiltonian, site_reorg_energy1, cutoff_freq1, site_reorg_energy2, cutoff_freq2, temperature, high_energy_mode_params, num_expansion_terms=0, time_interval=0.5):
    time = np.linspace(0,time_interval, int(time_interval*16000.))
    evals, evecs = utils.sorted_eig(site_hamiltonian)
    
    # correlation function coefficients for first over-damped oscillator and high energy modes
    coeffs = lbf_coeffs(site_reorg_energy1, cutoff_freq1, temperature, high_energy_mode_params, num_expansion_terms)
    # add correlation function coefficients for second over-damped oscillator
    coeffs = np.concatenate((coeffs, lbf_coeffs(site_reorg_energy2, cutoff_freq2, temperature, None, num_expansion_terms)))
    
    g_site = site_lbf_ed(time, coeffs)
    g_site_dot = site_lbf_dot_ed(time, coeffs)
    g_site_dot_dot = site_lbf_dot_dot_ed(time, coeffs)
    
    total_site_reorg_energy = site_reorg_energy1 + site_reorg_energy2
    if high_energy_mode_params is not None and high_energy_mode_params.any():
        total_site_reorg_energy += np.sum([mode[0]*mode[1] for mode in high_energy_mode_params])
    
    system_dim = site_hamiltonian.shape[0]
    rates = np.zeros((system_dim, system_dim))
    integrands = np.zeros((system_dim, system_dim, time.size), dtype='complex')
    
    # excitons are labelled from lowest in energy to highest
    for i in range(system_dim):
        for j in range(system_dim):
            if i != j:
                # get energy gap
                E_i = evals[i]
                E_j = evals[j]
                omega_ij = E_j - E_i #E_i - E_j if E_i > E_j else E_j - E_i
                # calculate overlaps (c_alpha and c_beta's)
                c_alphas = evecs[i]
                c_betas = evecs[j]
                # calculate integrand                
                integrand = np.array([np.exp(1.j*omega_ij*t - (np.sum(c_alphas**4) + np.sum(c_betas**4))*(1.j*total_site_reorg_energy*t + g_site[k]) + 
                                      2. * np.sum(c_alphas**2 * c_betas**2) * (g_site[k] + 1.j*total_site_reorg_energy*t)) *
                                      ((np.sum(c_alphas**2 * c_betas**2)*g_site_dot_dot[k]) - 
                                       ((np.sum(c_alphas * c_betas**3) - np.sum(c_alphas**3 * c_betas))*g_site_dot[k] + 2.j*np.sum(c_betas**3 * c_alphas)*total_site_reorg_energy)**2) for k,t in enumerate(time)])
                # perform integration
                rates[i,j] = 2.* integrate.simps(np.real(integrand), time)
                integrands[i,j] = integrand

    return rates#, integrands, time
Beispiel #5
0
def MRT_rates(site_hamiltonian, site_reorg_energies, cutoff_freq, temperature, high_energy_mode_params, num_expansion_terms=0, time_interval=0.5):
    time = np.linspace(0,time_interval, int(time_interval*2000.))
    evals, evecs = utils.sorted_eig(site_hamiltonian)
    system_dim = site_hamiltonian.shape[0]
    
    coeffs = np.array([lbf_coeffs(site_reorg_energies[i], cutoff_freq, temperature, high_energy_mode_params, num_expansion_terms) for i in range(system_dim)])
    g_site = np.array([site_lbf_ed(time, coeffs[i]) for i in range(system_dim)])
    g_site_dot = np.array([site_lbf_dot_ed(time, coeffs[i]) for i in range(system_dim)])
    g_site_dot_dot = np.array([site_lbf_dot_dot_ed(time, coeffs[i]) for i in range(system_dim)])
    
    if high_energy_mode_params is not None and high_energy_mode_params.any():
        site_reorg_energies += np.sum([mode[0]*mode[1] for mode in high_energy_mode_params])
    
    rates = np.zeros((system_dim, system_dim))
    integrands = np.zeros((system_dim, system_dim, time.size), dtype='complex')
    
    # excitons are labelled from lowest in energy to highest
    for i in range(system_dim):
        for j in range(system_dim):
            if i != j:
                # get energy gap
                E_i = evals[i]
                E_j = evals[j]
                omega_ij = E_i - E_j if E_i > E_j else E_j - E_i
                # calculate overlaps (c_alpha and c_beta's)
                c_alphas = evecs[i]
                c_betas = evecs[j]
                # calculate integrand
                integrand = np.array([np.exp(1.j*omega_ij*t - np.sum((c_alphas**4 + c_betas**4)*(1.j*site_reorg_energies*t + g_site.T[k])) + 
                                      2. * np.sum((c_alphas**2 * c_betas**2) * (g_site.T[k] + 1.j*site_reorg_energies*t))) *
                                      (np.sum(c_alphas**2 * c_betas**2 * g_site_dot_dot.T[k]) - 
                                       (np.sum((c_alphas * c_betas**3 - c_alphas**3 * c_betas)*g_site_dot.T[k]) + 2.j*np.sum(c_betas**3 * c_alphas * site_reorg_energies))**2) for k,t in enumerate(time)])
                # perform integration
                rates[i,j] = 2.* integrate.simps(np.real(integrand), time)
                integrands[i,j] = integrand

    return rates#, integrands, time
Beispiel #6
0
timestep = 0.01
time = np.arange(0, duration + timestep, timestep)
#init_dv = np.array([0.35, 0.12, 0.1, 0.1, 0.34, 0.61, 0.46, 0.5]) # init state in site basis

site_history_sum = np.zeros((average_site_hamiltonian.shape[0], time.size))

for n in range(num_realisations):
    print 'Calculating realisation ' + str(n + 1) + ' at time ' + str(
        datetime.now().time())

    # calculate Hamiltonian for this realisation ie. add site_shifts to average site energies and construct Hamiltonian
    site_hamiltonian = np.diag(
        average_site_energies + total_site_reorg_energy + site_shifts[n]
    ) + couplings + couplings.T  # now including reorganisation shift
    evals, evecs = utils.sorted_eig(
        site_hamiltonian
    )  # make sure to return excitons in basis going from lowest to highest energy with sorted_eig
    site_reorg_energies = np.zeros(site_hamiltonian.shape[0])
    site_reorg_energies.fill(total_site_reorg_energy)
    exciton_reorg_energies = np.zeros(site_hamiltonian.shape[0])
    for i in range(site_hamiltonian.shape[0]):
        exciton_reorg_energies[i] = os.exciton_reorg_energy(
            evecs[i], site_reorg_energies)  # calculate exciton reorg energies
    evals = evals - exciton_reorg_energies  # shift exciton energies down by exciton reorg energies

    # calculate modified Redfield rates
    rates = os.MRT_rate_PE545_quick(evals, evecs, g_site, g_site_dot,
                                    g_site_dot_dot, total_site_reorg_energy,
                                    temperature, integration_time)
    # construct Liouvillian for system
    liouvillian = np.zeros((rates.shape[0], rates.shape[1]))
font = {'size':16}
matplotlib.rc('font', **font)

np.set_printoptions(precision=3, linewidth=150, suppress=True)

data = np.load('../../data/PSIIRC_incoherent_HEOM_full_system_data.npz')

dm_history = data['dm_history']
system_hamiltonian = data['system_hamiltonian']
time = data['time']
jump_rates = data['jump_rates']
jump_operators = data['jump_operators']

print jump_rates
print jump_operators

evalues, evectors = utils.sorted_eig(system_hamiltonian[1:7,1:7])
site_exciton_transform = np.eye(10)
site_exciton_transform[1:7,1:7] = evectors.T

exciton_dm_history = np.array([np.dot(site_exciton_transform.T, np.dot(dm, site_exciton_transform)) for dm in dm_history])

labels = ['g', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'CT1', 'CT2', 'empty']

for i in range(system_hamiltonian.shape[0]):
    plt.plot(time, exciton_dm_history[:,i,i], linewidth=2, label=labels[i])
plt.legend().draggable()
plt.xlabel('time (ps)')
plt.ylabel('population')
plt.show()
    def __init__(self, hamiltonian, environment, beta, jump_operators=None, jump_rates=None, N=1, \
                 num_matsubara_freqs=0, temperature_correction=False, dissipator_test=False):
        '''
        Constructor
        '''
        self.system_hamiltonian = hamiltonian
        self.environment = environment
        self.beta = beta
        self.jump_operators = jump_operators
        self.jump_rates = jump_rates
        self.truncation_level = N
        self.num_matsubara_freqs = num_matsubara_freqs
        self.temperature_correction = temperature_correction
        '''
        dissipator_test is a flag to include the Lindblad dissipator in the top level of 
        the hierarchy only
        It is used in self.liouvillian() and self.construct_hierarchy_matrix_super_fast()
        '''
        self.dissipator_test = dissipator_test

        self.system_evalues, self.system_evectors = utils.sorted_eig(
            self.system_hamiltonian)
        self.system_evectors = self.system_evectors.T
        self.system_dimension = self.system_hamiltonian.shape[0]

        if self.num_matsubara_freqs > 0 or self.temperature_correction:
            self.matsubara_freqs = self.calculate_matsubara_freqs()
        self.Vx_operators, self.Vo_operators = [], []

        # if tuple or UBOscillator or OBOscillator put into list of tuples
        if type(self.environment
                ) is tuple:  # multiple oscillators, identical on each site
            self.environment = [self.environment] * self.system_dimension
        elif isinstance(
                environment,
            (OBOscillator,
             UBOscillator)):  # single oscillator identical on each site
            self.environment = [(self.environment, )] * self.system_dimension

        if type(self.environment) is list:  # environment defined per site
            self.diag_coeffs = []
            self.phix_coeffs = []
            self.thetax_coeffs = []
            self.thetao_coeffs = []
            self.tc_terms = []
            for i, site in enumerate(self.environment):
                if site:
                    site_coupling_operator = np.zeros(
                        (self.system_dimension, self.system_dimension))
                    site_coupling_operator[i, i] = 1.
                    site_Vx_operator = self.commutator_to_superoperator(
                        site_coupling_operator, type='-')
                    site_Vo_operator = self.commutator_to_superoperator(
                        site_coupling_operator, type='+')
                    tc_term = 0
                    for osc in site:
                        if isinstance(osc, OBOscillator):
                            self.diag_coeffs.append(osc.cutoff_freq)
                            self.phix_coeffs.append(self.phix_coeff_OBO(osc))
                            #site_coupling_operator = np.zeros(self.system_dimension)
                            self.thetax_coeffs.append(
                                self.thetax_coeff_OBO(osc))
                            self.thetao_coeffs.append(
                                self.thetao_coeff_OBO(osc))
                            self.Vx_operators.append(site_Vx_operator)
                            self.Vo_operators.append(site_Vo_operator)
                        elif isinstance(osc, UBOscillator):
                            self.diag_coeffs.append(0.5 * osc.damping)
                            self.diag_coeffs.append(-1.j * osc.zeta)
                            self.phix_coeffs.append(
                                self.phix_coeff_UBO(osc, pm=1))
                            self.phix_coeffs.append(
                                self.phix_coeff_UBO(osc, pm=-1))
                            self.thetax_coeffs.append(
                                self.thetax_coeff_UBO(osc, pm=1))
                            self.thetax_coeffs.append(
                                self.thetax_coeff_UBO(osc, pm=-1))
                            self.thetao_coeffs.append(
                                self.thetao_coeff_UBO(osc, pm=1))
                            self.thetao_coeffs.append(
                                self.thetao_coeff_UBO(osc, pm=-1))
                            self.Vx_operators.append(site_Vx_operator)
                            self.Vx_operators.append(site_Vx_operator)
                            self.Vo_operators.append(site_Vo_operator)
                            self.Vo_operators.append(site_Vo_operator)
                        tc_term += osc.temp_correction_sum() \
                                        - np.sum([osc.temp_correction_sum_kth_term(k) for k in range(1,self.num_matsubara_freqs+1)])
                    self.tc_terms.append(
                        tc_term * np.dot(site_Vx_operator, site_Vx_operator))
                    for k in range(1, self.num_matsubara_freqs + 1):
                        self.diag_coeffs.append(self.matsubara_freqs[k - 1])
                        self.phix_coeffs.append(self.phix_coeff_MF(site, k))
                        self.thetax_coeffs.append(self.thetax_coeff_MF(
                            site, k))
                        self.thetao_coeffs.append(0)
                        self.Vx_operators.append(site_Vx_operator)
                        self.Vo_operators.append(site_Vo_operator)
        else:
            raise ValueError("Environment defined in invalid format!")

        self.num_aux_dm_indices = len(self.diag_coeffs)
        self.diag_coeffs = np.array(self.diag_coeffs)
        self.phix_coeffs = np.array(self.phix_coeffs)
        self.thetax_coeffs = np.array(self.thetax_coeffs)
        self.thetao_coeffs = np.array(self.thetao_coeffs)
        self.Vx_operators = np.array(self.Vx_operators)
        self.Vo_operators = np.array(self.Vo_operators)
Beispiel #9
0
 def __init__(self, hamiltonian, drude_reorg_energy, drude_cutoff, beta, \
              jump_operators=None, jump_rates=None, underdamped_mode_params=[], \
              num_matsubara_freqs=0, temperature_correction=False, \
              sites_to_couple=[]):
     '''
     Constructor
     '''
     self.init_system_dm = None
     self.drude_reorg_energy = drude_reorg_energy
     self.drude_cutoff = drude_cutoff
     self.beta = beta
     self.system_hamiltonian = hamiltonian
     self.system_evalues, self.system_evectors = utils.sorted_eig(self.system_hamiltonian)
     self.system_evectors = self.system_evectors.T
     
     self.jump_operators = jump_operators
     self.jump_rates = jump_rates
     
     self.system_dimension = self.system_hamiltonian.shape[0]
     if np.any(sites_to_couple):
         if sites_to_couple.ndim != 1 or len(sites_to_couple) != self.system_hamiltonian.shape[0] or np.all(sites_to_couple == 0):
             raise ValueError("sites_to_couple should be a 1d array containing 1s and 0s indicating the index of sites" + \
                              " to couple to a bath described by hierarchical equations of motion.")
         self.sites_to_couple = sites_to_couple
         self.heom_sys_dim = np.count_nonzero(self.sites_to_couple)
     else:
         self.heom_sys_dim = self.system_dimension
         self.sites_to_couple = np.ones(self.system_dimension)
     
     # commutator operators for each site coupling to a bath
     self.Vx_operators, self.Vo_operators = self.construct_commutator_operators()
     
     # zeroth order freqs for identical Drude spectral density on each site are just cutoff freq
     self.drude_zeroth_order_freqs = np.zeros(self.heom_sys_dim, dtype='complex64')
     self.drude_zeroth_order_freqs.fill(self.drude_cutoff)
     
     # underdamped_mode_params should be a list of tuples
     # each tuple having frequency, Huang-Rhys factor and damping for each mode in that order
     self.underdamped_mode_params = underdamped_mode_params
     self.num_modes = len(self.underdamped_mode_params)
     if np.any(self.underdamped_mode_params):
         self.BO_zeroth_order_freqs = np.zeros((self.num_modes, self.heom_sys_dim))
         self.BO_zetas = np.zeros((self.num_modes, self.heom_sys_dim))
         for i,mode in enumerate(self.underdamped_mode_params):
             self.BO_zeroth_order_freqs[i].fill(mode[2])
             self.BO_zetas[i].fill(np.sqrt(mode[0]**2 - mode[2]**2/4.))
     
     self.num_matsubara_freqs = num_matsubara_freqs
     self.temperature_correction = temperature_correction
     if self.num_matsubara_freqs > 0 or self.temperature_correction:
         self.matsubara_freqs = self.calculate_matsubara_freqs()
     
     '''Currently assumes there will be one Drude spectral density,
     with optional number of modes. Need to change to allow arbitrary combination of 
     over and underdamped Brownian oscillators.'''
     self.num_aux_dm_indices = (1 + 2*self.num_modes + self.num_matsubara_freqs)*self.heom_sys_dim
     
     '''Also assumes that spectral density is same on each site.
     Change to have different spectral densities on each site.'''
     # calculate coefficients of operators coupling to lower tiers and fill in vectors
     self.phix_coeffs = np.zeros(self.num_aux_dm_indices, dtype='complex64')
     self.thetax_coeffs = np.zeros(self.num_aux_dm_indices, dtype='complex64')
     self.thetao_coeffs = np.zeros(self.num_aux_dm_indices, dtype='complex64')
     self.phix_coeffs[:self.heom_sys_dim].fill(self.drude_phix_coeffs(0))
     self.thetax_coeffs[:self.heom_sys_dim].fill(self.drude_thetax_coeff(0))
     self.thetao_coeffs[:self.heom_sys_dim].fill(self.drude_thetao_coeff(0))
     for i in range(self.num_modes):
         freq = self.underdamped_mode_params[i][0]
         reorg_energy = self.underdamped_mode_params[i][0]*self.underdamped_mode_params[i][1]
         damping = self.underdamped_mode_params[i][2]
         self.phix_coeffs[self.heom_sys_dim*(1+2*i):self.heom_sys_dim*(2+2*i)].fill(self.mode_phix_coeff(freq, reorg_energy, damping, 0, 1.))
         self.phix_coeffs[self.heom_sys_dim*(2+2*i):self.heom_sys_dim*(3+2*i)].fill(self.mode_phix_coeff(freq, reorg_energy, damping, 0, -1.))
         self.thetax_coeffs[self.heom_sys_dim*(1+2*i):self.heom_sys_dim*(2+2*i)].fill(self.mode_thetax_coeff(freq, reorg_energy, damping, 0, -1.))
         self.thetax_coeffs[self.heom_sys_dim*(2+2*i):self.heom_sys_dim*(3+2*i)].fill(self.mode_thetax_coeff(freq, reorg_energy, damping, 0, 1.))
         self.thetao_coeffs[self.heom_sys_dim*(1+2*i):self.heom_sys_dim*(2+2*i)].fill(self.mode_thetao_coeff(freq, reorg_energy, damping, 0, -1.))
         self.thetao_coeffs[self.heom_sys_dim*(2+2*i):self.heom_sys_dim*(3+2*i)].fill(self.mode_thetao_coeff(freq, reorg_energy, damping, 0, 1.))            
         
     mf_start_idx = (1 + 2*self.num_modes)*self.heom_sys_dim
     for k in range(1, self.num_matsubara_freqs+1):
         self.phix_coeffs[mf_start_idx+((k-1)*self.heom_sys_dim):mf_start_idx+(k*self.heom_sys_dim)].fill(self.mf_phix_coeff(self.underdamped_mode_params, k))
         self.thetax_coeffs[mf_start_idx+((k-1)*self.heom_sys_dim):mf_start_idx+(k*self.heom_sys_dim)].fill(self.mf_thetax_coeff(self.underdamped_mode_params, k))
                (np.sum(c_alphas ** 2 * c_betas ** 2) * g_site_dot_dot[k])
                - (
                    (np.sum(c_alphas * c_betas ** 3) - np.sum(c_alphas ** 3 * c_betas)) * g_site_dot[k]
                    + 2.0j * np.sum(c_betas ** 3 * c_alphas) * site_reorg_energy
                )
                ** 2
            )
            for k, t in enumerate(time)
        ]
    )


mixing_integral1 = []
mixing_integral2 = []
for i, delta_E in enumerate(delta_E_values):
    evals, evecs = utils.sorted_eig(hamiltonian(delta_E, 20.0))
    rates, abs_lineshapes, fl_lineshapes, mixing_function, time2 = os.modified_redfield_relaxation_rates(
        hamiltonian(delta_E, 20.0), np.array([reorg_energy, reorg_energy]), cutoff_freq, None, temperature, 0, 0.5
    )
    #     mixing_integral1.append(integrate.simps(mixing_function[0,1], time2[:-5]))
    #     mixing_integral2.append(integrate.simps(new_mixing_function(time, evecs[0], evecs[1], reorg_energy, site_lbf, site_lbf_dot, site_lbf_dot_dot)))
    mixing_integral1.append(mixing_function[0, 1])
    mixing_integral2.append(
        new_mixing_function(time, evecs[0], evecs[1], reorg_energy, site_lbf, site_lbf_dot, site_lbf_dot_dot)
    )

plt.plot(delta_E_values, mixing_integral1[0], label="1")
plt.plot(delta_E_values, mixing_integral2[0], label="2", linewidth=2, ls="--", color="red")
plt.legend()
# plt.plot(delta_E_values, [np.abs(mixing_integral1[i] - mixing_integral2[i]) for i in range(len(mixing_integral1))])
plt.show()
Beispiel #11
0
    def __init__(self, hamiltonian, environment, beta, jump_operators=None, jump_rates=None, N=1, \
                 num_matsubara_freqs=0, temperature_correction=False, dissipator_test=False):
        '''
        Constructor
        '''
        self.system_hamiltonian = hamiltonian
        self.environment = environment
        self.beta = beta
        self.jump_operators = jump_operators
        self.jump_rates = jump_rates
        self.truncation_level = N
        self.num_matsubara_freqs = num_matsubara_freqs
        self.temperature_correction = temperature_correction
        
        '''
        dissipator_test is a flag to include the Lindblad dissipator in the top level of 
        the hierarchy only
        It is used in self.liouvillian() and self.construct_hierarchy_matrix_super_fast()
        '''
        self.dissipator_test = dissipator_test
        
        self.system_evalues, self.system_evectors = utils.sorted_eig(self.system_hamiltonian)
        self.system_evectors = self.system_evectors.T
        self.system_dimension = self.system_hamiltonian.shape[0]
        
        if self.num_matsubara_freqs>0 or self.temperature_correction:
            self.matsubara_freqs = self.calculate_matsubara_freqs()
        self.Vx_operators, self.Vo_operators = [],[]
        
        # if tuple or UBOscillator or OBOscillator put into list of tuples
        if type(self.environment) is tuple: # multiple oscillators, identical on each site
            self.environment = [self.environment] * self.system_dimension
        elif isinstance(environment, (OBOscillator, UBOscillator)): # single oscillator identical on each site
            self.environment = [(self.environment,)] * self.system_dimension
        
        if type(self.environment) is list:# environment defined per site
            self.diag_coeffs = []
            self.phix_coeffs = []
            self.thetax_coeffs = []
            self.thetao_coeffs = []
            self.tc_terms = []
            for i,site in enumerate(self.environment):
                if site:
                    site_coupling_operator = np.zeros((self.system_dimension, self.system_dimension))
                    site_coupling_operator[i,i] = 1.
                    site_Vx_operator = self.commutator_to_superoperator(site_coupling_operator, type='-')
                    site_Vo_operator = self.commutator_to_superoperator(site_coupling_operator, type='+')
                    tc_term = 0
                    for osc in site:
                        if isinstance(osc, OBOscillator):
                            self.diag_coeffs.append(osc.cutoff_freq)
                            self.phix_coeffs.append(self.phix_coeff_OBO(osc))
                            #site_coupling_operator = np.zeros(self.system_dimension)
                            self.thetax_coeffs.append(self.thetax_coeff_OBO(osc))
                            self.thetao_coeffs.append(self.thetao_coeff_OBO(osc))
                            self.Vx_operators.append(site_Vx_operator)
                            self.Vo_operators.append(site_Vo_operator)
                        elif isinstance(osc, UBOscillator):
                            self.diag_coeffs.append(0.5*osc.damping)
                            self.diag_coeffs.append(-1.j*osc.zeta)
                            self.phix_coeffs.append(self.phix_coeff_UBO(osc, pm=1))
                            self.phix_coeffs.append(self.phix_coeff_UBO(osc, pm=-1))
                            self.thetax_coeffs.append(self.thetax_coeff_UBO(osc, pm=1))
                            self.thetax_coeffs.append(self.thetax_coeff_UBO(osc, pm=-1))
                            self.thetao_coeffs.append(self.thetao_coeff_UBO(osc, pm=1))
                            self.thetao_coeffs.append(self.thetao_coeff_UBO(osc, pm=-1))
                            self.Vx_operators.append(site_Vx_operator)
                            self.Vx_operators.append(site_Vx_operator)
                            self.Vo_operators.append(site_Vo_operator)
                            self.Vo_operators.append(site_Vo_operator)
                        tc_term += osc.temp_correction_sum() \
                                        - np.sum([osc.temp_correction_sum_kth_term(k) for k in range(1,self.num_matsubara_freqs+1)])
                    self.tc_terms.append(tc_term * np.dot(site_Vx_operator, site_Vx_operator))
                    for k in range(1,self.num_matsubara_freqs+1):
                        self.diag_coeffs.append(self.matsubara_freqs[k-1])
                        self.phix_coeffs.append(self.phix_coeff_MF(site, k))
                        self.thetax_coeffs.append(self.thetax_coeff_MF(site, k))
                        self.thetao_coeffs.append(0)
                        self.Vx_operators.append(site_Vx_operator)
                        self.Vo_operators.append(site_Vo_operator)
        else:
            raise ValueError("Environment defined in invalid format!")

        self.num_aux_dm_indices = len(self.diag_coeffs)
        self.diag_coeffs = np.array(self.diag_coeffs)
        self.phix_coeffs = np.array(self.phix_coeffs)
        self.thetax_coeffs = np.array(self.thetax_coeffs)
        self.thetao_coeffs = np.array(self.thetao_coeffs)
        self.Vx_operators = np.array(self.Vx_operators)
        self.Vo_operators = np.array(self.Vo_operators)
try:
    data = np.load(lbf_fn)
    lbf = data['lbf']
    lbf_dot = data['lbf_dot']
    lbf_dot_dot = data['lbf_dot_dot']
except IOError:
    lbf_coeffs = os.lbf_coeffs(reorg_energy, cutoff_freq, temperature, None, num_expansion_terms)
    lbf = os.site_lbf_ed(time, lbf_coeffs)
    lbf_dot = os.site_lbf_dot_ed(time, lbf_coeffs)
    lbf_dot_dot = os.site_lbf_dot_ed(time, lbf_coeffs)
    np.savez(lbf_fn, lbf=lbf, lbf_dot=lbf_dot, lbf_dot_dot=lbf_dot_dot, time=time)

print 'Calculating MRT rates at ' + str(time_utils.getTime())
MRT_rates = np.zeros(energy_gap_values.size)
for i,H in enumerate(hamiltonians):
    evals,evecs = utils.sorted_eig(H)
    MRT_rates[i] = os.modified_redfield_rates_general(evals, evecs, lbf, lbf_dot, lbf_dot_dot, reorg_energy, temperature, time)[0][0,1]

# define function for HEOM calculation pool
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
g_site, g_site_dot, g_site_dot_dot, total_site_reorg_energy = os.modified_redfield_params(
    time, site_reorg_energy, cutoff_freq, temperature, mode_params,
    num_expansion_terms)
total_site_reorg_energies = np.array(
    [total_site_reorg_energy, total_site_reorg_energy])
rates_data = []

print 'Calculating rates with high energy modes....'
for V in coupling_values:
    print 'Calculating rates for coupling ' + str(V)
    rates = []
    for i, delta_E in enumerate(delta_E_values):
        site_hamiltonian = hamiltonian(delta_E, V) + np.diag(
            total_site_reorg_energies
        )  # adjust site energies by reorganisation shift
        evals, evecs = utils.sorted_eig(site_hamiltonian)
        # calculate exciton reorganisation energies
        exciton_reorg_energies = np.array([
            os.exciton_reorg_energy(evecs[i], total_site_reorg_energies)
            for i in range(site_hamiltonian.shape[0])
        ])
        print exciton_reorg_energies
        evals = evals - exciton_reorg_energies  # adjust to bare exciton reorganisation energies
        MRT = os.modified_redfield_rates(evals, evecs, g_site, g_site_dot,
                                         g_site_dot_dot,
                                         total_site_reorg_energy, temperature,
                                         time)
        rates.append(MRT[0, 1])
    rates_data.append(rates)

#np.savez('../../data/modified_redfield_test_high_energy_modes_data.npz', delta_E_values=delta_E_values, coupling_values=coupling_values, rates=rates_data)
g_site = os.site_lbf_ed(integration_time, coeffs)
g_site_dot = os.site_lbf_dot_ed(integration_time, coeffs)
g_site_dot_dot = os.site_lbf_dot_dot_ed(integration_time, coeffs)
total_site_reorg_energy = reorg_energy1 + reorg_energy2 + np.sum([mode[0]*mode[1] for mode in mode_params])

shift_before_diagonalisation = True

# in each realisation pick the next value from the distribution for each site to construct the Hamiltonian
for n in range(num_realisations):
    print 'Calculating realisation number ' + str(n+1)
    realisation_energies = np.zeros(site_energies.size)
    for i in range(site_energies.size):
        realisation_energies[i] = site_energy_samples[i][n]
    if not shift_before_diagonalisation:
        hamiltonian = np.diag(realisation_energies) + couplings + couplings.T
        evals, evecs = utils.sorted_eig(hamiltonian)
    else:
        hamiltonian = np.diag(realisation_energies + total_site_reorg_energy) + couplings + couplings.T # shift site energies by reorg energy
        evals, evecs = utils.sorted_eig(hamiltonian) # diagonalise
        site_reorg_energies = np.zeros(hamiltonian.shape[0])
        site_reorg_energies.fill(total_site_reorg_energy)
        exciton_reorg_energies = np.zeros(hamiltonian.shape[0])
        for i in range(hamiltonian.shape[0]):
            exciton_reorg_energies[i] = os.exciton_reorg_energy(evecs[i], site_reorg_energies) # calculate exciton reorg energies
        evals = evals - exciton_reorg_energies # shift exciton energies down by exciton reorg energies
        
    # calculate the rates and time evolution for the realisation
    realisation_rates = os.MRT_rate_PE545_quick(evals, evecs, g_site, g_site_dot, g_site_dot_dot, total_site_reorg_energy, temperature, integration_time)
    
    liouvillian = np.zeros((realisation_rates.shape[0], realisation_rates.shape[1]))
    for i,row in enumerate(realisation_rates.T):
Beispiel #15
0
    except IOError:
        print 'Starting lbf calculations at ' + str(time_utils.getTime())
        lbf_coeffs = os.lbf_coeffs(site_drude_reorg_energy, cutoff_freq,
                                   temperature, single_mode_params, 100)
        lbf = os.site_lbf_ed(time, lbf_coeffs)
        lbf_dot = os.site_lbf_dot_ed(time, lbf_coeffs)
        lbf_dot_dot = os.site_lbf_dot_dot_ed(time, lbf_coeffs)
        print 'Finished calculating lbfs at ' + str(time_utils.getTime())
        np.savez(lbf_fn,
                 lbf=lbf,
                 lbf_dot=lbf_dot,
                 lbf_dot_dot=lbf_dot_dot,
                 time=time)

    # calculate MRT rates
    evals, evecs = utils.sorted_eig(hamiltonian[:6, :6])

    exciton_reorg_energies = np.array([
        os.exciton_reorg_energy(exciton, site_reorg_energies)
        for exciton in evecs
    ])
    # print evals - exciton_reorg_energies
    # evals,evecs = utils.sort_evals_evecs(evals-exciton_reorg_energies, evecs)
    # print evals

    # MRT_rates2 = os.modified_redfield_rates_general_unordered(evals-exciton_reorg_energies, evecs, lbf, lbf_dot, lbf_dot_dot, total_site_reorg_energy, temperature, time)
    #
    # liouvillian2 = MRT_rates2 - np.diag(np.sum(MRT_rates2, axis=0))
    #
    # print evals
    # print MRT_rates2
Beispiel #16
0
matplotlib.rc('font', **font)

np.set_printoptions(precision=3, linewidth=150, suppress=True)

data = np.load('../../data/PSIIRC_incoherent_HEOM_full_system_data.npz')

dm_history = data['dm_history']
system_hamiltonian = data['system_hamiltonian']
time = data['time']
jump_rates = data['jump_rates']
jump_operators = data['jump_operators']

print jump_rates
print jump_operators

evalues, evectors = utils.sorted_eig(system_hamiltonian[1:7, 1:7])
site_exciton_transform = np.eye(10)
site_exciton_transform[1:7, 1:7] = evectors.T

exciton_dm_history = np.array([
    np.dot(site_exciton_transform.T, np.dot(dm, site_exciton_transform))
    for dm in dm_history
])

labels = ['g', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'CT1', 'CT2', 'empty']

for i in range(system_hamiltonian.shape[0]):
    plt.plot(time, exciton_dm_history[:, i, i], linewidth=2, label=labels[i])
plt.legend().draggable()
plt.xlabel('time (ps)')
plt.ylabel('population')
Beispiel #17
0
# basis { PEB_50/61C, DBV_A, DVB_B, PEB_82C, PEB_158C, PEB_50/61D, PEB_82D, PEB_158D }
site_energies = np.array(
    [18532., 18008., 17973., 18040., 18711., 19574., 19050.,
     18960.])  # no reorganisation shift included

couplings = np.array([[0, 1., -37., 37., 23., 92., -16., 12.],
                      [0, 0, 4., -11., 33., -39., -46., 3.],
                      [0, 0, 0, 45., 3., 2., -11., 34.],
                      [0, 0, 0, 0, -7., -17., -3., 6.],
                      [0, 0, 0, 0, 0, 18., 7., 6.],
                      [0, 0, 0, 0, 0, 0, 40., 26.], [0, 0, 0, 0, 0, 0, 0, 7.],
                      [0, 0, 0, 0, 0, 0, 0, 0]])

site_hamiltonian = np.diag(site_energies) + couplings + couplings.T

evals, evecs = utils.sorted_eig(site_hamiltonian)

site_reorg_shift = 110.
site_reorg_energies = np.zeros(site_energies.size)
site_reorg_energies.fill(site_reorg_shift)
shifted_site_hamiltonian = site_hamiltonian + np.diag(site_reorg_energies)

shifted_evals, shifted_evecs = utils.sorted_eig(shifted_site_hamiltonian)
exciton_reorg_energies = os.exciton_reorg_energy(shifted_evecs,
                                                 site_reorg_energies)

print evals
print shifted_evals - exciton_reorg_energies
print exciton_reorg_energies
for i, el in enumerate(evecs.flatten()):
    print shifted_evecs.flatten()[i] + 0.0000001 > el > shifted_evecs.flatten(
except IOError:
    lbf_coeffs = os.lbf_coeffs(reorg_energy, cutoff_freq, temperature, None,
                               num_expansion_terms)
    lbf = os.site_lbf_ed(time, lbf_coeffs)
    lbf_dot = os.site_lbf_dot_ed(time, lbf_coeffs)
    lbf_dot_dot = os.site_lbf_dot_ed(time, lbf_coeffs)
    np.savez(lbf_fn,
             lbf=lbf,
             lbf_dot=lbf_dot,
             lbf_dot_dot=lbf_dot_dot,
             time=time)

print 'Calculating MRT rates at ' + str(time_utils.getTime())
MRT_rates = np.zeros(energy_gap_values.size)
for i, H in enumerate(hamiltonians):
    evals, evecs = utils.sorted_eig(H)
    MRT_rates[i] = os.modified_redfield_rates_general(evals, evecs, lbf,
                                                      lbf_dot, lbf_dot_dot,
                                                      reorg_energy,
                                                      temperature, time)[0][0,
                                                                            1]


# define function for HEOM calculation pool
def HEOM_calculation(hamiltonian):
    reorg_energy = 100.
    cutoff_freq = 53.
    temperature = 300.
    init_state = np.array([[1., 0], [0, 0]])

    duration = 5.
     data = np.load(lbf_fn)
     lbf = data['lbf']
     lbf_dot = data['lbf_dot']
     lbf_dot_dot = data['lbf_dot_dot']
     time = data['time']
 except IOError:
     print 'Starting lbf calculations at ' + str(time_utils.getTime())
     lbf_coeffs = os.lbf_coeffs(site_drude_reorg_energy, cutoff_freq, temperature, single_mode_params, 100)
     lbf = os.site_lbf_ed(time, lbf_coeffs)
     lbf_dot = os.site_lbf_dot_ed(time, lbf_coeffs)
     lbf_dot_dot = os.site_lbf_dot_dot_ed(time, lbf_coeffs)
     print 'Finished calculating lbfs at ' + str(time_utils.getTime())
     np.savez(lbf_fn, lbf=lbf, lbf_dot=lbf_dot, lbf_dot_dot=lbf_dot_dot, time=time)
 
 # calculate MRT rates
 evals,evecs = utils.sorted_eig(hamiltonian[:6,:6])
 
 exciton_reorg_energies = np.array([os.exciton_reorg_energy(exciton, site_reorg_energies) for exciton in evecs])
 # print evals - exciton_reorg_energies
 # evals,evecs = utils.sort_evals_evecs(evals-exciton_reorg_energies, evecs)
 # print evals
 
 # MRT_rates2 = os.modified_redfield_rates_general_unordered(evals-exciton_reorg_energies, evecs, lbf, lbf_dot, lbf_dot_dot, total_site_reorg_energy, temperature, time)
 # 
 # liouvillian2 = MRT_rates2 - np.diag(np.sum(MRT_rates2, axis=0))
 # 
 # print evals
 # print MRT_rates2
 
 print evals - exciton_reorg_energies
 #MRT_rates,evals,evecs = os.modified_redfield_rates_general(evals-exciton_reorg_energies, evecs, lbf, lbf_dot, lbf_dot_dot, total_site_reorg_energy, temperature, time)
# calculate line broadening functions etc...
time_interval = 10
time = np.linspace(0, time_interval, 32000.*time_interval)
num_expansion_terms = 20
g_site, g_site_dot, g_site_dot_dot, total_site_reorg_energy = os.modified_redfield_params(time, site_reorg_energy, cutoff_freq, temperature, mode_params, num_expansion_terms)
total_site_reorg_energies = np.array([total_site_reorg_energy, total_site_reorg_energy])
rates_data = []
   
print 'Calculating rates with high energy modes....'
for V in coupling_values:
    print 'Calculating rates for coupling ' + str(V)
    rates = []
    for i,delta_E in enumerate(delta_E_values):
        site_hamiltonian = hamiltonian(delta_E, V) + np.diag(total_site_reorg_energies) # adjust site energies by reorganisation shift
        evals, evecs = utils.sorted_eig(site_hamiltonian)
        # calculate exciton reorganisation energies
        exciton_reorg_energies = np.array([os.exciton_reorg_energy(evecs[i], total_site_reorg_energies) for i in range(site_hamiltonian.shape[0])])
        print exciton_reorg_energies
        evals = evals - exciton_reorg_energies # adjust to bare exciton reorganisation energies
        MRT = os.modified_redfield_rates(evals, evecs, g_site, g_site_dot, g_site_dot_dot, total_site_reorg_energy, temperature, time)
        rates.append(MRT[0,1])
    rates_data.append(rates)
      
#np.savez('../../data/modified_redfield_test_high_energy_modes_data.npz', delta_E_values=delta_E_values, coupling_values=coupling_values, rates=rates_data)
for i,rates in enumerate(rates_data):
    plt.subplot(1,3,i+1)
    plt.plot(delta_E_values, utils.WAVENUMS_TO_INVERSE_PS*np.array(rates))
plt.show()

# data = np.load('../../data/modified_redfield_test_high_energy_modes_data.npz')
Beispiel #21
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]])
coherent_hamiltonian = np.diag(average_site_CT_energies) + couplings + couplings.T

system_dimension = 10
system_hamiltonian = np.zeros((system_dimension,system_dimension))
system_hamiltonian[1:7,1:7] = coherent_hamiltonian[:6,:6]

evalues, evectors = utils.sorted_eig(coherent_hamiltonian[:6,:6])
site_exciton_transform = np.eye(10)
site_exciton_transform[1:7, 1:7] = evectors.T

reorg_energy = 35.
cutoff_freq = 40.
temperature = 300.

# jump operators. basis { ground , P_D1 , P_D2 , Chl_D1 , Chl_D2 , Phe_D1 , Phe_D2 , CT1 , CT2 , empty }
# 2 for pumping from ground state
# 12 for primary CT
# 2 for secondary CT
# 2 for coupling to leads
jump_operators = np.zeros((18, system_dimension, system_dimension))
# excitation: ground -> Chl_D1
jump_operators[0] = np.dot(site_exciton_transform, np.dot(np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# basis { PEB_50/61C, DBV_A, DVB_B, PEB_82C, PEB_158C, PEB_50/61D, PEB_82D, PEB_158D }
site_energies = np.array([18532., 18008., 17973., 18040., 18711., 19574., 19050., 18960.]) # no reorganisation shift included

couplings = np.array([[0, 1., -37., 37., 23., 92., -16., 12.],
                      [0, 0, 4., -11., 33., -39., -46., 3.],
                      [0, 0, 0, 45., 3., 2., -11., 34.],
                      [0, 0, 0, 0, -7., -17., -3., 6.],
                      [0, 0, 0, 0, 0, 18., 7., 6.],
                      [0, 0, 0, 0, 0, 0, 40., 26.],
                      [0, 0, 0, 0, 0, 0, 0, 7.],
                      [0, 0, 0, 0, 0, 0, 0, 0]])

site_hamiltonian = np.diag(site_energies) + couplings + couplings.T

evals, evecs = utils.sorted_eig(site_hamiltonian)

site_reorg_shift = 110.
site_reorg_energies = np.zeros(site_energies.size)
site_reorg_energies.fill(site_reorg_shift)
shifted_site_hamiltonian = site_hamiltonian + np.diag(site_reorg_energies)

shifted_evals, shifted_evecs = utils.sorted_eig(shifted_site_hamiltonian)
exciton_reorg_energies = os.exciton_reorg_energy(shifted_evecs, site_reorg_energies)

print evals
print shifted_evals - exciton_reorg_energies
print exciton_reorg_energies
for i,el in enumerate(evecs.flatten()):
    print shifted_evecs.flatten()[i] + 0.0000001 > el > shifted_evecs.flatten()[i] - 0.0000001
Beispiel #23
0
# try to reproduce dimer rates using code copied from Mathematica
rates_data = []
time_interval = 0.5
time = np.linspace(0, time_interval, int(time_interval * 2000))
lbf_coeffs = os.lbf_coeffs(reorg_energy, cutoff_freq, temperature, None, 0)
g_site = os.site_lbf_ed(time, lbf_coeffs)
g_site_dot = os.site_lbf_dot_ed(time, lbf_coeffs)
g_site_dot_dot = os.site_lbf_dot_dot_ed(time, lbf_coeffs)
scaling = 1.

for i, V in enumerate(coupling_values):
    print 'calculating rates for coupling ' + str(V)
    rates = []
    for delta_E in delta_E_values:
        evals, evecs = utils.sorted_eig(hamiltonian(delta_E, V))
        print evals
        exciton_reorg_energies = np.array([
            os.exciton_reorg_energy(exciton, [reorg_energy, reorg_energy])
            for exciton in evecs
        ])
        print exciton_reorg_energies
        rates.append(
            os.modified_redfield_rates_general(
                evals, evecs, np.array([g_site, scaling * g_site]),
                np.array([g_site_dot, scaling * g_site_dot]),
                np.array([g_site_dot_dot, scaling * g_site_dot_dot]),
                np.array([reorg_energy, scaling * reorg_energy]), temperature,
                time)[0][0, 1])
        #rates.append(os.MRT_rates(hamiltonian(delta_E, V), np.array([reorg_energy, reorg_energy]), cutoff_freq, temperature, None)[0,1])
    plt.subplot(1, coupling_values.size, i + 1)
Beispiel #24
0
g_site_dot_dot = os.site_lbf_dot_dot_ed(integration_time, coeffs)
total_site_reorg_energy = reorg_energy1 + reorg_energy2 + np.sum([mode[0]*mode[1] for mode in mode_params])
# parameters for time evolution
duration = 5.
timestep = 0.01
time = np.arange(0, duration+timestep, timestep)
#init_dv = np.array([0.35, 0.12, 0.1, 0.1, 0.34, 0.61, 0.46, 0.5]) # init state in site basis

site_history_sum = np.zeros((average_site_hamiltonian.shape[0], time.size))

for n in range(num_realisations):
    print 'Calculating realisation ' + str(n+1) + ' at time ' +str(datetime.now().time())
    
    # calculate Hamiltonian for this realisation ie. add site_shifts to average site energies and construct Hamiltonian
    site_hamiltonian = np.diag(average_site_energies + total_site_reorg_energy + site_shifts[n]) + couplings + couplings.T # now including reorganisation shift
    evals, evecs = utils.sorted_eig(site_hamiltonian) # make sure to return excitons in basis going from lowest to highest energy with sorted_eig
    site_reorg_energies = np.zeros(site_hamiltonian.shape[0])
    site_reorg_energies.fill(total_site_reorg_energy)
    exciton_reorg_energies = np.zeros(site_hamiltonian.shape[0])
    for i in range(site_hamiltonian.shape[0]):
        exciton_reorg_energies[i] = os.exciton_reorg_energy(evecs[i], site_reorg_energies) # calculate exciton reorg energies
    evals = evals - exciton_reorg_energies # shift exciton energies down by exciton reorg energies
    
    # calculate modified Redfield rates
    rates = os.MRT_rate_PE545_quick(evals, evecs, g_site, g_site_dot, g_site_dot_dot, total_site_reorg_energy, temperature, integration_time)
    # construct Liouvillian for system
    liouvillian = np.zeros((rates.shape[0], rates.shape[1]))
    for i,row in enumerate(rates.T):
        liouvillian[i,i] = -np.sum(row)
    liouvillian += rates