def displacement(system_0, system_1, box_reference='final'): """Compute the displacement vectors between all matching atoms for two systems.""" assert system_0.natoms == system_1.natoms, 'systems have different number of atoms' if box_reference == 'final': disp = dvect(system_0.atoms.view['pos'], system_1.atoms.view['pos'], system_1.box, system_1.pbc) elif box_reference == 'initial': disp = dvect(system_0.atoms.view['pos'], system_1.atoms.view['pos'], system_0.box, system_0.pbc) elif box_reference is None: disp = system_1.atoms.view['pos'] - system_0.atoms.view['pos'] else: raise ValueError("box_reference must be 'final', 'initial', or None") return disp
def displacement(system_0, system_1): """Compute the displacement vectors between all matching atoms for two systems.""" assert system_0.natoms == system_1.natoms, 'systems have different number of atoms' disp = dvect(system_0.atoms.view['pos'], system_1.atoms.view['pos'], system_1.box, system_1.pbc) return disp
def nlist(system, cutoff, cmult=1): """ Calculates a neighbor list for all atoms in a System taking periodic boundaries into account. Keyword Arguments: system -- System to calculate the neighbor list for. cutoff -- radial cutoff distance for neighbors. cmult -- parameter associated with the binning routine. Default value is most likely the fastest.""" natoms = system.natoms vects = system.box.vects origin = system.box.origin pos = system.atoms.view['pos'] pbc = system.pbc #Determine orthogonal superbox that fully encompases the system corners = origin + np.array([[0,0,0], vects[0], vects[1], vects[2], vects[0] + vects[1], vects[0] + vects[2], vects[1] + vects[2], vects[0] + vects[1] + vects[2]]) supermin = corners.min(axis=0) - 2*cutoff supermax = corners.max(axis=0) + 2*cutoff #Construct bins binsize = cutoff/cmult xbins = np.arange(supermin[0], supermax[0], binsize) ybins = np.arange(supermin[1], supermax[1], binsize) zbins = np.arange(supermin[2], supermax[2], binsize) #Create index lists for real atoms x_index = np.digitize(pos[:, 0], xbins) - 1 y_index = np.digitize(pos[:, 1], ybins) - 1 z_index = np.digitize(pos[:, 2], zbins) - 1 xyz_index = np.hstack((x_index[:, np.newaxis], y_index[:, np.newaxis], z_index[:, np.newaxis])) atom_index = np.arange(natoms, dtype=int) real_bins = unique_rows(xyz_index) #create iterators based on pbc check = [xrange(1), xrange(1), xrange(1)] for i in xrange(3): if pbc[i]: check[i] = xrange(-1, 2) #construct list of ghost atoms in the superbox ghost_pos = [] for x in check[0]: for y in check[1]: for z in check[2]: if x == 0 and y == 0 and z == 0: pass else: newpos = x*vects[0] + y*vects[1] + z*vects[2] + pos bool_check = np.empty_like(newpos, dtype=bool) for i in xrange(3): bool_check[:, i] = np.all([newpos[:, i] > supermin[i], newpos[:, i] < supermax[i]], axis=0) new_index = np.where(np.all(bool_check, axis=1))[0] try: ghost_pos = np.vstack((ghost_pos, newpos[new_index])) ghost_index = np.hstack((ghost_index, new_index)) except: ghost_pos = newpos[new_index] ghost_index = new_index #append index lists with ghost atoms if len(ghost_pos) > 0: x_index = np.digitize(ghost_pos[:, 0], xbins) - 1 y_index = np.digitize(ghost_pos[:, 1], ybins) - 1 z_index = np.digitize(ghost_pos[:, 2], zbins) - 1 xyz_g_index = np.hstack((x_index[:, np.newaxis], y_index[:, np.newaxis], z_index[:, np.newaxis])) xyz_index = np.vstack((xyz_index, xyz_g_index)) atom_index = np.hstack((atom_index, ghost_index)) neighbors = np.zeros((natoms, 41), dtype=np.int) #assign atoms and ghost atoms to xyz bins xyz_bins = np.zeros((len(xbins), len(ybins), len(zbins), 41), dtype=np.int) for i in xrange(len(atom_index)): x,y,z = xyz_index[i] xyz_bins[x,y,z,0] += 1 try: xyz_bins[x,y,z, xyz_bins[x,y,z,0]] = atom_index[i] except: old_size = len(xyz_bins[0,0,0]) newbins = np.zeros((len(xbins), len(ybins), len(zbins), old_size + 10), dtype=np.int) newbins[:, :, :, :old_size] = xyz_bins[:, :, :, :old_size] xyz_bins = newbins xyz_bins[x,y,z, xyz_bins[x,y,z,0]] = atom_index[i] #iterate over all bins with real atoms for bin in real_bins: x,y,z = bin #short = all atoms in current bin short = xyz_bins[x,y,z, 1:xyz_bins[x,y,z,0]+1] long = deepcopy(short) #add all atoms in half of the nearby bins to long for dx, dy, dz in box_iter(cmult): try: long = np.hstack((long, xyz_bins[x+dx,y+dy,z+dz, 1:xyz_bins[x+dx,y+dy,z+dz,0]+1])) except: long = xyz_bins[x+dx,y+dy,z+dz, 1:xyz_bins[x+dx,y+dy,z+dz,0]+1] #compare all atoms in short to medium (which is long starting with u+1). for u in xrange(len(short)): u_pos = pos[short[u]] u_index = short[u] medium = long[u+1:] v_pos = pos[medium] try: d = np.linalg.norm(dvect(u_pos, v_pos, system.box, system.pbc), axis=1) except: d = np.linalg.norm([dvect(u_pos, v_pos, system.box, system.pbc)], axis=1) vlist = medium[np.where(d < cutoff)] for v_index in vlist: neighbors = __append_neighbor(neighbors, u_index, v_index) #sort each atom's neighbors for i in xrange(len(neighbors)): neighbors[i][1 : neighbors[i][0]+1] = np.sort(neighbors[i][1 : neighbors[i][0]+1]) return neighbors