def cal_sstates(self, tp, energies, s, q): #To see how much the transmision from one orbital(local basis) in lead a # to the orbital in the lead b, the transmission is decomposited to # Bloch wave in leads MinErr = 1e-8 MaxLambda = 1 + MinErr energies = np.real(energies) ne = len(energies) t_all = np.zeros([ne, tp.lead_num, tp.lead_num]) t_lead_all = [] for i in range(tp.lead_num): t_lead_all.append([]) for j in range(tp.lead_num): t_lead_all[i].append(np.zeros([tp.nblead[i], tp.nblead[j], ne])) total_t = [] total_vc = [] total_k = [] total_vl = [] sk1 = [] sk2 = [] for n, energy in enumerate(energies): t, vc, k, vl = self.central_scattering_states(tp, energy, s, q) total_t.append(t) total_vc.append(vc) total_k.append(k) total_vl.append(vl) for i in range(tp.lead_num): for j in range(tp.lead_num): t0 = t[i][j] t_all[n, i, j] = np.sum(np.dot(t0.T.conj(), t0)) for m1 in range(t0.shape[0]): sk1.append( self.lead_k_matrix(tp, i, s, q, k[i][m1], 'S')) for m2 in range(t0.shape[1]): sk2.append( self.lead_k_matrix(tp, i, s, q, k[j][m2], 'S')) for m1 in range(t0.shape[0]): for m2 in range(t0.shape[1]): w1 = (vl[j][:, m1].conj() * np.dot(sk1[m1], vl[j][:, m1])).real w1[find(w1 < 0)] = 0 w1 /= np.sum(w1) w2 = (vl[i][:, m2].conj() * np.dot(sk2[m2], vl[i][:, m2])).real w2[find(w2 < 0)] = 0 w2 /= np.sum(w2) t_lead_all[i][j][:, :, n] += abs(t0[m1, m2])**2 * np.dot( w2, w1.T.conj()) return np.array(t_lead_all), np.array(t_all)
def cal_sstates(self, tp, energies, s, q): #To see how much the transmision from one orbital(local basis) in lead a # to the orbital in the lead b, the transmission is decomposited to # Bloch wave in leads MinErr = 1e-8 MaxLambda = 1 + MinErr energies = np.real(energies) ne = len(energies) t_all = np.zeros([ne, tp.lead_num, tp.lead_num]) t_lead_all = [] for i in range(tp.lead_num): t_lead_all.append([]) for j in range(tp.lead_num): t_lead_all[i].append(np.zeros([tp.nblead[i], tp.nblead[j], ne])) total_t = [] total_vc = [] total_k = [] total_vl = [] sk1 = [] sk2 = [] for n, energy in enumerate(energies): t, vc, k, vl = self.central_scattering_states(tp, energy, s, q) total_t.append(t) total_vc.append(vc) total_k.append(k) total_vl.append(vl) for i in range(tp.lead_num): for j in range(tp.lead_num): t0 = t[i][j] t_all[n, i, j] = np.sum(np.dot(t0.T.conj(), t0)) for m1 in range(t0.shape[0]): sk1.append(self.lead_k_matrix(tp, i, s, q, k[i][m1], 'S')) for m2 in range(t0.shape[1]): sk2.append(self.lead_k_matrix(tp, i, s, q, k[j][m2], 'S')) for m1 in range(t0.shape[0]): for m2 in range(t0.shape[1]): w1 = (vl[j][:, m1].conj() * np.dot(sk1[m1], vl[j][:, m1])).real w1[find(w1 < 0)] = 0 w1 /= np.sum(w1) w2 = (vl[i][:, m2].conj() * np.dot(sk2[m2], vl[i][:, m2])).real w2[find(w2 < 0)] = 0 w2 /= np.sum(w2) t_lead_all[i][j][:, :, n] += abs(t0[m1, m2]) ** 2 * np.dot(w2, w1.T.conj()) return np.array(t_lead_all), np.array(t_all)
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 lead_scattering_states(self, tp, energy, l, s, q): #Calculating the scattering states in electrodes #l ---- index of electrode #s ---- index of spin #q ---- index of local k point #if it is multi-terminal system, should add a part that can rotate # the lead hamiltonian MaxLambda = 1e2 MinErr = 1e-8 energy += tp.bias[l] hes00 = tp.lead_hsd[l].H[s][q].recover() - \ tp.lead_hsd[l].S[q].recover() * energy hes01 = tp.lead_couple_hsd[l].H[s][q].recover() - \ tp.lead_couple_hsd[l].S[q].recover() * energy nb = hes00.shape[-1] dtype = hes00.dtype A = np.zeros([2 * nb, 2 * nb], dtype) B = np.zeros([2 * nb, 2 * nb], dtype) A[:nb, nb:2 * nb] = np.eye(nb) A[nb:2 * nb, :nb] = hes01.T.conj() A[nb:2 * nb, nb:2 * nb] = hes00 B[:nb, :nb] = np.eye(nb) B[nb:2 * nb, nb:2 * nb] = -hes01 from scipy.linalg import eig D, V = eig(A, B) index = np.argsort(abs(D)) D = D[index] V = V[:, index] #delete NaN index = find(np.abs(D) >= 0) D = D[index] V = V[:, index] #delete some unreasonable solutions index = find(abs(D) > MaxLambda) cutlen = len(D) - index[0] index = np.arange(cutlen, len(D) - cutlen) D = D[index] V = V[:, index] k = np.log(D) * (-1.j) / 2 / np.pi Vk = V[:nb] #sort scattering states proindex = find(abs(k.imag) < MinErr) if len(proindex) > 0: k_sort = np.sort(k[proindex].real) index = np.argsort(k[proindex].real) k[proindex] = k[proindex[index]].real Vk[:, proindex] = Vk[:, proindex[index]] #normalization the scattering states j = proindex[0] while j <= proindex[-1]: same_k_index = find(abs((k - k[j]).real) < MinErr) sk = self.lead_k_matrix(tp, l, s, q, k[j]) Vk[:, same_k_index] = eig_states_norm(Vk[:, same_k_index], sk) j += len(same_k_index) return np.array(k[proindex]), np.array(Vk[:, proindex])
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 lead_scattering_states(self, tp, energy, l, s, q): #Calculating the scattering states in electrodes #l ---- index of electrode #s ---- index of spin #q ---- index of local k point #if it is multi-terminal system, should add a part that can rotate # the lead hamiltonian MaxLambda = 1e2 MinErr = 1e-8 energy += tp.bias[l] hes00 = tp.lead_hsd[l].H[s][q].recover() - \ tp.lead_hsd[l].S[q].recover() * energy hes01 = tp.lead_couple_hsd[l].H[s][q].recover() - \ tp.lead_couple_hsd[l].S[q].recover() * energy nb = hes00.shape[-1] dtype = hes00.dtype A = np.zeros([2*nb, 2*nb], dtype) B = np.zeros([2*nb, 2*nb], dtype) A[:nb, nb:2*nb] = np.eye(nb) A[nb:2*nb, :nb] = hes01.T.conj() A[nb:2*nb, nb:2*nb] = hes00 B[:nb, :nb] = np.eye(nb) B[nb:2*nb, nb:2*nb] = -hes01 from scipy.linalg import eig D, V = eig(A, B) index = np.argsort(abs(D)) D = D[index] V = V[:, index] #delete NaN index = find(np.abs(D) >= 0) D = D[index] V = V[:, index] #delete some unreasonable solutions index = find(abs(D) > MaxLambda) cutlen = len(D) - index[0] index = np.arange(cutlen, len(D) - cutlen) D = D[index] V = V[:, index] k = np.log(D) * (-1.j) / 2 / np.pi Vk = V[:nb] #sort scattering states proindex = find(abs(k.imag) < MinErr) if len(proindex) > 0: k_sort = np.sort(k[proindex].real) index = np.argsort(k[proindex].real) k[proindex] = k[proindex[index]].real Vk[:, proindex] = Vk[:, proindex[index]] #normalization the scattering states j = proindex[0] while j <= proindex[-1]: same_k_index = find(abs((k - k[j]).real) < MinErr) sk = self.lead_k_matrix(tp, l, s, q, k[j]) Vk[:, same_k_index] = eig_states_norm(Vk[:, same_k_index], sk) j += len(same_k_index) return np.array(k[proindex]), np.array(Vk[:, proindex])