pymatgen.io.atat — pymatgen 2020.7.3 documentation

# Source code for pymatgen.io.atat

    # coding: utf-8
    # Copyright (c) Pymatgen Development Team.
    # Distributed under the terms of the MIT License.

    """
    Classes for reading/writing mcsqs files following the rndstr.in format.
    """

    import numpy as np
    from pymatgen.core.structure import Structure
    from pymatgen.core.lattice import Lattice
    from pymatgen.core.periodic_table import get_el_sp, Specie

    __author__ = "Matthew Horton"
    __copyright__ = "Copyright 2017, The Materials Project"
    __maintainer__ = "Matthew Horton"
    __email__ = "mkhorton@lbl.gov"
    __status__ = "Production"
    __date__ = "October 2017"

    class Mcsqs:
        """
        Handle input/output for the crystal definition format
        used by mcsqs and other ATAT codes.
        """

        def __init__(self, structure):
            """
            :param structure: input Structure
            """

            self.structure = structure

        def to_string(self):
            """
            Returns a structure in mcsqs rndstr.in format.
            :return (str):
            """

            # add lattice vectors
            m = self.structure.lattice.matrix
            output = ["{:6f} {:6f} {:6f}".format(*l) for l in m]

            # define coord system, use Cartesian
            output.append("1.0 0.0 0.0")
            output.append("0.0 1.0 0.0")
            output.append("0.0 0.0 1.0")

            # add species
            for site in self.structure:
                species_str = []
                for sp, occu in sorted(site.species.items()):
                    if isinstance(sp, Specie):
                        sp = sp.element
                    species_str.append("{}={}".format(sp, occu))
                species_str = ",".join(species_str)
                output.append(
                    "{:6f} {:6f} {:6f} {}".format(
                        site.frac_coords[0],
                        site.frac_coords[1],
                        site.frac_coords[2],
                        species_str,
                    )
                )

            return "\n".join(output)

        @staticmethod
        def structure_from_string(data):
            """
            Parses a rndstr.in or lat.in file into pymatgen's
            Structure format.

            :param data: contents of a rndstr.in or lat.in file
            :return: Structure object
            """

            data = data.splitlines()
            data = [x.split() for x in data if x]  # remove empty lines

            # following specification/terminology given in manual
            if len(data[0]) == 6:  # lattice parameters
                a, b, c, alpha, beta, gamma = map(float, data[0])
                coord_system = Lattice.from_parameters(a, b, c, alpha, beta, gamma).matrix
                lattice_vecs = np.array(
                    [
                        [data[1][0], data[1][1], data[1][2]],
                        [data[2][0], data[2][1], data[2][2]],
                        [data[3][0], data[3][1], data[3][2]],
                    ],
                    dtype=float,
                )
                first_species_line = 4
            else:
                coord_system = np.array(
                    [
                        [data[0][0], data[0][1], data[0][2]],
                        [data[1][0], data[1][1], data[1][2]],
                        [data[2][0], data[2][1], data[2][2]],
                    ],
                    dtype=float,
                )
                lattice_vecs = np.array(
                    [
                        [data[3][0], data[3][1], data[3][2]],
                        [data[4][0], data[4][1], data[4][2]],
                        [data[5][0], data[5][1], data[5][2]],
                    ],
                    dtype=float,
                )
                first_species_line = 6

            scaled_matrix = np.matmul(coord_system, lattice_vecs)
            lattice = Lattice(scaled_matrix)

            all_coords = []
            all_species = []
            for l in data[first_species_line:]:

                coords = np.array([l[0], l[1], l[2]], dtype=float)
                scaled_coords = np.matmul(coords, np.linalg.inv(lattice_vecs))
                all_coords.append(scaled_coords)

                species_strs = "".join(l[3:])  # join multiple strings back together
                species_strs = species_strs.replace(" ", "")  # trim any white space
                species_strs = species_strs.split(",")  # comma-delimited

                species = {}

                for species_str in species_strs:
                    species_str = species_str.split("=")
                    if len(species_str) == 1:
                        # assume occupancy is 1.0
                        species_str = [species_str[0], 1.0]
                    species[get_el_sp(species_str[0])] = float(species_str[1])

                all_species.append(species)

            return Structure(lattice, all_species, all_coords)