Source code for gg.predefined_sites

"""Predefined Surfaces"""

from typing import Optional
from ase import Atoms
from gg.sites import Sites
from gg.sites import (
    get_com_sites,
    get_surface_sites_by_coordination,
    get_tagged_sites,
    get_unconstrained_sites,
)


[docs] class FlexibleSites(Sites): """A class that identifies sites based on constraints, tags, or explicit indices.""" def __init__( self, constraints: bool = False, index: Optional[list[int]] = None, tag: Optional[int] = None, opp_tag: bool = False, com: Optional[float] = None, max_bond_ratio: Optional[float] = 1.2, max_bond: Optional[float] = 0, contact_error: Optional[float] = 0.3, ): """ Args: constraints (bool, optional): If True, only unconstrained atoms are considered. Defaults to False. index (List[int], optional): A list of specific atom indices to consider. Defaults to None. tag (int, optional): If provided, only atoms with this tag are considered. Defaults to None. opp_tag (bool, optional): If True, considers atoms without the specified tag. Defaults to False. com (float, optional): If provided, considers atoms above the center of mass (COM) in the z-direction. The value determines the fraction of the z-range above the COM to consider. Defaults to None. max_bond_ratio (float, optional): Tolerance for bond distances. Defaults to 1.2. max_bond (float, optional): Maximum bond distance. Defaults to 0 (no limit). contact_error (float, optional): Tolerance for atoms being too close. Defaults to 0.2. """ super().__init__( max_bond_ratio=max_bond_ratio, max_bond=max_bond, contact_error=contact_error, ) # Validate inputs if index is None and not constraints and tag is None and com is None: raise RuntimeError( "Specify at least one of: index, constraints, tag, or com." ) self.constraints = constraints self.index = index self.tag = tag self.opp_tag = opp_tag self.com = com
[docs] def get_sites(self, atoms: Atoms) -> list[int]: """ Identifies sites based on the specified rules. Args: atoms (Atoms): The ASE Atoms object. Returns: List[int]: List of atom indices identified as sites. """ # Start with all indices if no specific index list is provided indices = self.index if self.index is not None else list(range(len(atoms))) # Apply constraints filter if self.constraints: indices = list(set(indices) & set(get_unconstrained_sites(atoms))) # Apply tag filter if self.tag is not None: if self.opp_tag: # Get indices of atoms without the specified tag tagged_indices = set(get_tagged_sites(atoms, tag=self.tag)) indices = list(set(indices) - tagged_indices) else: # Get indices of atoms with the specified tag tagged_indices = set(get_tagged_sites(atoms, tag=self.tag)) indices = list(set(indices) & tagged_indices) # Apply COM filter if self.com is not None: above_com_indices = set(get_com_sites(atoms, fraction=self.com)) indices = list(set(indices) & above_com_indices) return indices
[docs] class SurfaceSites(Sites): """A class that figures out the surface atom by coordination number""" def __init__( self, max_coord: dict, max_bond_ratio: Optional[float] = 1.2, max_bond: Optional[float] = 0, contact_error: Optional[float] = 0.3, com: Optional[bool] = 0.1, ): """ Args: max_coord (dict): Dictionary of the maximum coordination of each element used. Only atoms with coordination less than this value will be considered. max_bond_ratio (float): Tolerance in the sum of covallent radii between two atoms to be considered a bond. Defaults to 1.2 (equivalent to 20% tolerance) max_bond (float): Maximum distance of a bond allowed, ignored if equal to zero. Defaults to 0 Contact Error (float): To ensure atoms arent too close to each other, the fraction of tolerance allowed. Defaults to 0.2 (equivalent to 20% tolerance) com (Optional[bool], optional): If true atoms below the center of mass are ignored Defaults to True. """ super().__init__(max_bond_ratio, max_bond, contact_error) self.max_coord = max_coord self.com = com self.df = None
[docs] def get_sites( self, atoms: Atoms, self_interaction: bool = False, bothways: bool = True ) -> list: """ Args: atoms (ase.Atoms): Atoms object to determine sites. self_interaction (bool): Input of ase.neighborlist. Defaults to True. bothways (bool): Input of ase.neighborlist. Defaults to False. Returns: list: list of atoms index considered for modifications. """ indices = get_surface_sites_by_coordination( atoms, max_coord=self.max_coord, max_bond_ratio=self.max_bond_ratio, max_bond=self.max_bond, self_interaction=self_interaction, bothways=bothways, ) # Apply COM filter if self.com: above_com_indices = set(get_com_sites(atoms, fraction=self.com)) indices = list(set(indices) & above_com_indices) return indices