Esempio n. 1
0
def main(options):
    Log.CreatePipeOutput(options)
    #VC.OptionsCheck(options)
    Log.PrintMainHeader(options)

    try:
        fdf = glob.glob(options.onlyTSdir + '/RUN.fdf')
        TSrun = True
    except:
        fdf = glob.glob(options.FCwildcard +
                        '/RUN.fdf')  # This should be made an input flag
        TSrun = False
    SCDM = Supercell_DynamicalMatrix(fdf, TSrun)

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

    # Write mesh
    k1, k2, k3 = ast.literal_eval(options.mesh)
    rvec = 2 * N.pi * N.array([SCDM.Sym.b1, SCDM.Sym.b2, SCDM.Sym.b3])
    import Inelastica.physics.mesh as Kmesh
    # Full mesh
    kmesh = Kmesh.kmesh(2**k1,
                        2**k2,
                        2**k3,
                        meshtype=['LIN', 'LIN', 'LIN'],
                        invsymmetry=False)
    WriteKpoints(options.DestDir + '/mesh_%ix%ix%i' % tuple(kmesh.Nk),
                 N.dot(kmesh.k, rvec))
    # Mesh reduced by inversion symmetry
    kmesh = Kmesh.kmesh(2**k1,
                        2**k2,
                        2**k3,
                        meshtype=['LIN', 'LIN', 'LIN'],
                        invsymmetry=True)
    WriteKpoints(options.DestDir + '/mesh_%ix%ix%i_invsym' % tuple(kmesh.Nk),
                 N.dot(kmesh.k, rvec))

    # Evaluate electron k-points
    if options.kfile:
        # Prepare Hamiltonian etc in Gamma for whole supercell
        natoms = SIO.GetFDFlineWithDefault(fdf[0], 'NumberOfAtoms', int, -1,
                                           'Error')
        SCDM.PrepareGradients(options.onlySdir,
                              N.array([0., 0., 0.]),
                              1,
                              natoms,
                              AbsEref=False,
                              atype=N.complex,
                              TSrun=TSrun)
        SCDM.nao = SCDM.h0.shape[-1]
        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,
                                                      TSrun=TSrun)
            else:
                ev, evec = SCDM.ComputeElectronStates(k,
                                                      verbose=False,
                                                      TSrun=TSrun)
                # 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)
                if options.nbands and options.nbands < SCDM.rednao:
                    nbands = options.nbands
                else:
                    nbands = SCDM.rednao
                ncf.createDimension('bands', nbands)
                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[:, :nbands]
            evecsRe[i, :] = evec[:, :, :nbands].real
            evecsIm[i, :] = evec[:, :, :nbands].imag
        ncf.sync()
        # Include basis orbitals in netcdf file
        if SCDM.Sym.basis.NN == len(SCDM.OrbIndx):
            lasto = N.zeros(SCDM.Sym.basis.NN + 1, N.float)
            lasto[:SCDM.Sym.basis.NN] = SCDM.OrbIndx[:SCDM.Sym.basis.NN, 0]
            lasto[SCDM.Sym.basis.NN] = SCDM.OrbIndx[SCDM.Sym.basis.NN - 1,
                                                    1] + 1
        else:
            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()

    if TSrun:  # only electronic calculation
        # Ugly hack to get my old code to work again. -Magnus
        if options.FermiSurface == True:
            from . import BandStruct as BS
            options.fdfFile = 'RUN.fdf'
            options.eMin, options.eMax = -10, 10
            options.NNk = 101
            BS.general = options
            BS.main()

        return SCDM.Sym.path

    # Compute phonon eigenvalues
    if options.qfile:
        SCDM.SymmetrizeFC(options.radius)
        SCDM.SetMasses()
        qpts, dq, qlabels, qticks = ReadKpoints(options.qfile)
        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()
                # Write only AXSF files for the first q-point
                PH.WriteAXSFFiles(options.DestDir + '/q%i_re.axsf' % i,
                                  SCDM.Sym.basis.xyz, SCDM.Sym.basis.anr, hw,
                                  U.real, 1, SCDM.Sym.basis.NN)
                PH.WriteAXSFFiles(options.DestDir + '/q%i_im.axsf' % i,
                                  SCDM.Sym.basis.xyz, SCDM.Sym.basis.anr, hw,
                                  U.imag, 1, SCDM.Sym.basis.NN)
                PH.WriteFreqFile(options.DestDir + '/q%i.freq' % i, hw)
            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()
        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
Esempio n. 2
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')
Esempio n. 3
0
def GetOptions(argv, **kwargs):
    # if text string is specified, convert to list
    if isinstance(argv, basestring): argv = argv.split()

    import optparse as o

    d = """Script that calculates STM images using the Bardeen approximation outlined in PRB 93 115434 (2016) and PRB 96 085415 (2017). The script is divided into 3 parts:
1) Calculation of the scattering states at the Fermi-energy on the same real space grid as TranSiesta (real-space cutoff). These are saved in DestDir/SystemLabel.A[LR][0-99].nc files and are reused if found. NEEDS: TranSiesta calculation. 
2) Propagation of the scattering states from a surface (defined by a constant charge density) out into the vacuum region. After the x-y plane, where the average potential of the slice is maximum (the separation plane), is found, the potential is ascribed a constant value at this average. Saves the propagated wavefunctions at the separation plane in DestDir/[kpoint]/FD[kpoint].nc. NEEDS: TotalPotential.grid.nc and Rho.grid.nc. 
3) Conductance calculation where the tip/substrate wavefunctions are displaced to simulate the conductance at different tip-positions. The k averaged STM image and the STM images of individual k points are saved in DestDir/STMimage.nc.
"""

    p = o.OptionParser("usage: %prog [options] DestinationDirectory", description=d)
    p.add_option("-F", "--DeviceFirst", dest='DeviceFirst', default=0, type='int',
                 help="First device atom (SIESTA numbering) [TS.TBT.PDOSFrom]")
    p.add_option("-L", "--DeviceLast", dest='DeviceLast', default=0, type='int',
                 help="Last device atom (SIESTA numbering) [TS.TBT.PDOSTo]")
    p.add_option("-e", "--Energy", dest='energy', default=0.0, type='float',
                 help="Energy where scattering states are evaluated [%default eV]")
    p.add_option("--eta", dest="eta", help="Imaginary part added to all energies (device and leads) [%default eV]",
                 type='float', default=0.000001)
    p.add_option("-l", "--etaLead", dest="etaLead", help="Additional imaginary part added ONLY in the leads (surface GF) [%default eV]",
                 type='float', default=0.0)
    p.add_option("-f", "--fdf", dest='fn', default='./RUN.fdf', type='string',
                 help="Input fdf-file for TranSIESTA calculations [%default]")
    p.add_option("-s", "--iSpin", dest='iSpin', default=0, type='int',
                 help="Spin channel [%default]")
    p.add_option("-p", "--savePOS", dest='savePOS', default=False, action='store_true',
                 help="Save the individual solutions as .pos files")
    p.add_option("--shift", dest='shift', default=False, action='store_true',
                 help="Shift current 1/2 cell in x, y directions")

    # Electrode stuff
    p.add_option("--bulk", dest='UseBulk', default=-1, action='store_true',
                 help="Use bulk in electrodes. The Hamiltonian from the electrode calculation is inserted into the electrode region in the TranSIESTA cell [TS.UseBulkInElectrodes]")
    p.add_option("--nobulk", dest='UseBulk', default=-1, action='store_false',
                 help="Use only self-energies in the electrodes. The full Hamiltonian of the TranSIESTA cell is used in combination with self-energies for the electrodes [TS.UseBulkInElectrodes]")

    # Scale (artificially) the coupling to the electrodes
    p.add_option("--scaleSigL", dest="scaleSigL", help="Scale factor applied to Sigma_L [default=%default]",
                 type='float', default=1.0)
    p.add_option("--scaleSigR", dest="scaleSigR", help="Scale factor applied to Sigma_R [default=%default]",
                 type='float', default=1.0)

    p.add_option("-u", "--useSigNC", dest='signc', default=False, action='store_true',
                 help="Use SigNCfiles [%default]")

    # Use spectral matrices?
    p.add_option("--SpectralCutoff", dest="SpectralCutoff", help="Cutoff value for SpectralMatrix functions (for ordinary matrix representation set cutoff<=0.0) [default=%default]",
                 type='float', default=0.0)
    p.add_option("-n", "--nCPU", dest='nCPU', default=1, type='int',
                 help="Number of processors [%default]")

    # k-grid
    p.add_option("-x", "--Nk1", dest='Nk1', default=1, type='int',
                  help="k-points Nk1 along a1 [%default]")
    p.add_option("-y", "--Nk2", dest='Nk2', default=1, type='int',
                  help="k-points Nk2 along a2 [%default]")

    #FD calculation
    p.add_option("-r", "--rhoiso", dest='rhoiso', default=1e-3, type='float',
                 help="Density at the isosurface from which the localized-basis wave functions are propagated [default=%default Bohr^-3Ry^-1]")
    p.add_option("--ssp", dest='ShiftSeparationPlane', default=0, type='float',
                 help="Manually shift the separation plane (>0 means away from the substrate) [default=%default Ang]")
    p.add_option("--sc", dest='samplingscale', default=2, type='int',
                 help="Sampling scale of wave functions in lateral plane. 1 means same real-space resolution as used in TranSiesta, while 2 means doubling of the lateral lattice constants, etc. [default=%default]")
    p.add_option("-t", "--tolsolve", dest='tolsolve', default=1e-6, type='float',
                 help="Tolerance for the iterative linear solver (scipy.linalg.isolve.gmres) [default=%default]")
    p.add_option("--savelocwfs", dest='savelocwfs', default=False, action='store_true',
                 help="Save localized-basis wave functions.")

    (options, args) = p.parse_args(argv)

    # Get the last positional argument
    options.DestDir = VC.GetPositional(args, "You need to specify a destination directory!")
    # With this one can overwrite the logging information
    if "log" in kwargs:
        options.Logfile = kwargs["log"]
    else:
        options.Logfile = 'STM.log'
    options.kpoints = Kmesh.kmesh(options.Nk1, options.Nk2, 1, meshtype=['LIN', 'LIN', 'LIN'], invsymmetry=False)
    return options