Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
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.º 5
0
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
Ejemplo n.º 6
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.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
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))