def make_berry_parser(): import re from pwproc.util import parser_one_line def parse_vector(vec, *, num_re=re.compile(r"-?[.\d]+")): return tuple(map(float, num_re.findall(vec))) gdir_re = re.compile(r"^[ \w]* direction of vector ([123])$") phase_re = re.compile(r"^ +TOTAL PHASE: +(-?[.\d]+) \(mod (1|2)\)$") vec_re = re.compile(r"^ +The polarization direction is: +\(( *(?:-?[.\d]+[ ,]*){3})\)$") pol_re = re.compile(r"^ +P = +(-?[.\d]+) +\(mod +([.\d]+)\) +C/m\^2$") g_parser = parser_one_line(gdir_re, lambda m: int(m.group(1))) phase_parser = parser_one_line(phase_re, lambda m: (float(m.group(1)), int(m.group(2)))) vec_parser = parser_one_line(vec_re, lambda m: parse_vector(m.group(1))) pol_parser = parser_one_line(pol_re, lambda m: tuple(map(float, m.group(1, 2)))) def berry_parser(f_name): # type: (Path) -> Polarization with open(f_name) as f: gdir = g_parser(f) f.seek(0) phase = phase_parser(f) f.seek(0) vec = vec_parser(f) f.seek(0) pol = pol_parser(f) return Polarization(gdir, phase, vec, pol) return berry_parser
def get_init_basis(path): # type: (Path) -> Tuple[float, Basis] """Extracts the initial basis in angstrom from pw.x output.""" from scipy import constants from pwproc.util import parser_one_line, parser_with_header bohr_to_ang = constants.value('Bohr radius') / constants.angstrom alat_re = re.compile( r"[ \t]+lattice parameter \(alat\)[ \t]+=[ \t]+([\d.]+)[ \t]+a\.u\.") basis_head_re = re.compile( r"[ \t]+crystal axes: \(cart. coord. in units of alat\)") basis_line_re = re.compile( r"[ \t]+a\([\d]\) = \(((?:[ \t]+[-.\d]+){3}[ \t]+)\)") alat_parser = parser_one_line(alat_re, lambda m: float(m.group(1))) basis_parser = parser_with_header(basis_head_re, basis_line_re, lambda m: parse_vector(m.group(1))) with open(path) as f: alat: float = alat_parser(f) # TODO: Remove seek and run parsers in correct order f.seek(0) basis = basis_parser(f) # Convert basis from alat to angstrom assert len(basis) == 3 basis = Basis(np.array(basis)) basis *= alat * bohr_to_ang return alat, basis
def get_scf_energy(path): # type: (str) -> float """Get the energy in Ry from pw.x output.""" import re from pwproc.util import parser_one_line energy_re = re.compile(r"![\s]+total energy[\s]+=[\s]+(-[\d.]+) Ry") energy_parser = parser_one_line(energy_re, lambda m: float(m.group(1))) with open(path) as f: return energy_parser(f)
def find_fermi(path): # type: (Path) -> Iterable[float] """Extract all records of the Fermi energy from pw.x output.""" import re from pwproc.util import parser_one_line fermi_re = re.compile(r"[ \t]+the Fermi energy is[ \t]+(-?[.\d]+) ev") fermi_parser = parser_one_line(fermi_re, lambda m: float(m.group(1)), find_multiple=True) with open(path) as f: fe = fermi_parser(f) return fe
def get_save_file(path): # type: (Path) -> str """Extract the prefix from pw.x output.""" from pwproc.util import parser_one_line save_re = re.compile( r"^[ \t]+Writing output data file (?:\./)?([-.\w]+).save/?$") save_parser = parser_one_line(save_re, lambda m: m.group(1)) with open(path) as f: prefix = save_parser(f) if prefix is None: raise ParserError("Could not find calculation prefix") return prefix