Source code for scine_puffin.utilities.surface_helper

# -*- coding: utf-8 -*-
from __future__ import annotations
__copyright__ = """ This code is licensed under the 3-clause BSD license.
Copyright ETH Zurich, Department of Chemistry and Applied Biosciences, Reiher Group.
See LICENSE.txt for details.
"""

from ast import literal_eval
from typing import TYPE_CHECKING
from platform import python_version

from pymatgen.core import Lattice
from pymatgen.core.surface import Slab
import pymatgen

from scine_puffin.utilities.imports import module_exists, MissingDependency

if module_exists("scine_database") or TYPE_CHECKING:
    import scine_database as db
else:
    db = MissingDependency("scine_database")
if module_exists("scine_utilities") or TYPE_CHECKING:
    import scine_utilities as utils
else:
    utils = MissingDependency("scine_utilities")


[docs]def get_slab_dict(structure: db.Structure, properties: db.Collection) -> dict: """ Generate the dictionary defining a pymatgen Slab object from a database Structure, which must hold the required information as a property. Notes ----- This code is taken from scine.chemoton.utilities.surfaces.pymatgen_interface Parameters ---------- structure : db.Structure The periodic Structure properties : db.Collection The properties collection to link the structure's properties Returns ------- dict A dictionary that can be used as a constructor for the pymatgen.core.surface.Slab Raises ------ RuntimeError The property 'slab_dict' not present """ if not structure.has_property("slab_dict"): raise RuntimeError(f"Slab information is missing for structure '{str(structure)}'") dict_info = db.StringProperty(structure.get_property('slab_dict'), properties) dict_info_string = dict_info.get_data() # remove some specific extra strings from representation to be able to make dict out of string dict_info_string = dict_info_string.replace("]])", "]]") dict_info_string = dict_info_string.replace("array(", "") # transform into dict return literal_eval(dict_info_string)
[docs]def update_slab_dict(structure: db.Structure, properties: db.Collection, replace_property: bool = False) -> None: """ Update the slab dict property of the given structure with its current positions and periodic boundary conditions Notes ----- This code is taken from scine.chemoton.utilities.surfaces.pymatgen_interface Parameters ---------- structure : db.Structure The structure holding the property properties : db.Collection The properties collection to link the structure's properties replace_property : bool, optional If the old property should be replaced with the new one Raises ------ RuntimeError The structure is not periodic """ slab_dict_name = "slab_dict" slab = Slab.from_dict(get_slab_dict(structure, properties)) pbc_string = structure.get_model().periodic_boundaries if not pbc_string or pbc_string.lower() == "none": raise RuntimeError("Structure is missing periodic boundary conditions") pbc = utils.PeriodicBoundaries(pbc_string) atoms = structure.get_atoms() ele = [utils.ElementInfo.symbol(e) for e in atoms.elements] coords = pbc.transform(atoms.positions, False) lattice = _construct_pmg_lattice(pbc) new_slab = Slab(lattice, ele, coords, slab.miller_index, slab.oriented_unit_cell, slab.shift, slab.scale_factor, coords_are_cartesian=False) if not replace_property: dict_property = db.StringProperty(structure.get_property(slab_dict_name), properties) dict_property.set_data(str(new_slab.as_dict())) return structure.clear_properties(slab_dict_name) new_property = db.StringProperty.make(slab_dict_name, structure.get_model(), str(new_slab.as_dict()), properties) structure.set_property(slab_dict_name, new_property.id())
def _construct_pmg_lattice(pbc: utils.PeriodicBoundaries) -> Lattice: matrix = pbc.matrix * utils.ANGSTROM_PER_BOHR if python_version() >= "3.8": from importlib.metadata import version pymatgen_version = version(pymatgen.__name__) elif hasattr(pymatgen, "__version__"): pymatgen_version = getattr(pymatgen, "__version__") else: pymatgen_version = "0" if pymatgen_version >= "2022": return Lattice(matrix, pbc.periodicity) # type: ignore # pylint: disable=too-many-function-args return Lattice(matrix)