Beispiel #1
0
    def reset(self, mat, init=False):
        assert mat.dtype == self.dtype
        ind = get_matrix_index(self.mol_index)
        if init:
            self.mol_h = Banded_Sparse_Matrix(self.dtype, mat[ind.T, ind],
                                               self.band_indices[0])
            if self.band_indices[0] == None:
                self.band_indices[0] = self.mol_h.band_index            
        else:
            self.mol_h.reset(mat[ind.T, ind])

        for i in range(self.lead_num):
            for j in range(self.lead_nlayer[i] - 1):
                ind = get_matrix_index(self.ll_index[i][j])
                ind1 = get_matrix_index(self.ll_index[i][j + 1])
                indr1, indc1 = get_matrix_index(self.ll_index[i][j],
                                                      self.ll_index[i][j + 1])
                indr2, indc2 = get_matrix_index(self.ll_index[i][j + 1],
                                                  self.ll_index[i][j])
                if init:
                    self.diag_h[i][j] = Banded_Sparse_Matrix(self.dtype,
                                                             mat[ind1.T, ind1],
                                                 self.band_indices[i + 1][j])
                    if self.band_indices[i + 1][j] == None:
                        self.band_indices[i + 1][j] = \
                                                  self.diag_h[i][j].band_index
                else:
                    self.diag_h[i][j].reset(mat[ind1.T, ind1])
                self.upc_h[i][j] = mat[indr1, indc1]
                self.dwnc_h[i][j] = mat[indr2, indc2]
Beispiel #2
0
    def get_left_channels(self, tp, energy, s, k):
        # to get the left scattering channel from lead to scattering region
        sigma = self.calculate_sigma(tp, s, k, energy)
        g_s_ii = self.calculate_green_function_of_k_point(tp, s, k, energy,
                                                          sigma, full=True)
        nb = g_s_ii.shape[-1]
        dtype = g_s_ii.dtype
        lambda_l_ii = np.zeros([nb, nb], dtype)
        lambda_r_ii = np.zeros([nb, nb], dtype)
        ind = get_matrix_index(tp.hsd.S[0].ll_index[0][-1])
        lambda_l_ii[ind.T, ind] = 1.j * (sigma[0].recover() -
                                                  sigma[0].recover().T.conj())
        ind = get_matrix_index(tp.hsd.S[0].ll_index[1][-1])        
        lambda_r_ii[ind.T, ind] = 1.j * (sigma[1].recover() -
                                                  sigma[1].recover().T.conj())
        s_mm = tp.hsd.S[k].recover()
        s_s_i, s_s_ii = np.linalg.eig(s_mm)
        s_s_i = np.abs(s_s_i)
        s_s_sqrt_i = np.sqrt(s_s_i) # sqrt of eigenvalues  
        s_s_sqrt_ii = np.dot(s_s_ii * s_s_sqrt_i, dagger(s_s_ii))
        s_s_isqrt_ii = np.dot(s_s_ii / s_s_sqrt_i, dagger(s_s_ii))

        lambdab_r_ii = np.dot(np.dot(s_s_isqrt_ii, lambda_r_ii),s_s_isqrt_ii)
        a_l_ii = np.dot(np.dot(g_s_ii, lambda_l_ii), dagger(g_s_ii))
        ab_l_ii = np.dot(np.dot(s_s_sqrt_ii, a_l_ii), s_s_sqrt_ii)
        lambda_i, u_ii = np.linalg.eig(ab_l_ii)
        ut_ii = np.sqrt(lambda_i / (2.0 * np.pi)) * u_ii
        m_ii = 2 * np.pi * np.dot(np.dot(dagger(ut_ii), lambdab_r_ii),ut_ii)
        T_i,c_in = np.linalg.eig(m_ii)
        T_i = np.abs(T_i)
        channels = np.argsort(-T_i)
        c_in = np.take(c_in, channels, axis=1)
        T_n = np.take(T_i, channels)
        v_in = np.dot(np.dot(s_s_isqrt_ii, ut_ii), c_in)
        return T_n, v_in
Beispiel #3
0
 def combine_inv_mat(self, inv_mat):
     nb = self.nb
     mat = np.zeros([nb, nb], complex)
     for i in range(self.lead_num):
         indr, indc = get_matrix_index(self.ll_index[i][0],
                                       self.ll_index[i][-1])
         mat[indr, indc] = inv_mat[i][self.lead_num]
         for j in range(self.lead_num):
             for k in range(1, self.lead_nlayer[j]):
                 indr, indc = get_matrix_index(self.ll_index[j][k],
                                               self.ll_index[i][-1])
                 mat[indr, indc] = inv_mat[i][j][k - 1]
     return mat
Beispiel #4
0
 def recover(self, ex=False):
     if ex:
         nb = self.ex_nb
         lead_nlayer = self.ex_lead_nlayer
         ll_index = self.ex_ll_index
     else:
         nb = self.nb
         lead_nlayer = self.lead_nlayer
         ll_index = self.ll_index            
     
     mat = np.zeros([nb, nb], self.dtype)
     ind = get_matrix_index(ll_index[0][0])
     
     mat[ind.T, ind] = self.mol_h.recover()
     
     gmi = get_matrix_index
     for i in range(self.lead_num):
         for j in range(lead_nlayer[i] - 1):
             ind = gmi(ll_index[i][j])
             ind1 = gmi(ll_index[i][j + 1])
             indr1, indc1 = gmi(ll_index[i][j], ll_index[i][j + 1])
             indr2, indc2 = gmi(ll_index[i][j + 1], ll_index[i][j])                
             mat[ind1.T, ind1] = self.diag_h[i][j].recover()
             mat[indr1, indc1] = self.upc_h[i][j]
             mat[indr2, indc2] = self.dwnc_h[i][j]
     return mat        
Beispiel #5
0
    def get_left_channels(self, tp, energy, s, k):
        # to get the left scattering channel from lead to scattering region
        sigma = self.calculate_sigma(tp, s, k, energy)
        g_s_ii = self.calculate_green_function_of_k_point(tp,
                                                          s,
                                                          k,
                                                          energy,
                                                          sigma,
                                                          full=True)
        nb = g_s_ii.shape[-1]
        dtype = g_s_ii.dtype
        lambda_l_ii = np.zeros([nb, nb], dtype)
        lambda_r_ii = np.zeros([nb, nb], dtype)
        ind = get_matrix_index(tp.hsd.S[0].ll_index[0][-1])
        lambda_l_ii[ind.T, ind] = 1.j * (sigma[0].recover() -
                                         sigma[0].recover().T.conj())
        ind = get_matrix_index(tp.hsd.S[0].ll_index[1][-1])
        lambda_r_ii[ind.T, ind] = 1.j * (sigma[1].recover() -
                                         sigma[1].recover().T.conj())
        s_mm = tp.hsd.S[k].recover()
        s_s_i, s_s_ii = np.linalg.eig(s_mm)
        s_s_i = np.abs(s_s_i)
        s_s_sqrt_i = np.sqrt(s_s_i)  # sqrt of eigenvalues
        s_s_sqrt_ii = np.dot(s_s_ii * s_s_sqrt_i, dagger(s_s_ii))
        s_s_isqrt_ii = np.dot(s_s_ii / s_s_sqrt_i, dagger(s_s_ii))

        lambdab_r_ii = np.dot(np.dot(s_s_isqrt_ii, lambda_r_ii), s_s_isqrt_ii)
        a_l_ii = np.dot(np.dot(g_s_ii, lambda_l_ii), dagger(g_s_ii))
        ab_l_ii = np.dot(np.dot(s_s_sqrt_ii, a_l_ii), s_s_sqrt_ii)
        lambda_i, u_ii = np.linalg.eig(ab_l_ii)
        ut_ii = np.sqrt(lambda_i / (2.0 * np.pi)) * u_ii
        m_ii = 2 * np.pi * np.dot(np.dot(dagger(ut_ii), lambdab_r_ii), ut_ii)
        T_i, c_in = np.linalg.eig(m_ii)
        T_i = np.abs(T_i)
        channels = np.argsort(-T_i)
        c_in = np.take(c_in, channels, axis=1)
        T_n = np.take(T_i, channels)
        v_in = np.dot(np.dot(s_s_isqrt_ii, ut_ii), c_in)
        return T_n, v_in
Beispiel #6
0
    def central_scattering_states(self, tp, energy, s, q):
        #To get the scattering states corresponding to a Bloch vector in lead
        MaxLambda = 1e2
        MinErr = 1e-8
        bc = tp.inner_mol_index
        nc = len(bc)
        molhes = tp.hsd.H[s][q].recover(True) - \
                              tp.hsd.S[q].recover(True) * energy
        blead = []
        lead_hes = []
        lead_couple_hes = []
        for i in range(tp.lead_num):
            blead.append(tp.lead_layer_index[i][-1])
            lead_hes.append(tp.lead_hsd[i].H[s][q].recover() -
                            tp.lead_hsd[i].S[q].recover() * energy)
            lead_couple_hes.append(tp.lead_couple_hsd[i].H[s][q].recover() -
                                   tp.lead_couple_hsd[i].S[q].recover() *
                                   energy)

        ex_ll_index = tp.hsd.S[0].ex_ll_index

        total_k = []
        total_vk = []
        total_lam = []
        total_v = []
        total_pro_right_index = []
        total_pro_left_index = []
        total_left_index = []
        total_right_index = []
        total_kr = []
        total_kt = []
        total_lambdar = []
        total_lambdat = []
        total_vkr = []
        total_vkt = []
        total_vr = []
        total_vt = []
        total_len_k = []
        total_nblead = []
        total_bA1 = []
        total_bA2 = []
        total_bproin = []
        total_nbB2 = []
        total_bB2 = []

        for i in range(tp.lead_num):
            k, vk = self.lead_scattering_states(tp, energy, i, s, q)
            total_k.append(k)
            total_vk.append(vk)

            lam = np.exp(2 * np.pi * k * 1.j)
            total_lam.append(lam)

            #calculating v = dE/dk
            de2 = 1e-8
            k2, vk2 = self.lead_scattering_states(tp, energy + de2, i, s, q)
            v = de2 / (k2 - k) / 2 / np.pi
            total_v.append(v)

            #seperating left scaterring states and right scattering states
            #left scattering: lead->mol, right scattering: mol->lead
            proindex = find(abs(k.imag) < MinErr)
            pro_left_index = proindex[find(v[proindex].real < 0)]
            pro_left_index = pro_left_index[-np.arange(len(pro_left_index)) -
                                            1]

            pro_right_index = proindex[find(v[proindex].real > 0)]

            left_index = find(k.imag > MinErr)
            left_index = np.append(left_index, pro_left_index)

            right_index = pro_right_index.copy()
            right_index = np.append(right_index, find(k.imag < -MinErr))

            total_pro_left_index.append(pro_left_index)
            total_pro_right_index.append(pro_right_index)
            total_left_index.append(left_index)
            total_right_index.append(right_index)

            kr = k[left_index]
            kt = k[right_index]
            total_kr.append(kr)
            total_kt.append(kt)

            lambdar = np.diag(np.exp(2 * np.pi * kr * 1.j))
            lambdat = np.diag(np.exp(2 * np.pi * kt * 1.j))
            total_lambdar.append(lambdar)
            total_lambdat.append(lambdat)

            vkr = np.take(vk, left_index, axis=1)
            vkt = np.take(vk, right_index, axis=1)
            vr = v[pro_left_index]
            vt = v[pro_right_index]
            total_vkr.append(vkr)
            total_vkt.append(vkt)
            total_vr.append(vr)
            total_vt.append(vt)

            #abstract basis information
            len_k = len(right_index)
            total_len_k.append(len_k)

            #lead i basis seqeunce in whole matrix
            nblead = len(ex_ll_index[i][-1])
            total_nblead.append(nblead)
            bA1 = nc + int(np.sum(total_nblead[:i])) + np.arange(nblead)
            #sequence of the incident wave
            bA2 = nc + int(np.sum(total_len_k[:i])) + np.arange(len_k)
            # the first n in vkt are scattering waves, the rest are the decaying ones
            # the first n in vkr are decaying waves, the rest are the scattering ones
            total_bA1.append(bA1)
            total_bA2.append(bA2)

            bproin = np.arange(len(pro_right_index)) + \
                                          len(kr) - len(pro_right_index)
            ### this line need to check it...
            total_bproin.append(bproin)
            nbB2 = len(bproin)
            total_nbB2.append(nbB2)
            bB2 = int(np.sum(total_nbB2[:i])) + np.arange(nbB2)
            total_bB2.append(bB2)

        ind = get_matrix_index(bc)
        Acc = molhes[ind.T, ind]

        total_Alc = []
        total_hcl = []
        total_All = []
        total_Acl = []
        total_Bc = []
        total_Bl = []

        for i in range(tp.lead_num):
            ind1, ind2 = get_matrix_index(blead[i], bc)
            Alc = molhes[ind1, ind2]
            ind1, ind2 = get_matrix_index(bc, blead[i])
            hcl = molhes[ind1, ind2]
            vkt = total_vkt[i]
            All = np.dot(tp.lead_hsd[i].H[s][q].recover(), vkt) + \
                    np.dot(np.dot(tp.lead_couple_hsd[i].H[s][q].recover(), \
                                                     vkt), total_lambdat[i])
            Acl = np.dot(hcl, vkt)
            bpi = total_bproin[i]
            vkr = total_vkr[i]
            vkr_bpi = np.take(vkr, bpi, axis=1)
            Bc = -np.dot(hcl, vkr_bpi)
            ind = get_matrix_index(bpi)
            Bl = -np.dot(tp.lead_hsd[i].H[s][q].recover(), vkr_bpi) + \
                    np.dot(np.dot(tp.lead_couple_hsd[i].H[s][q].recover(),
                        vkr_bpi) ,total_lambdar[i][ind.T, ind])
            total_Alc.append(Alc)
            total_Acl.append(Acl)
            total_hcl.append(hcl)
            total_All.append(All)
            total_Bc.append(Bc)
            total_Bl.append(Bl)
        total_bc = molhes.shape[-1]
        MatA = np.zeros([total_bc, nc + np.sum(total_len_k)], complex)
        MatB = np.zeros([total_bc, np.sum(total_nbB2)], complex)
        ind = get_matrix_index(np.arange(nc))
        MatA[ind.T, ind] = Acc
        for i in range(tp.lead_num):
            ind1, ind2 = get_matrix_index(total_bA1[i], total_bA2[i])
            MatA[ind1, ind2] = total_All[i]
            ind1, ind2 = get_matrix_index(np.arange(nc), total_bA2[i])
            MatA[ind1, ind2] = total_Acl[i]
            ind1, ind2 = get_matrix_index(total_bA1[i], np.arange(nc))
            MatA[ind1, ind2] = total_Alc[i]
            ind1, ind2 = get_matrix_index(np.arange(nc), total_bB2[i])
            MatB[ind1, ind2] = total_Bc[i]
            ind1, ind2 = get_matrix_index(total_bA1[i], total_bB2[i])
            MatB[ind1, ind2] = total_Bl[i]
        Vx, residues, rank, singular = np.linalg.lstsq(MatA, MatB)

        total_vl = []
        for i in range(tp.lead_num):
            total_k[i] = total_k[i][total_pro_right_index[i]]
            total_vl.append(
                np.take(total_vk[i], total_pro_right_index[i], axis=1))

        total_vc = []
        t = []
        for i in range(tp.lead_num):
            t.append([])
            for j in range(tp.lead_num):
                t[i].append([])
        for i in range(tp.lead_num):
            ind1, ind2 = get_matrix_index(np.arange(nc), total_bB2[i])
            total_vc.append(Vx[ind1, ind2])
            for j in range(tp.lead_num):
                bx = total_bA2[j]
                bx = bx[:len(total_pro_right_index[j])]
                ind1, ind2 = get_matrix_index(bx, total_bB2[i])
                #t[j].append(Vx[ind1, ind2])
                t[j][i] = Vx[ind1, ind2]
                for m in range(len(total_pro_left_index[i])):
                    for n in range(len(total_pro_right_index[j])):
                        t[j][i][n, m] *= np.sqrt(
                            abs(total_vt[i][n] / total_vr[j][m]))
        return np.array(t), np.array(total_vc), \
                                         np.array(total_k), np.array(total_vl)
Beispiel #7
0
    def central_scattering_states(self, tp, energy, s, q):
        #To get the scattering states corresponding to a Bloch vector in lead
        MaxLambda = 1e2
        MinErr = 1e-8
        bc = tp.inner_mol_index
        nc = len(bc)
        molhes = tp.hsd.H[s][q].recover(True) - \
                              tp.hsd.S[q].recover(True) * energy
        blead = []
        lead_hes = []
        lead_couple_hes = []
        for i in range(tp.lead_num):
            blead.append(tp.lead_layer_index[i][-1])
            lead_hes.append(tp.lead_hsd[i].H[s][q].recover() -
                                       tp.lead_hsd[i].S[q].recover() * energy)
            lead_couple_hes.append(tp.lead_couple_hsd[i].H[s][q].recover() -
                                tp.lead_couple_hsd[i].S[q].recover() * energy)

        ex_ll_index = tp.hsd.S[0].ex_ll_index    
        
        total_k = []
        total_vk = []
        total_lam = []
        total_v = []
        total_pro_right_index = []
        total_pro_left_index = []
        total_left_index = []
        total_right_index = []
        total_kr = []
        total_kt = []
        total_lambdar = []
        total_lambdat = []
        total_vkr = []
        total_vkt = []
        total_vr = []
        total_vt = []
        total_len_k = []
        total_nblead = []
        total_bA1 = []
        total_bA2 = []
        total_bproin = []
        total_nbB2 = []
        total_bB2 = []
                
        for i in range(tp.lead_num):
            k, vk = self.lead_scattering_states(tp, energy, i, s, q)
            total_k.append(k)
            total_vk.append(vk)
            
            lam = np.exp(2 * np.pi * k * 1.j)
            total_lam.append(lam)
            
            #calculating v = dE/dk
            de2 = 1e-8
            k2, vk2 = self.lead_scattering_states(tp, energy + de2, i, s, q)
            v = de2 / (k2 - k) / 2 / np.pi 
            total_v.append(v)
            
            #seperating left scaterring states and right scattering states
            #left scattering: lead->mol, right scattering: mol->lead
            proindex = find(abs(k.imag) < MinErr)
            pro_left_index = proindex[find(v[proindex].real < 0)]
            pro_left_index = pro_left_index[-np.arange(len(pro_left_index))
                                                                          - 1]
            
            pro_right_index = proindex[find(v[proindex].real > 0)]
               
            left_index = find(k.imag > MinErr)
            left_index = np.append(left_index, pro_left_index)
            
            right_index = pro_right_index.copy()
            right_index = np.append(right_index, find(k.imag < -MinErr))
            
            total_pro_left_index.append(pro_left_index)
            total_pro_right_index.append(pro_right_index)
            total_left_index.append(left_index)
            total_right_index.append(right_index)
           
            kr = k[left_index]
            kt = k[right_index]
            total_kr.append(kr)
            total_kt.append(kt)
            
            lambdar = np.diag(np.exp(2 * np.pi * kr * 1.j))
            lambdat = np.diag(np.exp(2 * np.pi * kt * 1.j))
            total_lambdar.append(lambdar)
            total_lambdat.append(lambdat)
            
            vkr = np.take(vk, left_index, axis=1)
            vkt = np.take(vk, right_index, axis=1)
            vr = v[pro_left_index]
            vt = v[pro_right_index]
            total_vkr.append(vkr)
            total_vkt.append(vkt)
            total_vr.append(vr)
            total_vt.append(vt)
            
            #abstract basis information
            len_k = len(right_index)
            total_len_k.append(len_k)
            
            #lead i basis seqeunce in whole matrix
            nblead = len(ex_ll_index[i][-1])
            total_nblead.append(nblead)
            bA1 = nc + int(np.sum(total_nblead[:i])) + np.arange(nblead)
            #sequence of the incident wave   
            bA2 = nc + int(np.sum(total_len_k[:i])) + np.arange(len_k)
            # the first n in vkt are scattering waves, the rest are the decaying ones
            # the first n in vkr are decaying waves, the rest are the scattering ones
            total_bA1.append(bA1)
            total_bA2.append(bA2)  
           
            bproin = np.arange(len(pro_right_index)) + \
                                          len(kr) - len(pro_right_index)
            ### this line need to check it...
            total_bproin.append(bproin)
            nbB2 = len(bproin)
            total_nbB2.append(nbB2)
            bB2 = int(np.sum(total_nbB2[:i])) + np.arange(nbB2)
            total_bB2.append(bB2)

        ind = get_matrix_index(bc)              
        Acc = molhes[ind.T, ind]
           
        total_Alc = []
        total_hcl = []
        total_All = []
        total_Acl = []
        total_Bc = []
        total_Bl = []    
            
        for i in range(tp.lead_num):
            ind1, ind2 = get_matrix_index(blead[i], bc)         
            Alc = molhes[ind1, ind2]
            ind1, ind2 = get_matrix_index(bc, blead[i])         
            hcl = molhes[ind1, ind2]
            vkt = total_vkt[i]
            All = np.dot(tp.lead_hsd[i].H[s][q].recover(), vkt) + \
                    np.dot(np.dot(tp.lead_couple_hsd[i].H[s][q].recover(), \
                                                     vkt), total_lambdat[i])
            Acl = np.dot(hcl, vkt)
            bpi = total_bproin[i]
            vkr = total_vkr[i]
            vkr_bpi = np.take(vkr, bpi, axis=1)
            Bc = -np.dot(hcl, vkr_bpi)
            ind = get_matrix_index(bpi)
            Bl = -np.dot(tp.lead_hsd[i].H[s][q].recover(), vkr_bpi) + \
                    np.dot(np.dot(tp.lead_couple_hsd[i].H[s][q].recover(),
                        vkr_bpi) ,total_lambdar[i][ind.T, ind])
            total_Alc.append(Alc)
            total_Acl.append(Acl)
            total_hcl.append(hcl)
            total_All.append(All)
            total_Bc.append(Bc)
            total_Bl.append(Bl)
        total_bc = molhes.shape[-1]
        MatA = np.zeros([total_bc, nc + np.sum(total_len_k)], complex)    
        MatB = np.zeros([total_bc, np.sum(total_nbB2)], complex)
        ind = get_matrix_index(np.arange(nc))
        MatA[ind.T, ind] = Acc
        for i in range(tp.lead_num):
            ind1, ind2 = get_matrix_index(total_bA1[i], total_bA2[i])
            MatA[ind1, ind2] = total_All[i]
            ind1, ind2 = get_matrix_index(np.arange(nc), total_bA2[i])
            MatA[ind1, ind2] = total_Acl[i]
            ind1, ind2 = get_matrix_index(total_bA1[i], np.arange(nc))
            MatA[ind1, ind2] = total_Alc[i]
            ind1, ind2 = get_matrix_index(np.arange(nc), total_bB2[i])
            MatB[ind1, ind2] = total_Bc[i]
            ind1, ind2 = get_matrix_index(total_bA1[i], total_bB2[i])
            MatB[ind1, ind2] = total_Bl[i]
        Vx, residues, rank, singular = np.linalg.lstsq(MatA, MatB)
        
        total_vl = []
        for i in range(tp.lead_num):
            total_k[i] = total_k[i][total_pro_right_index[i]]
            total_vl.append(np.take(total_vk[i],
                                    total_pro_right_index[i], axis=1))
         
        total_vc = []
        t = []
        for i in range(tp.lead_num):
            t.append([])
            for j in range(tp.lead_num):
                t[i].append([])
        for i in range(tp.lead_num):
            ind1, ind2 = get_matrix_index(np.arange(nc), total_bB2[i])
            total_vc.append(Vx[ind1, ind2])
            for j in range(tp.lead_num):
                bx = total_bA2[j]
                bx = bx[:len(total_pro_right_index[j])]
                ind1, ind2 = get_matrix_index(bx, total_bB2[i])
                #t[j].append(Vx[ind1, ind2])
                t[j][i] = Vx[ind1, ind2]
                for m in range(len(total_pro_left_index[i])):
                    for n in range(len(total_pro_right_index[j])):
                        t[j][i][n, m] *= np.sqrt(abs(total_vt[i][n]/
                                                          total_vr[j][m]))
        return np.array(t), np.array(total_vc), \
                                         np.array(total_k), np.array(total_vl)