def parser(name, data): """ Parse turbomole specific input file """ tmol = Molecule(name) for i in range(len(data)): if "$coord" in data[i]: for l in data[i + 1:]: if '$' in l: break line = l.split() tmol.newAtom(line[3].capitalize(), line[0:3], fmt='bohr') break return tmol, None
def parser(name, data): """ Parse sybyl mol2 files """ tmol = Molecule(name) parsing = False for line in data: if not line.strip(): continue elif line.strip()[0] == '#': continue elif "@<TRIPOS>ATOM" in line: parsing = True elif parsing: if "@<TRIPOS>" in line: tmol.setFmt("angstrom", scale=True) return tmol, None at = line.strip().split() tmol.newAtom(at[5].upper(), at[2:5], charge=float(at[8]))
def parser(name, data): """ Parse AIMALL output to molecule Creates atoms from NACPs Other critical points will be parsed directly """ tmol = Molecule(name) i = 0 while i < len(data): line = data[i].split() if line and line[0] == 'CP#': i += 1 cptype = data[i].split()[3] if cptype == 'NACP': cptype = data[i].split()[4].rstrip('0123456789') tmol.newAtom(cptype, line[4:], fmt='bohr') i += 1 return tmol, None
def parser(name, data): """ Parse xyz files (angstrom) """ # create list of mol, trajectory support tmol = Molecule(name, steps=0) i = 0 while i < len(data): # handle empty lines at eof or between molecules if not data[i].strip().isdigit(): i += 1 continue # fixed format nat and comment tmol.newStep() nat = int(data[i]) tmol.comment = data[i + 1].strip() # read coordinates and types tmol.newAtoms(nat) for j in range(nat): line = data[j + i + 2].split() tmol.setAtom(j, line[0], line[1:4]) tmol.setFmt('angstrom', scale=True) i += nat + 2 return tmol, None
def parser(name, data): """ Parse Lammps custom dump files Preliminary implementation! Needs to be 'custom' format with either: 'id element xs ys yz' or 'id element x y z' Only orthogonal cells for now Assumes angstrom """ tmol = Molecule(name, steps=0) i = 0 while i < len(data): line = data[i] if 'ITEM' in line: if 'TIMESTEP' in line: i += 2 tmol.newStep() elif 'NUMBER OF ATOMS' in line: nat = int(data[i + 1]) i += 2 elif 'BOX BOUNDS' in line: tvec = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] tvec[0][0] = float(data[i + 1].split()[1]) -\ float(data[i + 1].split()[0]) tvec[1][1] = float(data[i + 2].split()[1]) -\ float(data[i + 2].split()[0]) tvec[2][2] = float(data[i + 3].split()[1]) -\ float(data[i + 3].split()[0]) tmol.setVec(tvec) tmol.setCellDim(1, fmt='angstrom') i += 4 elif 'ATOMS' in line: line = line.split() if 'id' not in line or 'element' not in line or\ ('xs' not in line and 'x' not in line): raise NotImplementedError("Lammps dump in not (yet) " "recognized format") # ididx = line.index('id') - 2 elidx = line.index('element') - 2 if 'xs' in line: xidx = line.index('xs') - 2 yidx = line.index('ys') - 2 zidx = line.index('zs') - 2 fmt = 'crystal' else: xidx = line.index('x') - 2 yidx = line.index('y') - 2 zidx = line.index('z') - 2 fmt = 'angstrom' if 'q' in line: qidx = line.index('q') - 2 else: qidx = False tmol.newAtoms(nat) for j in range(nat): at = data[j + 1 + i].split() if qidx: tmol.setAtom(j, at[elidx], [at[xidx], at[yidx], at[zidx]], charge=float(at[qidx])) else: tmol.setAtom(j, at[elidx], [at[xidx], at[yidx], at[zidx]]) tmol.setFmt(fmt, scale=True) i += nat + 1 else: i += 1 return tmol, None
def parser(name, data): """ Parse Lammps data file Element parsed via comment in 'Masses' part Assumes angstrom, atom_style in [angle,atomic,bond,charge,full,molecular] """ tmol = Molecule(name) i = 0 tvec = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] while i < len(data): line = data[i].strip() if 'atoms' in line: nat = int(line.split()[0]) elif 'atom types' in line: types = [0] * int(line.split()[0]) elif 'xlo xhi' in line: tvec[0][0] = float(line.split()[1]) - float(line.split()[0]) elif 'ylo yhi' in line: tvec[1][1] = float(line.split()[1]) - float(line.split()[0]) elif 'zlo zhi' in line: tvec[2][2] = float(line.split()[1]) - float(line.split()[0]) elif 'xy xz yz' in line: tvec[1][0], tvec[2][0], tvec[2][1] = line.split()[:3] elif 'Masses' in line: for j in range(i + 2, i + 2 + len(types)): if '#' in data[j]: el = data[j].split('#') t = el[1].strip() types[int(el[0].split()[0]) - 1] = t tmol.pse[t]['m'] = float(el[0].split()[1]) else: raise NotImplementedError("Can't deduce elements") i += len(types) + 1 elif 'Atoms' in line: atomlist = [] for j in range(i + 2, i + 2 + nat): atomlist.append(data[j].strip().split()) if '#' in line and line.split('#')[1].strip() in lammps_atom_style: style = lammps_atom_style[line.split('#')[1]. strip()].split('} ') atypepos = style.index('{2:d') cpos = style.index('{3: .4f') try: qpos = style.index('{6: .4f') except: qpos = None else: # make a guess for column-content: nargs = len(atomlist[0]) atypepos = 1 cpos = -3 testimageflags = 0 for j in range(nargs, 1, -1): try: test = [int(k[j]) for k in atomlist] except: pass else: # check for imageflags (3 integer columns) if nargs > 7 and j > 3: testimageflags += 1 if testimageflags == 3: cpos = -6 # check if one of the first two entries # and not an empty charge column elif j == 2 and set(test) != set([0]): atypepos = j break # guess where charge is found: if nargs + cpos - 1 > atypepos: qpos = atypepos + 1 else: qpos = False # gotta load 'em all! tmol.newAtoms(nat) for j, at in enumerate(atomlist): tmol.setAtom(j, types[int(at[atypepos]) - 1], at[cpos:cpos + 3 if cpos + 3 else None], float(at[qpos]) if qpos else None) tmol.setFmt('angstrom', scale=True) tmol.setVec(tvec) tmol.setCellDim(1, fmt='angstrom') i += 1 return tmol, None
def parser(name, data): """ Parse Gaussian Cube file """ tmol = Molecule(name) fmt = "bohr" # two lines of comments, combine tmol.comment = data[0] + ";" + data[1] # nat, origin[3] nat = int(data[2].split()[0]) origin = [float(data[2].split()[i]) for i in [1, 2, 3]] # n of datapoints(dir), cell_vec[3] nvol = [0, 0, 0] tvec = [0, 0, 0] for i in [0, 1, 2]: line = data[i + 3].split() nvol[i] = int(line[0]) if nvol[i] < 0: nvol[i] = -nvol[i] fmt = "angstrom" tvec[i] = [float(line[j]) * nvol[i] for j in [1, 2, 3]] tmol.setVec(tvec) pse = list(glob_pse.keys()) tmol.newAtoms(nat) for i in range(nat): # line = Z, charge, coord(x, y, z) line = data[i + 6].split() tmol.setAtom(i, pse[int(line[0])], line[2:5], charge=float(line[1])) tmol.setFmt(fmt, scale=False) tmol.setCellDim(1, fmt=fmt) # rest of file has datagrid, x is outer loop, z inner vol = [[[0] * nvol[2] for i in range(nvol[1])] for j in range(nvol[0])] i = 6 + nat line = data[i].split() for x in range(nvol[0]): for y in range(nvol[1]): for z in range(nvol[2]): while not line and i < (len(data) - 1): i += 1 line = data[i].split() vol[x][y][z] = float(line.pop(0)) tmol.setVol(vol, origin) return tmol, None
def parser(name, data): """ Parse CPMD Input file """ tmol = Molecule(name) tparam = deepcopy(param["default"]) tparam["name"] = name i = 0 ibrav = '14' symmetries = {'ISOLATED': '0', 'CUBIC': '1', 'FACE CENTERED CUBIC': '2', 'FCC': '2', 'BODY CENTERED CUBIC': '3', 'BCC': '3', 'HEXAGONAL': '4', 'TRIGONAL': '5', 'RHOMBOHEDRAL': '5', 'TETRAGONAL': '6', 'BODY CENTERED TETRAGONAL': '7', 'BCT': '7', 'ORTHORHOMBIC': '8', 'MONOCLINIC': '12', 'TRICLINIC': '14'} fmt = 'bohr' unitvec = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] scalevec = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] types = [] while i < len(data): if data[i][0] == '!' or data[i].split() == []: i += 1 elif '&' in data[i] and data[i].strip() != "&END": # start recording namelist nl = data[i].strip() i += 1 while "&END" not in data[i]: if nl == "&SYSTEM" and "ANGSTROM" in data[i]: fmt = "angstrom" elif nl == "&SYSTEM" and "KPOINTS" in data[i]: if "MONKHORST" in data[i]: kpoints = data[i + 1].split() if "SHIFT=" in data[i]: kpoints += data[i].split("SHIFT=")[1].split()[0:3] else: kpoints += ['0', '0', '0'] tmol.setKpoints('active', 'mpg') tmol.setKpoints('mpg', kpoints) i += 1 else: kpoints = [] crystal = False bands = False if "SCALED" in data[i]: crystal = True if "BANDS" in data[i]: bands = True j = 1 line = data[i + j].split() while not all([float(k) == 0 for k in line]): kpoints.append(line[1:4] + [line[0]]) kpoints.append(line[4:] + ['0']) j += 1 line = data[i + j].split() i += j else: nk = int(data[i + 1]) for j in range(nk): kpoints.append(data[i + j + 2].split()) i += 1 + nk tmol.setKpoints('active', 'discrete') tmol.setKpoints('discrete', kpoints) tmol.setKpoints('options', {'crystal': crystal, 'bands': bands}) elif nl == "&SYSTEM" and "SCALE" in data[i]: if "CARTESIAN" in data[i]: fmt = "alat" else: fmt = "crystal" for token in data[i].strip().split(): if 'S=' in token: scalevec[0][0] = 1 / float(token.strip('S=')) scalevec[1][1] = 1 / float(token.strip('S=')) scalevec[2][2] = 1 / float(token.strip('S=')) elif 'SX=' in token: scalevec[0][0] = 1 / float(token.strip('SX=')) elif 'SY=' in token: scalevec[1][1] = 1 / float(token.strip('SY=')) elif 'SZ=' in token: scalevec[2][2] = 1 / float(token.strip('SZ=')) elif nl == "&SYSTEM" and "SYMMETRY" in data[i]: arg = data[i + 1].strip() if arg.isdigit(): ibrav = arg else: ibrav = symmetries[arg] i += 1 elif nl == "&SYSTEM" and "CELL" in data[i]: cell = list(map(float, data[i + 1].split())) if "VECTORS" in data[i]: while len(cell) < 9: i += 1 cell += list(map(float, data[i + 1].split())) ibrav = '-2' else: # cell = [a,b/a,c/a,cos(alpha),cos(beta),cos(gamma)] a, b, c, alpha, beta, gamma = cell tmol.setCellDim(a) if "ABSOLUTE" in data[i]: # cell = [a, b, c, ...] b = b / a c = c / a if "DEGREE" in data[i]: # cell = [..., alpha, beta, gamma] alpha, beta, gamma =\ map(cos, map(deg2rad, [alpha, beta, gamma])) i += 1 elif nl == "&ATOMS" and data[i][0] == '*': atype = regex('[-_.]', data[i][1:].strip())[0] while atype in types: if not atype[-1].isdigit(): atype += "1" else: atype = atype[:-1] + str(int(atype[-1]) + 1) types.append(atype) tmol.pse[atype]['CPPP'] = data[i][1:].strip() tmol.pse[atype]['CPNL'] = data[i + 1].strip() nat = int(data[i + 2]) for j in range(nat): tmol.newAtom(atype, data[i + 3 + j].split()[:3]) i += 2 + nat elif nl == "&ATOMS" and "CONSTRAINTS" in data[i]: # parse coordinate-fixes j = 1 constraints = "" line = data[i + j] while "END" not in line: if "FIX" in line and ("ALL" in line or "QM" in line): for at in range(tmol.nat): tmol.setAtom(at, fix=[True, True, True]) elif "FIX" in line and "ELEM" in line: j += 1 vals = data[i + j].split() Z = int(vals.pop(0)) if "SEQ" in line: beg = int(vals.pop(0)) - 1 end = int(vals.pop(0)) r = range(beg, end) else: r = range(tmol.nat) for at in r: if tmol.pse[tmol.getAtom(at)[0]]["Z"] == Z: tmol.setAtom(at, fix=[True, True, True]) elif "FIX" in line and "PPTY" in line: j += 1 vals = data[i + j].split() PP = int(vals.pop(0)) - 1 if "SEQ" in line: beg = int(vals.pop(0)) - 1 end = int(vals.pop(0)) r = range(beg, end) else: r = range(tmol.nat) for at in r: if tmol.getAtom(at)[0] == types[PP]: tmol.setAtom(at, fix=[True, True, True]) elif "FIX" in line and "SEQ" in line: j += 1 vals = data[i + j].split() for at in range(int(vals[0]) - 1, int(vals[1])): tmol.setAtom(at, fix=[True, True, True]) elif "FIX" in line and "ATOM" in line: j += 1 vals = data[i + j].split() count = int(vals.pop(0)) for k in range(count): if not vals: j += 1 vals = data[i + j].split() tmol.setAtom(int(vals.pop(0)) - 1, fix=[True, True, True]) elif "FIX" in line and "COOR" in line: j += 1 vals = data[i + j].split() count = int(vals.pop(0)) for k in range(count): j += 1 fixcoord = list(map(int, data[i + j].split())) tmol.setAtom(fixcoord[0] - 1, fix=[ bool(not fixcoord[1]), bool(not fixcoord[2]), bool(not fixcoord[3])]) elif line.strip(): constraints += line j += 1 line = data[i + j] if constraints: tparam[nl] += "CONSTRAINTS\n" + constraints +\ "END CONSTRAINTS\n" i += j elif nl == "&ATOMS" and "ISOTOPE" in data[i]: j = 0 for t in types: j += 1 mass = data[i + j].strip() tmol.pse[t]['m'] = float(mass) i += j else: tparam[nl] += data[i] i += 1 else: i += 1 # apply cell vec (scale SX etc.) if scalevec != unitvec: tmol.setVec(scalevec, scale=True) tmol.setVec(unitvec) # parse cell parameters if ibrav == '-2': tmol.setVec([cell[0:3], cell[3:6], cell[6:9]]) elif ibrav == '1': # simple cubic pass elif ibrav == '2': # face centered cubic tmol.setVec([[-0.5, 0, 0.5], [0, 0.5, 0.5], [-0.5, 0.5, 0]]) elif ibrav == '3': # body centered cubic tmol.setVec([[0.5, 0.5, 0.5], [-0.5, 0.5, 0.5], [-0.5, -0.5, 0.5]]) elif ibrav == '4': # hexagonal tmol.setVec([[1, 0, 0], [-0.5, sqrt(3) * 0.5, 0], [0, 0, c]]) elif ibrav == '5': # trigonal tx = sqrt((1 - alpha) / 2) ty = sqrt((1 - alpha) / 6) tz = sqrt((1 + 2 * alpha) / 3) tmol.setVec([[tx, -ty, tz], [0, 2 * ty, tz], [-tx, -ty, tz]]) elif ibrav == '6': # simple tetragonal tmol.setVec([[1, 0, 0], [0, 1, 0], [0, 0, c]]) elif ibrav == '7': # body centered tetragonal tmol.setVec([[0.5, -0.5, c * 0.5], [0.5, 0.5, c * 0.5], [-0.5, -0.5, c * 0.5]]) elif ibrav == '0' or ibrav == '8': # simple orthorhombic tmol.setVec([[1, 0, 0], [0, b, 0], [0, 0, c]]) elif ibrav == '12': # simple monoclinic tmol.setVec([[1, 0, 0], [b * alpha, b * sqrt(1 - alpha**2), 0], [0, 0, c]]) elif ibrav == '14': # triclinic singam = sqrt(1 - gamma**2) tmol.setVec([[1, 0, 0], [b * gamma, b * singam, 0], [c * beta, c * (alpha - beta * gamma) / singam, c * sqrt(1 + 2 * alpha * beta * gamma - alpha * alpha - beta * beta - gamma * gamma) / singam]]) # scale alat with explicit vectors if fmt == 'alat' and ibrav == '-2': vec = tmol.getVec() a = sqrt(vec[0][0] * vec[0][0] + vec[0][1] * vec[0][1] + vec[0][2] * vec[0][2]) b = sqrt(vec[1][0] * vec[1][0] + vec[1][1] * vec[1][1] + vec[1][2] * vec[1][2]) c = sqrt(vec[2][0] * vec[2][0] + vec[2][1] * vec[2][1] + vec[2][2] * vec[2][2]) tmol.setVec([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) tmol.setVec([[a, 0, 0], [0, b, 0], [0, 0, c]], scale=True) tmol.setVec(vec) # scale crystal, alat /w symmetry, angstrom-atoms tmol.setFmt(fmt, scale=True) # scale angstrom-cell tmol.setCellDim(tmol.getCellDim(fmt='bohr'), fmt=fmt) return tmol, tparam
def parser(name, data): """ Parse PWScf output to trajectory """ tmol = Molecule(name, steps=0) i = 0 vec = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] gamma = False while i < len(data): line = data[i].split() # ignore empty lines if not line: pass # read number of atoms elif line[0:3] == ['number', 'of', 'atoms/cell']: nat = int(line[4]) # read cell dimension elif line[0] == 'celldm(1)=': celldm = float(line[1]) # read initial cell vectors elif line[0:2] == ['crystal', 'axes:']: for j in [0, 1, 2]: temp = data[i + 1 + j].split() vec[j] = [float(x) for x in temp[3:6]] # read initial positions: elif line[0] == 'site': tmol.newStep() tmol.setCellDim(celldm) tmol.setVec(vec) tmol.newAtoms(nat) for j in range(nat): atom = data[j + i + 1].split() tmol.setAtom(j, atom[1], atom[6:9]) tmol.setFmt('alat', scale=True) i += nat # read k-points: elif line[0] == 'gamma-point': gamma = True elif line[0:3] == ['number', 'of', 'k'] and not gamma: nk = int(line[4]) if nk < 100: kpoints = [] for j in range(i + 2, i + nk + 2): kp = data[j].split() kpoints.append([kp[4], kp[5], kp[6].strip('), '), kp[9]]) tmol.setKpoints('discrete', kpoints) tmol.setKpoints('active', 'discrete') i += nk # read step-vectors if cell is variable elif line[0] == 'CELL_PARAMETERS': for j in [0, 1, 2]: temp = data[i + 1 + j].split() vec[j] = [float(x) for x in temp[0:3]] # read step-coordinates elif line[0] == 'ATOMIC_POSITIONS': tmol.newStep() tmol.setCellDim(celldm) tmol.setVec(vec) tmol.newAtoms(nat) for j in range(nat): atom = data[j + i + 1].split() tmol.setAtom(j, atom[0], atom[1:4], fix=[not int(x) for x in atom[4:]]) tmol.setFmt(line[1].strip('()'), scale=True) i += nat # break on reaching final coordinates (duplicate) elif line[0] == 'Begin': break # ignore everything else else: pass i += 1 return tmol, None
def parser(name, data): """ Parse (animated) XCrysDen structure files Optionally contains datagrids/animations/forces Parses multiple datagrids into multiple steps """ animated = False periodic = False pbcformats = ["MOLECULE", "POLYMER", "SLAB", "CRYSTAL"] i = 0 while i < len(data): if data[i][0] == '#': pass elif "ANIMSTEPS" in data[i]: tmol = Molecule(name, steps=int(data[i].strip("ANIMSTEPS \r\n"))) animated = True elif data[i].strip() in pbcformats: periodic = True # Parse coordinates of isolated molecule elif not periodic and "ATOMS" in data[i]: if animated: tmol.changeStep(int(data[i].strip("ATOMS \r\n")) - 1) else: tmol = Molecule(name, steps=1) j = 1 while i + j < len(data) and len(data[i + j].split()) in [4, 7]: line = data[i + j].split() tmol.newAtom(line[0], line[1:4]) j += 1 tmol.setFmt("angstrom", scale=True) i += j - 1 # Parse periodic structure containing cell and coordinates elif periodic and "PRIMVEC" in data[i]: vec = [data[i + j].split() for j in range(1, 4)] if animated and data[i].strip("PRIMVEC \r\n"): tmol.changeStep(int(data[i].strip("PRIMVEC ")) - 1) tmol.setVec(vec) tmol.setCellDim(1, fmt='angstrom') elif animated: tmol.setVecAll(vec) tmol.setCellDimAll(1, fmt='angstrom') else: tmol = Molecule(name, steps=1) tmol.setVec(vec) tmol.setCellDim(1, fmt='angstrom') i += 3 elif periodic and "PRIMCOORD" in data[i]: if animated: tmol.changeStep(int(data[i].strip("PRIMCOORD \r\n")) - 1) nat = int(data[i + 1].split()[0]) tmol.newAtoms(nat) for j in range(nat): line = data[j + 2 + i].split() tmol.setAtom(j, line[0], line[1:4]) tmol.setFmt("angstrom", scale=True) i += nat + 1 elif periodic and "CONVVEC" in data[i]: # could be used, but not atm pass elif periodic and "CONVCOORD" in data[i]: # pragma: no cover # should not even be there pass elif "BEGIN_" in data[i]: datatype = data[i].strip("BEGIN_BLOCK_ \r\n") endblock = "END_BLOCK_" + datatype endgrid = "END_" + datatype j = 1 grids = [] # only parse 3D datagrids while endblock not in data[i + j]: if datatype in data[i + j] and datatype == "DATAGRID_3D": nvol = list(map(int, data[i + j + 1].split())) vol = [[[0] * nvol[2] for y in range(nvol[1])] for z in range(nvol[0])] origin = list(map(float, data[i + j + 2].split())) # assume spanning space equals cell j += 6 line = data[i + j].split() for z in range(nvol[2]): for y in range(nvol[1]): for x in range(nvol[0]): while not (line or endgrid in data[i + j + 1]): j += 1 line = data[i + j].split() vol[x][y][z] = float(line.pop(0)) del vol[-1] for n in vol: del n[-1] for m in n: del m[-1] grids.append((vol, origin)) j += 1 j += 1 if grids: tmol.changeStep(0) tmol.setVol(*grids[0]) if len(grids) > 1: for k in range(1, len(grids)): tmol.copyStep() tmol.setVol(*grids[k]) i += j i += 1 return tmol, None
def parser(name, data): """ Parse Empire specific xyz file """ tmol = Molecule(name) nat = int(data[0]) tmol.comment = data[1].strip() tmol.newAtoms(nat) for j in range(nat): line = data[j + 2].split() tmol.setAtom(j, line[0], line[1:4]) tmol.setFmt("angstrom", scale=True) vec = [0, 0, 0] for i in range(3): vec[i] = [float(x) for x in data[nat + 3 + i].split()] tmol.setVec(vec) tmol.setCellDim(1, fmt="angstrom") return tmol, None
def parser(name, data): """ Parse PWScf input files Namelists will be parsed and saved in PW parameter set Supported Cards: - ATOMIC_SPECIES - ATOMIC_POSITIONS - K_POINTS - CELL_PARAMETERS Not supported: - CONSTRAINTS - OCCUPATIONS - ATOMIC_FORCES (PWSCFv5) """ tmol = Molecule(name) tparam = {"type": "pwi", "name": name} tvec = [] # parse data and create tparam while data: header = data.pop(0).strip().split() # ignore empty lines if not header: pass # parse namelists elif header[0][0] == '&': tnl = OrderedDict() # parse entries line = regex(', \s*(?![^()]*\))', data.pop(0).strip()) while line[0] != '/': for j in range(len(line)): if line[j]: tnl[line[j].split('=')[0].strip()] =\ line[j].split('=')[1].strip() line = regex(', \s*(?![^()]*\))', data.pop(0).strip()) tparam[header[0].lower()] = tnl # parse card elif header[0][0].isupper(): # ATOMIC_SPECIES: # Name Weight PP-file if header[0] == 'ATOMIC_SPECIES': for i in range(int(tparam['&system']['ntyp'])): line = data.pop(0).strip().split() tmol.pse[line[0]]['m'] = float(line[1]) tmol.pse[line[0]]['PWPP'] = line[2] # ATOMIC_POSITIONS fmt # Name x y z elif header[0] == 'ATOMIC_POSITIONS': fmt = header[1].strip('{()}') tmol.newAtoms(int(tparam['&system']['nat'])) for i in range(int(tparam['&system']['nat'])): # support empty lines temp = data.pop(0).split() while not temp: temp = data.pop(0).split() tmol.setAtom(i, temp[0], temp[1:4], fix=[not int(x) for x in temp[4:]]) # K_POINTS fmt elif header[0] == 'K_POINTS': active = header[1].strip('{()}') # Gamma point only if active == 'gamma': tmol.setKpoints('active', 'gamma') # Monkhorst Pack Grid: # x y z offset elif active == 'automatic': line = data.pop(0).split() tmol.setKpoints('mpg', line) tmol.setKpoints('active', 'mpg') # else: # number of kpoints # x y z weight else: nk = int(data.pop(0).split()[0]) kpoints = [] for i in range(nk): kpoints.append(data.pop(0).split()) tmol.setKpoints('discrete', kpoints) tmol.setKpoints('active', 'discrete') if active == 'tpiba': pass elif active == 'tpiba_b': tmol.setKpoints('options', {'bands': True, 'crystal': False}) elif active == 'crystal': tmol.setKpoints('options', {'bands': False, 'crystal': True}) elif active == 'crystal_b': tmol.setKpoints('options', {'bands': True, 'crystal': True}) # CELL_PARAMETERS # only needed if ibrav=0 # tbd changed between pw4 and pw5, ignored for now elif header[0] == 'CELL_PARAMETERS': for i in [0, 1, 2]: line = data.pop(0).strip().split() tvec.append([float(x) for x in line]) else: pass # Identify cell parameter representation, parse it ibrav = tparam['&system']['ibrav'] tparam['&system']['ibrav'] = '0' # Get cell values sys = tparam['&system'] a = b = c = cosab = cosac = cosbc = None if 'celldm(1)' in sys: a = float(sys['celldm(1)']) del sys['celldm(1)'] tmol.setCellDim(a, fmt='bohr') if 'celldm(2)' in sys: b = float(sys['celldm(2)']) del sys['celldm(2)'] if 'celldm(3)' in sys: c = float(sys['celldm(3)']) del sys['celldm(3)'] if 'celldm(4)' in sys: cosab = float(sys['celldm(4)']) del sys['celldm(4)'] if 'celldm(5)' in sys: cosac = float(sys['celldm(5)']) del sys['celldm(5)'] if 'celldm(6)' in sys: cosbc = float(sys['celldm(6)']) del sys['celldm(6)'] if ibrav == '14': cosab, cosbc = cosbc, cosab elif 'A' in sys: a = float(sys['A']) del sys['A'] tmol.setCellDim(a, fmt='angstrom') if 'B' in sys: b = float(sys['B']) / a del sys['B'] if 'C' in sys: c = float(sys['C']) / a del sys['C'] if 'cosAB' in sys: cosab = float(sys['cosAB']) del sys['cosAB'] if 'cosAC' in sys: cosac = float(sys['cosAC']) del sys['cosAC'] if 'cosBC' in sys: cosbc = float(sys['cosBC']) del sys['cosBC'] elif ibrav != '0': raise ValueError('Neither celldm(1) nor A specified') def checkCellVal(v, n): if v is None: raise ValueError(n + ' is needed, but was not specified') if ibrav == '0': # check if CELL_PARAMETERS card has been read # if not present, throw error if not tvec: raise ValueError('ibrav=0, but CELL_PARAMETERS missing') else: tmol.setVec(tvec) elif ibrav == '1': # simple cubic pass elif ibrav == '2': # face centered cubic tmol.setVec([[-0.5, 0, 0.5], [0, 0.5, 0.5], [-0.5, 0.5, 0]]) elif ibrav == '3': # body centered cubic tmol.setVec([[0.5, 0.5, 0.5], [-0.5, 0.5, 0.5], [-0.5, -0.5, 0.5]]) elif ibrav == '4': # hexagonal checkCellVal(c, 'c') tmol.setVec([[1, 0, 0], [-0.5, sqrt(3) * 0.5, 0], [0, 0, c]]) elif ibrav == '5': # trigonal checkCellVal(cosab, 'cosab') tx = sqrt((1 - cosab) / 2) ty = sqrt((1 - cosab) / 6) tz = sqrt((1 + 2 * cosab) / 3) tmol.setVec([[tx, -ty, tz], [0, 2 * ty, tz], [-tx, -ty, tz]]) elif ibrav == '-5': # trigonal, alternative checkCellVal(cosab, 'cosab') tx = sqrt((1 - cosab) / 2) ty = sqrt((1 - cosab) / 6) tz = sqrt((1 + 2 * cosab) / 3) u = (tz - 2 * sqrt(2) * ty) / sqrt(3) v = (tz + sqrt(2) * ty) / sqrt(3) tmol.setVec([[u, v, v], [v, u, v], [v, v, u]]) elif ibrav == '6': # simple tetragonal checkCellVal(c, 'c') tmol.setVec([[1, 0, 0], [0, 1, 0], [0, 0, c]]) elif ibrav == '7': # body centered tetragonal checkCellVal(c, 'c') tmol.setVec([[0.5, -0.5, c * 0.5], [0.5, 0.5, c * 0.5], [-0.5, -0.5, c * 0.5]]) elif ibrav == '8': # simple orthorhombic checkCellVal(c, 'c') checkCellVal(b, 'b') tmol.setVec([[1, 0, 0], [0, b, 0], [0, 0, c]]) elif ibrav == '9': # basis centered orthorhombic checkCellVal(c, 'c') checkCellVal(b, 'b') tmol.setVec([[0.5, b * 0.5, 0], [-0.5, b * 0.5, 0], [0, 0, c]]) elif ibrav == '10': # face centered orthorhombic checkCellVal(c, 'c') checkCellVal(b, 'b') tmol.setVec([[0.5, 0, c * 0.5], [0.5, b * 0.5, 0], [0, b * 0.5, c * 0.5]]) elif ibrav == '11': # body centered orthorhombic checkCellVal(c, 'c') checkCellVal(b, 'b') tmol.setVec([[0.5, b * 0.5, c * 0.5], [-0.5, b * 0.5, c * 0.5], [-0.5, -b * 0.5, c * 0.5]]) elif ibrav == '12': # simple monoclinic checkCellVal(c, 'c') checkCellVal(b, 'b') checkCellVal(cosab, 'cosab') tmol.setVec([[1, 0, 0], [b * cosab, b * sqrt(1 - cosab**2), 0], [0, 0, c]]) elif ibrav == '-12': # simple monoclinic, alternate definition checkCellVal(c, 'c') checkCellVal(b, 'b') checkCellVal(cosac, 'cosac') tmol.setVec([[1, 0, 0], [0, b, 0], [c * cosac, 0, c * sqrt(1 - cosac**2)]]) elif ibrav == '13': # base centered monoclinic checkCellVal(c, 'c') checkCellVal(b, 'b') checkCellVal(cosab, 'cosab') tmol.setVec([[0.5, 0, -c * 0.5], [b * cosab, b * sqrt(1 - cosab**2), 0], [0.5, 0, c * 0.5]]) elif ibrav == '14': # triclinic checkCellVal(c, 'c') checkCellVal(b, 'b') checkCellVal(cosab, 'cosab') checkCellVal(cosac, 'cosac') checkCellVal(cosbc, 'cosbc') singam = sqrt(1 - cosab**2) tmol.setVec([[1, 0, 0], [b * cosab, b * singam, 0], [c * cosac, c * (cosbc - cosac * cosab) / singam, c * sqrt(1 + 2 * cosbc * cosac * cosab - cosbc * cosbc - cosac * cosac - cosab * cosab) / singam]]) # scale atoms after creating cell: tmol.setFmt(fmt, scale=True) # delete nat and ntype before returning del tparam['&system']['nat'] del tparam['&system']['ntyp'] return tmol, tparam