Source code for structuretoolkit.analyse.distance

import numpy as np
from ase.atoms import Atoms


[docs] def get_distances_array( structure: Atoms, p1: np.ndarray | None = None, p2: np.ndarray | None = None, mic: bool = True, vectors: bool = False, ) -> np.ndarray: """ Return distance matrix of every position in p1 with every position in p2. If p2 is not set, it is assumed that distances between all positions in p1 are desired. p2 will be set to p1 in this case. If both p1 and p2 are not set, the distances between all atoms in the box are returned. Args: structure (ase.atoms.Atoms): The structure object p1 (numpy.ndarray/list, optional): Nx3 array of positions. Defaults to None. p2 (numpy.ndarray/list, optional): Nx3 array of positions. Defaults to None. mic (bool, optional): Minimum image convention. Defaults to True. vectors (bool, optional): Return vectors instead of distances. Defaults to False. Returns: numpy.ndarray: NxN if vector=False and NxNx3 if vector=True """ if p1 is None and p2 is not None: p1 = p2 p2 = None if p1 is None: p1 = structure.positions if p2 is None: p2 = structure.positions p1 = np.asarray(p1) p2 = np.asarray(p2) diff_relative = ( p2.reshape(-1, 3)[np.newaxis, :, :] - p1.reshape(-1, 3)[:, np.newaxis, :] ) diff_relative = diff_relative.reshape(p1.shape[:-1] + p2.shape[:-1] + (3,)) if not mic: if vectors: return diff_relative else: return np.linalg.norm(diff_relative, axis=-1) return find_mic(structure=structure, v=diff_relative, vectors=vectors)
[docs] def find_mic(structure: Atoms, v: np.ndarray, vectors: bool = True) -> np.ndarray: """ Find vectors following minimum image convention (mic). In principle this function does the same as ase.geometry.find_mic Args: structure (ase.atoms.Atoms): The structure object v (numpy.ndarray/list): 3d vector or a list/array of 3d vectors vectors (bool): Whether to return vectors (distances are returned if False) Returns: numpy.ndarray: numpy.ndarray of the same shape as input with mic """ if any(structure.pbc): v = np.einsum("ji,...j->...i", np.linalg.inv(structure.cell), v) v[..., structure.pbc] -= np.rint(v)[..., structure.pbc] v = np.einsum("ji,...j->...i", structure.cell, v) if vectors: return np.asarray(v) return np.linalg.norm(v, axis=-1)