コード例 #1
0
def main():
    elec1 = NEGF.ElectrodeSelfEnergy(
        'Self-energy-FCC111/ELEC-1x1/Au3D_BCA.TSHS', 3, 3)
    elec3 = NEGF.ElectrodeSelfEnergy(
        'Self-energy-FCC111/ELEC-3x3/Au3D_BCA.TSHS', 1, 1)
    elec1.semiinf = 2
    elec3.semiinf = 2
    maxerr = 0.0

    for ii in range(10):
        ee = RA.random() * 10 - 5 + RA.random() * 5.0j
        k = RA.random(2)
        print " Checking energy: %f+%fi k-point: %f,%f" % (ee.real, ee.imag,
                                                           k[0], k[1])

        Sig1 = elec1.getSig(ee, k, left=True, Bulk=True)
        Sig3 = elec3.getSig(ee, k, left=True, Bulk=True)
        tmp = N.max(abs(Sig1 - Sig3))
        maxerr = max(tmp, maxerr)
        print 'Left, Bulk : max(abs(Sig1-Sig3)) ', tmp
        Sig1 = elec1.getSig(ee, k, left=False, Bulk=True)
        Sig3 = elec3.getSig(ee, k, left=False, Bulk=True)
        tmp = N.max(abs(Sig1 - Sig3))
        maxerr = max(tmp, maxerr)
        print 'Right, Bulk : max(abs(Sig1-Sig3)) ', tmp
        Sig1 = elec1.getSig(ee, k, left=True, Bulk=False)
        Sig3 = elec3.getSig(ee, k, left=True, Bulk=False)
        tmp = N.max(abs(Sig1 - Sig3))
        maxerr = max(tmp, maxerr)
        print 'Left, no-Bulk : max(abs(Sig1-Sig3)) ', tmp
        Sig1 = elec1.getSig(ee, k, left=False, Bulk=False)
        Sig3 = elec3.getSig(ee, k, left=False, Bulk=False)
        tmp = N.max(abs(Sig1 - Sig3))
        maxerr = max(tmp, maxerr)
        print 'Right, no-Bulk : max(abs(Sig1-Sig3)) ', tmp

    print
    print "#########################################"
    print "#########################################"
    print "Maximum error : ", maxerr
    if maxerr > 0.001:
        print "ERROR!"
        kuk
    else:
        print "Test passed!"
    print "#########################################"
    print "#########################################"
    print
コード例 #2
0
ファイル: TestFCC100.py プロジェクト: QinglangL/inelastica
def main():
    maxerr = 0.0

    elec1 = NEGF.ElectrodeSelfEnergy('Self-energy-FCC100/ELEC-1x1/ABAB.TSHS', 3, 3)
    elec3 = NEGF.ElectrodeSelfEnergy('Self-energy-FCC100/ELEC-3x3/ABAB.TSHS', 1, 1)

    maxerr = comp_SE(elec1, elec3)
    del elec1, elec3

    print
    print "#########################################"
    print "#########################################"
    print "Maximum error : ", maxerr
    if maxerr > 0.001:
        print "ERROR!"
        kuk
    else:
        print "Test passed!"
    print "#########################################"
    print "#########################################"
    print
コード例 #3
0
def calcTraces(options, GF1, GF2, basis, NCfile, ihw):
    # Calculate various traces over the electronic structure
    # Electron-phonon couplings
    ihw = int(ihw)
    M = N.array(NCfile.variables['He_ph'][ihw, options.iSpin, :, :], N.complex)
    try:
        M += 1.j * N.array(
            NCfile.variables['ImHe_ph'][ihw, options.iSpin, :, :], N.complex)
    except:
        print 'Warning: Variable ImHe_ph not found'
    # Calculation of intermediate quantity
    MARGLGM = MM.mm(M, GF1.ARGLG, M)
    MARGLGM2 = MM.mm(M, GF2.ARGLG, M)
    # LOE expressions in compact form
    t1 = MM.mm(MARGLGM, GF2.AR)
    t2 = MM.mm(MARGLGM2, GF1.AL)
    # Note that compared with Eq. (10) of PRB89, 081405 (2014) we here use
    # the definition B_lambda = MM.trace(t1-dagger(t2)), which in turn gives
    # ReB = MM.trace(t1).real-MM.trace(t2).real
    # ImB = MM.trace(t1).imag+MM.trace(t2).imag
    K23 = MM.trace(t1).imag + MM.trace(t2).imag
    K4 = MM.trace(MM.mm(M, GF1.ALT, M, GF2.AR))
    aK23 = 2 * (MM.trace(t1).real - MM.trace(t2).real)  # asymmetric part
    # Non-Hilbert term defined here with a minus sign
    GF1.nHT[ihw] = NEGF.AssertReal(K23 + K4, 'nHT[%i]' % ihw)
    GF1.HT[ihw] = NEGF.AssertReal(aK23, 'HT[%i]' % ihw)
    # Power, damping and current rates
    GF1.P1T[ihw] = NEGF.AssertReal(MM.trace(MM.mm(M, GF1.A, M, GF2.A)),
                                   'P1T[%i]' % ihw)
    GF1.P2T[ihw] = NEGF.AssertReal(MM.trace(MM.mm(M, GF1.AL, M, GF2.AR)),
                                   'P2T[%i]' % ihw)
    GF1.ehDampL[ihw] = NEGF.AssertReal(MM.trace(MM.mm(M, GF1.AL, M, GF2.AL)),
                                       'ehDampL[%i]' % ihw)
    GF1.ehDampR[ihw] = NEGF.AssertReal(MM.trace(MM.mm(M, GF1.AR, M, GF2.AR)),
                                       'ehDampR[%i]' % ihw)
    # Remains from older version (see before rev. 219):
    #GF.dGnout.append(EC.calcCurrent(options,basis,GF.HNO,mm(Us,-0.5j*(tmp1-dagger(tmp1)),Us)))
    #GF.dGnin.append(EC.calcCurrent(options,basis,GF.HNO,mm(Us,mm(G,MA1M,Gd)-0.5j*(tmp2-dagger(tmp2)),Us)))
    # NB: TF Should one use GF.HNO (nonorthogonal) or GF.H (orthogonalized) above?

    if options.LOEscale == 0.0:
        # Check against original LOE-WBA formulation
        isym1 = MM.mm(GF1.ALT, M, GF2.AR, M)
        isym2 = MM.mm(MM.dagger(GF1.ARGLG), M, GF2.A, M)
        isym3 = MM.mm(GF1.ARGLG, M, GF2.A, M)
        isym = MM.trace(isym1) + 1j / 2. * (MM.trace(isym2) - MM.trace(isym3))
        print 'LOE-WBA check: Isym diff', K23 + K4 - isym
        iasym1 = MM.mm(MM.dagger(GF1.ARGLG), M, GF2.AR - GF2.AL, M)
        iasym2 = MM.mm(GF1.ARGLG, M, GF2.AR - GF2.AL, M)
        iasym = MM.trace(iasym1) + MM.trace(iasym2)
        print 'LOE-WBA check: Iasym diff', aK23 - iasym

        # Compute inelastic shot noise terms according to the papers
        # Haupt, Novotny & Belzig, PRB 82, 165441 (2010) and
        # Avriller & Frederiksen, PRB 86, 155411 (2012)
        # Zero-temperature limit
        TT = MM.mm(GF1.GammaL,
                   GF1.AR)  # this matrix has the correct shape for MM
        ReGr = (GF1.Gr + GF1.Ga) / 2.
        tmp = MM.mm(GF1.Gr, M, ReGr, M, GF1.AR)
        tmp = tmp + MM.dagger(tmp)
        Tlambda0 = MM.mm(GF1.GammaL, tmp)
        tmp1 = MM.mm(M, GF1.AR, M)
        tmp2 = MM.mm(M, GF1.A, M, GF1.Gr, GF1.GammaR)
        tmp = tmp1 + 1j / 2. * (MM.dagger(tmp2) - tmp2)
        Tlambda1 = MM.mm(GF1.GammaL, GF1.Gr, tmp, GF1.Ga)
        MARGL = MM.mm(M, GF1.AR, GF1.GammaL)
        tmp1 = MM.mm(MARGL, GF1.AR, M)
        tmp2 = MM.mm(MARGL, GF1.Gr, M, GF1.Gr, GF1.GammaR)
        tmp = tmp1 + tmp2
        tmp = tmp + MM.dagger(tmp)
        Qlambda = MM.mm(-GF1.Ga, GF1.GammaL, GF1.Gr, tmp)
        tmp = -2 * TT
        OneMinusTwoT = tmp + N.identity(len(GF1.GammaL))
        # Store relevant traces
        GF1.dIel[ihw] = NEGF.AssertReal(MM.trace(Tlambda0), 'dIel[%i]' % ihw)
        GF1.dIinel[ihw] = NEGF.AssertReal(MM.trace(Tlambda1),
                                          'dIinel[%i]' % ihw)
        GF1.dSel[ihw] = NEGF.AssertReal(
            MM.trace(MM.mm(OneMinusTwoT, Tlambda0)), 'dSel[%i]' % ihw)
        GF1.dSinel[ihw] = NEGF.AssertReal(
            MM.trace(Qlambda + MM.mm(OneMinusTwoT, Tlambda1)),
            'dSinel[%i]' % ihw)
コード例 #4
0
def main(options):
    """
    Main routine to compute inelastic transport characteristics (dI/dV, d2I/dV2, IETS etc)

    Parameters
    ----------
    options : an ``options`` instance
    """
    CF.CreatePipeOutput(options.DestDir + '/' + options.Logfile)
    VC.OptionsCheck(options, 'Inelastica')
    CF.PrintMainHeader('Inelastica', options)

    options.XV = '%s/%s.XV' % (options.head, options.systemlabel)
    options.geom = MG.Geom(options.XV, BufferAtoms=options.buffer)
    # Voltage fraction over left-center interface
    VfracL = options.VfracL  # default is 0.5
    print 'Inelastica: Voltage fraction over left-center interface: VfracL =', VfracL
    # Set up electrodes and device Greens function
    elecL = NEGF.ElectrodeSelfEnergy(options.fnL, options.NA1L, options.NA2L,
                                     options.voltage * VfracL)
    elecL.scaling = options.scaleSigL
    elecL.semiinf = options.semiinfL
    elecR = NEGF.ElectrodeSelfEnergy(options.fnR, options.NA1R, options.NA2R,
                                     options.voltage * (VfracL - 1.))
    elecR.scaling = options.scaleSigR
    elecR.semiinf = options.semiinfR
    # Read phonons
    NCfile = NC4.Dataset(options.PhononNetCDF, 'r')
    print 'Inelastica: Reading ', options.PhononNetCDF
    hw = NCfile.variables['hw'][:]
    # Work with GFs etc for positive (V>0: \mu_L>\mu_R) and negative (V<0: \mu_L<\mu_R) bias voltages
    GFp = NEGF.GF(options.TSHS,
                  elecL,
                  elecR,
                  Bulk=options.UseBulk,
                  DeviceAtoms=options.DeviceAtoms,
                  BufferAtoms=options.buffer)
    # Prepare lists for various trace factors
    #GF.dGnout = []
    #GF.dGnin = []
    GFp.P1T = N.zeros(len(hw), N.float)  # M.A.M.A (total e-h damping)
    GFp.P2T = N.zeros(len(hw), N.float)  # M.AL.M.AR (emission)
    GFp.ehDampL = N.zeros(len(hw), N.float)  # M.AL.M.AL (L e-h damping)
    GFp.ehDampR = N.zeros(len(hw), N.float)  # M.AR.M.AR (R e-h damping)
    GFp.nHT = N.zeros(len(hw), N.float)  # non-Hilbert/Isym factor
    GFp.HT = N.zeros(len(hw), N.float)  # Hilbert/Iasym factor
    GFp.dIel = N.zeros(len(hw), N.float)
    GFp.dIinel = N.zeros(len(hw), N.float)
    GFp.dSel = N.zeros(len(hw), N.float)
    GFp.dSinel = N.zeros(len(hw), N.float)
    #
    GFm = NEGF.GF(options.TSHS,
                  elecL,
                  elecR,
                  Bulk=options.UseBulk,
                  DeviceAtoms=options.DeviceAtoms,
                  BufferAtoms=options.buffer)
    GFm.P1T = N.zeros(len(hw), N.float)  # M.A.M.A (total e-h damping)
    GFm.P2T = N.zeros(len(hw), N.float)  # M.AL.M.AR (emission)
    GFm.ehDampL = N.zeros(len(hw), N.float)  # M.AL.M.AL (L e-h damping)
    GFm.ehDampR = N.zeros(len(hw), N.float)  # M.AR.M.AR (R e-h damping)
    GFm.nHT = N.zeros(len(hw), N.float)  # non-Hilbert/Isym factor
    GFm.HT = N.zeros(len(hw), N.float)  # Hilbert/Iasym factor
    GFm.dIel = N.zeros(len(hw), N.float)
    GFm.dIinel = N.zeros(len(hw), N.float)
    GFm.dSel = N.zeros(len(hw), N.float)
    GFm.dSinel = N.zeros(len(hw), N.float)
    # Calculate transmission at Fermi level
    GFp.calcGF(options.energy + options.eta * 1.0j,
               options.kpoint[0:2],
               ispin=options.iSpin,
               etaLead=options.etaLead,
               useSigNCfiles=options.signc,
               SpectralCutoff=options.SpectralCutoff)
    L = options.bufferL
    # Pad lasto with zeroes to enable basis generation...
    lasto = N.zeros((GFp.HS.nua + L + 1, ), N.int)
    lasto[L:] = GFp.HS.lasto
    basis = SIO.BuildBasis(options.fn, options.DeviceAtoms[0] + L,
                           options.DeviceAtoms[1] + L, lasto)
    basis.ii -= L
    TeF = MM.trace(GFp.TT).real
    GFp.TeF = TeF
    GFm.TeF = TeF
    # Check consistency of PHrun vs TSrun inputs
    IntegrityCheck(options, GFp, basis, NCfile)
    # Calculate trace factors one mode at a time
    print 'Inelastica: LOEscale =', options.LOEscale
    if options.LOEscale == 0.0:
        # LOEscale=0.0 => Original LOE-WBA method, PRB 72, 201101(R) (2005) [cond-mat/0505473].
        GFp.calcGF(options.energy + options.eta * 1.0j,
                   options.kpoint[0:2],
                   ispin=options.iSpin,
                   etaLead=options.etaLead,
                   useSigNCfiles=options.signc,
                   SpectralCutoff=options.SpectralCutoff)
        GFm.calcGF(options.energy + options.eta * 1.0j,
                   options.kpoint[0:2],
                   ispin=options.iSpin,
                   etaLead=options.etaLead,
                   useSigNCfiles=options.signc,
                   SpectralCutoff=options.SpectralCutoff)
        for ihw in (hw > options.modeCutoff).nonzero()[0]:
            calcTraces(options, GFp, GFm, basis, NCfile, ihw)
            calcTraces(options, GFm, GFp, basis, NCfile, ihw)
        writeFGRrates(options, GFp, hw, NCfile)
    else:
        # LOEscale=1.0 => Generalized LOE, PRB 89, 081405(R) (2014) [arXiv:1312.7625]
        for ihw in (hw > options.modeCutoff).nonzero()[0]:
            GFp.calcGF(options.energy + hw[ihw] * options.LOEscale * VfracL +
                       options.eta * 1.0j,
                       options.kpoint[0:2],
                       ispin=options.iSpin,
                       etaLead=options.etaLead,
                       useSigNCfiles=options.signc,
                       SpectralCutoff=options.SpectralCutoff)
            GFm.calcGF(options.energy + hw[ihw] * options.LOEscale *
                       (VfracL - 1.) + options.eta * 1.0j,
                       options.kpoint[0:2],
                       ispin=options.iSpin,
                       etaLead=options.etaLead,
                       useSigNCfiles=options.signc,
                       SpectralCutoff=options.SpectralCutoff)
            calcTraces(options, GFp, GFm, basis, NCfile, ihw)
            if VfracL != 0.5:
                GFp.calcGF(options.energy - hw[ihw] * options.LOEscale *
                           (VfracL - 1.) + options.eta * 1.0j,
                           options.kpoint[0:2],
                           ispin=options.iSpin,
                           etaLead=options.etaLead,
                           useSigNCfiles=options.signc,
                           SpectralCutoff=options.SpectralCutoff)
                GFm.calcGF(options.energy -
                           hw[ihw] * options.LOEscale * VfracL +
                           options.eta * 1.0j,
                           options.kpoint[0:2],
                           ispin=options.iSpin,
                           etaLead=options.etaLead,
                           useSigNCfiles=options.signc,
                           SpectralCutoff=options.SpectralCutoff)
            calcTraces(options, GFm, GFp, basis, NCfile, ihw)

    # Multiply traces with voltage-dependent functions
    data = calcIETS(options, GFp, GFm, basis, hw)
    NCfile.close()
    NEGF.SavedSig.close()
    CF.PrintMainFooter('Inelastica')
    return data
コード例 #5
0
def main():
    if not SIO.F90imported:
        print "To test the F90 routines you better compile them first"
        kuk

    print 'TESTING reading routines:\n'

    # Test readTSHS routines
    for file in ['Self-energy-FCC111/ELEC-1x1/Au3D_BCA.TSHS', 'sample.onlyS']:
        HS1 = SIO.HS('../TestCalculations/' + file, UseF90helpers=False)
        HS2 = SIO.HS('../TestCalculations/' + file, UseF90helpers=True)
        compare_H(HS1, HS2)

    # Test readTSHS routines new vs. old
    for file in [
            'Self-energy-FCC100/ELEC-1x1/ABAB.TSHS',
            'Self-energy-FCC111/ELEC-1x1/Au3D_BCA.TSHS'
    ]:
        HS1 = SIO.HS('../TestCalculations/' + file, UseF90helpers=True)
        HS2 = SIO.HS('../TestCalculations/' +
                     file.replace('.TSHS', '_NEW.TSHS'),
                     UseF90helpers=True)
        compare_H(HS1, HS2, not_checks={'xij': False})

    # Test removeUnitCellXij
    print 'TESTING removeUnitCellXij method'
    elec1 = NEGF.ElectrodeSelfEnergy(
        '../TestCalculations/Self-energy-FCC111/ELEC-1x1/Au3D_BCA.TSHS',
        1,
        1,
        UseF90helpers=True)
    elec2 = NEGF.ElectrodeSelfEnergy(
        '../TestCalculations/Self-energy-FCC111/ELEC-1x1/Au3D_BCA.TSHS',
        1,
        1,
        UseF90helpers=False)
    maxerr = N.max(abs(elec1.HS.xij - elec2.HS.xij))
    print "Maximum difference between Xij :", maxerr

    for ii in range(10):
        k = N.array(RA.random(3), N.float)
        print " Checking k-point: %f,%f,%f" % (k[0], k[1], k[2])
        elec1.HS.kpoint = N.zeros((3, ),
                                  N.float)  # To ensure it is calculated!
        elec1.HS.setkpoint(k, UseF90helpers=True)
        H1, S1 = elec1.HS.H.copy(), elec1.HS.S.copy()
        elec2.HS.kpoint = N.zeros((3, ),
                                  N.float)  # To ensure it is calculated!
        elec2.HS.setkpoint(k, UseF90helpers=False)
        H2, S2 = elec2.HS.H.copy(), elec2.HS.S.copy()
        tmp1 = N.max(abs(H1 - H2))
        tmp2 = N.max(abs(S1 - S2))
        print "Max difference kpointhelper: ", max(tmp1, tmp2)
        if maxerr > 1e-9:
            print "ERROR!"
            kuk

        ee = RA.random(1) + 0.0001j
        elec1.semiinf = 2
        elec2.semiinf = 2
        SGF1 = elec1.getSig(ee, k[0:2].copy(), UseF90helpers=True)
        SGF2 = elec2.getSig(ee, k[0:2].copy(), UseF90helpers=False)
        SGFerr = N.max(abs(SGF1 - SGF2))
        print "Max difference for self-energy: ", SGFerr
        maxerr = max(tmp1, tmp2, SGFerr, maxerr)
        if maxerr > 1e-9:
            print "ERROR!"
            kuk

    # SurfaceGF
    print '\nTESTING pyTBT.surfaceGF method (1x1 vs 3x3)'
    elecF90 = NEGF.ElectrodeSelfEnergy(
        '../TestCalculations/Self-energy-FCC111/ELEC-1x1/Au3D_BCA.TSHS',
        3,
        3,
        UseF90helpers=True)
    elecNoF90 = NEGF.ElectrodeSelfEnergy(
        '../TestCalculations/Self-energy-FCC111/ELEC-1x1/Au3D_BCA.TSHS',
        3,
        3,
        UseF90helpers=False)

    for ii in range(10):
        k = N.array(RA.random(3), N.float)
        print " Checking k-point: %f,%f,%f" % (k[0], k[1], k[2])
        elecF90.HS.kpoint = N.zeros((3, ),
                                    N.float)  # To ensure it is calculated!
        elecF90.HS.setkpoint(k, UseF90helpers=True)
        H1, S1 = elecF90.HS.H.copy(), elecF90.HS.S.copy()
        elecNoF90.HS.kpoint = N.zeros((3, ),
                                      N.float)  # To ensure it is calculated!
        elecNoF90.HS.setkpoint(k, UseF90helpers=False)
        H2, S2 = elecNoF90.HS.H.copy(), elecNoF90.HS.S.copy()
        tmp1 = N.max(abs(H1 - H2))
        tmp2 = N.max(abs(S1 - S2))
        print "Max difference kpointhelper: ", max(tmp1, tmp2)
        if maxerr > 1e-9:
            print "ERROR!"
            kuk

        ee = RA.random(1) + 0.0001j
        elecF90.semiinf = 2
        elecNoF90.semiinf = 2
        SGFf90 = elecF90.getSig(ee, k[0:2].copy(), UseF90helpers=True)
        SGF = elecNoF90.getSig(ee, k[0:2].copy(), UseF90helpers=False)
        SGFerr = N.max(abs(SGFf90 - SGF))
        print "Max difference for self-energy: ", SGFerr
        maxerr = max(tmp1, tmp2, SGFerr, maxerr)
        if maxerr > 1e-9:
            print "ERROR!"
            kuk

    print "Maximum error : ", maxerr
    print
    print "###############################################################"
    print "###############################################################"
    if maxerr > 1e-9:
        print "ERROR!"
        kuk
    else:
        print "Tests passed for remove Xij, expansion_SE, readTSHS, and setkpoint!"
    print "###############################################################"
    print "###############################################################"
    print
コード例 #6
0
def main(options):
    """
    Main routine to compute eigenchannel scattering states

    Parameters
    ----------
    options : an ``options`` instance
    """

    Log.CreatePipeOutput(options)
    VC.OptionsCheck(options)
    Log.PrintMainHeader(options)

    # Read geometry
    XV = '%s/%s.XV' % (options.head, options.systemlabel)
    geom = MG.Geom(XV, BufferAtoms=options.buffer)

    # Set up device Greens function
    elecL = NEGF.ElectrodeSelfEnergy(options.fnL, options.NA1L, options.NA2L,
                                     options.voltage / 2.)
    elecL.scaling = options.scaleSigL
    elecL.semiinf = options.semiinfL
    elecR = NEGF.ElectrodeSelfEnergy(options.fnR, options.NA1R, options.NA2R,
                                     -options.voltage / 2.)
    elecR.scaling = options.scaleSigR
    elecR.semiinf = options.semiinfR
    DevGF = NEGF.GF(options.TSHS,
                    elecL,
                    elecR,
                    Bulk=options.UseBulk,
                    DeviceAtoms=options.DeviceAtoms,
                    BufferAtoms=options.buffer)
    DevGF.calcGF(options.energy + options.eta * 1.0j,
                 options.kpoint[0:2],
                 ispin=options.iSpin,
                 etaLead=options.etaLead,
                 useSigNCfiles=options.signc,
                 SpectralCutoff=options.SpectralCutoff)
    NEGF.SavedSig.close()  # Make sure saved Sigma is written to file

    # Transmission
    print('Transmission Ttot(%.4feV) = %.16f' %
          (options.energy, N.trace(DevGF.TT).real))

    # Build basis
    options.nspin = DevGF.HS.nspin
    L = options.bufferL
    # Pad lasto with zeroes to enable basis generation...
    lasto = N.zeros((DevGF.HS.nua + L + 1, ), N.int)
    lasto[L:] = DevGF.HS.lasto
    basis = SIO.BuildBasis(options.fn, options.DeviceAtoms[0] + L,
                           options.DeviceAtoms[1] + L, lasto)
    basis.ii -= L

    # Calculate Eigenchannels
    DevGF.calcEigChan(options.numchan)

    # Compute bond currents?
    if options.kpoint[0] != 0.0 or options.kpoint[1] != 0.0:
        print(
            'Warning: The current implementation of bond currents is only valid for the Gamma point (should be easy to fix)'
        )
        BC = False
    else:
        BC = True

    # Eigenchannels from left
    ECleft = DevGF.ECleft
    for jj in range(options.numchan):
        options.iSide, options.iChan = 0, jj + 1
        writeWavefunction(options, geom, basis, ECleft[jj])
        if BC:
            Curr = calcCurrent(options, basis, DevGF.H, ECleft[jj])
            writeCurrent(options, geom, Curr)

    # Calculate eigenchannels from right
    if options.bothsides:
        ECright = DevGF.ECright
        for jj in range(options.numchan):
            options.iSide, options.iChan = 1, jj + 1
            writeWavefunction(options, geom, basis, ECright[jj])
            if BC:
                Curr = calcCurrent(options, basis, DevGF.H, ECright[jj])
                writeCurrent(options, geom, Curr)

    # Calculate total "bond currents"
    if BC:
        Curr = -calcCurrent(options, basis, DevGF.H, DevGF.AL)
        options.iChan, options.iSide = 0, 0
        writeCurrent(options, geom, Curr)
        Curr = -calcCurrent(options, basis, DevGF.H, DevGF.AR)
        options.iSide = 1
        writeCurrent(options, geom, Curr)

    # Calculate eigenstates of device Hamiltonian (MPSH)
    if options.MolStates > 0.0:
        try:
            import scipy.linalg as SLA
            ev, es = SLA.eigh(DevGF.H, DevGF.S)
            print(
                'EigenChannels: Eigenvalues (in eV) of computed molecular eigenstates:'
            )
            print(ev)
            # Write eigenvalues to file
            fn = options.DestDir + '/' + options.systemlabel + '.EIGVAL'
            print('EigenChannels: Writing', fn)
            fnfile = open(fn, 'w')
            fnfile.write('# Device region = [%i,%i], units in eV\n' %
                         (options.DeviceFirst, options.DeviceLast))
            for i, val in enumerate(ev):
                fnfile.write('%i %.8f\n' % (i, val))
            fnfile.close()
            # Compute selected eigenstates
            for ii, val in enumerate(ev):
                if N.abs(val) < options.MolStates:
                    fn = options.DestDir + '/' + options.systemlabel + '.S%.3i.E%.3f' % (
                        ii, val)
                    writeWavefunction(options, geom, basis, es[:, ii], fn=fn)
        except:
            print(
                'You need to install scipy to solve the generalized eigenvalue problem'
            )
            print('for the molecular eigenstates in the nonorthogonal basis')

    Log.PrintMainFooter(options)
    return DevGF
コード例 #7
0
def main(options):
    """
    Main routine to compute elastic transmission probabilities etc.

    Parameters
    ----------
    options : an ``options`` instance
    """
    CF.CreatePipeOutput(options.DestDir + '/' + options.Logfile)
    VC.OptionsCheck(options, 'pyTBT')
    CF.PrintMainHeader('pyTBT', options)

    # K-points
    if options.Gk1 > 1:
        Nk1, t1 = options.Gk1, 'GK'
    else:
        Nk1, t1 = options.Nk1, 'LIN'
    if options.Gk2 > 1:
        Nk2, t2 = options.Gk2, 'GK'
    else:
        Nk2, t2 = options.Nk2, 'LIN'
    # Generate full k-mesh:
    mesh = Kmesh.kmesh(Nk1,
                       Nk2,
                       Nk3=1,
                       meshtype=[t1, t2, 'LIN'],
                       invsymmetry=not options.skipsymmetry)
    mesh.mesh2file(
        '%s/%s.%ix%i.mesh' %
        (options.DestDir, options.systemlabel, mesh.Nk[0], mesh.Nk[1]))
    # Setup self-energies and device GF
    elecL = NEGF.ElectrodeSelfEnergy(options.fnL, options.NA1L, options.NA2L,
                                     options.voltage / 2.)
    elecL.scaling = options.scaleSigL
    elecL.semiinf = options.semiinfL
    elecR = NEGF.ElectrodeSelfEnergy(options.fnR, options.NA1R, options.NA2R,
                                     -options.voltage / 2.)
    elecR.scaling = options.scaleSigR
    elecR.semiinf = options.semiinfR
    DevGF = NEGF.GF(options.TSHS,
                    elecL,
                    elecR,
                    Bulk=options.UseBulk,
                    DeviceAtoms=options.DeviceAtoms,
                    BufferAtoms=options.buffer)
    nspin = DevGF.HS.nspin

    # k-sample only self-energies?
    if options.singlejunction:
        elecL.mesh = mesh
        mesh = Kmesh.kmesh(3, 3, 1)

    if options.dos:
        DOSL = N.zeros((nspin, len(options.Elist), DevGF.nuo), N.float)
        DOSR = N.zeros((nspin, len(options.Elist), DevGF.nuo), N.float)

        # MPSH projections?
        MPSHL = N.zeros((nspin, len(options.Elist), DevGF.nuo), N.float)
        MPSHR = N.zeros((nspin, len(options.Elist), DevGF.nuo), N.float)
        # evaluate eigenstates at Gamma
        import scipy.linalg as SLA
        DevGF.setkpoint(N.zeros(2))
        ev0, es0 = SLA.eigh(DevGF.H, DevGF.S)
        print 'MPSH eigenvalues:', ev0
        #print 'MPSH eigenvector normalizations:',N.diag(MM.mm(MM.dagger(es0),DevGF.S,es0)).real # right

    # Loop over spin
    for iSpin in range(nspin):
        # initialize transmission and shot noise arrays
        Tkpt = N.zeros((len(options.Elist), mesh.NNk, options.numchan + 1),
                       N.float)
        SNkpt = N.zeros((len(options.Elist), mesh.NNk, options.numchan + 1),
                        N.float)
        # prepare output files
        outFile = options.DestDir + '/%s.%ix%i' % (options.systemlabel,
                                                   mesh.Nk[0], mesh.Nk[1])
        if nspin < 2: thisspinlabel = outFile
        else: thisspinlabel = outFile + ['.UP', '.DOWN'][iSpin]
        fo = open(thisspinlabel + '.AVTRANS', 'write')
        fo.write('# Nk1(%s)=%i Nk2(%s)=%i eta=%.2e etaLead=%.2e\n' %
                 (mesh.type[0], mesh.Nk[0], mesh.type[1], mesh.Nk[1],
                  options.eta, options.etaLead))
        fo.write('# E   Ttot(E)   Ti(E)(i=1-%i)   RelErrorTtot(E)\n' %
                 options.numchan)
        foSN = open(thisspinlabel + '.AVNOISE', 'write')
        foSN.write('# Nk1(%s)=%i Nk2(%s)=%i eta=%.2e etaLead=%.2e\n' %
                   (mesh.type[0], mesh.Nk[0], mesh.type[1], mesh.Nk[1],
                    options.eta, options.etaLead))
        foSN.write('# E   SNtot(E)   SNi(E)(i=1-%i)\n' % options.numchan)
        foFF = open(thisspinlabel + '.FANO', 'write')
        foFF.write('# Nk1(%s)=%i Nk2(%s)=%i eta=%.2e etaLead=%.2e\n' %
                   (mesh.type[0], mesh.Nk[0], mesh.type[1], mesh.Nk[1],
                    options.eta, options.etaLead))
        foFF.write('# E   Fano factor \n')
        # Loop over energy
        for ie, ee in enumerate(options.Elist):
            Tavg = N.zeros((options.numchan + 1, len(mesh.w)), N.float)
            SNavg = N.zeros((options.numchan + 1, len(mesh.w)), N.float)
            AavL = N.zeros((DevGF.nuo, DevGF.nuo), N.complex)
            AavR = N.zeros((DevGF.nuo, DevGF.nuo), N.complex)
            # Loops over k-points
            for ik in range(mesh.NNk):
                DevGF.calcGF(ee + options.eta * 1.0j,
                             mesh.k[ik, :2],
                             ispin=iSpin,
                             etaLead=options.etaLead,
                             useSigNCfiles=options.signc,
                             SpectralCutoff=options.SpectralCutoff)
                # Transmission and shot noise
                T, SN = DevGF.calcTEIG(options.numchan)
                for iw in range(len(mesh.w)):
                    Tavg[:, iw] += T * mesh.w[iw, ik]
                    SNavg[:, iw] += SN * mesh.w[iw, ik]
                Tkpt[ie, ik] = T
                SNkpt[ie, ik] = SN
                # DOS calculation:
                if options.dos:
                    if options.SpectralCutoff > 0.0:
                        AavL += mesh.w[0, ik] * MM.mm(DevGF.AL.L, DevGF.AL.R,
                                                      DevGF.S)
                        AavR += mesh.w[0, ik] * MM.mm(DevGF.AR.L, DevGF.AR.R,
                                                      DevGF.S)
                    else:
                        AavL += mesh.w[0, ik] * MM.mm(DevGF.AL, DevGF.S)
                        AavR += mesh.w[0, ik] * MM.mm(DevGF.AR, DevGF.S)
            # Print calculated quantities
            err = (N.abs(Tavg[0, 0] - Tavg[0, 1]) +
                   N.abs(Tavg[0, 0] - Tavg[0, 2])) / 2
            relerr = err / Tavg[0, 0]
            print 'ispin= %i, e= %.4f, Tavg= %.8f, RelErr= %.1e' % (
                iSpin, ee, Tavg[0, 0], relerr)
            transline = '\n%.10f ' % ee
            noiseline = '\n%.10f ' % ee
            for ichan in range(options.numchan + 1):
                if ichan == 0:
                    transline += '%.8e ' % Tavg[ichan, 0]
                    noiseline += '%.8e ' % SNavg[ichan, 0]
                else:
                    transline += '%.4e ' % Tavg[ichan, 0]
                    noiseline += '%.4e ' % SNavg[ichan, 0]
            transline += '%.2e ' % relerr
            fo.write(transline)
            foSN.write(noiseline)
            foFF.write('\n%.10f %.8e' % (ee, SNavg[0, 0] / Tavg[0, 0]))
            # Partial density of states:
            if options.dos:
                DOSL[iSpin, ie, :] += N.diag(AavL).real / (2 * N.pi)
                DOSR[iSpin, ie, :] += N.diag(AavR).real / (2 * N.pi)
                MPSHL[iSpin, ie, :] += N.diag(MM.mm(MM.dagger(es0), AavL,
                                                    es0)).real / (2 * N.pi)
                MPSHR[iSpin, ie, :] += N.diag(MM.mm(MM.dagger(es0), AavR,
                                                    es0)).real / (2 * N.pi)
                print 'ispin= %i, e= %.4f, DOSL= %.4f, DOSR= %.4f' % (
                    iSpin, ee, N.sum(DOSL[iSpin,
                                          ie, :]), N.sum(DOSR[iSpin, ie, :]))
        fo.write('\n')
        fo.close()
        foSN.write('\n')
        foSN.close()
        foFF.write('\n')
        foFF.close()

        # Write k-point-resolved transmission
        fo = open(thisspinlabel + '.TRANS', 'write')
        for ik in range(mesh.NNk):
            w = mesh.w[:, ik]
            fo.write('\n\n# k = %f, %f    w = %f %f %f %f' %
                     (mesh.k[ik, 0], mesh.k[ik, 1], w[0], w[1], w[2], w[3]))
            for ie, ee in enumerate(options.Elist):
                transline = '\n%.10f ' % ee
                for ichan in range(options.numchan + 1):
                    if ichan == 0:
                        transline += '%.8e ' % Tkpt[ie, ik, ichan]
                    else:
                        transline += '%.4e ' % Tkpt[ie, ik, ichan]
                fo.write(transline)
        fo.write('\n')
        fo.close()

        # Write k-point-resolved shot noise
        fo = open(thisspinlabel + '.NOISE', 'write')
        for ik in range(mesh.NNk):
            w = mesh.w[:, ik]
            fo.write('\n\n# k = %f, %f    w = %f %f %f %f' %
                     (mesh.k[ik, 0], mesh.k[ik, 1], w[0], w[1], w[2], w[3]))
            for ie, ee in enumerate(options.Elist):
                noiseline = '\n%.10f ' % ee
                for ichan in range(options.numchan + 1):
                    if ichan == 0:
                        noiseline += '%.8e ' % SNkpt[ie, ik, ichan]
                    else:
                        noiseline += '%.4e ' % SNkpt[ie, ik, ichan]
                fo.write(noiseline)
        fo.write('\n')
        fo.close()

    # End loop over spin
    NEGF.SavedSig.close()  # Make sure saved Sigma is written to file

    if options.dos:
        # Read basis
        L = options.bufferL
        # Pad lasto with zeroes to enable basis generation...
        lasto = N.zeros((DevGF.HS.nua + L + 1, ), N.int)
        lasto[L:] = DevGF.HS.lasto
        basis = SIO.BuildBasis(options.fn, 1 + L, DevGF.HS.nua + L, lasto)
        basis.ii -= L
        WritePDOS(outFile + '.PDOS.gz', options, DevGF, DOSL + DOSR, basis)
        WritePDOS(outFile + '.PDOSL.gz', options, DevGF, DOSL, basis)
        WritePDOS(outFile + '.PDOSR.gz', options, DevGF, DOSR, basis)

        WriteMPSH(outFile + '.MPSH.gz', options, DevGF, MPSHL + MPSHR, ev0)
        WriteMPSH(outFile + '.MPSHL.gz', options, DevGF, MPSHL, ev0)
        WriteMPSH(outFile + '.MPSHR.gz', options, DevGF, MPSHR, ev0)

    CF.PrintMainFooter('pyTBT')
コード例 #8
0
ファイル: STM.py プロジェクト: eminamitani/inelastica-local
def calcTSWF(options, ikpoint):
    kpoint = options.kpoints.k[ikpoint]
    def calcandwrite(A, txt, kpoint, ikpoint):
        if isinstance(A, MM.SpectralMatrix):
            A=A.full()
        A=A*PC.Rydberg2eV # Change to 1/Ryd
        ev, U = LA.eigh(A)
        Utilde = N.empty(U.shape, U.dtype)
        for jj, val in enumerate(ev): # Problems with negative numbers
            if val<0: val=0
            Utilde[:, jj]=N.sqrt(val/(2*N.pi))*U[:, jj]
        indx2 = N.where(abs(abs(ev)>1e-4))[0] # Pick non-zero states

        ev=ev[indx2]
        Utilde=Utilde[:, indx2]
        indx=ev.real.argsort()[::-1]
        fn=options.DestDir+'/%i/'%(ikpoint)+options.systemlabel+'.%s'%(txt)

        path = './'+options.DestDir+'/'
        #FermiEnergy = SIO.HS(options.systemlabel+'.TSHS').ef

        def noWfs(side):
            tmp = len(glob.glob(path+str(ikpoint)+'/'+options.systemlabel+'.A'+side+'*'))
            return tmp
        if noWfs('L')==0 or noWfs('R')==0 and len(glob.glob(path+str(ikpoint)+'/FD*'))==0:
            print('Calculating localized-basis states from spectral function %s ...'%(txt))
            tlb = time.clock()
            calcWF2(options, geom, options.DeviceAtoms, basis, Utilde[:, indx], [N1, N2, N3, minN3, maxN3], Fold=True, k=kpoint, fn=fn)
            times = N.round(time.clock()-tlb, 2); timem = N.round(times/60, 2)
            print('Finished in '+str(times)+' s = '+str(timem)+' min')

        if noWfs('L')>0 and noWfs('R')>0 and len(glob.glob(path+str(ikpoint)+'/FD*'))==0 and str('%s'%(txt))==str('AR'):
            print('\nLocalized-basis states are calculated in k point '+str(ikpoint)+'/.')
            print('------------------------------------------------------')
            print('Finite-difference calculation of vacuum states starts!')
            timeFD = time.clock()
            STMFD.main(options, kpoint, ikpoint)
            print('FD calculation in k-point folder '+str(ikpoint)+'/ done in '+str(N.round((time.clock()-timeFD)/60, 2))+' min.')
            print('------------------------------------------------------')
            if options.savelocwfs == False:
                os.system('rm -f '+path+str(ikpoint)+'/'+options.systemlabel+'*')

    #Read geometry
    XV = '%s/%s.XV'%(options.head, options.systemlabel)
    geom = MG.Geom(XV, BufferAtoms=options.buffer)

    #Set up device Greens function
    elecL = NEGF.ElectrodeSelfEnergy(options.fnL, options.NA1L, options.NA2L, options.voltage/2.)
    elecL.scaling = options.scaleSigL
    elecL.semiinf = options.semiinfL
    elecR = NEGF.ElectrodeSelfEnergy(options.fnR, options.NA1R, options.NA2R, -options.voltage/2.)
    elecR.scaling = options.scaleSigR
    elecR.semiinf = options.semiinfR
    DevGF = NEGF.GF(options.TSHS, elecL, elecR, Bulk=options.UseBulk,
                    DeviceAtoms=options.DeviceAtoms,
                    BufferAtoms=options.buffer)

    DevGF.calcGF(options.energy+options.eta*1.0j, kpoint[0:2], ispin=options.iSpin,
                 etaLead=options.etaLead, useSigNCfiles=options.signc, SpectralCutoff=options.SpectralCutoff)
    NEGF.SavedSig.close() #Make sure saved Sigma is written to file
    #Transmission
    print('Transmission Ttot(%.4feV) = %.16f'%(options.energy, N.trace(DevGF.TT).real))

    #Build basis
    options.nspin = DevGF.HS.nspin
    L = options.bufferL
    #Pad lasto with zeroes to enable basis generation...
    lasto = N.zeros((DevGF.HS.nua+L+1,), N.int)
    lasto[L:] = DevGF.HS.lasto
    basis = SIO.BuildBasis(options.fn,
                           options.DeviceAtoms[0]+L,
                           options.DeviceAtoms[1]+L, lasto)
    basis.ii -= L

    file = NC.Dataset('TotalPotential.grid.nc', 'r')
    N1, N2, N3 = len(file.dimensions['n1']), len(file.dimensions['n2']), len(file.dimensions['n3'])
    cell = file.variables['cell'][:]
    file.close()

    #Find device region in a3 axis
    U = LA.inv(N.array([cell[0]/N1, cell[1]/N2, cell[2]/N3]).transpose())
    gridindx = N.dot(geom.xyz[options.DeviceAtoms[0]-1:options.DeviceAtoms[1]]/PC.Bohr2Ang, U)
    minN3, maxN3 = N.floor(N.min(gridindx[:, 2])).astype(N.int), N.ceil(N.max(gridindx[:, 2])).astype(N.int)
    if not N.allclose(geom.pbc, cell*PC.Bohr2Ang):
        print('Error: TotalPotential.grid.nc has different cell compared to geometry')
        sys.exit(1)

    print('\nk-point folder '+str(ikpoint)+'/')
    print('Checking/calculating localized-basis states ...')
    calcandwrite(DevGF.AL, 'AL', kpoint, ikpoint)
    calcandwrite(DevGF.AR, 'AR', kpoint, ikpoint)