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
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')
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
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