Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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