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_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_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 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 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_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_volume(fout): mm = ascii_out.read(fout) omega = ascii_out.name_sep_val(mm, 'Vol', pos=1) return omega
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 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 input_structure(scf_in, put_in_box=True): ndim = 3 # assume 3 dimensions with open(scf_in, 'r+') as f: mm = mmap(f.fileno(), 0) # end with from qharv.reel.ascii_out import name_sep_val ntyp = name_sep_val(mm, 'ntyp', dtype=int) if ntyp != 1: raise NotImplementedError('only support 1 type of atom for now') # end if # read lattice mm.seek(0) idx = mm.find(b'ibrav') mm.seek(idx) ibrav_line = mm.readline() ibrav = int(ibrav_line.split('=')[-1]) if ibrav != 0: raise NotImplementedError('only ibrav = 0 is supported') # end if idx = mm.find(b'CELL_PARAMETERS') mm.seek(idx) header = mm.readline() unit = header.split()[-1] axes = np.zeros([ndim, ndim]) for idim in range(ndim): line = mm.readline() axes[idim, :] = map(float, line.split()) # end for cell = {'unit': unit, 'axes': axes} # read atomic positions mm.seek(0) # rewind idx = mm.find(b'nat') mm.seek(idx) nat_line = mm.readline() nat = int(nat_line.split('=')[-1]) idx = mm.find(b'ATOMIC_POSITIONS') mm.seek(idx) header = mm.readline() unit = header.split()[-1] pos = np.zeros([nat, ndim]) for iat in range(nat): line = mm.readline() pos[iat, :] = map(float, line.split()[-3:]) # end for iat try: line = mm.readline() float(line.split()[-3:]) raise RuntimeError('next lines looks like positions too!\n%s' % line) except: pass # expect to see an empty line # end try if put_in_box: atpos = { 'pos_unit': unit, 'pos': pos_in_box(np.array(pos), np.array(axes)).tolist() } else: atpos = {'pos_unit': unit, 'pos': pos} # end if entry = {'infile': scf_in} entry.update(cell) entry.update(atpos) return entry
def read_forces(scf_out, ndim=3, which='total'): """ read the forces in a pwscf output, assume only one force block 'which' decides which block of forces to read, choices are: ['total', 'non-local', 'local', 'ionic', 'core', 'Hubbard', 'scf'] !!!! assuming QE uses Ry, will convert to Ha """ Ry = 0.5 # Ha begin_tag_dict = { 'total': 'Forces acting on atoms', 'non-local': 'The non-local contrib. to forces', 'ionic': 'The ionic contribution to forces', 'local': 'The local contribution to forces', 'core': 'The core correction contribution to forces', 'Hubbard': 'The Hubbard contrib. to forces', 'scf': 'The SCF correction term to forces' } end_tag_dict = { 'total': 'The non-local contrib. to forces', 'non-local': 'The ionic contribution to forces', 'ionic': 'The local contribution to forces', 'local': 'The core correction contribution to forces', 'core': 'The Hubbard contrib. to forces', 'Hubbard': 'The SCF correction term to forces', 'scf': 'Total force =' } fhandle = open(scf_out, 'r+') mm = mmap(fhandle.fileno(), 0) natom = name_sep_val(mm, 'number of atoms', dtype=int) # locate force block begin_tag = begin_tag_dict[which] end_tag = end_tag_dict[which] begin_idx = mm.find(begin_tag.encode()) end_idx = mm.find(end_tag.encode()) if begin_idx == -1: raise RuntimeError('cannot locate %s' % begin_tag) elif end_idx == -1: # maybe verbosity='low' end_idx = mm.find(b'Total force =') if end_idx == -1: raise RuntimeError('cannot locate %s' % end_tag) # end if # end if force_block = mm[begin_idx:end_idx] # parse force block for forces forces = np.zeros([natom, ndim]) iatom = 0 for line in force_block.split(b'\n'): if line.strip().startswith(b'atom'): tokens = line.split() if len(tokens) == 9: # found an atom myforce = np.array(tokens[-3:], dtype=float) forces[iatom, :] = tokens[-3:] iatom += 1 # end if # end if # end for if iatom != natom: raise RuntimeError('found %d forces for %d atoms' % (iatom, natom)) # end if fhandle.close() return forces * Ry