wmaee.utils.geometry
1import operator 2import itertools 3import numpy as np 4from ase import Atoms 5from typing import Union, Tuple, Dict, Any 6 7from wmaee.core.requirements import test_pmg 8if test_pmg(): 9 from pymatgen.core import Structure 10 from pymatgen.io.ase import AseAtomsAdaptor 11 12def find_neighbors(atoms: Union[Atoms, Any], 13 rcut: float = 3.0, 14 mindist: float = 0.1, 15 properties: Tuple[str, ...] = ('indices', 'distances', 'images', 'vecs') 16 ) -> Dict[int, Tuple[np.ndarray, ...]]: 17 """ 18 Find neighbors for each atom within a specified cutoff distance and minimum distance. 19 20 This function applies the minimum image convention to consider periodic boundary conditions. 21 22 Parameters 23 ---------- 24 atoms : Union[Atoms, Any] 25 The atoms object to query. It can be an Atoms object or any other compatible type. 26 rcut : float, optional 27 The cutoff distance for neighbor search, by default 3.0. 28 mindist : float, optional 29 The minimum distance for neighbor search, by default 0.1. 30 properties : Tuple[str, ...], optional 31 An iterable of properties to return for each atom. 32 Available options are 'indices', 'distances', 'images', 'vecs', by default ('indices', 'distances', 'images', 'vecs'). 33 34 Returns 35 ------- 36 Dict[int, Tuple[np.ndarray, ...]] 37 A dictionary where the keys represent the atom ids, and the values are tuples containing the desired properties. 38 - 'indices': Indices of neighboring atoms. 39 - 'distances': Distances to neighboring atoms. 40 - 'images': Indices of periodic images of neighboring atoms. 41 - 'vecs': Vectors pointing from the central atom to its neighbors. 42 """ 43 if test_pmg() and isinstance(atoms, Structure): 44 atoms = AseAtomsAdaptor.get_atoms(atoms) 45 46 a, b, c = atoms.cell 47 stride = len(atoms) 48 image_vector = np.zeros((stride * 27, 3), dtype=float) 49 indices = np.hstack([np.arange(len(atoms))] * 27) 50 image_indices = np.zeros_like(image_vector, dtype=int) 51 52 for i, (ta, tb, tc) in enumerate(itertools.product(*[[-1, 0, 1]] * 3)): 53 start, end = (i * stride), ((i + 1) * stride) 54 image_vector[start:end] = a * ta + b * tb + c * tc 55 image_vector[start:end] += atoms.positions 56 image_indices[start:end] = [ta, tb, tc] 57 58 result = dict() 59 position_vector = np.zeros_like(image_vector) 60 61 for i, pos in enumerate(atoms.positions): 62 position_vector[:] = pos 63 distance_vectors = position_vector - image_vector 64 distances = np.linalg.norm(distance_vectors, axis=1) 65 mask = np.logical_and(distances >= mindist, distances < rcut) 66 result[i] = dict(indices=indices[mask], distances=distances[mask], images=image_indices[mask], vecs=distance_vectors[mask, :]) 67 68 mapper = operator.itemgetter(*properties) 69 return {i: mapper(d) for i, d in result.items()}
def
find_neighbors( atoms: Union[ase.atoms.Atoms, Any], rcut: float = 3.0, mindist: float = 0.1, properties: Tuple[str, ...] = ('indices', 'distances', 'images', 'vecs')) -> Dict[int, Tuple[numpy.ndarray, ...]]:
13def find_neighbors(atoms: Union[Atoms, Any], 14 rcut: float = 3.0, 15 mindist: float = 0.1, 16 properties: Tuple[str, ...] = ('indices', 'distances', 'images', 'vecs') 17 ) -> Dict[int, Tuple[np.ndarray, ...]]: 18 """ 19 Find neighbors for each atom within a specified cutoff distance and minimum distance. 20 21 This function applies the minimum image convention to consider periodic boundary conditions. 22 23 Parameters 24 ---------- 25 atoms : Union[Atoms, Any] 26 The atoms object to query. It can be an Atoms object or any other compatible type. 27 rcut : float, optional 28 The cutoff distance for neighbor search, by default 3.0. 29 mindist : float, optional 30 The minimum distance for neighbor search, by default 0.1. 31 properties : Tuple[str, ...], optional 32 An iterable of properties to return for each atom. 33 Available options are 'indices', 'distances', 'images', 'vecs', by default ('indices', 'distances', 'images', 'vecs'). 34 35 Returns 36 ------- 37 Dict[int, Tuple[np.ndarray, ...]] 38 A dictionary where the keys represent the atom ids, and the values are tuples containing the desired properties. 39 - 'indices': Indices of neighboring atoms. 40 - 'distances': Distances to neighboring atoms. 41 - 'images': Indices of periodic images of neighboring atoms. 42 - 'vecs': Vectors pointing from the central atom to its neighbors. 43 """ 44 if test_pmg() and isinstance(atoms, Structure): 45 atoms = AseAtomsAdaptor.get_atoms(atoms) 46 47 a, b, c = atoms.cell 48 stride = len(atoms) 49 image_vector = np.zeros((stride * 27, 3), dtype=float) 50 indices = np.hstack([np.arange(len(atoms))] * 27) 51 image_indices = np.zeros_like(image_vector, dtype=int) 52 53 for i, (ta, tb, tc) in enumerate(itertools.product(*[[-1, 0, 1]] * 3)): 54 start, end = (i * stride), ((i + 1) * stride) 55 image_vector[start:end] = a * ta + b * tb + c * tc 56 image_vector[start:end] += atoms.positions 57 image_indices[start:end] = [ta, tb, tc] 58 59 result = dict() 60 position_vector = np.zeros_like(image_vector) 61 62 for i, pos in enumerate(atoms.positions): 63 position_vector[:] = pos 64 distance_vectors = position_vector - image_vector 65 distances = np.linalg.norm(distance_vectors, axis=1) 66 mask = np.logical_and(distances >= mindist, distances < rcut) 67 result[i] = dict(indices=indices[mask], distances=distances[mask], images=image_indices[mask], vecs=distance_vectors[mask, :]) 68 69 mapper = operator.itemgetter(*properties) 70 return {i: mapper(d) for i, d in result.items()}
Find neighbors for each atom within a specified cutoff distance and minimum distance.
This function applies the minimum image convention to consider periodic boundary conditions.
Parameters
- atoms (Union[Atoms, Any]): The atoms object to query. It can be an Atoms object or any other compatible type.
- rcut (float, optional): The cutoff distance for neighbor search, by default 3.0.
- mindist (float, optional): The minimum distance for neighbor search, by default 0.1.
- properties (Tuple[str, ...], optional): An iterable of properties to return for each atom. Available options are 'indices', 'distances', 'images', 'vecs', by default ('indices', 'distances', 'images', 'vecs').
Returns
- Dict[int, Tuple[np.ndarray, ...]]: A dictionary where the keys represent the atom ids, and the values are tuples containing the desired properties.
- 'indices': Indices of neighboring atoms.
- 'distances': Distances to neighboring atoms.
- 'images': Indices of periodic images of neighboring atoms.
- 'vecs': Vectors pointing from the central atom to its neighbors.