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]
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
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
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
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
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)
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)