Пример #1
0
def main(options):
    CF.CreatePipeOutput(options.DestDir+'/'+options.Logfile)
    CF.PrintMainHeader('Phonons',vinfo,options)

    # Determine SIESTA input fdf files in FCruns
    fdf = glob.glob(options.FCwildcard+'/RUN.fdf')

    print 'Phonons.Analyze: This run uses'
    FCfirst,FClast = min(options.DynamicAtoms),max(options.DynamicAtoms)
    print '  ... FCfirst     = %4i, FClast     = %4i, Dynamic atoms = %4i'\
          %(FCfirst,FClast,len(options.DynamicAtoms))
    print '  ... DeviceFirst = %4i, DeviceLast = %4i, Device atoms  = %4i'\
          %(options.DeviceFirst,options.DeviceLast,options.DeviceLast-options.DeviceFirst+1)
    print '  ... PBC First   = %4i, PBC Last   = %4i, Device atoms  = %4i'\
          %(options.PBCFirst,options.PBCLast,options.PBCLast-options.PBCFirst+1)

    print '\nSetting array type to %s\n'%options.atype

    # Build Dynamical Matrix
    DM = DynamicalMatrix(fdf,options.DynamicAtoms)
    DM.SetMasses(options.Isotopes)
    # Compute modes
    DM.ComputePhononModes(DM.mean)
    # Compute e-ph coupling
    if options.CalcCoupl:
       DM.PrepareGradients(options.onlySdir,options.kpoint,options.DeviceFirst,options.DeviceLast,options.AbsEref,options.atype)
       DM.ComputeEPHcouplings(options.PBCFirst,options.PBCLast,options.EPHAtoms,options.Restart,options.CheckPointNetCDF,
                              WriteGradients=options.WriteGradients)
       # Write data to files
       DM.WriteOutput(options.DestDir+'/Output',options.SinglePrec,options.GammaPoint)
       CF.PrintMainFooter('Phonons')
       return DM.h0,DM.s0,DM.hw,DM.heph
    else:
       DM.WriteOutput(options.DestDir+'/Output',options.SinglePrec,options.GammaPoint)
       CF.PrintMainFooter('Phonons')
       return DM.hw
Пример #2
0
def main(options):
    CF.CreatePipeOutput(options.DestDir + '/' + options.Logfile)
    VC.OptionsCheck(options, 'EigenChannels')
    CF.PrintMainHeader('EigenChannels', vinfo, 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, EigT = DevGF.ECleft, DevGF.EigTleft
    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, EigT = DevGF.ECright, DevGF.EigTright
        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
            file = open(fn, 'w')
            file.write('# Device region = [%i,%i], units in eV\n' %
                       (options.DeviceFirst, options.DeviceLast))
            for i in range(len(ev)):
                file.write('%i %.8f\n' % (i, ev[i]))
            file.close()
            # Compute selected eigenstates
            for ii in range(len(ev)):
                if N.abs(ev[ii]) < options.MolStates:
                    fn = options.DestDir + '/' + options.systemlabel + '.S%.3i.E%.3f' % (
                        ii, ev[ii])
                    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'

    CF.PrintMainFooter('EigenChannels')
Пример #3
0
def main(options):
    CF.CreatePipeOutput(options.DestDir + '/' + options.Logfile)
    #VC.OptionsCheck(options,'Phonons')

    CF.PrintMainHeader('Bandstructures', vinfo, options)

    SC = Supercell(options.xvfilename, options.tshsfilename)

    # Write high-symmetry path
    WritePath(options.DestDir + '/symmetry-path', SC.Sym.path, options.steps)

    # Evaluate electron k-points
    # Prepare Hamiltonian etc in Gamma for whole supercell
    natoms = SC.Sym.NN
    # Read TSHS
    SC.TSHS = SIO.HS(options.tshsfilename)
    SC.nao = SC.TSHS.nuo
    SCDM.FirstOrb = SCDM.OrbIndx[0][0]  # First atom = 1
    SCDM.LastOrb = SCDM.OrbIndx[SCDM.Sym.basis.NN - 1][1]  # Last atom = Sym.NN
    SCDM.rednao = SCDM.LastOrb + 1 - SCDM.FirstOrb
    # Read kpoints
    kpts, dk, klabels, kticks = ReadKpoints(options.kfile)
    if klabels:
        # Only write ascii if labels exist
        WriteKpoints(options.DestDir + '/kpoints', kpts, klabels)
    # Prepare netcdf
    ncfn = options.DestDir + '/Electrons.nc'
    ncf = NC4.Dataset(ncfn, 'w')
    # Grid
    ncf.createDimension('gridpts', len(kpts))
    ncf.createDimension('vector', 3)
    grid = ncf.createVariable('grid', 'd', ('gridpts', 'vector'))
    grid[:] = kpts
    grid.units = '1/Angstrom'
    # Geometry
    ncf.createDimension('atoms', SCDM.Sym.basis.NN)
    xyz = ncf.createVariable('xyz', 'd', ('atoms', 'vector'))
    xyz[:] = SCDM.Sym.basis.xyz
    xyz.units = 'Angstrom'
    pbc = ncf.createVariable('pbc', 'd', ('vector', 'vector'))
    pbc.units = 'Angstrom'
    pbc[:] = [SCDM.Sym.a1, SCDM.Sym.a2, SCDM.Sym.a3]
    rvec1 = ncf.createVariable('rvec', 'd', ('vector', 'vector'))
    rvec1.units = '1/Angstrom (incl. factor 2pi)'
    rvec1[:] = rvec
    ncf.sync()
    # Loop over kpoints
    for i, k in enumerate(kpts):
        if i < 100:  # Print only for the first 100 points
            ev, evec = SCDM.ComputeElectronStates(k, verbose=True)
        else:
            ev, evec = SCDM.ComputeElectronStates(k, verbose=False)
            # otherwise something simple
            if i % 100 == 0:
                print '%i out of %i k-points computed' % (i, len(kpts))
        if i == 0:
            ncf.createDimension('nspin', SCDM.nspin)
            ncf.createDimension('orbs', SCDM.rednao)
            ncf.createDimension('bands', SCDM.rednao)
            evals = ncf.createVariable('eigenvalues', 'd',
                                       ('gridpts', 'nspin', 'bands'))
            evals.units = 'eV'
            evecsRe = ncf.createVariable('eigenvectors.re', 'd',
                                         ('gridpts', 'nspin', 'orbs', 'bands'))
            evecsIm = ncf.createVariable('eigenvectors.im', 'd',
                                         ('gridpts', 'nspin', 'orbs', 'bands'))
            # Check eigenvectors
            print 'SupercellPhonons: Checking eigenvectors at', k
            for j in range(SCDM.nspin):
                ev2 = N.diagonal(
                    MM.mm(MM.dagger(evec[j]), SCDM.h0_k[j], evec[j]))
                print ' ... spin %i: Allclose=' % j, N.allclose(ev[j],
                                                                ev2,
                                                                atol=1e-5,
                                                                rtol=1e-3)
        ncf.sync()
    # Write to NetCDF
    evals[i, :] = ev
    evecsRe[i, :] = evec.real
    evecsIm[i, :] = evec.imag
    ncf.sync()
    # Include basis orbitals in netcdf file
    lasto = SCDM.OrbIndx[:SCDM.Sym.basis.NN + 1, 0]
    orbbasis = SIO.BuildBasis(fdf[0], 1, SCDM.Sym.basis.NN, lasto)
    # Note that the above basis is for the geometry with an atom FC-moved in z.
    #print dir(orbbasis)
    #print orbbasis.xyz # Hence, this is not the correct geometry of the basis atoms!
    center = ncf.createVariable('orbcenter', 'i', ('orbs', ))
    center[:] = N.array(orbbasis.ii - 1, dtype='int32')
    center.description = 'Atom index (counting from 0) of the orbital center'
    nn = ncf.createVariable('N', 'i', ('orbs', ))
    nn[:] = N.array(orbbasis.N, dtype='int32')
    ll = ncf.createVariable('L', 'i', ('orbs', ))
    ll[:] = N.array(orbbasis.L, dtype='int32')
    mm = ncf.createVariable('M', 'i', ('orbs', ))
    mm[:] = N.array(orbbasis.M, dtype='int32')
    # Cutoff radius and delta
    Rc = ncf.createVariable('Rc', 'd', ('orbs', ))
    Rc[:] = orbbasis.coff
    Rc.units = 'Angstrom'
    delta = ncf.createVariable('delta', 'd', ('orbs', ))
    delta[:] = orbbasis.delta
    delta.units = 'Angstrom'
    # Radial components of the orbitals
    ntb = len(orbbasis.orb[0])
    ncf.createDimension('ntb', ntb)
    rii = ncf.createVariable('rii', 'd', ('orbs', 'ntb'))
    rii[:] = N.outer(orbbasis.delta, N.arange(ntb))
    rii.units = 'Angstrom'
    radialfct = ncf.createVariable('radialfct', 'd', ('orbs', 'ntb'))
    radialfct[:] = orbbasis.orb
    # Sort eigenvalues to connect crossing bands?
    if options.sorting:
        for i in range(SCDM.nspin):
            evals[:, i, :] = SortBands(evals[:, i, :])
        # Produce nice plots if labels exist
    if klabels:
        if SCDM.nspin == 1:
            PlotElectronBands(options.DestDir + '/Electrons.agr', dk,
                              evals[:, 0, :], kticks)
        elif SCDM.nspin == 2:
            PlotElectronBands(options.DestDir + '/Electrons.UP.agr', dk,
                              evals[:, 0, :], kticks)
            PlotElectronBands(options.DestDir + '/Electrons.DOWN.agr', dk,
                              evals[:, 1, :], kticks)
    ncf.close()

    # Compute phonon eigenvalues
    SCDM.SymmetrizeFC(options.radius)
    SCDM.SetMasses()
    if options.qfile:
        qpts, dq, qlabels, qticks = ReadKpoints(options.qfile)
    else:
        qpts, dq, qlabels, qticks = ReadKpoints(options.DestDir +
                                                '/symmetry-path')
    if qlabels:
        # Only write ascii if labels exist
        WriteKpoints(options.DestDir + '/qpoints', qpts, qlabels)
    # Prepare netcdf
    ncfn = options.DestDir + '/Phonons.nc'
    ncf = NC4.Dataset(ncfn, 'w')
    # Grid
    ncf.createDimension('gridpts', len(qpts))
    ncf.createDimension('vector', 3)
    grid = ncf.createVariable('grid', 'd', ('gridpts', 'vector'))
    grid[:] = qpts
    grid.units = '1/Angstrom'
    # Geometry
    ncf.createDimension('atoms', SCDM.Sym.basis.NN)
    xyz = ncf.createVariable('xyz', 'd', ('atoms', 'vector'))
    xyz[:] = SCDM.Sym.basis.xyz
    xyz.units = 'Angstrom'
    pbc = ncf.createVariable('pbc', 'd', ('vector', 'vector'))
    pbc.units = 'Angstrom'
    pbc[:] = [SCDM.Sym.a1, SCDM.Sym.a2, SCDM.Sym.a3]
    rvec1 = ncf.createVariable('rvec', 'd', ('vector', 'vector'))
    rvec1.units = '1/Angstrom (incl. factor 2pi)'
    rvec1[:] = rvec
    ncf.sync()
    # Loop over q
    for i, q in enumerate(qpts):
        if i < 100:  # Print only for the first 100 points
            hw, U = SCDM.ComputePhononModes_q(q, verbose=True)
        else:
            hw, U = SCDM.ComputePhononModes_q(q, verbose=False)
            # otherwise something simple
            if i % 100 == 0:
                print '%i out of %i q-points computed' % (i, len(qpts))
        if i == 0:
            ncf.createDimension('bands', len(hw))
            ncf.createDimension('displ', len(hw))
            evals = ncf.createVariable('eigenvalues', 'd',
                                       ('gridpts', 'bands'))
            evals.units = 'eV'
            evecsRe = ncf.createVariable('eigenvectors.re', 'd',
                                         ('gridpts', 'bands', 'displ'))
            evecsIm = ncf.createVariable('eigenvectors.im', 'd',
                                         ('gridpts', 'bands', 'displ'))
            # Check eigenvectors
            print 'SupercellPhonons.Checking eigenvectors at', q
            tmp = MM.mm(N.conjugate(U), SCDM.FCtilde, N.transpose(U))
            const = PC.hbar2SI * (1e20 / (PC.eV2Joule * PC.amu2kg))**0.5
            hw2 = const * N.diagonal(tmp)**0.5  # Units in eV
            print ' ... Allclose=', N.allclose(hw,
                                               N.absolute(hw2),
                                               atol=1e-5,
                                               rtol=1e-3)
            ncf.sync()
        evals[i] = hw
        evecsRe[i] = U.real
        evecsIm[i] = U.imag
    ncf.sync()
    # Sort eigenvalues to connect crossing bands?
    if options.sorting:
        evals = SortBands(evals)
    # Produce nice plots if labels exist
    if qlabels:
        PlotPhononBands(options.DestDir + '/Phonons.agr', dq,
                        N.array(evals[:]), qticks)
    ncf.close()

    # Compute e-ph couplings
    if options.kfile and options.qfile:
        SCDM.ReadGradients(AbsEref=False)
        ncf = NC4.Dataset(options.DestDir + '/EPH.nc', 'w')
        ncf.createDimension('kpts', len(kpts))
        ncf.createDimension('qpts', len(qpts))
        ncf.createDimension('modes', len(hw))
        ncf.createDimension('nspin', SCDM.nspin)
        ncf.createDimension('bands', SCDM.rednao)
        ncf.createDimension('vector', 3)
        kgrid = ncf.createVariable('kpts', 'd', ('kpts', 'vector'))
        kgrid[:] = kpts
        qgrid = ncf.createVariable('qpts', 'd', ('qpts', 'vector'))
        qgrid[:] = qpts
        evalfkq = ncf.createVariable('evalfkq', 'd',
                                     ('kpts', 'qpts', 'nspin', 'bands'))
        # First (second) band index n (n') is the initial (final) state, i.e.,
        # Mkq(k,q,mode,spin,n,n') := < n',k+q | dV_q(mode) | n,k >
        MkqAbs = ncf.createVariable(
            'Mkqabs', 'd',
            ('kpts', 'qpts', 'modes', 'nspin', 'bands', 'bands'))
        GkqAbs = ncf.createVariable(
            'Gkqabs', 'd',
            ('kpts', 'qpts', 'modes', 'nspin', 'bands', 'bands'))
        ncf.sync()
        # Loop over k-points
        for i, k in enumerate(kpts):
            kpts[i] = k
            # Compute initial electronic states
            evi, eveci = SCDM.ComputeElectronStates(k, verbose=True)
            # Loop over q-points
            for j, q in enumerate(qpts):
                # Compute phonon modes
                hw, U = SCDM.ComputePhononModes_q(q, verbose=True)
                # Compute final electronic states
                evf, evecf = SCDM.ComputeElectronStates(k + q, verbose=True)
                evalfkq[i, j, :] = evf
                # Compute electron-phonon couplings
                m, g = SCDM.ComputeEPHcouplings_kq(
                    k, q)  # (modes,nspin,bands,bands)
                # Data to file
                # M (modes,spin,i,l) = m(modes,k,j) init(i,j) final(k,l)
                #                            0 1 2       0,1        0 1
                #                                ^-------^
                #                              ^----------------------^
                for ispin in range(SCDM.nspin):
                    evecfd = MM.dagger(evecf[ispin])  # (bands,bands)
                    M = N.tensordot(N.tensordot(m[:, ispin],
                                                eveci[ispin],
                                                axes=[2, 0]),
                                    evecfd,
                                    axes=[1, 1])
                    G = N.tensordot(N.tensordot(g[:, ispin],
                                                eveci[ispin],
                                                axes=[2, 0]),
                                    evecfd,
                                    axes=[1, 1])
                    MkqAbs[i, j, :, ispin] = N.absolute(M)
                    GkqAbs[i, j, :, ispin] = N.absolute(G)
                ncf.sync()
        ncf.close()
    return SCDM.Sym.path
Пример #4
0
def main(options):
    CF.CreatePipeOutput(options.DestDir+'/'+options.Logfile)
    VC.OptionsCheck(options,'Inelastica')
    CF.PrintMainHeader('Inelastica',vinfo,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