def GetOrbitalIndices(self): # Determine snr (siesta number) for each label csl = SIO.GetFDFblock(self.fdf, KeyWord='ChemicalSpeciesLabel') csl2snr = {} for set in csl: csl2snr[set[2]] = set[0] # Determine nao (number of orbitals) for each snr ionNCfiles = glob.glob(self.directory + '/*.ion.nc*') snr2nao = {} for ionfile in ionNCfiles: if ionfile.endswith('.gz'): print('Phonons.GetOrbitalIndices: Unzipping: ' + ionfile) os.system('gunzip ' + ionfile) ionfile = ionfile[:-3] file = NC4.Dataset(ionfile, 'r') thissnr = int(csl2snr[file.Label]) snr2nao[thissnr] = file.Number_of_orbitals file.close() print('Phonons.GetOrbitalIndices: Dictionary snr2nao = ' + str(snr2nao)) # Determine which orbital indices that belongs to a certain atom orbitalIndices = [] tmpOrb = 0 for num in self.geom.snr: nao = snr2nao[num] orbitalIndices.append([tmpOrb, tmpOrb + int(nao) - 1]) tmpOrb += nao self.orbitalIndices = N.array(orbitalIndices) self.nao = tmpOrb # total number of orbitals self.snr2nao = snr2nao # orbitals per species return self.orbitalIndices, self.nao
def __init__(self, dirr, restart, iistep, initial=None, final=None): self.dirr = dirr self.converged, self.Fmax = False, 0.0 self.ii = iistep self.fixed = (iistep == 0) or (iistep == opts.NNEB + 1) if restart or self.fixed: self.FDFgeom = MG.Geom(self.dirr + "/" + opts.fn) self.XVgeom = readxv(self.dirr) self.v = N.array(self.FDFgeom.xyz) * 0 if not restart and not self.fixed: os.makedirs(dirr) SUR.CopyInputFiles(opts.initial+"/CGrun/", dirr,\ ['.fdf', '.vps', '.psf']) # Interpolate ixyz, fxyz = N.array(initial.XVgeom.xyz), N.array(final.XVgeom.xyz) mix = float(iistep) / (opts.NNEB + 1.0) xyz = (1 - mix) * ixyz + mix * fxyz self.FDFgeom = copy.copy(initial.XVgeom) self.FDFgeom.xyz = [xyz[ii, :] for ii in range(len(xyz))] self.FDFgeom.writeFDF(self.dirr + "/STRUCT.fdf") self.v = N.array(self.FDFgeom.xyz) * 0 # Append lines to RUN.fdf elm = dirr + "/" + opts.fn f = open(elm, 'r') lines = f.readlines() f.close() f = open(elm, 'w') f.write('### Lines appended %s \n' % time.ctime()) f.write("MD.TypeOfRun CG\n") f.write("MD.NumCGsteps 0\n") f.write("MD.UseSaveXV False\n") f.write("MD.UseSaveCG False\n") f.write('# end of lines appended %s \n' % time.ctime()) for line in lines: f.write(line) f.close() self.done = self.checkDone() const = SIO.GetFDFblock(dirr + "/" + opts.fn, "GeometryConstraints") if opts.const2 != None: self.const = [[opts.const2[0], opts.const2[0]]] else: self.const = [] for ii in const: self.const += [[int(ii[2]) - 1, int(ii[4]) - 1]]
def __init__(self, dirr, restart, iistep, initial=None, final=None): self.dirr = dirr self.converged, self.Fmax = False, 0.0 self.ii = iistep self.fixed = (iistep == 0) or (iistep == general.NNEB + 1) if not restart and not self.fixed: os.makedirs(dirr) SUR.CopyInputFiles(general.initial + "/CGrun/", dirr, ['.fdf', '.vps', '.psf']) # Interpolate ixyz, fxyz = N.array(initial.XVgeom.xyz), N.array(final.XVgeom.xyz) mix = float(iistep) / (general.NNEB + 1.0) xyz = (1 - mix) * ixyz + mix * fxyz self.FDFgeom = copy.copy(initial.XVgeom) self.FDFgeom.xyz = [xyz[ii, :] for ii in range(len(xyz))] self.FDFgeom.writeFDF(self.dirr + "/STRUCT.fdf") # Append lines to RUN.fdf elm = dirr + "/RUN.fdf" f = open(elm, 'r') lines = f.readlines() f.close() f = open(elm, 'w') f.write('### Lines appended %s \n' % time.ctime()) f.write("SolutionMethod diagon\n") f.write("MD.TypeOfRun CG\n") f.write("MD.NumCGsteps 0\n") f.write("TS.SaveHS True\n") f.write("MD.UseSaveXV False\n") f.write("MD.UseSaveCG False\n") f.write('# end of lines appended %s \n' % time.ctime()) for line in lines: f.write(line) f.close() self.done = self.checkDone() self.const = SIO.GetFDFblock(dirr + "/RUN.fdf", "GeometryConstraints")
def get_elec_vars(lr): # Look up old format first TSHS = SIO.GetFDFlineWithDefault(opts.fn, 'TS.HSFile' + lr, str, '', exe) NA1 = SIO.GetFDFlineWithDefault(opts.fn, 'TS.ReplicateA1' + lr, int, 1, exe) NA2 = SIO.GetFDFlineWithDefault(opts.fn, 'TS.ReplicateA2' + lr, int, 1, exe) # default semi-inf direction semiinf = 2 # Proceed looking up new format, which precedes belec = 'TS.Elec.' + lr print('Looking for new electrode format in: %%block {}'.format(belec)) # Default replication stuff TSHS = SIO.GetFDFlineWithDefault(opts.fn, belec + '.TSHS', str, TSHS, exe) NA1 = SIO.GetFDFlineWithDefault(opts.fn, belec + '.Bloch.A1', int, NA1, exe) NA2 = SIO.GetFDFlineWithDefault(opts.fn, belec + '.Bloch.A2', int, NA2, exe) NA3 = SIO.GetFDFlineWithDefault(opts.fn, belec + '.Bloch.A3', int, 1, exe) # Overwrite block block = SIO.GetFDFblock(opts.fn, KeyWord=belec) for line in block: print(line) # Lower-case, FDF is case-insensitive key = line[0].lower() if key in ['tshs', 'tshs-file', 'hs', 'hs-file']: TSHS = line[1] elif key in [ 'replicate-a', 'rep-a', 'replicate-a1', 'rep-a1', 'bloch-a1' ]: NA1 = int(line[1]) elif key in [ 'replicate-b', 'rep-b', 'replicate-a2', 'rep-a2', 'bloch-a2' ]: NA2 = int(line[1]) elif key in [ 'replicate-c', 'rep-c', 'replicate-a3', 'rep-a3', 'bloch-a3' ]: NA3 = int(line[1]) elif key in ['replicate', 'rep', 'bloch']: # We have *at least* 2 integers NA1 = int(line[1]) NA2 = int(line[2]) NA3 = int(line[3]) elif key in ['semi-inf-direction', 'semi-inf-dir', 'semi-inf']: # This is lower-case checked axis = line[1][1:].lower() if 'a' == axis or 'a1' == axis: semiinf = 0 elif 'b' == axis or 'a2' == axis: semiinf = 1 elif 'c' == axis or 'a3' == axis: semiinf = 2 # Simple check of input, this may be overwritten later if semiinf != 2 and NA1 * NA2 * NA3 > 1: raise ValueError( ("Cannot provide semi-infinite directions " "other than A3-direction with repetition.")) if TSHS[0] != '/': # path is relative TSHS = opts.head + '/' + TSHS return TSHS, NA1, NA2, semiinf
def OptionsCheck(opts): """ Generic routine for adjusting most used options for routines. I.e. Inelastica/EigenChannels/pyTBT. """ import Inelastica.io.siesta as SIO import os import os.path as osp # Module name exe = opts.module # Destination directory if not osp.isdir(opts.DestDir): print('\n' + exe + ': Creating folder {0}'.format(opts.DestDir)) os.mkdir(opts.DestDir) if not osp.isfile(opts.fn): raise IOError("FDF-file not found: " + opts.fn) # Read SIESTA files opts.head = osp.split(opts.fn)[0] if opts.head == '': # set filepath if missing opts.head = '.' print(exe + ": Reading keywords from {0} \n".format(opts.fn)) opts.systemlabel = SIO.GetFDFlineWithDefault(opts.fn, 'SystemLabel', str, 'siesta', exe) opts.TSHS = '%s/%s.TSHS' % (opts.head, opts.systemlabel) # These first keys can be used, but they are superseeded by keys in the TS.Elec.<> block # Hence if they are read in first it will do it in correct order. if opts.UseBulk < 0: # Note NRP: # in principle this is now a per-electrode setting which # may be useful for certain systems... opts.UseBulk = SIO.GetFDFlineWithDefault(opts.fn, 'TS.UseBulkInElectrodes', bool, True, exe) opts.UseBulk = SIO.GetFDFlineWithDefault(opts.fn, 'TS.Elecs.Bulk', bool, opts.UseBulk, exe) def get_elec_vars(lr): # Look up old format first TSHS = SIO.GetFDFlineWithDefault(opts.fn, 'TS.HSFile' + lr, str, '', exe) NA1 = SIO.GetFDFlineWithDefault(opts.fn, 'TS.ReplicateA1' + lr, int, 1, exe) NA2 = SIO.GetFDFlineWithDefault(opts.fn, 'TS.ReplicateA2' + lr, int, 1, exe) # default semi-inf direction semiinf = 2 # Proceed looking up new format, which precedes belec = 'TS.Elec.' + lr print('Looking for new electrode format in: %%block {}'.format(belec)) # Default replication stuff TSHS = SIO.GetFDFlineWithDefault(opts.fn, belec + '.TSHS', str, TSHS, exe) NA1 = SIO.GetFDFlineWithDefault(opts.fn, belec + '.Bloch.A1', int, NA1, exe) NA2 = SIO.GetFDFlineWithDefault(opts.fn, belec + '.Bloch.A2', int, NA2, exe) NA3 = SIO.GetFDFlineWithDefault(opts.fn, belec + '.Bloch.A3', int, 1, exe) # Overwrite block block = SIO.GetFDFblock(opts.fn, KeyWord=belec) for line in block: print(line) # Lower-case, FDF is case-insensitive key = line[0].lower() if key in ['tshs', 'tshs-file', 'hs', 'hs-file']: TSHS = line[1] elif key in [ 'replicate-a', 'rep-a', 'replicate-a1', 'rep-a1', 'bloch-a1' ]: NA1 = int(line[1]) elif key in [ 'replicate-b', 'rep-b', 'replicate-a2', 'rep-a2', 'bloch-a2' ]: NA2 = int(line[1]) elif key in [ 'replicate-c', 'rep-c', 'replicate-a3', 'rep-a3', 'bloch-a3' ]: NA3 = int(line[1]) elif key in ['replicate', 'rep', 'bloch']: # We have *at least* 2 integers NA1 = int(line[1]) NA2 = int(line[2]) NA3 = int(line[3]) elif key in ['semi-inf-direction', 'semi-inf-dir', 'semi-inf']: # This is lower-case checked axis = line[1][1:].lower() if 'a' == axis or 'a1' == axis: semiinf = 0 elif 'b' == axis or 'a2' == axis: semiinf = 1 elif 'c' == axis or 'a3' == axis: semiinf = 2 # Simple check of input, this may be overwritten later if semiinf != 2 and NA1 * NA2 * NA3 > 1: raise ValueError( ("Cannot provide semi-infinite directions " "other than A3-direction with repetition.")) if TSHS[0] != '/': # path is relative TSHS = opts.head + '/' + TSHS return TSHS, NA1, NA2, semiinf # Look up electrode block block = SIO.GetFDFblock(opts.fn, KeyWord='TS.Elecs') if len(block) == 0: # Did not find the electrode block, defaults to old naming scheme opts.fnL, opts.NA1L, opts.NA2L, opts.semiinfL = get_elec_vars('Left') opts.fnR, opts.NA1R, opts.NA2R, opts.semiinfR = get_elec_vars('Right') elif len(block) == 2: # NB: The following assumes that the left electrode is the first in the block! opts.fnL, opts.NA1L, opts.NA2L, opts.semiinfL = get_elec_vars( block[0][0]) opts.fnR, opts.NA1R, opts.NA2R, opts.semiinfR = get_elec_vars( block[1][0]) else: print(block) raise IOError('Currently only two electrodes are supported') # Read in number of buffer atoms opts.buffer, L, R = SIO.GetBufferAtomsList(opts.TSHS, opts.fn) opts.bufferL = L opts.bufferR = R if 'maxBias' in opts.__dict__: # Bias range opts.maxBias = abs(opts.maxBias) opts.minBias = -abs(opts.maxBias) # Device region if opts.DeviceFirst <= 0: opts.DeviceFirst = SIO.GetFDFlineWithDefault(opts.fn, 'TS.TBT.PDOSFrom', int, 1, exe) opts.DeviceFirst -= L if opts.DeviceLast <= 0: opts.DeviceLast = SIO.GetFDFlineWithDefault(opts.fn, 'TS.TBT.PDOSTo', int, 1e10, exe) opts.DeviceLast -= L opts.NumberOfAtoms = SIO.GetFDFlineWithDefault(opts.fn, 'NumberOfAtoms', int, 1e10, exe) opts.NumberOfAtoms -= L + R if opts.DeviceLast < opts.DeviceFirst: print( exe + ' error: DeviceLast<DeviceFirst not allowed. Setting DeviceLast=DeviceFirst' ) opts.DeviceLast = opts.DeviceFirst opts.DeviceAtoms = [ max(opts.DeviceFirst, 1), min(opts.DeviceLast, opts.NumberOfAtoms) ] # Voltage opts.voltage = SIO.GetFDFlineWithDefault(opts.fn, 'TS.Voltage', float, 0.0, exe) ############# # Here comes some specifics related to different executables: ############# if "VfracL" in opts.__dict__: if opts.VfracL < 0.0 or opts.VfracL > 1.0: raise RuntimeError( 'Option VfracL must be a value in the range [0,1].') if "PhononNetCDF" in opts.__dict__: if not osp.isfile(opts.PhononNetCDF): raise IOError("Electron-phonon coupling NetCDF file not found: " + opts.PhononNetCDF) if "eta" in opts.__dict__: if opts.eta < 0: raise RuntimeError("eta must be a posivite number") if "etaLead" in opts.__dict__: if opts.etaLead < 0: raise RuntimeError("etaLead must be a posivite number") if "PhExtDamp" in opts.__dict__: if opts.PhExtDamp < 0: raise RuntimeError("PhExtDamp must be a posivite number") if "biasPoints" in opts.__dict__: if opts.biasPoints < 6: raise AssertionError("BiasPoints must be larger than 5") if "iSpin" in opts.__dict__: if not opts.iSpin in [0, 1]: raise AssertionError("Spin must be either 0 or 1") if "Emin" in opts.__dict__: if opts.Emin == 1e10: opts.Emin = SIO.GetFDFlineWithDefault(opts.fn, 'TS.TBT.Emin', float, 0.0, 'pyTBT') if "Emax" in opts.__dict__: if opts.Emax == 1e10: opts.Emax = SIO.GetFDFlineWithDefault(opts.fn, 'TS.TBT.Emax', float, 1.0, 'pyTBT') if "NPoints" in opts.__dict__: if opts.NPoints <= 0: opts.NPoints = SIO.GetFDFlineWithDefault(opts.fn, 'TS.TBT.NPoints', int, 1, 'pyTBT') # Create list of energies try: opts.Elist # Do not overwrite if some Elist is already specified except: if opts.NPoints == 1: opts.Elist = _np.array((opts.Emin, ), _np.float) else: # Linspace is just what we need opts.Elist = _np.linspace(opts.Emin, opts.Emax, opts.NPoints)