Source code for ase2sprkkr.bindings.es_finder

"""
Binding for the es_finder package, that can determine the ideal positions
of empty spheres to fill the gaps in the primitive cell.
"""
from __future__ import annotations

import numpy as np

try:
  from es_finder.core.driver import run_finder
  from es_finder.core.parameters import Parameters
  from es_finder.core.symmetry import Symmetry
  from es_finder.adapter.pymatgen import StructureAdapter
  from pymatgen.io.ase import AseAtomsAdaptor
  import_error = None
  is_enabled = True
except ImportError as error:
  import_error = error
  run_finder = None
  is_enabled = False

from ase import Atoms
from ..sprkkr.sprkkr_atoms import SPRKKRAtoms
from ..physics.winger_seitz_radii import winger_seitz_radii
from typing import Dict, Union
from .empty_spheres import EmptySpheresResult


[docs] def empty_spheres(atoms: Atoms, *, overlap_matrix:Union[float,np.ndarray]=0.18, radii_ratios_map: Dict[str, float]=None, max_es_overlap:float = 0.24, # Maximum overlap of ES adjust_overlap:float = 0.28, # Overlap that will be adjusted to max. overlap min_es_radius: float = 0.2, # Min. accepted sphere radius max_es_radius :float = 1.0, # Max. accepted sphere radius symmetrize_threshold: float = 0.7, # Threshold for overlap when symmetrization is used max_iterations: int = 100, # Number of iterations for the sphere search grid: np.ndarray = np.array([[48, 0, 0], [0, 48, 0], [0, 0, 48]]), verbosity: int = 0, # Verbosity of output ): """ Compute the best coverage of the primitive cell with spheres. The function computes: - the best radii of atomic-sites spheres - the positions of 'vacuum pseudoatom' spheres and their radii to be added to the structure Parameters ---------- atoms The structure, that will be filled in with empty spheres extend If True, the atoms will be extended by the empty spheres sites overlap_matrix #TODO radii_ratios_map Dict, that defines the ratios of radii of used chemical elements. It is dimensionless value (it is not the sizes, only the ratios of the given values, that matter). The default walues are :mod:`Winger-Seitz radii<ase2sprkkr.physics.winger_seitz_radii>`. If only some of the elements are provided, they are supplemented with the default values. max_es_overlap Max allowed overlap of empty spheres. adjust_overlap #TODO max_es_radius Maximum radius of empty shperes min_es_radius Minimum radius of empty shperes symetrize_threshold #TODO Threshold for overlap when symmetrization is used max_iterations Number of iterations for sphere finding algorithm grid #TODO verbosity Verbosity of the output of the algorithm """ if run_finder is None: raise ImportError('Cannot import es_finder or pymatgen. Please install it, or set empty_spheres parameter to False') \ from import_error params = dict(locals()) for i in ('atoms', 'overlap_matrix', 'radii_ratios_map'): del params[i] if radii_ratios_map: radii_ratios_map = { **winger_seitz_radii, **radii_ratios_map } else: radii_ratios_map = winger_seitz_radii atoms = SPRKKRAtoms.promote_ase_atoms(atoms) sym_dataset = atoms.spacegroup_info.dataset if sym_dataset is None: sym_dataset = { 'translations' : np.empty((0,3)), 'rotations' : np.empty((0,3,3)), 'number' : 0, 'hall_number' : 0, 'hall' : '', } symmetry=Symmetry( sym_dataset['rotations'], sym_dataset['translations'], sym_dataset['number'], sym_dataset['hall_number'], sym_dataset['hall'] ) pmg_structure = AseAtomsAdaptor.get_structure(atoms) for s in map(str, pmg_structure.species): if not s in radii_ratios_map: radii_ratios_map[s] = 1.0 structure = StructureAdapter(pmg_structure, radii_ratios_map, overlap_matrix) params = Parameters(**params) from ..common.no_output import NoOutput with NoOutput(suppress=verbosity<=0): res = run_finder(params, structure, symmetry) return EmptySpheresResult(res.es_positions, res.es_radii @ atoms.cell)