def atoms_moved(cell1, cell2, tol=0.1): """Return a list of atoms that have moved between the two cells. If lattices are compatible, take periodic boundary conditions into account. Arguments: cell1,2 -- The supercells to compare tol -- The tolerance in Å Return value -- A list of (atom index, distance moved) tuples. """ (latt, nat) = check_cells(cell1, cell2) if latt: at1 = cell1.get_scaled_positions() at2 = cell2.get_scaled_positions() else: at1 = cell1.positions at2 = cell2.positions nmax = min(natoms(cell1), natoms(cell2)) am = [] for nn in range(nmax): dvec = at1[nn, :] - at2[nn, :] if latt: dvec = np.dot(vg.vec_pbc(dvec), cell1.get_cell()) dist = np.linalg.norm(dvec) if dist > tol: am.append((nn, dist, dvec)) return am
def nearest_neighbors(atoms, tol=1.0, num_neigh=None): """Nearest neighbors and distances. Arguments: atoms -- The ASE Atoms object with all the atoms. tol -- Return only distances smaller than this. Default 1.0 Å. num_neigh -- Number of nearest neighbors per atom returned. Returns -- List containing (source_atom, target_atom, dist) tuples. """ at = atoms.get_scaled_positions() nn = [] for anum in range(len(at)): dvec = at - at[anum] dvec = np.dot(vg.vec_pbc(dvec), \ atoms.get_cell()) dist = np.empty(dvec.shape[0]) for ii in range(len(dvec)): dist[ii] = np.linalg.norm(dvec[ii]) if num_neigh == None: mask = dist < tol for ii in range(len(mask)): if mask[ii] and ii != anum: nn.append((anum, ii, dist[ii])) else: sind = dist.argsort() for ii in range(min(num_neigh + 1, len(dist))): if anum != sind[ii]: nn.append((anum, sind[ii], dist[sind[ii]])) return nn
def atoms_distance(atoms, atom1, atom2, proj=None): """Measure the distance between two atoms. Atoms are indexed starting from 0, following the usual Python convention. Note that this is different from VASP itself, which starts indexing from 1. This method takes into account periodic boundary conditions. Arguments: atoms -- ASE Atoms object containing the atoms. atom1 -- The index of one of the atoms, starting from 0. atom2 -- The index of the other atom, starting from 0. proj -- Projection along a vector or plane. If a string, it can contain x, y, z and the method then measures the distance in the plane defined by the string. If it's a sequence of three numbers, the method measures the distance projected along the vector. """ at = atoms.get_scaled_positions() dvec = at[atom1, :] - at[atom2, :] dvec = np.dot(vg.vec_pbc(dvec), \ atoms.get_cell()) if proj == None: return np.linalg.norm(dvec) elif type(proj) == str: if len(proj) != 2: raise TypeError("Length of string specifying plane must be 2.") pvec = dvec.copy() if proj.find("x") == -1: pvec[0] = 0. if proj.find("y") == -1: pvec[1] = 0. if proj.find("z") == -1: pvec[2] = 0. return abs(np.dot(dvec, pvec) / np.linalg.norm(pvec)) else: return abs(np.dot(dvec, proj) / np.linalg.norm(proj))