Пример #1
0
def _proc_geom_buffs(
        geom_buff: Tuple[str, Sequence[Basis], Species, Sequence[Tau]],
        geom_init: Tuple[str, float, Basis, Species,
                         Tau], target_coord: str, relax_dims: _RelaxDims
) -> Tuple[Sequence[Basis], Species, Sequence[Tau]]:
    from itertools import starmap
    from pwproc.geometry import convert_coords

    # Unpack geometry
    ctype_i, alat, basis_i, species_i, pos_i = geom_init
    ctype, basis_steps, species, pos = geom_buff

    assert (species_i == species)

    # Convert coordinates if needed
    pos_i = convert_coords(alat, basis_i, pos_i, ctype_i, target_coord)
    basis_steps = (basis_i, ) * len(pos) if len(basis_steps) == 0 else tuple(
        basis_steps)
    pos = tuple(
        starmap(
            lambda basis, tau: convert_coords(alat, basis, tau, ctype,
                                              target_coord),
            zip(basis_steps, pos)))

    # Unpack relax dimensions
    n_steps, relax_kind, relax_done, zmag_relax = relax_dims

    # The geometry is unchanged in a magnetization check, just eliminate the last
    if zmag_relax:
        pos = pos[:-1]
        basis_steps = basis_steps[:-1]

    # Check length of buffer
    if relax_done:
        # The final duplicate SCF in vc-relax does not register on the step count
        # The converged geometry is printed again after SCF at the end of relax
        # However the first geometry is captured in the init_geom buffer
        if len(pos) != n_steps:
            raise ParserError("Unexpected length for geometry")

        # Remove final duplicate geometry
        if relax_kind == 'relax':
            pos = pos[:-1]
            basis_steps = basis_steps[:-1]
    else:
        # First geometry is not counted here
        if len(pos) == n_steps - 1:
            pass
        elif len(pos) == n_steps:
            # Geometry written for a step that did not finish
            pos = pos[:-1]
            basis_steps = basis_steps[:-1]
        else:
            raise ParserError("Unexpected length for geometry")

    return (basis_i, ) + basis_steps, species, (pos_i, ) + pos
Пример #2
0
def parse_scf(path, coord_type='crystal'):
    # type: (str, str) -> GeometryData
    """Parse pw.x output file.

    :param path: path to pw.x output
    :param coord_type: coordinate type of output

    :returns: GeometryData
    """
    from pwproc.geometry import convert_coords, GeometryData
    from pwproc.parsers import get_save_file, get_init_basis, get_init_coord

    # Run parsers on output to get geometry
    prefix = get_save_file(path)
    alat, basis = get_init_basis(path)
    ctype, species, pos = get_init_coord(path)

    # Parse file for energy
    energy = get_scf_energy(path)

    # Convert coordinates if needed
    pos = convert_coords(alat, basis, pos, ctype, coord_type)

    return GeometryData(prefix,
                        basis,
                        species,
                        pos,
                        energy=energy,
                        coord_type=coord_type)
Пример #3
0
    def convert_coords(self, new_coords):
        # type: (str) -> None
        from pwproc.geometry import convert_coords

        self.tau = tuple(
            convert_coords(1.0, b, t, self.coord_type, new_coords)
            for b, t in zip(self.basis, self.tau))
        self._coord_type = new_coords
Пример #4
0
def read_poscar(lines, out_type='angstrom'):
    # type: (Iterable[str], str) -> Tuple[str, float, Basis, Species, Tau]
    from itertools import chain, repeat
    from pwproc.util import parse_vector
    from pwproc.geometry import convert_coords

    # Read data from input
    lines = iter(lines)
    name = next(lines).strip()
    alat = float(next(lines))
    basis = tuple(next(lines) for _ in range(3))
    s_name = next(lines)
    s_num = next(lines)

    # Read atomic positions
    coord_line = next(lines).strip().lower()
    if coord_line == 'direct':
        in_type = 'crystal'
    elif coord_line == 'cartesian':
        in_type = 'angstrom'
    else:
        raise ValueError('Poscar error {}'.format(coord_line))

    pos = [line for line in lines]

    # parse the basis
    basis = alat * Basis(np.array(tuple(map(parse_vector, basis))))

    # Parse the species label
    species_pairs = tuple(zip(s_name.split(), map(int, s_num.split())))
    species = tuple(chain(*(repeat(s, n) for s, n in species_pairs)))
    species = Species(species)

    # Parse positions
    pos = alat * Tau(np.array(tuple(map(parse_vector, pos))))

    # Convert the input coordinates
    pos = convert_coords(alat, basis, pos, in_type, out_type)

    return name, alat, basis, species, pos
Пример #5
0
 def convert_coords(self, new_coord):
     # type: (str) -> None
     from pwproc.geometry import convert_coords
     self.tau = convert_coords(1.0, self.basis, self.tau, self.coord_type,
                               new_coord)
     self._coord_type = new_coord