def readVFE(filename): with open(filename, 'r') as f: cleanStr = f.read() # Define Grammars header = pp.OneOrMore(pp.pythonStyleComment).setParseAction( pp.replaceWith('')) divider = (pp.Literal('---') + pp.restOfLine).setParseAction( pp.replaceWith('')) flt = pp.Word(pp.nums + '.+-') colHeader = pp.Suppress(pp.Literal('Temp (K) vfe (J/mol-c)')) tempTable = pp.Group(pp.OneOrMore(pp.Group(flt * 2))) datum = pp.Group(colHeader + tempTable) data = pp.OneOrMore(datum) # Parse String try: for grammar in [header, divider]: cleanStr = grammar.transformString(cleanStr) ppresults = data.parseString(cleanStr).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() # Format Results results = {} for ppr in ppresults: temps = list(map(float, list(zip(*ppr[0]))[0])) vfes = list(map(float, list(zip(*ppr[0]))[1])) key = 'Temp (K)' if key not in results: results[key] = temps key = 'VFE (J/mol-c)' if key not in results: results[key] = vfes else: results[key] = [sum(x) for x in zip(results[key], vfes)] return results
def anaddb2cols(file): header = pp.OneOrMore(pp.pythonStyleComment) pt = pp.Group(pp.Word(pp.nums + ".+-E") * 2) text = header.suppress() + pp.OneOrMore(pt) f = open(file, 'r') try: data = text.parseString(f.read()).asList() except pp.ParseException as pe: print(("Parsing Error using pyparsing: invalid input:", pe)) sys.exit() f.close() return list(map(list, list(zip(*data))))
def read_s2(filename, tempgrid): with open(filename, 'r') as f: cleanStr = f.read() # Define Grammars header = pp.OneOrMore(pp.pythonStyleComment).setParseAction( pp.replaceWith('')) divider = (pp.Literal('---') + pp.restOfLine).setParseAction( pp.replaceWith('')) index = pp.Word(pp.nums) path = pp.Literal('Path Indices:').suppress() + pp.Group( pp.OneOrMore(index)) colon = pp.Literal(':') flt = pp.Word(pp.nums + '.+-') pathlength = pp.Suppress( pp.Literal('Path Len') + pp.SkipTo(colon) + colon) + flt # Debug: FDV # print tempgrid # sys.exit() # ntemp = int(tempgrid.split()[0]) ntemp = int(tempgrid[0]) if ntemp is 1: datum = pp.Group(path + pathlength + flt) else: colHeader = pp.Suppress(pp.Literal('Temp (K) s^2 (1e-3 Ang^2)')) tempTable = pp.Group(pp.OneOrMore(pp.Group(flt * 2))) datum = pp.Group(path + pathlength + colHeader + tempTable) data = pp.OneOrMore(datum) # Parse String try: for grammar in [header, divider]: cleanStr = grammar.transformString(cleanStr) ppresults = data.parseString(cleanStr).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() # Format Results results = {} for ppr in ppresults: key = ','.join(ppr[0]) if ntemp is 1: temps = float(tempgrid.split()[1]) dwfs = float(ppr[2]) else: temps = list(map(float, list(zip(*ppr[2]))[0])) dwfs = list(map(float, list(zip(*ppr[2]))[1])) results[key] = { 'Pathlength (Ang)': float(ppr[1]), 'Temp (K)': temps, 's^2': dwfs } return results
def readSpecFn(filename): header = pp.OneOrMore(pp.pythonStyleComment) pt = pp.Group(pp.Word(pp.nums + ".+-E") * 5) text = header.suppress() + pp.OneOrMore(pt) f = open(filename, 'r') try: data = text.parseString(f.read()).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() f.close() cols = list(map(list, list(zip(*data)))) # w [meV], mag, ph, re, im return [cols[0], cols[3], cols[4]]
def readColumns(filename, columns=[1, 2]): # Read file and clear out comments with open(filename, 'r') as file: cleanStr = file.read() comments = pp.ZeroOrMore(pp.pythonStyleComment).setParseAction( pp.replaceWith('')) try: cleanStr = comments.transformString(cleanStr) except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() # Define grammar for ncols of data based on number of entries in first row floating = pp.Word(pp.nums + ".+-E").setParseAction(lambda t: float(t[0])) EOL = pp.LineEnd().suppress() row1entry = floating.copy().setWhitespaceChars(" \t") row1 = pp.Group(pp.ZeroOrMore(EOL) + pp.OneOrMore(row1entry) + EOL) row = pp.Forward() def defineTotalCols(toks): ncols = len(toks[0]) row << pp.Group(floating * ncols) return None row1.addParseAction(defineTotalCols) text = row1 + pp.ZeroOrMore(row) try: data = text.parseString(cleanStr).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() cols = list(map(list, list(zip(*data)))) return [cols[i - 1] for i in columns]
def combineReImSE(reFilename, imFilename): header = pp.OneOrMore(pp.pythonStyleComment) pt = pp.Group(pp.Word(pp.nums + ".+-E") * 2) text = header.suppress() + pp.OneOrMore(pt) reFile = open(reFilename, 'r') imFile = open(imFilename, 'r') try: rePts = text.parseString(reFile.read()).asList() imPts = text.parseString(imFile.read()).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() reFile.close() imFile.close() enCol = list(map(list, list(zip(*rePts))))[0] # in meV? reCol = list(map(list, list(zip(*rePts))))[1] # in meV? imCol = list(map(list, list(zip(*imPts))))[1] se = [enCol, []] for i in range(len(enCol)): se[1].append(complex(float(reCol[i]), float(imCol[i]))) return se
def eli2couplings(filePrefix): header = pp.OneOrMore(pp.pythonStyleComment) pt = pp.Group(pp.Word(pp.nums + ".+-E") * 2) text = header.suppress() + pp.OneOrMore(pt) pdsFile = open(filePrefix + 'PDS', 'r') a2fFile = open(filePrefix + 'A2F', 'r') try: pdsRow = text.parseString(pdsFile.read()).asList() a2fRow = text.parseString(a2fFile.read()).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() pdsFile.close() a2fFile.close() enCol = list(map(list, list(zip(*pdsRow))))[0] pdsCol = list(map(list, list(zip(*pdsRow))))[1] a2fCol = list(map(list, list(zip(*a2fRow))))[1] couplings = [enCol,[]] for i, pds in enumerate(pdsCol): if float(pds) == 0.0: couplings[1].append(0.0) else: couplings[1].append( float(a2fCol[i]) / float(pds) ) return couplings
def kgrid2qgrid(file): token = pp.Keyword('kpt') qpt = pp.Group(pp.Word(pp.nums + ".+-E")*3) kpt = (pp.SkipTo(token) + token).suppress() + pp.OneOrMore(qpt) f = open(file, 'r') try: pts = kpt.parseString(f.read()).asList() except pp.ParseException as pe: print(("Parsing Error using pyparsing: invalid input:", pe)) sys.exit() f.close() qpts = [] for p in pts: qpts.append(' '.join(p)) return qpts
def expandedList(string, length=3): assert isinstance(string, str) value = pp.Word(pp.nums + ".+-E") prefix = pp.Combine(pp.Optional(pp.Word(pp.nums)) + pp.Literal('*')) numList = pp.OneOrMore(pp.Optional(prefix) + value) expanded = [] num = 1 for x in numList.parseString(string).asList(): if num != 1: expanded.extend([x]*num) num = 1 elif '*' in x: if x[:-1] == '': num = length else: num = int(x[:-1]) else: expanded.append(x) return expanded
def read_u2(filename, tempgrid): with open(filename, 'r') as f: cleanStr = f.read() # Define Grammars header = pp.OneOrMore(pp.pythonStyleComment).setParseAction( pp.replaceWith('')) divider = (pp.Literal('===') + pp.restOfLine).setParseAction( pp.replaceWith('')) index = pp.Word(pp.nums) at_index = pp.Literal('Atom Index:').suppress() + pp.Group( pp.OneOrMore(index)) dir = pp.Word(pp.alphas, max=1) coord_dir = pp.Group(pp.OneOrMore('-')).suppress() + pp.Literal( 'Direction').suppress() + dir + pp.Group(pp.OneOrMore('-')).suppress() colon = pp.Literal(':') flt = pp.Word(pp.nums + '.+-') # Modified by FDV # ntemp = int(tempgrid.split()[0]) ntemp = int(tempgrid[0]) if ntemp is 1: colHeader = pp.Suppress(pp.Literal('u^2 (1e-3 Ang^2):')) datum = pp.Group(at_index + coord_dir + colHeader + flt) else: colHeader = pp.Suppress(pp.Literal('Temp (K) u^2 (1e-3 Ang^2)')) tempTable = pp.Group(pp.OneOrMore(pp.Group(flt * 2))) datum = pp.Group(at_index + coord_dir + colHeader + tempTable) data = pp.OneOrMore(datum) # Parse String try: for grammar in [header, divider]: cleanStr = grammar.transformString(cleanStr) ppresults = data.parseString(cleanStr).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() # Format Results results = {} for ppr in ppresults: key = ','.join([ppr[0][0], ppr[1]]) if ntemp is 1: temps = float(tempgrid.split()[1]) dwfs = float(ppr[2]) else: temps = list(map(float, list(zip(*ppr[2]))[0])) dwfs = list(map(float, list(zip(*ppr[2]))[1])) results[key] = {'Temp (K)': temps, 'u^2': dwfs} return results
def ifc2dym(file, input): from decimal import Decimal, ROUND_UP import math index = pp.Word(pp.nums) vector = pp.Group(pp.Word(pp.nums + ".+-E")*3) matrix = pp.Group(vector * 3) ifcblock = pp.Group(index*2 + vector + matrix) text = pp.OneOrMore(ifcblock) f = open(file, 'r') try: data = text.parseString(f.read()).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() f.close() natom = int(data[-1][0]) # if natom is not int() # check natom against System? nifc = int(data[-1][1]) # Create and fill ifcInfo data structure ifcInfo = [[{} for b in range(nifc)] for a in range(natom)] for info in data: atomIndex = int(info[0]) - 1 ifcIndex = int(info[1]) - 1 atomPos = list(map(float, info[2])) ifcMatrix= [list(map(float, row)) for row in info[3]] ifcInfo[atomIndex][ifcIndex] = {'pos':atomPos,'ifc':ifcMatrix} # Modified by FDV # With the change in formatting at input reading, we don't need to do this here # anymore. # # Convert ABINIT input strings into indexed numerical data # acell = map(float, expandedList(input['acell'])) acell = input['cell_scaling_abc'][0] # try: # parsedMatrix = matrix.parseString(input['rprim']).asList()[0] # rprim = [map(float, row) for row in parsedMatrix] # except pp.ParseException as pe: # print 'Parsing Error using pyparsing: invalid input:', pe # sys.exit() rprim = input['cell_vectors'] # Modified by FDV # With the change in formatting at input reading, we don't need to do this here # znucl = map(int, expandedList(input['znucl'], length=natom)) Symbs = [ cu.AtLbl2AtSym(Line[0]) for Line in input['cell_struc_xyz_red'] ] znucl = [ cu.AtSym2AtNum(Symb) for Symb in Symbs ] ncluster = 300.0 n = int(math.ceil((pow(ncluster/natom, 1.0/3.0) - 1.0) / 2.0)) copyRange = list(range(-n, n+1)) copyGrid = ((i,j,k) for i in copyRange for j in copyRange for k in copyRange) # Build cluster cluster = [] for ijk in copyGrid: # Debug: FDV # print rprim # print acell # print ijk # dx = [a*sum(i*c for i,c in zip(ijk,row)) for row, a in zip(rprim,acell)] # print dx # sys,exit() dx = [a*sum(i*c for i,c in zip(ijk,row)) for row, a in zip(rprim,acell)] for iAt in range(natom): clusterAtom = {'cellIndex':iAt} cellCoord = list(map(float, ifcInfo[iAt][0]['pos'])) clusterAtom['coord'] = list(map(sum, list(zip(cellCoord, dx)))) clusterAtom['dist'] = math.sqrt(sum(a*a for a in clusterAtom['coord'])) clusterAtom['Z'] = znucl[iAt] clusterAtom['mass'] = amu[znucl[iAt]] if all(i == 0 for i in ijk): clusterAtom['central'] = True cluster.append(clusterAtom) ru8 = lambda x: Decimal(x).quantize(Decimal('0.12345678'),rounding=ROUND_UP) cluster.sort(key=lambda atom:(ru8(atom['dist']), atom['cellIndex'], ru8(atom['coord'][0]), ru8(atom['coord'][1]), ru8(atom['coord'][2]) )) ncluster = len(cluster) # Get distance/displacement for cluster pairs used for geometric matching clustPair = [[{} for j in range(ncluster)] for i in range(ncluster)] for i,j in ((i,j) for i in range(ncluster) for j in range(i,ncluster)): if i is j: clustPair[i][j]['dist'] = 0.0 clustPair[i][j]['xi-xj'] = [0.0, 0.0, 0.0] else: displ = list(map(lambda x,y:x-y, cluster[i]['coord'], cluster[j]['coord'])) clustPair[i][j]['dist'] = math.sqrt(sum(x*x for x in displ)) clustPair[j][i]['dist'] = clustPair[i][j]['dist'] clustPair[i][j]['xi-xj'] = displ clustPair[j][i]['xi-xj'] = [-x for x in displ] # Get distance/displacement for reference pairs used for geometric matching refPair = [[{} for b in range(nifc)] for a in range(natom)] for a,b in ((a,b) for a in range(natom) for b in range(nifc)): displ = list(map(lambda x,y:x-y, ifcInfo[a][0]['pos'], ifcInfo[a][b]['pos'])) refPair[a][b]['dist'] = math.sqrt(sum(x*x for x in displ)) refPair[a][b]['xa0-xab'] = displ # Start building a type-2 DYM dict dym = {'dymType':2} # Section 1: Number of atoms in cluster dym['nAt'] = ncluster # Section 2: List of atomic numbers for each atom in cluster dym['atNums'] = [atom['Z'] for atom in cluster] # Section 3: List of atomic masses for each atom in cluster dym['atMasses'] = [atom['mass'] for atom in cluster] # Section 4: List of positions for each atom in cluster dym['atCoords'] = [atom['coord'] for atom in cluster] # Section 5: 3x3 block of dynamical matrix for each pair of atoms in cluster maxDiff = 0.001 cutoffDist = 10.0 areClose = lambda x,y: abs(x-y) <= maxDiff dym['dm'] = [[None for j in range(ncluster)] for i in range(ncluster)] for i,j in ((i,j) for i in range(ncluster) for j in range(ncluster)): dist = clustPair[i][j]['dist'] displ = clustPair[i][j]['xi-xj'] if dist > cutoffDist: dym['dm'][i][j] = [[0.0]*3]*3 else: found = False # Loop over reference pairs of same original cell index atomCellIndex = cluster[i]['cellIndex'] for b,refPairB in enumerate(refPair[atomCellIndex]): refDist = refPairB['dist'] refDispl = refPairB['xa0-xab'] # Found reference pair with same geometry if areClose(dist, refDist) and all(map(areClose, displ, refDispl)): clustPair[i][j]['refifc'] = b dym['dm'][i][j] = ifcInfo[atomCellIndex][b]['ifc'] found = True # At end of reference list with no match found if not found: raise Exception('Error: cannnot find reference for pair ' + str((i+1,j+1))) # Ordering of cluster atoms for printing purposes dym['printOrder'] = list(range(ncluster)) # Section Type-2: Info for central cell atoms # Modified by FDV # With the change in formatting at input reading, we don't need to do this here # typat = map(int, expandedList(input['typat'], length=natom)) Labels = [ Line[0] for Line in input['pspfiles'] ] Type_Ind_dict = dict(list(zip(Labels,list(range(1,len(Labels)+1))))) typat = [ Type_Ind_dict[Label] for Label in Labels ] dym['nTypeAt'] = len(set(typat)) dym['nCellAt'] = natom dym['centerAt'] = {z:[] for z in znucl} for i,atom in ((i,a) for i,a in enumerate(cluster) if 'central' in a): atomInfo = {'clustIndex':i} atomInfo.update({k:atom[k] for k in ('cellIndex','coord')}) dym['centerAt'][atom['Z']].append(atomInfo) return dym
def readDym(dymFilename): integer = pp.Word(pp.nums).setParseAction(lambda t: int(t[0])) floating = pp.Word(pp.nums + ".+-E").setParseAction(lambda t: float(t[0])) vector = pp.Group(floating * 3) matrix = pp.Group(vector * 3) dymtype = integer ncluster = integer.copy() # Uses unique ParseAction for Forward atNums = pp.Forward() # Placeholders for grabbing ncluster entries atMasses = pp.Forward() atCoords = pp.Forward() def countedParseAction(toks): n = toks[0] atNums << pp.Group(integer * n) atMasses << pp.Group(floating * n) atCoords << pp.Group(vector * n) return None ncluster.addParseAction(countedParseAction) dm = pp.Group(pp.OneOrMore(pp.Group(integer * 2 + matrix))) specifics = pp.SkipTo(pp.stringEnd) text = dymtype + ncluster + atNums + atMasses + atCoords + dm + specifics with open(dymFilename, 'r') as f: try: data = text.parseString(f.read()).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() # Construct dym object dym = {'dymType': data[0]} dym['nAt'] = data[1] dym['atNums'] = data[2] dym['atMasses'] = data[3] dym['atCoords'] = data[4] dym['dm'] = [[None for j in range(dym['nAt'])] for i in range(dym['nAt'])] for i, j in ((i, j) for i in range(dym['nAt']) for j in range(dym['nAt'])): index = i * dym['nAt'] + j if data[5][index][0] == i + 1 and data[5][index][1] == j + 1: dym['dm'][i][j] = data[5][index][2] # Parse dymtype-specific items if dym['dymType'] == 2: nUnique = integer nCell = integer centralZAtom = pp.Group(integer + integer + vector) zAtomList = pp.Group(integer + pp.countedArray(centralZAtom)) typeSpecific = nUnique + nCell + pp.Group(pp.OneOrMore(zAtomList)) # Parse try: data = typeSpecific.parseString(data[6]).asList() except pp.ParseException as pe: print(('Parsing Error using pyparsing: invalid input:', pe)) sys.exit() # Store type-specific information if dym['dymType'] == 2: dym['nTypeAt'] = data[0] dym['nCellAt'] = data[1] dym['centerAt'] = {} for zAtomList in data[2]: z = zAtomList[0] dym['centerAt'][z] = [] for centralZAtom in zAtomList[1]: atomInfo = {} atomInfo['clustIndex'] = centralZAtom[0] atomInfo['cellIndex'] = centralZAtom[1] atomInfo['coord'] = centralZAtom[2] dym['centerAt'][z].append(atomInfo) return dym
def generateInput(config, input, output): # Debug: FDV # pp_debug.pprint(input) # pp_debug.pprint(output) # sys.exit() # Start with the preparation of the POTCAR since that is needed for all # calculations # In VASP the order of the content of the POTCAR and that of the POSCAR are # related, so we have to be careful on how we order things and we need to # remember that order for future calculations. # First we parse cell_red_xyz to find the atom labels # Debug: FDV print(input) sys.exit() # Switch based on what output is required files = [] dir = config['xcDir'] ppFilelist = pp.OneOrMore(pp.Word(pp.printables)) pseudos = ppFilelist.parseString(input['pspfiles']).asList() # Lattice optimization if set(output.keys()) == set(['aopt']): filebase = '0.abinit.opt' pathbase = os.path.join(dir, filebase) abinitFileList = abinitFiles(pathbase, pseudos) writeList(abinitFileList, pathbase + '.files') writeDict(optInput(input), pathbase + '.in') files.append(filebase + '.files') # Symmetry-reduced q-grid for use with ANADDB elif set(output.keys()) == set(['qptlist']): filebase = '0.abinit.qgrid' pathbase = os.path.join(dir, filebase) abinitFileList = abinitFiles(pathbase, pseudos) writeList(abinitFileList, pathbase + '.files') writeDict(qgridInput(input), pathbase + '.in') files.append(filebase + '.files') # Internal energy elif set(output.keys()) == set(['eint']): filebase = '1.abinit.U' pathbase = os.path.join(dir, filebase) abinitFileList = abinitFiles(pathbase, pseudos) writeList(abinitFileList, pathbase + '.files') writeDict(UInput(input), pathbase + '.in') files.append(filebase + '.files') # Electron-phonon calculation using ANADDB elif set(output.keys()).issubset( set(['pdos', 'a2f', 'a2', 'dynmat', 'eint'])): filebase = '1.abinit.elphon' pathbase = os.path.join(dir, filebase) abFileList = abinitFiles(pathbase, pseudos) writeList(abFileList, pathbase + '.files') writeDict(elphonInput(input), pathbase + '.in') dsPrefix = abFileList[3] + '_DS' files.append(filebase + '.files') filebase = '2.mrgddb.elphon' pathbase = os.path.join(dir, filebase) qptRange = list(range(3, 3 + len(input['qptlist']))) ddbFileList = ddbFiles(pathbase, dsPrefix, qptRange) writeList(ddbFileList, pathbase + '.files') files.append(filebase + '.files') filebase = '3.mrggkk.elphon' pathbase = os.path.join(dir, filebase) atdirRange = list(range(1, 1 + 3 * int(input['natom']))) gkkFileList = gkkFiles(pathbase, dsPrefix, qptRange, atdirRange) writeList(gkkFileList, pathbase + '.files') files.append(filebase + '.files') filebase = '4.anaddb.ifc' pathbase = os.path.join(dir, filebase) anaFileList = anaddbFiles(pathbase, ddbFileList[0], gkkFileList[0]) writeList(anaFileList, pathbase + '.files') writeDict(ifcInput(input), pathbase + '.in') files.append(filebase + '.files') # Return ordered list of *.files return files