def get_smatrix(ht, energy=0.0, delta=0.000001, as_matrix=False, check=False): """Calculate the S-matrix of an heterostructure""" # now do the Fisher Lee trick smatrix = [[None, None], [None, None]] # smatrix in list form from green import gauss_inverse # calculate the desired green functions # get the selfenergies, using the same coupling as the lead (selfl, selfr) = get_surface_selfenergies(ht, energy=energy, delta=delta, pristine=True) if ht.block_diagonal: ht2 = enlarge_hlist(ht) # get the enlaged hlist with the leads # selfenergy of the leads (coupled to another cell of the lead) gmatrix = effective_tridiagonal_hamiltonian(ht2.central_intra, selfl, selfr, energy=energy, delta=delta) # print(selfr) else: # not block diagonal gmatrix = build_effective_hlist(ht, energy=energy, delta=delta, selfl=selfl, selfr=selfr) # print(selfr) # gamma functions gammar = 1j * (selfr - selfr.H) gammal = 1j * (selfl - selfl.H) # calculate the relevant terms of the Green function g11 = gauss_inverse(gmatrix, 0, 0) g12 = gauss_inverse(gmatrix, 0, -1) g21 = gauss_inverse(gmatrix, -1, 0) g22 = gauss_inverse(gmatrix, -1, -1) # print (gammal*g12*gammar*g21).trace() ######## now build up the s matrix with the fisher trick # the identity can have different dimension ignore for now.... iden = np.matrix(np.identity(g11.shape[0], dtype=complex)) # create idntity iden11 = np.matrix(np.identity(g11.shape[0], dtype=complex)) # create idntity iden22 = np.matrix(np.identity(g22.shape[0], dtype=complex)) # create idntity smatrix[0][0] = -iden + 1j * sqrtm(gammal) * g11 * sqrtm(gammal) # matrix smatrix[0][1] = 1j * sqrtm(gammal) * g12 * sqrtm( gammar) # transmission matrix smatrix[1][0] = 1j * sqrtm(gammar) * g21 * sqrtm( gammal) # transmission matrix smatrix[1][1] = -iden + 1j * sqrtm(gammar) * g22 * sqrtm(gammar) # matrix if as_matrix: from scipy.sparse import bmat, csc_matrix smatrix2 = [[csc_matrix(smatrix[i][j]) for j in range(2)] for i in range(2)] smatrix = bmat(smatrix2).todense() if check: # check whether the matrix is unitary error = np.max(np.abs(smatrix.I - smatrix.H)) # check unitariety if error > 0.001: raise return smatrix
def get_smatrix(ht,energy=0.0,delta=0.0001,as_matrix=False): """Calculate the S-matrix of an heterostructure""" # selfenergy of the leads (coupled to another cell of the lead) (selfl,selfr) = get_surface_selfenergies(ht,energy=energy,delta=delta) if ht.block_diagonal: raise # not implemented # gamma functions gammar = 1j*(selfr-selfr.H) gammal = 1j*(selfl-selfl.H) # now do the Fisher Lee trick smatrix = [[None,None],[None,None]] # smatrix in list form gmatrix = build_effective_hlist(ht,energy=energy,delta=delta,selfl=selfl, selfr=selfr) # calculate the relevant terms of the Green function from green import gauss_inverse # calculate the desired green functions g11 = gauss_inverse(gmatrix,0,0) g12 = gauss_inverse(gmatrix,0,-1) g21 = gauss_inverse(gmatrix,-1,0) g22 = gauss_inverse(gmatrix,-1,-1) # print (gammal*g12*gammar*g21).trace() ######## now build up the s matrix with the fisher trick # the identity can have different dimension ignore for now.... iden = np.matrix(np.identity(g11.shape[0],dtype=complex)) # create idntity iden11 = np.matrix(np.identity(g11.shape[0],dtype=complex)) # create idntity iden22 = np.matrix(np.identity(g22.shape[0],dtype=complex)) # create idntity smatrix[0][0] = -iden + 1j*sqrtm(gammal)*g11*sqrtm(gammal) # matrix smatrix[1][0] = -1j*sqrtm(gammal)*g12*sqrtm(gammar) # transmission matrix smatrix[0][1] = -1j*sqrtm(gammar)*g21*sqrtm(gammal) # transmission matrix smatrix[1][1] = -iden + 1j*sqrtm(gammar)*g22*sqrtm(gammar) # matrix ################################## # alternative way, rotating into the diagonal basis for gamma # (bgl,bgr) = get_bulk_green(ht,energy=energy,delta=delta) # vl = 1j*(bgl-bgl.H) # left velocity matrix # vr = 1j*(bgr-bgr.H) # left velocity matrix # (Dgammal, Rl) = sqrtm_rotated(gammar) # (Dgammar, Rr) = sqrtm_rotated(gammal) # (Dgammal, RR) = sqrtm_rotated(vl) # (Dgammar, RR) = sqrtm_rotated(vr) # smatrix[0][0] = -iden11 + 1j*Dgammal*Rl*g11*Rl.H*Dgammal # matrix # smatrix[1][1] = -iden22 + 1j*Dgammar*Rr*g22*Rr.H*Dgammar # matrix # smatrix[0][1] = 1j*Dgammal*Rl*g12*Rr.H*Dgammar # matrix # smatrix[1][0] = 1j*Dgammar*Rr*g21*Rl.H*Dgammal # matrix # raise # bullshit # smatrix[0][0] = -iden + 1j*sqrtm(vl)*g11*sqrtm(vl) # matrix # smatrix[0][1] = 1j*sqrtm(vl)*g12*sqrtm(vr) # transmission matrix # smatrix[1][0] = 1j*sqrtm(vr)*g21*sqrtm(vl) # transmission matrix # smatrix[1][1] = -iden + 1j*sqrtm(vr)*g22*sqrtm(vr) # matrix # from scipy.sparse import csc_matrix # print csc_matrix(gammar - sqrtm(gammar)*sqrtm(gammar)).data if as_matrix: from scipy.sparse import bmat,csc_matrix smatrix2 = [[csc_matrix(smatrix[i][j]) for i in range(2)] for j in range(2)] smatrix = bmat(smatrix2).todense() return smatrix
def get_smatrix(ht,energy=0.0,delta=0.000001,as_matrix=False,check=False): """Calculate the S-matrix of an heterostructure""" # now do the Fisher Lee trick smatrix = [[None,None],[None,None]] # smatrix in list form from green import gauss_inverse # calculate the desired green functions # get the selfenergies, using the same coupling as the lead if ht.interpolated_selfenergy: selfl = ht.get_selfenergy(energy,delta=delta,lead=0) selfr = ht.get_selfenergy(energy,delta=delta,lead=1) else: (selfl,selfr) = get_surface_selfenergies(ht,energy=energy,delta=delta, pristine=True) if ht.block_diagonal: ht2 = enlarge_hlist(ht) # get the enlaged hlist with the leads # selfenergy of the leads (coupled to another cell of the lead) gmatrix = effective_tridiagonal_hamiltonian(ht2.central_intra,selfl,selfr, energy=energy,delta=delta) # print(selfr) else: # not block diagonal gmatrix = build_effective_hlist(ht,energy=energy,delta=delta,selfl=selfl, selfr=selfr) # print(selfr) # gamma functions gammar = 1j*(selfr-selfr.H) gammal = 1j*(selfl-selfl.H) # calculate the relevant terms of the Green function g11 = gauss_inverse(gmatrix,0,0) g12 = gauss_inverse(gmatrix,0,-1) g21 = gauss_inverse(gmatrix,-1,0) g22 = gauss_inverse(gmatrix,-1,-1) # print (gammal*g12*gammar*g21).trace() ######## now build up the s matrix with the fisher trick # the identity can have different dimension ignore for now.... iden = np.matrix(np.identity(g11.shape[0],dtype=complex)) # create idntity iden11 = np.matrix(np.identity(g11.shape[0],dtype=complex)) # create idntity iden22 = np.matrix(np.identity(g22.shape[0],dtype=complex)) # create idntity smatrix[0][0] = -iden + 1j*sqrtm(gammal)*g11*sqrtm(gammal) # matrix smatrix[0][1] = 1j*sqrtm(gammal)*g12*sqrtm(gammar) # transmission matrix smatrix[1][0] = 1j*sqrtm(gammar)*g21*sqrtm(gammal) # transmission matrix smatrix[1][1] = -iden + 1j*sqrtm(gammar)*g22*sqrtm(gammar) # matrix if as_matrix: from scipy.sparse import bmat,csc_matrix smatrix2 = [[csc_matrix(smatrix[i][j]) for j in range(2)] for i in range(2)] smatrix = bmat(smatrix2).todense() if check: # check whether the matrix is unitary error = np.max(np.abs(smatrix.I -smatrix.H)) # check unitariety if error> 0.001: raise return smatrix
def plot_local_central_dos(hetero, energies=0.0, gf=None): """ Plots the local density of states in the central part""" from green import dyson from green import gf_convergence from hamiltonians import is_number if gf == None: gf = gf_convergence("lead") if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm dimhc = len(intra) # dimension of the central part if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # dimension of the central part dimhc = len(hetero.central_intra) * len(intra) iden = np.matrix(np.identity(len(intra), dtype=complex)) # create idntity ldos = np.array([0.0 for i in range(dimhc)]) # initialice ldos # initialize ldos for energy in energies: # loop over energies # right green function gr = None gl = None # perform dyson calculation intra = hetero.right_intra inter = hetero.right_inter gr = dyson(intra, inter, energy=energy, gf=gf) hetero.right_green = gr # save green function # left green function intra = hetero.left_intra inter = hetero.left_inter gl = dyson(intra, inter, energy=energy, gf=gf) hetero.left_green = gl # save green function # save green functions # hetero.write_green() # left selfenergy inter = hetero.left_coupling selfl = inter * gl * inter.H # left selfenergy # right selfenergy inter = hetero.right_coupling selfr = inter * gr * inter.H # right selfenergy # central green function intra = hetero.central_intra # dyson equation for the center # full matrix if not hetero.block_diagonal: heff = intra + selfl + selfr hetero.heff = heff gc = (energy + 1j * eps) * iden - heff gc = gc.I # calculate inverse # get the local density of states ldos += np.array([-gc[i, i].imag for i in range(len(gc))]) # if save_heff: # hetero.write_heff() # reduced matrix if hetero.block_diagonal: from copy import deepcopy heff = deepcopy(intra) heff[0][0] = intra[0][0] + selfl heff[-1][-1] = intra[-1][-1] + selfr dd = (energy + 1j * gf.eps) * iden for i in range(len(intra)): # add the diagonal energy part heff[i][i] = heff[i][i] - dd # this has the wrong sign!! # now change the sign for i in range(len(intra)): for j in range(len(intra)): try: heff[i][j] = -heff[i][j] except: heff[i][j] = heff[i][j] # save the green function hetero.heff = heff # if save_heff: # from scipy.sparse import bmat # hetero.heff = bmat(heff) # hetero.write_heff() # calculate the inverse from green import gauss_inverse # routine to invert the matrix # list with the diagonal matrices ldos_e = ldos * 0.0 # initialice ldos at this energy ii = 0 # counter for the element for i in range(len(heff)): # loop over blocks gci = gauss_inverse(heff, i, i) # calculate each block element for j in range(len(heff[0][0])): # loop over each block ldos_e[ii] = -gci[j, j].imag ii += 1 # increase counter if not ii == dimhc: print("Wrong dimensions", ii, dimhc) raise ldos += ldos_e # add to the total ldos # save the effective hamiltonian if hetero.has_spin: # resum ldos if there is spin degree of freedom ldos = [ldos[2 * i] + ldos[2 * i + 1] for i in range(len(ldos) / 2)] if hetero.has_eh: # resum ldos if there is eh ldos = [ldos[2 * i] + ldos[2 * i + 1] for i in range(len(ldos) / 2)] # ne = len(ldos)/2 # ldos = [ldos[i]+ldos[ne+i] for i in range(ne)] ldos = np.array(ldos) # transform into an array if min(ldos) < 0.0: print("Negative density of states") raise g = hetero.central_geometry # geometry of the central part fldos = open("LDOS.OUT", "w") # open file for ldos fldos.write("# X Y LDOS\n") for (ix, iy, il) in zip(g.x, g.y, ldos): fldos.write(str(ix) + " " + str(iy) + " " + str(il) + "\n") fldos.close() # scale the ldos # save the LDOS in a file if True: # if True>0.001: # ldos = np.sqrt(ldos) # ldos = np.arctan(7.*ldos/max(ldos)) print("Sum of the LDOS =", sum(ldos)) ldos = ldos * 300 / max(ldos) else: ldos = ldos * 0.0 # now create the figure fig = py.figure() # create figure fig.subplots_adjust(0.2, 0.2) fig.set_facecolor("white") # face in white sldos = fig.add_subplot(111) # create subplot for the DOS # plot the lattice if not len(g.x) == len(ldos): raise sldos.scatter(g.x, g.y, color="red", s=ldos) # plot the lattice sldos.scatter(g.x, g.y, color="black", s=4) # plot the lattice sldos.set_xlabel("X") sldos.set_xlabel("Y") sldos.axis("equal") # same scale in axes return fig
def landauer(hetero, energy=0.0, delta=0.0001, error=0.0000001, do_leads=True, gr=None, gl=None, has_eh=False): """ Calculates transmission using Landauer formula""" try: # if it is a list return [ landauer(hetero, energy=e, delta=delta, error=error, do_leads=do_leads, gr=gr, gl=gl, has_eh=has_eh) for e in energy ] except: # contnue if it is not a list pass import green from hamiltonians import is_number if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm dimhc = len(intra) # dimension of the central part if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # dimension of the central part dimhc = len(hetero.central_intra) * len(intra) iden = np.matrix(np.identity(len(intra), dtype=complex)) # create idntity intra = hetero.right_intra inter = hetero.right_inter if do_leads: grb, gr = green.green_renormalization(intra, inter, error=error, energy=energy, delta=delta) hetero.right_green = gr # save green function else: gr = hetero.right_green # get the saved green function # left green function intra = hetero.left_intra inter = hetero.left_inter if do_leads: glb, gl = green.green_renormalization(intra, inter, error=error, energy=energy, delta=delta) hetero.left_green = gl # save green function else: gl = hetero.left_green # get the saved green function # left selfenergy inter = hetero.left_coupling selfl = inter * gl * inter.H # left selfenergy # right selfenergy inter = hetero.right_coupling selfr = inter * gr * inter.H # right selfenergy ################################# # calculate spectral functions ################################# gammar = 1j * (selfr - selfr.H) gammal = 1j * (selfl - selfl.H) ################################# # dyson equation for the center ################################# # central green function intra = hetero.central_intra # full matrix if not hetero.block_diagonal: heff = intra + selfl + selfr hetero.heff = heff gc = (energy + 1j * delta) * iden - heff gc = gc.I # calculate inverse if has_eh: # if it has electron-hole, trace over electrons raise G = (gammar * gc * gammal.H * gc.H) G = np.sum([G[2 * i, 2 * i] for i in range(len(G) / 2)]).real else: G = (gammar * gc * gammal.H * gc.H).trace()[0, 0].real return G # reduced matrix if hetero.block_diagonal: from copy import deepcopy heff = deepcopy(intra) heff[0][0] = intra[0][0] + selfl heff[-1][-1] = intra[-1][-1] + selfr dd = (energy + 1j * delta) * iden for i in range(len(intra)): # add the diagonal energy part heff[i][i] = heff[i][i] - dd # this has the wrong sign!! # now change the sign for i in range(len(intra)): for j in range(len(intra)): try: heff[i][j] = -heff[i][j] except: heff[i][j] = heff[i][j] # calculate green function from green import gauss_inverse # routine to invert the matrix # calculate only some elements of the central green function gc1n = gauss_inverse(heff, 0, len(heff) - 1) # calculate element 1,n # and apply Landauer formula if has_eh: # if it has electron-hole, trace over electrons raise G = (gammal * gc1n * gammar.H * gc1n.H) G = np.sum([G[2 * i, 2 * i] for i in range(len(G) / 2)]).real else: G = (gammal * gc1n * gammar.H * gc1n.H).trace()[0, 0].real return G # return transmission
def plot_local_central_dos(hetero,energies=0.0,gf=None): """ Plots the local density of states in the central part""" from green import dyson from green import gf_convergence from hamiltonians import is_number if gf==None: gf = gf_convergence("lead") if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm dimhc = len(intra) # dimension of the central part if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # dimension of the central part dimhc = len(hetero.central_intra)*len(intra) iden = np.matrix(np.identity(len(intra),dtype=complex)) # create idntity ldos = np.array([0.0 for i in range(dimhc)]) # initialice ldos # initialize ldos for energy in energies: # loop over energies # right green function gr = None gl = None # perform dyson calculation intra = hetero.right_intra inter = hetero.right_inter gr = dyson(intra,inter,energy=energy,gf=gf) hetero.right_green = gr # save green function # left green function intra = hetero.left_intra inter = hetero.left_inter gl = dyson(intra,inter,energy=energy,gf=gf) hetero.left_green = gl # save green function # save green functions # hetero.write_green() # print "Saved green functions" # left selfenergy inter = hetero.left_coupling selfl = inter*gl*inter.H # left selfenergy # right selfenergy inter = hetero.right_coupling selfr = inter*gr*inter.H # right selfenergy # central green function intra = hetero.central_intra # dyson equation for the center # full matrix if not hetero.block_diagonal: heff = intra + selfl + selfr hetero.heff = heff gc = (energy+1j*eps)*iden - heff gc = gc.I # calculate inverse # get the local density of states ldos += np.array([-gc[i,i].imag for i in range(len(gc))]) # if save_heff: # print "Saving effective hamiltonian in ",hetero.file_heff # hetero.write_heff() # reduced matrix if hetero.block_diagonal: from copy import deepcopy heff = deepcopy(intra) heff[0][0] = intra[0][0] + selfl heff[-1][-1] = intra[-1][-1] + selfr dd = (energy+1j*gf.eps)*iden for i in range(len(intra)): # add the diagonal energy part heff[i][i] = heff[i][i] - dd # this has the wrong sign!! # now change the sign for i in range(len(intra)): for j in range(len(intra)): try: heff[i][j] = -heff[i][j] except: heff[i][j] = heff[i][j] # save the green function hetero.heff = heff # if save_heff: # print "Saving effective hamiltonian in ",hetero.file_heff # from scipy.sparse import bmat # hetero.heff = bmat(heff) # hetero.write_heff() # calculate the inverse from green import gauss_inverse # routine to invert the matrix # list with the diagonal matrices ldos_e = ldos*0.0 # initialice ldos at this energy ii = 0 # counter for the element for i in range(len(heff)): # loop over blocks gci = gauss_inverse(heff,i,i) # calculate each block element for j in range(len(heff[0][0])): # loop over each block ldos_e[ii] = -gci[j,j].imag ii += 1 # increase counter if not ii==dimhc: print "Wrong dimensions",ii,dimhc raise ldos += ldos_e # add to the total ldos # save the effective hamiltonian if hetero.has_spin: # resum ldos if there is spin degree of freedom ldos = [ldos[2*i]+ldos[2*i+1] for i in range(len(ldos)/2)] if hetero.has_eh: # resum ldos if there is eh ldos = [ldos[2*i]+ldos[2*i+1] for i in range(len(ldos)/2)] # ne = len(ldos)/2 # ldos = [ldos[i]+ldos[ne+i] for i in range(ne)] ldos = np.array(ldos) # transform into an array if min(ldos)<0.0: print "Negative density of states" print ldos raise g = hetero.central_geometry # geometry of the central part fldos = open("LDOS.OUT","w") # open file for ldos fldos.write("# X Y LDOS\n") for (ix,iy,il) in zip(g.x,g.y,ldos): fldos.write(str(ix)+" "+str(iy)+" "+str(il)+"\n") fldos.close() # scale the ldos # save the LDOS in a file if True: # if True>0.001: # ldos = np.sqrt(ldos) # ldos = np.arctan(7.*ldos/max(ldos)) print "Sum of the LDOS =",sum(ldos) ldos = ldos*300/max(ldos) else: ldos = ldos*0.0 # now create the figure fig = py.figure() # create figure fig.subplots_adjust(0.2,0.2) fig.set_facecolor("white") # face in white sldos = fig.add_subplot(111) # create subplot for the DOS # plot the lattice if not len(g.x)==len(ldos): raise sldos.scatter(g.x,g.y,color="red",s=ldos) # plot the lattice sldos.scatter(g.x,g.y,color="black",s=4) # plot the lattice sldos.set_xlabel("X") sldos.set_xlabel("Y") sldos.axis("equal") # same scale in axes return fig
def landauer(hetero,energy=0.0,delta = 0.0001,error=0.0000001,do_leads=True, gr=None,gl=None,has_eh=False): """ Calculates transmission using Landauer formula""" try: # if it is a list return [landauer(hetero,energy=e,delta=delta,error=error, do_leads=do_leads,gr=gr,gl=gl,has_eh=has_eh) for e in energy] except: # contnue if it is not a list pass import green from hamiltonians import is_number if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm dimhc = len(intra) # dimension of the central part if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # dimension of the central part dimhc = len(hetero.central_intra)*len(intra) iden = np.matrix(np.identity(len(intra),dtype=complex)) # create idntity intra = hetero.right_intra inter = hetero.right_inter if do_leads: grb,gr = green.green_renormalization(intra,inter,error=error, energy=energy,delta=delta) hetero.right_green = gr # save green function else: gr = hetero.right_green # get the saved green function # left green function intra = hetero.left_intra inter = hetero.left_inter if do_leads: glb,gl = green.green_renormalization(intra,inter,error=error, energy=energy,delta=delta) hetero.left_green = gl # save green function else: gl = hetero.left_green # get the saved green function # left selfenergy inter = hetero.left_coupling selfl = inter*gl*inter.H # left selfenergy # right selfenergy inter = hetero.right_coupling selfr = inter*gr*inter.H # right selfenergy ################################# # calculate spectral functions ################################# gammar = 1j*(selfr-selfr.H) gammal = 1j*(selfl-selfl.H) ################################# # dyson equation for the center ################################# # central green function intra = hetero.central_intra # full matrix if not hetero.block_diagonal: heff = intra + selfl + selfr hetero.heff = heff gc = (energy+1j*delta)*iden - heff gc = gc.I # calculate inverse # print has_eh if has_eh: # if it has electron-hole, trace over electrons raise G = (gammar*gc*gammal.H*gc.H) G = np.sum([G[2*i,2*i] for i in range(len(G)/2)]).real else: G = (gammar*gc*gammal.H*gc.H).trace()[0,0].real return G # reduced matrix if hetero.block_diagonal: # print has_eh from copy import deepcopy heff = deepcopy(intra) heff[0][0] = intra[0][0] + selfl heff[-1][-1] = intra[-1][-1] + selfr dd = (energy+1j*delta)*iden for i in range(len(intra)): # add the diagonal energy part heff[i][i] = heff[i][i] - dd # this has the wrong sign!! # now change the sign for i in range(len(intra)): for j in range(len(intra)): try: heff[i][j] = -heff[i][j] except: heff[i][j] = heff[i][j] # calculate green function from green import gauss_inverse # routine to invert the matrix # calculate only some elements of the central green function gc1n = gauss_inverse(heff,0,len(heff)-1) # calculate element 1,n # and apply Landauer formula if has_eh: # if it has electron-hole, trace over electrons raise G = (gammal*gc1n*gammar.H*gc1n.H) G = np.sum([G[2*i,2*i] for i in range(len(G)/2)]).real else: G = (gammal*gc1n*gammar.H*gc1n.H).trace()[0,0].real # print "Landauer transmission E=",energy,"G=",G return G # return transmission
def landauer(hetero, energy=0.0, delta=0.0001, error=0.0000001, do_leads=True, gr=None, gl=None, has_eh=False, right_channel=None, left_channel=None): """ Calculates transmission using Landauer formula""" if not do_leads: # if use old Green function, ensure that they are right if energy != hetero.energy_green: do_leads = True print("Wrong energy in Landauer, recalculating Green functions") try: # if it is a list return [ landauer(hetero, energy=e, delta=delta, error=error, do_leads=do_leads, gr=gr, gl=gl, has_eh=has_eh) for e in energy ] except: # contnue if it is not a list pass import green from hamiltonians import is_number if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm dimhc = len(intra) # dimension of the central part if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # dimension of the central part dimhc = len(hetero.central_intra) * intra.shape[0] iden = np.matrix(np.identity(len(intra), dtype=complex)) # create idntity selfl = hetero.get_selfenergy(energy, lead=0, pristine=False) # left Sigma selfr = hetero.get_selfenergy(energy, lead=1, pristine=False) # right Sigma ################################# # calculate Gammas ################################# gammar = 1j * (selfr - selfr.H) gammal = 1j * (selfl - selfl.H) ################################# # dyson equation for the center ################################# # central green function intra = hetero.central_intra # full matrix if not hetero.block_diagonal: heff = intra + selfl + selfr hetero.heff = heff gc = (energy + 1j * delta) * iden - heff gc = gc.I # calculate inverse if has_eh: # if it has electron-hole, trace over electrons raise G = (gammar * gc * gammal.H * gc.H) G = np.sum([G[2 * i, 2 * i] for i in range(len(G) / 2)]).real else: G = (gammar * gc * gammal.H * gc.H).trace()[0, 0].real return G # reduced matrix if hetero.block_diagonal: from copy import deepcopy heff = deepcopy(intra) heff[0][0] = intra[0][0] + selfl heff[-1][-1] = intra[-1][-1] + selfr dd = (energy + 1j * delta) * iden for i in range(len(intra)): # add the diagonal energy part heff[i][i] = heff[i][i] - dd # this has the wrong sign!! # now change the sign for i in range(len(intra)): for j in range(len(intra)): try: heff[i][j] = -heff[i][j] except: heff[i][j] = heff[i][j] # calculate green function from green import gauss_inverse # routine to invert the matrix # calculate only some elements of the central green function gc1n = gauss_inverse(heff, 0, len(heff) - 1) # calculate element 1,n # and apply Landauer formula if has_eh: # if it has electron-hole, trace over electrons raise G = (gammal * gc1n * gammar.H * gc1n.H) G = np.sum([G[2 * i, 2 * i] for i in range(len(G) / 2)]).real else: # extract certain spin channels import extract gammal = extract.spin_channel(gammal, spin_column=left_channel, spin_row=left_channel) gammar = extract.spin_channel(gammar, spin_column=right_channel, spin_row=right_channel) gc1n = extract.spin_channel(gc1n, spin_column=left_channel, spin_row=right_channel) # landauer formula G = (gammal * gc1n * gammar.H * gc1n.H).trace()[0, 0].real return G # return transmission
def landauer(hetero,energies=0.0,delta = 0.001,error=0.00001): """ Calculates transmission using Landauer formula""" from green import dyson from green import gf_convergence import green from hamiltonians import is_number if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm dimhc = len(intra) # dimension of the central part if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # dimension of the central part dimhc = len(hetero.central_intra)*len(intra) iden = np.matrix(np.identity(len(intra),dtype=complex)) # create idntity trans = [] # list with the transmission for energy in energies: # loop over energies intra = hetero.right_intra inter = hetero.right_inter grb,gr = green.green_renormalization(intra,inter,error=error, energy=energy,delta=delta) # gr = dyson(intra,inter,energy=energy,gf=gf) hetero.right_green = gr # save green function # left green function intra = hetero.left_intra inter = hetero.left_inter glb,gl = green.green_renormalization(intra,inter,error=error, energy=energy,delta=delta) hetero.left_green = gl # save green function # left selfenergy inter = hetero.left_coupling selfl = inter*gl*inter.H # left selfenergy # right selfenergy inter = hetero.right_coupling selfr = inter*gr*inter.H # right selfenergy ################################# # calculate spectral functions ################################# gammar = selfr-selfr.H gammal = selfl-selfl.H ################################# # dyson equation for the center ################################# # central green function intra = hetero.central_intra # full matrix if not hetero.block_diagonal: heff = intra + selfl + selfr hetero.heff = heff gc = (energy+1j*delta)*iden - heff gc = gc.I # calculate inverse G = (gammar*gc*gammal.H*gc.H).trace()[0,0].real trans.append(G) # reduced matrix if hetero.block_diagonal: from copy import deepcopy heff = deepcopy(intra) heff[0][0] = intra[0][0] + selfl heff[-1][-1] = intra[-1][-1] + selfr dd = (energy+1j*delta)*iden for i in range(len(intra)): # add the diagonal energy part heff[i][i] = heff[i][i] - dd # this has the wrong sign!! # now change the sign for i in range(len(intra)): for j in range(len(intra)): try: heff[i][j] = -heff[i][j] except: heff[i][j] = heff[i][j] # calculate green function from green import gauss_inverse # routine to invert the matrix # calculate only some elements of the central green function gc1n = gauss_inverse(heff,0,len(heff)-1) # calculate element 1,n # and apply Landauer formula G = (gammal*gc1n*gammar.H*gc1n.H).trace()[0,0].real trans.append(G) print "Landauer transmission E=",energy,"G=",G return trans # return transmission
def landauer(hetero,energy=0.0,delta = 0.0001,error=0.0000001,do_leads=True, gr=None,gl=None,has_eh=False,right_channel=None, left_channel=None): """ Calculates transmission using Landauer formula""" if not do_leads: # if use old Green function, ensure that they are right if energy != hetero.energy_green: do_leads = True print("Wrong energy in Landauer, recalculating Green functions") try: # if it is a list return [landauer(hetero,energy=e,delta=delta,error=error, do_leads=do_leads,gr=gr,gl=gl,has_eh=has_eh) for e in energy] except: # contnue if it is not a list pass import green from hamiltonians import is_number if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm dimhc = len(intra) # dimension of the central part if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # dimension of the central part dimhc = len(hetero.central_intra)*intra.shape[0] iden = np.matrix(np.identity(len(intra),dtype=complex)) # create idntity selfl = hetero.get_selfenergy(energy,lead=0,pristine=False) # left Sigma selfr = hetero.get_selfenergy(energy,lead=1,pristine=False) # right Sigma ################################# # calculate Gammas ################################# gammar = 1j*(selfr-selfr.H) gammal = 1j*(selfl-selfl.H) ################################# # dyson equation for the center ################################# # central green function intra = hetero.central_intra # full matrix if not hetero.block_diagonal: heff = intra + selfl + selfr hetero.heff = heff gc = (energy+1j*delta)*iden - heff gc = gc.I # calculate inverse if has_eh: # if it has electron-hole, trace over electrons raise G = (gammar*gc*gammal.H*gc.H) G = np.sum([G[2*i,2*i] for i in range(len(G)/2)]).real else: G = (gammar*gc*gammal.H*gc.H).trace()[0,0].real return G # reduced matrix if hetero.block_diagonal: from copy import deepcopy heff = deepcopy(intra) heff[0][0] = intra[0][0] + selfl heff[-1][-1] = intra[-1][-1] + selfr dd = (energy+1j*delta)*iden for i in range(len(intra)): # add the diagonal energy part heff[i][i] = heff[i][i] - dd # this has the wrong sign!! # now change the sign for i in range(len(intra)): for j in range(len(intra)): try: heff[i][j] = -heff[i][j] except: heff[i][j] = heff[i][j] # calculate green function from green import gauss_inverse # routine to invert the matrix # calculate only some elements of the central green function gc1n = gauss_inverse(heff,0,len(heff)-1) # calculate element 1,n # and apply Landauer formula if has_eh: # if it has electron-hole, trace over electrons raise G = (gammal*gc1n*gammar.H*gc1n.H) G = np.sum([G[2*i,2*i] for i in range(len(G)/2)]).real else: # extract certain spin channels import extract gammal = extract.spin_channel(gammal,spin_column=left_channel, spin_row=left_channel) gammar = extract.spin_channel(gammar,spin_column=right_channel, spin_row=right_channel) gc1n = extract.spin_channel(gc1n,spin_column=left_channel, spin_row=right_channel) # landauer formula G = (gammal*gc1n*gammar.H*gc1n.H).trace()[0,0].real return G # return transmission
def get_smatrix(ht, energy=0.0, delta=0.0001, as_matrix=False): """Calculate the S-matrix of an heterostructure""" # selfenergy of the leads (coupled to another cell of the lead) (selfl, selfr) = get_surface_selfenergies(ht, energy=energy, delta=delta) if ht.block_diagonal: raise # not implemented # gamma functions gammar = 1j * (selfr - selfr.H) gammal = 1j * (selfl - selfl.H) # now do the Fisher Lee trick smatrix = [[None, None], [None, None]] # smatrix in list form gmatrix = build_effective_hlist(ht, energy=energy, delta=delta, selfl=selfl, selfr=selfr) # calculate the relevant terms of the Green function from green import gauss_inverse # calculate the desired green functions g11 = gauss_inverse(gmatrix, 0, 0) g12 = gauss_inverse(gmatrix, 0, -1) g21 = gauss_inverse(gmatrix, -1, 0) g22 = gauss_inverse(gmatrix, -1, -1) # print (gammal*g12*gammar*g21).trace() ######## now build up the s matrix with the fisher trick # the identity can have different dimension ignore for now.... iden = np.matrix(np.identity(g11.shape[0], dtype=complex)) # create idntity iden11 = np.matrix(np.identity(g11.shape[0], dtype=complex)) # create idntity iden22 = np.matrix(np.identity(g22.shape[0], dtype=complex)) # create idntity smatrix[0][0] = -iden + 1j * sqrtm(gammal) * g11 * sqrtm(gammal) # matrix smatrix[1][0] = -1j * sqrtm(gammal) * g12 * sqrtm( gammar) # transmission matrix smatrix[0][1] = -1j * sqrtm(gammar) * g21 * sqrtm( gammal) # transmission matrix smatrix[1][1] = -iden + 1j * sqrtm(gammar) * g22 * sqrtm(gammar) # matrix ################################## # alternative way, rotating into the diagonal basis for gamma # (bgl,bgr) = get_bulk_green(ht,energy=energy,delta=delta) # vl = 1j*(bgl-bgl.H) # left velocity matrix # vr = 1j*(bgr-bgr.H) # left velocity matrix # (Dgammal, Rl) = sqrtm_rotated(gammar) # (Dgammar, Rr) = sqrtm_rotated(gammal) # (Dgammal, RR) = sqrtm_rotated(vl) # (Dgammar, RR) = sqrtm_rotated(vr) # smatrix[0][0] = -iden11 + 1j*Dgammal*Rl*g11*Rl.H*Dgammal # matrix # smatrix[1][1] = -iden22 + 1j*Dgammar*Rr*g22*Rr.H*Dgammar # matrix # smatrix[0][1] = 1j*Dgammal*Rl*g12*Rr.H*Dgammar # matrix # smatrix[1][0] = 1j*Dgammar*Rr*g21*Rl.H*Dgammal # matrix # raise # bullshit # smatrix[0][0] = -iden + 1j*sqrtm(vl)*g11*sqrtm(vl) # matrix # smatrix[0][1] = 1j*sqrtm(vl)*g12*sqrtm(vr) # transmission matrix # smatrix[1][0] = 1j*sqrtm(vr)*g21*sqrtm(vl) # transmission matrix # smatrix[1][1] = -iden + 1j*sqrtm(vr)*g22*sqrtm(vr) # matrix # from scipy.sparse import csc_matrix # print csc_matrix(gammar - sqrtm(gammar)*sqrtm(gammar)).data if as_matrix: from scipy.sparse import bmat, csc_matrix smatrix2 = [[csc_matrix(smatrix[i][j]) for i in range(2)] for j in range(2)] smatrix = bmat(smatrix2).todense() return smatrix
def randm(): return np.random.random((4,4)) + 1j*np.random.random((4,4)) d = [randm() for i in range(n)] a = [randm() for i in range(n-1)] b = [randm() for i in range(n-1)] m = [[None for i in range(n)] for j in range(n)] for i in range(n): m[i][i] = d[i] for i in range(n-1): m[i][i+1] = a[i] m[i+1][i] = b[i] mden = bmat(m).todense() # dense matrix minv = [[None for i in range(n)] for j in range(n)] for i in range(n): for j in range(n): minv[i][j] = csc_matrix(green.gauss_inverse(m,i=i,j=j)) minv = bmat(minv).todense() print "Maximun error" print np.max(np.abs(mden.I - minv))