def minkowski_reduce(self): """Minkowski-reduce this cell, returning new cell and mapping. See also :func:`ase.geometry.minkowski_reduction.minkowski_reduce`.""" from ase.geometry.minkowski_reduction import minkowski_reduce rcell, op = minkowski_reduce(self) return Cell(rcell), op
def find_mic(v, cell, pbc=True): """Finds the minimum-image representation of vector(s) v""" pbc = cell.any(1) & pbc2pbc(pbc) v = np.array(v) single = len(v.shape) == 1 v = np.atleast_2d(v) if np.sum(pbc) > 0: cell = complete_cell(cell) rcell, _ = minkowski_reduce(cell, pbc=pbc) # in a Minkowski-reduced cell we only need to test nearest neighbors cs = [np.arange(-1 * p, p + 1) for p in pbc] neighbor_cells = list(itertools.product(*cs)) positions = wrap_positions(v, rcell, pbc=pbc, eps=0) vmin = positions.copy() vlen = np.linalg.norm(positions, axis=1) for nbr in neighbor_cells: trial = positions + np.dot(rcell.T, nbr) trial_len = np.linalg.norm(trial, axis=1) indices = np.where(trial_len < vlen) vmin[indices] = trial[indices] vlen[indices] = trial_len[indices] else: vmin = v.copy() vlen = np.linalg.norm(vmin, axis=1) if single: return vmin[0], vlen[0] else: return vmin, vlen
def general_find_mic(v, cell, pbc=True): """Finds the minimum-image representation of vector(s) v. Using the Minkowski reduction the algorithm is relatively slow but safe for any cell. """ cell = complete_cell(cell) rcell, _ = minkowski_reduce(cell, pbc=pbc) positions = wrap_positions(v, rcell, pbc=pbc, eps=0) # In a Minkowski-reduced cell we only need to test nearest neighbors, # or "Voronoi-relevant" vectors. These are a subset of combinations of # [-1, 0, 1] of the reduced cell vectors. # Define ranges [-1, 0, 1] for periodic directions and [0] for aperiodic # directions. ranges = [np.arange(-1 * p, p + 1) for p in pbc] # Get Voronoi-relevant vectors. # Pre-pend (0, 0, 0) to resolve issue #772 hkls = np.array([(0, 0, 0)] + list(itertools.product(*ranges))) vrvecs = hkls @ rcell # Map positions into neighbouring cells. x = positions + vrvecs[:, None] # Find minimum images lengths = np.linalg.norm(x, axis=2) indices = np.argmin(lengths, axis=0) vmin = x[indices, np.arange(len(positions)), :] vlen = lengths[indices, np.arange(len(positions))] return vmin, vlen
def minkowski_reduce(self): """Minkowski-reduce this cell, returning new cell and mapping. See also :func:`ase.geometry.minkowski_reduction.minkowski_reduce`.""" from ase.geometry.minkowski_reduction import minkowski_reduce cell, op = minkowski_reduce(self, self.any(1)) result = Cell(cell) return result, op