def parse_scf_conv(scf_out): from qharv.reel import ascii_out mm = ascii_out.read(scf_out) idxl = ascii_out.all_lines_with_tag(mm, 'iteration #') data = [] for idx in idxl: mm.seek(idx) # read iteration number iternow = ascii_out.name_sep_val(mm, 'iteration', sep='#', dtype=int) # find total energy and other info (!!!! must be in order) try: time = ascii_out.name_sep_val(mm, 'cpu time spent up to now', sep='is') enow = ascii_out.name_sep_val(mm, 'total energy') except: continue entry = {'istep': iternow, 'energy': enow, 'time': time} data.append(entry) return data
def get_ekmap(scf_out): """Obtain the internal variable 'equiv' from kpoint_grid.f90 in QE/PW store the maps between full BZ (fBZ) and irreducible BZ (iBZ) Args: scf_out (str): output file Return: (dict, dict): (fBZ->iBZ, iBZ->fBZ) maps """ from qharv.reel import ascii_out mm = ascii_out.read(scf_out) text = ascii_out.block_text(mm, 'equivalent kpoints begin', 'end') lines = text.split('\n') emap = {} # full kgrid to irreducible wedge kmap = {} # irreducible wedge to full kgrid for line in lines: tokens = line.split('equiv') if len(tokens) != 2: continue left, right = map(int, tokens) emap[left] = right if right in kmap: kmap[right].append(left) else: kmap[right] = [left] mm.close() return emap, kmap
def get_axsf_normal_mode(faxsf, imode): """ extract the first normal mode labeled by 'PRIMCOORD {imode:d}' assume the following format: PRIMCOORD 1 16 1 H 0.00000 0.00000 1.50303 -0.00000 0.00000 0.02501 H 0.63506 0.63506 0.00000 0.00000 -0.00000 0.02500 ... Args: faxsf (str): name of axsf file imode (int): index of normal mode Return: tuple: (elem,data), elem is a list of atomic symbols, data is a np.array of floats (6 columns in above example). """ from qharv.reel import ascii_out mm = ascii_out.read(faxsf) # search through all modes for requested imode all_idx = ascii_out.all_lines_with_tag(mm, 'PRIMCOORD') found = False for idx in all_idx: mm.seek(idx) line = mm.readline() myi = int(line.split()[1]) if myi != imode: continue # found imode found = True # get number of atoms line = mm.readline() natom = int(line.split()[0]) # get atomic symbols, positions and normal mode elem = [] data = [] for iatom in range(natom): line = mm.readline() tokens = line.split() elem.append(tokens[0]) data.append(map(float, tokens[1:])) # end for iatom # check that the next line is either next mode or empty line = mm.readline() expected = (line == '') or (line.startswith('PRIMCOORD')) if not expected: raise RuntimeError('failed to read mode %d correctly' % imode) # end if break # end for idx if not found: raise RuntimeError('failed to find mode %d in %s' % (imode, faxsf)) # end if return elem, np.array(data)
def get_dsk_amat(floc): """ extract A matrix from qmcfinitesize output k->0 behavior of 3D structure factor S(k) is fitted to a Gaussian S(k) = k^T A k Args: floc (str): location of qmcfinitesize output Returns: np.array: A matrix (3x3) """ mm = ascii_out.read(floc) amat = np.zeros([3,3]) # step 1: fill upper triangular part of amat xyzm = {'x':0,'y':1,'z':2} # map x,y,z to index keyl = ['a_xx','a_yy','a_zz','a_xy','a_xz','a_yz'] for key in keyl: # order of key matters! val = ascii_out.name_sep_val(mm,key) xyz_xyz = key.split('_')[-1] idx = tuple([xyzm[xyz] for xyz in xyz_xyz]) amat[idx] = val # end for # step 2: symmetrize amat amat[(1,0)] = amat[(0,1)] amat[(2,1)] = amat[(1,2)] amat[(2,0)] = amat[(0,2)] return amat
def read_lammps_log(flog, header='Per MPI rank memory', trailer='Loop time'): import pandas as pd from qharv.reel import ascii_out, scalar_dat mm = ascii_out.read(flog) blocks = ascii_out.all_lines_with_tag(mm, header) dfl = [] if len(blocks) < 1: return pd.DataFrame(dfl) for iblock, idx in enumerate(blocks): mm.seek(idx) pre = '# ' # !!!! assume first line is header try: # clean run from start to finish text1 = ascii_out.block_text(mm, header, trailer) text1 = strip_warnings(text1) df1 = scalar_dat.parse(pre+text1).astype(float) except Exception as err: mm.seek(idx) # !!!! decorator "stay" does not finish if Exception if type(err) is ValueError: # unfinished restart run text1 = ascii_out.block_text(mm, header, trailer='restart') text1 = strip_warnings(text1) df1 = scalar_dat.parse(pre+text1).astype(float) elif type(err) is RuntimeError: # unfinished final run text1 = ascii_out.block_text(mm, header, trailer, force_tail=True) text1 = strip_warnings(text1) df1 = scalar_dat.parse(pre+text1).astype(float) else: # give up raise err dfl.append(df1) mm.close() df = pd.concat(dfl, sort=False).reset_index(drop=True) return df
def read_kpoints(scf_out): from qharv.reel import ascii_out mm = ascii_out.read(scf_out) # get lattice units alat = ascii_out.name_sep_val(mm, 'lattice parameter (alat)') blat = 2 * np.pi / alat # start parsing k points idx = mm.find(b'number of k points') mm.seek(idx) # read first line # e.g. number of k points= 32 Fermi-Dirac smearing ... line = mm.readline().decode() nk = int(line.split('=')[1].split()[0]) # confirm units in second line line = mm.readline().decode() assert '2pi/alat' in line # start parsing kvectors data = np.zeros([nk, 4]) # ik, kx, ky, kz, wk for ik in range(nk): line = mm.readline().decode() kvec, wk = parse_kline(line, ik=ik) data[ik, :3] = kvec * blat data[ik, 3] = wk return data
def read_fsc_out(fout, chi2_tol=1e-12, rtol=0.01): from qharv.reel import ascii_out mm = ascii_out.read(fout) # check chi^2 idxl = ascii_out.all_lines_with_tag(mm, 'fitpn: Chi^2 =') for idx in idxl: mm.seek(idx) chi2 = ascii_out.name_sep_val(mm, 'fitpn: Chi^2', '=') assert chi2 < chi2_tol # rewind mm.seek(0) # get nelec nelec = ascii_out.name_sep_val(mm, 'nparts', '=', dtype=int) # read potential idx = mm.find(b'Potential energy correction') mm.seek(idx) idx = mm.find(b'using optimized potential') mm.seek(idx) dv = ascii_out.name_sep_val(mm, 'dV/N', '=') # check potential idx = mm.find(b'interpolating optimized potential') mm.seek(idx) dv0 = ascii_out.name_sep_val(mm, 'dV/N', '=') assert dv > 0 assert dv0 > 0 rdv = abs(dv - dv0) / dv0 assert rdv < rtol # read kinetic mm = ascii_out.read(fout) idx = mm.find(b'Kinetic energy correction') mm.seek(idx) idx = mm.find(b'using optimized potential') mm.seek(idx) dt = ascii_out.name_sep_val(mm, 'dT/N', '=') # check kinetic idx = mm.find(b'interpolating optimized potential') mm.seek(idx) dt0 = ascii_out.name_sep_val(mm, 'dT/N', '=') assert dt > 0 assert dt0 > 0 rdt = abs(dt - dt0) / dt0 assert rdt < rtol mm.close() return dv * nelec, dt * nelec
def get_data_block(floc, name, nhead=0): start_tag = '#'+name + '_START#' stop_tag = '#'+name + '_STOP#' mm = ascii_out.read(floc) text = ascii_out.block_text(mm,start_tag,stop_tag) lines= text.split('\n')[nhead:-1] # empty after the last \n data = np.array( [map(float,line.split()) for line in lines] ,dtype=float) return data
def get_tgrid_tshift(nscf_in): from qharv.reel import ascii_out mm = ascii_out.read(nscf_in) idx = mm.find(b'K_POINTS automatic') mm.seek(idx) mm.readline() kline = mm.readline() mm.close() nums = list(map(int, kline.split())) tgrid = np.array(nums[:3]) tshift = np.array(nums[3:]) return tgrid, tshift
def read_out_cell(scf_out, ndim=3): axes = np.zeros([ndim, ndim]) from qharv.reel import ascii_out mm = ascii_out.read(scf_out) idx = mm.find(b'crystal axes') mm.seek(idx) mm.readline() for idim in range(ndim): line = mm.readline() right = line.split('=')[-1] text = ascii_out.lr_mark(right, '(', ')') axes[idim, :] = map(float, text.split()) return axes
def read_cfg(fcfg): mm = ascii_out.read(fcfg) idxl = ascii_out.all_lines_with_tag(mm, 'ITEM:') data = {} for idx in idxl: mm.seek(idx) header = mm.readline() item_name = header.split(':')[-1].strip() entry = parse_item(mm, item_name) data.update(entry) return data
def get_axes(nscf_in, ndim=3): from qharv.reel import ascii_out mm = ascii_out.read(nscf_in) idx = mm.find(b'CELL_PARAMETERS') mm.seek(idx) mm.readline() cell = [] for idim in range(ndim): line = mm.readline().decode() nums = list(map(float, line.split())) cell.append(nums) mm.close() axes = np.array(cell) return axes
def get_weights(nscf_out, remove_copy=False, atol=1e-10): from qharv.reel import ascii_out mm = ascii_out.read(nscf_out) idx = ascii_out.all_lines_with_tag(mm, 'wk =') lines = ascii_out.all_lines_at_idx(mm, idx) weights = [] for line in lines: wt = float(line.strip('\n').split('wk =')[-1]) weights.append(wt) mm.close() nt = len(weights) if remove_copy: weights = weights[:nt / 2] wtot = sum(weights) if not np.isclose(wtot, 2.0, atol=atol): raise RuntimeError('wrong weight sum %3.2f; expected 2.0' % wtot) return np.array(weights)
def get_occupation_numbers(nscf_out, nmax=1024): from qharv.reel import ascii_out mm = ascii_out.read(nscf_out) idx = ascii_out.all_lines_with_tag(mm, 'occupation numbers') occl = [] for i in idx: mm.seek(i) mm.readline() occ = [] for j in range(nmax): line = mm.readline() tokens = line.split() if len(tokens) == 0: break occ += map(float, tokens) next_line = mm.readline() occl.append(occ) return np.array(occl)
def get_elem_pos(nscf_in): from qharv.reel import ascii_out mm = ascii_out.read(nscf_in) natom = ascii_out.name_sep_val(mm, 'nat', '=', dtype=int) idx = mm.find(b'ATOMIC_POSITIONS') mm.seek(idx) header = mm.readline().decode() eleml = [] posl = [] for iatom in range(natom): line = mm.readline() tokens = line.split() eleml.append(tokens[0]) posl.append(tokens[1:]) mm.close() elem = np.array(eleml, dtype=str) pos = np.array(posl, dtype=float) return elem, pos, header
def get_jk_kvecs(fout, header='kSpace coefficient groups', trailer='QMCHamiltonian::addOperator'): """ parse QMCPACK output for kSpace Jastrow kvecs """ from qharv.reel import ascii_out mm = ascii_out.read(fout) text = ascii_out.block_text(mm, header, trailer) data = [] for line in text.split('\n'): tokens = line.split() if len(tokens) != 4: continue data.append(map(float, tokens)) data = np.array(data) kvecs = data[:, :3] kmags = data[:, 3] return kvecs
def get_supertwists(qmc_out): """ read supercell twists from QMCPACK output Args: qmc_out (str): QMCPACK output, must contain "Super twist #" Return: np.array: an array of twist vectors (ntwist, ndim) """ from qharv.reel import ascii_out mm = ascii_out.read(qmc_out) idxl = ascii_out.all_lines_with_tag(mm, 'Super twist #') lines = ascii_out.all_lines_at_idx(mm, idxl) data = [] for line in lines: text = ascii_out.lr_mark(line, '[', ']') vec = np.array(text.split(), dtype=float) data.append(vec) mat = np.array(data) return mat
def parse_output(floc): """ get energy, volume and pressure from QE output """ etot = read_first_energy(floc) entry = {'energy': etot / 2.} # Ry to ha mm = read(floc) label_map = {'volume': 'unit-cell volume', 'natom': 'number of atoms/cell'} for key in label_map.keys(): val = name_sep_val(mm, label_map[key]) entry[key] = val # end for au_stressl, kbar_stressl = read_stress(floc) assert len(au_stressl) == 1 au_stress = au_stressl[0] entry['pressure'] = np.diag(au_stress).mean() / 2. # Ry to ha entry['stress'] = au_stress / 2. # Ry to ha return entry
def read_kfracs(scf_out): from qharv.reel import ascii_out mm = ascii_out.read(scf_out) # get number of kpoints idx = mm.find(b'number of k points') mm.seek(idx) line = mm.readline().decode() nk = int(line.split('=')[1].split()[0]) # find first line idx = mm.find(b'cryst. coord.') mm.seek(idx) mm.readline() # read kpoints and weights data = np.zeros([nk, 4]) for ik in range(nk): line = mm.readline().decode() kvec, wk = parse_kline(line) data[ik, :3] = kvec data[ik, 3] = wk return data
def read_ipi_xyz(fxyz): from ase import io from ase.cell import Cell from qharv.reel import ascii_out mm = ascii_out.read(fxyz) idxl = ascii_out.all_lines_with_tag(mm, '# ') traj = io.read(fxyz, ':', format='extxyz') nhead = len(idxl) nbody = len(traj) if nhead != nbody: msg = 'found %d headers for %d bodies' % (nhead, nbody) raise RuntimeError(msg) headers = [] for idx in idxl: mm.seek(idx) header = mm.readline().decode() headers.append(header) mm.close() for header, atoms in zip(headers, traj): tokens = header.strip('#').split() # read cell i0 = tokens.index('CELL(abcABC):') cellpart = tokens[i0+1:i0+7] cellpar = np.array(cellpart, dtype=float) cell = Cell.fromcellpar(cellpar) atoms.set_cell(cell) atoms.set_pbc(True) # read info atoms.info = {} for i, tok in enumerate(tokens): if (i >= i0) and (i < i0+7): continue if tok.endswith(':'): # key-val pair atoms.info[tok[:-1]] = tokens[i+1] if ('{' in tok) and ('}' in tok): # unit key, val = tok.split('{') atoms.info[key+'_unit'] = val[:-1] return traj
def get_volume(fout): mm = ascii_out.read(fout) omega = ascii_out.name_sep_val(mm, 'Vol', pos=1) return omega
def parse_nscf_bands(nscf_out, span=7, trailer='occupation numbers'): data = {} # build a dictionary as return value def scanf_7f(line, n): """ implement scanf("%7.*f") """ numl = [] for i in range(n): token = line[span * i:span * (i + 1)] num = float(token) numl.append(num) return numl def parse_float_body(body): """ parse a blob of floats """ lines = body.split('\n') numl = [] for line in lines: if len(line) == 0: continue numl += map(float, line.split()) return numl from qharv.reel import ascii_out ndim = 3 mm = ascii_out.read(nscf_out) alat = ascii_out.name_sep_val(mm, 'lattice parameter (alat)') blat = 2 * np.pi / alat # find the beginnings of each band bhead = ' k =' idxl = ascii_out.all_lines_with_tag(mm, bhead) nkpt = len(idxl) data['nkpt'] = nkpt # estimate the end of the last band idx1 = ascii_out.all_lines_with_tag(mm, trailer)[-1] # trick to use no if statement in the loop idxl = idxl + [idx1] kvecs = [] # (nkpt, ndim) mat = [] # (nkpt, nbnd) for ikpt in range(nkpt): # specify beginning and end of the band output idx0 = idxl[ikpt] idx1 = idxl[ikpt + 1] # parse band output # first read header mm.seek(idx0) header = mm.readline().decode() if not 'bands (ev)' in header: continue kxkykz = ascii_out.lr_mark(header, '=', '(') kvec = scanf_7f(kxkykz, ndim) kvecs.append(kvec) # then read body body = mm[mm.tell():idx1].decode().strip('\n') if trailer in body: idx2 = mm.find(trailer.encode()) body = mm[mm.tell():idx2].strip('\n') row = parse_float_body(body) mat.append(row) # end for ikpt data['kvecs'] = blat * np.array(kvecs) data['bands'] = np.array(mat) return data
def get_efermi(fout): from qharv.reel import ascii_out mm = ascii_out.read(fout) efermi = ascii_out.name_sep_val(mm, 'the Fermi energy', sep='is') return efermi
def read_sym_ops(scf_out, ndim=3): """ read symmetry operators Args: scf_out (str): QE output file ndim (int, optional): number of spatial dimensions, default is 3 Return: list: all symmetry operators, each is represented as a dictionary isym is index, name is description, vec is shift, mat is rotation """ from qharv.reel import ascii_out mm = ascii_out.read(scf_out) # find starting location of symmetry operator output idx = mm.find(b'Sym. Ops.') if idx == -1: msg = 'no symmetry operations printed in %s. Is verbosity high?' % scf_out raise RuntimeError(msg) # rewind to beginning of line idx0 = mm.rfind(b'\n', 0, idx) mm.seek(idx0 + 1) header = mm.readline().decode() nsym = int(header.split()[0]) # check the number of symmetry outputs idxl = ascii_out.all_lines_with_tag(mm, 'isym = ') if len(idxl) != nsym: raise RuntimeError('found %d symm. expected %d' % (len(idxl), nsym)) # parse symmetry operators symops = [] for idx in idxl: mm.seek(idx) # read symmetry index and name: isym, name line0 = mm.readline().decode() text0 = line0.split('=')[1] tokens0 = text0.split() isym = int(tokens0[0]) name = ' '.join(tokens0[1:]) # read translation vector: vec vec = [0] * ndim if 'cart. axis' in name: vect = ascii_out.lr_mark(line0, '[', ']') vec[:] = list(map(float, vect.split(','))) # read rotation matrix: mat mat = [] idx = mm.find(b'cryst.') mm.readline() # skip empty line for idim in range(ndim): line = mm.readline().decode() if 'cryst.' in line: line = line.split('=')[1] text = ascii_out.lr_mark(line, '(', ')') mat.append(list(map(float, text.split()))) entry = {'isym': isym, 'name': name, 'vec': vec, 'mat': mat} symops.append(entry) mm.close() return symops