# 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"
[docs]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
[docs] 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)
[docs] @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)