def central_dos(hetero,energies=[0.0],num_rep=100, mixing=0.7,eps=0.0001,green_guess=None,max_error=0.0001): """ Calculates the density of states of a heterostructure by a green function approach, input is a heterostructure class""" from green import dyson dos = [] # list with the density of states intra = hetero.central_intra # central intraterm iden = np.matrix(np.identity(len(intra),dtype=complex)) # create idntity for energy in energies: # loop over energies # right green function intra = hetero.right_intra inter = hetero.right_inter gr = dyson(intra,inter,energy=energy,num_rep=num_rep,mixing=mixing, eps=eps,green_guess=green_guess,max_error=max_error) # left green function intra = hetero.left_intra inter = hetero.left_inter gl = dyson(intra,inter,energy=energy,num_rep=num_rep,mixing=mixing, eps=eps,green_guess=green_guess,max_error=max_error) # 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 gc = energy*iden -intra -selfl -selfr # dyson equation for the center gc = gc.I # calculate inverse dos.append(-gc.trace()[0,0].imag) # calculate the trace of the Green function return dos
def effective_central_hamiltonian(hetero, energy=0.0, write=False, gf=None): """ Plots the local density of states in the central part""" from green import dyson from hamiltonians import is_number if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # perform dyson calculation intra = hetero.right_intra inter = hetero.right_inter gr = dyson(intra, inter, is_sparse=hetero.is_sparse, gf=gf) hetero.right_green = gr # save green function # left green function intra = hetero.left_intra inter = hetero.left_inter gl = dyson(intra, inter, is_sparse=hetero.is_sparse, 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 if save_heff: print "Saving effective hamiltonian in ", hetero.file_heff if write: # save hamiltonian if desired 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 # save the green function from scipy.sparse import bmat hetero.heff = bmat(heff) if write: # save hamiltonian print "Saving effective hamiltonian in ", hetero.file_heff hetero.write_heff()
def effective_central_hamiltonian(hetero,energy=0.0,write=False,gf=None): """ Plots the local density of states in the central part""" from green import dyson from hamiltonians import is_number if not hetero.block_diagonal: intra = hetero.central_intra # central intraterm if hetero.block_diagonal: intra = hetero.central_intra[0][0] # when it is diagonal # perform dyson calculation intra = hetero.right_intra inter = hetero.right_inter gr = dyson(intra,inter,is_sparse=hetero.is_sparse,gf=gf) hetero.right_green = gr # save green function # left green function intra = hetero.left_intra inter = hetero.left_inter gl = dyson(intra,inter,is_sparse=hetero.is_sparse,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 if save_heff: print "Saving effective hamiltonian in ",hetero.file_heff if write: # save hamiltonian if desired 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 # save the green function from scipy.sparse import bmat hetero.heff = bmat(heff) if write: # save hamiltonian print "Saving effective hamiltonian in ",hetero.file_heff hetero.write_heff()
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 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
from time import clock es = np.linspace(-3.0,3.0,500) told = clock() if True: bulk = [] surf = [] for e in es: dos_bulk,dos_surf = green.green_renormalization(h.intra, h.inter,energy=e) bulk.append(-dos_bulk.trace()[0,0].imag) surf.append(-dos_surf.trace()[0,0].imag) py.plot(es,surf,color="blue",marker="o") py.plot(es,bulk,color="red",marker="x") print told-clock() told = clock() if False: for e in es: dos = green.dyson(h.intra,h.inter,energy = e) dos = -dos.trace()[0,0].imag py.scatter(e,dos,color="red",marker="x") print told-clock() py.show()
def landauer(hetero, energies=0.0, gf=None, delta=0.001): """ Calculates transmission using Landauer formula""" from green import dyson from green import gf_convergence import green if gf == None: gf = gf_convergence("lead") 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, 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, 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 * gf.eps) * 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 * 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] # 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,energies=0.0,gf=None,delta = 0.001): """ 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, 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, 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*gf.eps)*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*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] # 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
py.figure() from time import clock es = np.linspace(-3.0, 3.0, 500) told = clock() if True: bulk = [] surf = [] for e in es: dos_bulk, dos_surf = green.green_renormalization(h.intra, h.inter, energy=e) bulk.append(-dos_bulk.trace()[0, 0].imag) surf.append(-dos_surf.trace()[0, 0].imag) py.plot(es, surf, color="blue", marker="o") py.plot(es, bulk, color="red", marker="x") print told - clock() told = clock() if False: for e in es: dos = green.dyson(h.intra, h.inter, energy=e) dos = -dos.trace()[0, 0].imag py.scatter(e, dos, color="red", marker="x") print told - clock() py.show()