Example #1
0
 def calcTEIG(self, channels=10):
     # Transmission matrix (complex array)
     TT = self.TT
     Trans = N.trace(TT)
     VC.Check("trans-imaginary-part", Trans.imag,
              "Transmission has large imaginary part")
     # Calculate eigenchannel transmissions too
     tval, tvec = LA.eig(TT)
     idx = (tval.real).argsort()[::-1]  # sort from largest to smallest
     tval = tval[idx]
     tvec = tvec[:, idx]
     # Compute shot noise
     Smat = MM.mm(TT, N.identity(len(TT)) - TT)
     sval = N.diag(MM.mm(MM.dagger(tvec), Smat, tvec))
     # set up arrays
     T = N.zeros(channels + 1)
     SN = N.zeros(channels + 1)
     T[0] = Trans.real
     SN[0] = N.trace(Smat).real
     for i in range(min(channels, len(TT))):
         T[i + 1] = tval[i].real
         SN[i + 1] = sval[i].real
     return T, SN
Example #2
0
def AssertReal(x, label):
    VC.Check("zero-imaginary-part", abs(x.imag),
             "Imaginary part too large in quantity %s" % label)
    return x.real
Example #3
0
    def __init__(self,
                 TSHSfile,
                 elecL,
                 elecR,
                 Bulk=True,
                 DeviceAtoms=[0, 0],
                 BufferAtoms=N.empty((0, ))):
        """
        Calculate Green's functions etc for TSHSfile connected to left/right 
        electrode (class ElectrodeSelfEnergy). 
        To speed up calculations folding to smaller device region suggested
        For spin-polarized calcGF has to be called for each ispin
        Variables:
        Gr     : Retarded Green's function, folded
        H,S    : Hamiltonian, overlap, folded
        H0,S0  : Hamiltonian, overlap, not folded
        nuo    : Size of Gr
        SigL, SigR, GamL, GamR : Self energy, Gamma NOTE, not same size as Gr! 
        nuoL, nuoR : Size of Sig, Gam
        nuo0, nuoL0, nuoR0 : Non-folded sizes
        FoldedL, FoldedR : True/False
        DeviceAtoms : start/end Siesta numbering of atoms included in device
        DeviceOrbs : Start/end of orbitals. Siesta ordering.
        BufferAtoms: A list of buffer atoms
        """
        self.elecL, self.elecR, self.Bulk = elecL, elecR, Bulk
        self.HS = SIO.HS(TSHSfile, BufferAtoms=BufferAtoms)
        print 'GF: UseBulk=', Bulk
        self.DeviceAtoms = DeviceAtoms
        if DeviceAtoms[0] <= 1:
            self.DeviceAtoms[0] = 1
            self.FoldedL = False
        else:
            self.FoldedL = True
        if DeviceAtoms[1] == 0 or DeviceAtoms[1] >= self.HS.nua:
            self.DeviceAtoms[1] = self.HS.nua
            self.FoldedR = False
        else:
            self.FoldedR = True
        self.DeviceOrbs = [
            self.HS.lasto[DeviceAtoms[0] - 1] + 1,
            self.HS.lasto[DeviceAtoms[1]]
        ]

        self.nuo0, self.nuoL0, self.nuoR0 = self.HS.nuo, elecL.NA1 * elecL.NA2 * elecL.HS.nuo, elecR.NA1 * elecR.NA2 * elecR.HS.nuo
        self.nuo = self.DeviceOrbs[1] - self.DeviceOrbs[0] + 1
        self.nuoL, self.nuoR = self.nuoL0, self.nuoR0  # Not folded, for folded case changed below

        print "GF:", TSHSfile
        print "Device atoms %i-%i, orbitals %i-%i" % (tuple(self.DeviceAtoms +
                                                            self.DeviceOrbs))
        if not self.FoldedL:
            print "Suggest left folding to atom : ", self.elecL.HS.nua * self.elecL.NA1 * self.elecL.NA2 + 1
        if not self.FoldedR:
            print "Suggest right folding to atom : ", self.HS.nua - self.elecR.HS.nua * self.elecR.NA1 * self.elecR.NA2

        if self.FoldedL or self.FoldedR:
            # Check that device region is large enough!
            kpoint = N.zeros((2, ), N.float)
            self.setkpoint(kpoint, ispin=0)  # At least for one spin

            devSt, devEnd = self.DeviceOrbs[0], self.DeviceOrbs[1]
            VC.Check("Device-Elec-overlap",
                     N.abs(self.S0[0:devSt, devEnd:self.nuo0]),
                     "Too much overlap directly from left-top right",
                     "Make device region larger")
            VC.Check("Device-Elec-overlap",
                     N.abs(self.H0[0:devSt, devEnd:self.nuo0]),
                     "Too large Hamiltonian directly from left-top right.",
                     "Make device region larger")
        if self.FoldedL:
            # Find orbitals in device region coupling to left and right.
            tau = abs(self.S0[0:devSt - 1, 0:devEnd])
            coupling = N.sum(tau, axis=0)
            ii = devEnd - 1
            while coupling[ii] < 1e-10:
                ii = ii - 1
            self.devEndL = max(ii + 1, self.nuoL0)
            self.nuoL = self.devEndL - devSt + 1
            print "Left self energy on orbitals %i-%i" % (devSt, self.devEndL)
        if self.FoldedR:
            tau = abs(self.S0[devEnd - 1:self.nuo0, 0:self.nuo0])
            coupling = N.sum(tau, axis=0)
            ii = devSt - 1
            while coupling[ii] < 1e-10:
                ii = ii + 1
            self.devStR = min(ii + 1, self.nuo0 - self.nuoR0 + 1)
            self.nuoR = devEnd - self.devStR + 1
            print "Right self energy on orbitals %i-%i" % (self.devStR, devEnd)
        # Quantities expressed in nonorthogonal basis:
        self.OrthogonalDeviceRegion = False
Example #4
0
    def calcg0_old(self, ee, ispin=0, left=True):
        """
        Only used if SciPy is not installed!
        For the left surface Green's function  (1 is surface layer, 0 is all the other atoms):
        (E S00-H00  E S01-H01)   (g00 g01)    ( I 0 )
        (E S10-H10  E S11-H11) * (g01 g11)  = ( 0 I ) ->
        call E S - H for t ...

        t00 g01 + t01 g11 = 0  -> g01 = - t00^-1 t01 g11
        t10 g01 + t11 g11 = I -> - t10 t00^-1 t01 g11 + t11 g11 = I -> 

        And we get the surface Green's function:

        g11 = (t11 - t10 t00^-1 t01)^-1 with the right size of unitcell t00^-1 = g11!
        g11 = (E S11 - H11 - (E S10 - H10) g11 (E S01 - H01))^-1

        In the calculations H01^+ and S01^+ are used instead of S10 and H10.
        (For complex energies (E S01 -H01)^+ is not (E S10 -H10) because the conjugate of the energy!!!!)

        For the right surface greens function same but different order on the MM.daggers!
        i.e., (E S - H - (E S01 - H01) gs (E S01^+ -H01^+)

        Algorith: Lopez Sancho*2 J Phys F:Met Phys 15 (1985) 851

        I'm still very suspicios of this algorithm ... but it works and is really quick!
        The convergence is always checked against gs (E S - H - (E S01^+ - H01^+) gs (E S01 -H01) ) = I!
        """
        H, S, H01, S01 = self.H[ispin, :, :], self.S, self.H01[
            ispin, :, :], self.S01

        alpha, beta = MM.dagger(H01) - ee * MM.dagger(S01), H01 - ee * S01
        eps, epss = H.copy(), H.copy()

        converged = False
        iteration = 0
        while not converged:
            iteration += 1
            oldeps, oldepss = eps.copy(), epss.copy()
            oldalpha, oldbeta = alpha.copy(), beta.copy()
            tmpa = LA.solve(ee * S - oldeps, oldalpha)
            tmpb = LA.solve(ee * S - oldeps, oldbeta)
            alpha, beta = MM.mm(oldalpha, tmpa), MM.mm(oldbeta, tmpb)
            eps = oldeps + MM.mm(oldalpha, tmpb) + MM.mm(oldbeta, tmpa)
            if left:
                epss = oldepss + MM.mm(oldalpha, tmpb)
            else:
                epss = oldepss + MM.mm(oldbeta, tmpa)
            LopezConvTest = N.max(abs(alpha) + abs(beta))
            if LopezConvTest < 1.0e-40:
                gs = LA.inv(ee * S - epss)
                if left:
                    test = ee * S - H - MM.mm(
                        ee * MM.dagger(S01) - MM.dagger(H01), gs,
                        ee * S01 - H01)
                else:
                    test = ee * S - H - MM.mm(
                        ee * S01 - H01, gs,
                        ee * MM.dagger(S01) - MM.dagger(H01))
                myConvTest = N.max(
                    abs(
                        MM.mm(test, gs) -
                        N.identity((self.HS.nuo), N.complex)))
                if myConvTest < VC.GetCheck("Lopez-Sancho"):
                    converged = True
                    if myConvTest > VC.GetCheck("Lopez-Sancho-warning"):
                        v = "RIGHT"
                        if left: v = "LEFT"
                        print "WARNING: Lopez-scheme not-so-well converged for " + v + " electrode at E = %.4f eV:" % ee, myConvTest
                else:
                    VC.Check("Lopez-Sancho", myConvTest,
                             "Error: gs iteration {0}".format(iteration))
        return gs