def lindemann_index(trajectory_dir="./"): """ Calculates the Lindemann index \delta = \frac{2}{N(N-1)} \sum_{i<j} \frac{\sqrt{\langle r_{ij}^2\rangle_t - \langle r_{ij} \rangle^2_t }}{ \langle r_{ij} \rangle_t } """ # Import vasprun.xml: traj = read_trajectory(dir=trajectory_dir, unwrap_pbcs=False) pos = traj.get_all_trajectories(coords="direct") nsteps = pos.shape[0] natoms = pos.shape[1] # Get all atom pairs: pairs = get_pairs(natoms) npairs = pairs.shape[0] print "%d steps, %d atoms, %d pairs" % (nsteps, natoms, npairs) stepsize = 50 samplesteps = np.arange(0, nsteps, stepsize) r = np.zeros((samplesteps.size, npairs)) # increase stepsize if we run out of memory r2 = np.zeros((samplesteps.size, npairs)) # increase stepsize if we run out of memory print "Allocated %.3f MB" % ((r.nbytes + r2.nbytes) / (1024.0 ** 2)) pbar = ProgressBar(widgets=["At step...", SimpleProgress()], maxval=samplesteps.size).start() for idx, s in enumerate(samplesteps): pbar.update(idx) x = pos[s, pairs[:, 0]] - pos[s, pairs[:, 1]] x = x - (2 * x).astype("int") # minimum image convention r2[idx] = lensq(x) r[idx] = np.sqrt(r2[idx]) pbar.finish() meanr2 = np.mean(r2, axis=0) meanr = np.mean(r, axis=0) return np.sum(np.sqrt((meanr2 - meanr ** 2)) / meanr) * 2 / (npairs * 2)
def lindemann_index(trajectory_dir='./'): """ Calculates the Lindemann index \delta = \frac{2}{N(N-1)} \sum_{i<j} \frac{\sqrt{\langle r_{ij}^2\rangle_t - \langle r_{ij} \rangle^2_t }}{ \langle r_{ij} \rangle_t } """ # Import vasprun.xml: traj = read_trajectory( dir = trajectory_dir, unwrap_pbcs = False ) pos = traj.get_all_trajectories( coords = 'direct' ) nsteps = pos.shape[0] natoms = pos.shape[1] # Get all atom pairs: pairs = get_pairs(natoms) npairs = pairs.shape[0] print "%d steps, %d atoms, %d pairs" % (nsteps, natoms, npairs) stepsize = 50 samplesteps = np.arange(0,nsteps,stepsize) r = np.zeros((samplesteps.size, npairs)) # increase stepsize if we run out of memory r2 = np.zeros((samplesteps.size, npairs)) # increase stepsize if we run out of memory print "Allocated %.3f MB" % ((r.nbytes+r2.nbytes)/(1024.**2)) pbar = ProgressBar(widgets=['At step...',SimpleProgress()], maxval = samplesteps.size).start() for idx,s in enumerate(samplesteps): pbar.update(idx) x = pos[s,pairs[:,0]] - pos[s,pairs[:,1]] x = x - (2*x).astype('int') # minimum image convention r2[idx] = lensq(x) r[idx] = np.sqrt(r2[idx]) pbar.finish() meanr2 = np.mean(r2,axis=0) meanr = np.mean(r,axis=0) return np.sum(np.sqrt((meanr2 - meanr**2))/meanr)*2/(npairs*2)
parser.add_argument('--abs_diff', '-a', action='store_true', help='Print abs(displacements) for all atoms' ) parser.add_argument('--rad_diff', '-r', action='store_true', help='Print radial displacements (displacement vector norms) for all atoms' ) parser.add_argument('--no_unwrap', '-n', action='store_true', help='Don\'t try to unwrap motion over periodic boundaries.' ) parser.add_argument('infile', nargs='?', default='POSCAR', type=argparse.FileType('r'), help='POSCAR filename') args = parser.parse_args() # Read atoms from POSCAR: poscar1 = PoscarParser(args.infile).get_structure() pos = poscar1.get_positions( coords = 'direct' ) natoms = pos.shape[0] # Build array of pair indices: pairs = get_pairs(natoms) npairs = pairs.shape[0] print "%d atoms, %d pairs" % (natoms, npairs) # Find displacement vectors for all atoms: x = pos[pairs[:,0]] - pos[pairs[:,1]] # Use minimum image convention to threat bonds over PBCs # Note: This will not work with *very* tilted unit cells x = x - (2*x).astype('int') X = direct_to_cartesian(x, poscar1.get_cell()) r2 = (X**2).sum(axis=1) r = np.sqrt(r2)
action='store_true', help='Don\'t try to unwrap motion over periodic boundaries.') parser.add_argument('infile', nargs='?', default='POSCAR', type=argparse.FileType('r'), help='POSCAR filename') args = parser.parse_args() # Read atoms from POSCAR: poscar1 = PoscarParser(args.infile).get_structure() pos = poscar1.get_positions(coords='direct') natoms = pos.shape[0] # Build array of pair indices: pairs = get_pairs(natoms) npairs = pairs.shape[0] print "%d atoms, %d pairs" % (natoms, npairs) # Find displacement vectors for all atoms: x = pos[pairs[:, 0]] - pos[pairs[:, 1]] # Use minimum image convention to threat bonds over PBCs # Note: This will not work with *very* tilted unit cells x = x - (2 * x).astype('int') X = direct_to_cartesian(x, poscar1.get_cell()) r2 = (X**2).sum(axis=1) r = np.sqrt(r2)
def main(): import ase #from connectivities import connectivities, partition, plot atoms = ase.io.read('CONTCAR', format='vasp') #dists, idx, bonds = connectivities(atoms, maxdist=2.5) #groups = partition(atoms, dists, idx, mincount=50, maxwidth=2.0) #cats = categorize(atoms, dists, idx) #cats[0] pos = atoms.positions # Get all atom pairs: n = len(atoms) pairs = get_pairs(n) # Filter pairs based on atom types: bond = (14, 14) pnum = atoms.numbers[pairs] # numbers == (bond[0],bond[1]) or numbers == (bond[1],bond[0]) : mask = np.any(np.column_stack( (np.all(pnum == bond, axis=1), np.all(pnum == reversed(bond), axis=1))), axis=1) del pnum # Calculate distancess: neighbours = [(-1, 2), (-1, 2), (-1, 2)] vectors = atoms.positions[pairs[:, 0]] - atoms.positions[pairs[:, 1]] tmp = np.zeros((len(vectors), 2)) tmp[:, 0] = lensq(vectors) for d0 in range(*neighbours[0]): for d1 in range(*neighbours[1]): for d2 in range(*neighbours[2]): if d0 == d1 == d2 == 0: continue tmp[:, 1] = lensq(vectors + np.dot(np.array([d0, d1, d2]), atoms.cell)) tmp.min(axis=1, out=tmp[:, 0]) # # vectors må korrigeres for PBC. Sjekk om vi kan få pair list rett ut fra ASE # dists = np.sqrt(tmp[:, 0]) del tmp # Filter pairs based on bond lengths: maxdist = 2.8 if maxdist is not None: # add to mask mask = np.all(np.column_stack((mask, dists <= maxdist)), axis=1) dists = dists[mask] pairs = pairs[mask, :] vectors = vectors[mask, :] import matplotlib.pyplot as plt vec2d = np.zeros((vectors.shape[0], 2)) x = np.array([1, 0, 0]) y = np.array([0, 1, 0]) vec2d = vectors[:, ::2] pos2d = pos[pairs[:, 0], ::2] print vec2d.shape print pos2d.shape plt.quiver(pos[:, 0], pos[:, 1], vec2d[:, 0], vec2d[:, 1]) plt.show()
def get_shortest_bond(self, include_self = False, safe_mode = True, rmax = 3.0): """ Returns a tupple containing the shortest bond length in Angstrom, followed by the indices of the two atoms making up the bond Parameters: include_self : bool (default False) Whether to check for bonds between an atom and its _own_ periodic image. This is only needed for very small unit cells, typically with a single atom. safe_mode : bool (default True) Much slower, but safer for non-cubic cells rmax : float (default 3.0) Maximum bond length (in Angstrom) to check for (only used in safe_mode) """ a = self._cell[0] b = self._cell[1] c = self._cell[2] pos = self._positions natoms = pos.shape[0] if natoms == 1: print "Note from get_shortest_bond(): include_self is enabled since only a single atom was found!" include_self = True # Limit to sphere of radius Rc if safe_mode: #if include_self: # print "include_self and safe_mode are not currently compatible. sorry" # return natoms = self.get_num_atoms() a = self._cell[0] b = self._cell[1] c = self._cell[2] # Find distance between opposing faces of the cell: wa = abs(np.dot(a,np.cross(b,c))) / np.linalg.norm(np.cross(b,c)) wb = abs(np.dot(b,np.cross(c,a))) / np.linalg.norm(np.cross(c,a)) wc = abs(np.dot(c,np.cross(a,b))) / np.linalg.norm(np.cross(a,b)) # If half the max radius exceeds one of the face-to-face distances (wa, wb or wc), # we add more atoms in the given direction(s) as necessary. la = 1 + int(2*rmax/wa) lb = 1 + int(2*rmax/wb) lc = 1 + int(2*rmax/wc) print "dim:",la,lb,lc #p2 = self.get_supercell_positions(la,lb,lc, coords='d') pos = np.zeros((natoms*la*lb*lc,3)) #offsets = np.zeros((natoms*la*lb*lc,3), dtype=np.int) #c = np.diag((1,1,1)) # since we use direct coordinates for i in range(la): for j in range(lb): for k in range(lc): m = i*lb*lc + j*lc + k pos[m*natoms:(m+1)*natoms] = self._positions + np.array((i, j, k)) #offsets[m*natoms:(m+1)*natoms] = [i, j, k] indices = np.tile(np.arange(natoms), la*lb*lc) paired = np.zeros(natoms, dtype=np.int) minr = np.zeros(natoms) for j in np.arange(natoms): # Center at atom <index>: pos -= pos[j] # Minimum image convention with coordinates in range lb*[-0.5,0.5> pos[:,0] -= la*(pos[:,0]*2/la).astype('int') pos[:,1] -= lb*(pos[:,1]*2/lb).astype('int') pos[:,2] -= lc*(pos[:,2]*2/lc).astype('int') cart = direct_to_cartesian(pos,self._cell) dr = np.sqrt(np.sum(cart**2,1)) cond = np.logical_and(dr < rmax, dr > 0.0) dr = dr[cond] if dr.shape[0] == 0: print "[Warning]: No neighbours found within %.2f Angstrom of atom %d" % (rmax,j) minr[j] = 1001.0 continue so = np.argsort(dr) #pos = pos[cond] #offsets = (2*pos).astype('int') ##indices = indices[cond] ## sort: #dr = dr[so] #pos = pos[so] #offsets = offsets[so] #indices = indices[so] #indices, dr, offsets, pos = self.get_neighbours(j) paired[j] = indices[cond][so][0] minr[j] = dr[so][0] #pairs[j,nearest] = #minpair = pairs[j,nearest] #minr = dr[0] #print nearest,shortest minidx = np.argmin(minr) minr = minr[minidx] if minr > 1000.0: print "[Error]: No bonds shorter than %.2f Angstrom found. Please increase rmax" % rmax return (minr,minidx,paired[minidx]) else: # Build array of pair indices: pairs = get_pairs(natoms, include_self=include_self) npairs = pairs.shape[0] # Find displacement vectors for all pairs: x = pos[pairs[:,0]] - pos[pairs[:,1]] # Use minimum image convention to threat bonds over PBCs # Note: use safe_mode with tilted unit cells in which the # shortest bond is close to half of one of the cell dimensions x = x - (2*x).astype('int') X = direct_to_cartesian(x, self._cell) r2 = (X**2).sum(axis=1) r = np.sqrt(r2) meanr2 = np.mean(r2,axis=0) meanr = np.mean(r,axis=0) minidx = np.argmin(r) minpair = pairs[minidx] minr = r[minidx] return (minr,minpair[0],minpair[1])
def main(): import ase #from connectivities import connectivities, partition, plot atoms = ase.io.read('CONTCAR', format='vasp') #dists, idx, bonds = connectivities(atoms, maxdist=2.5) #groups = partition(atoms, dists, idx, mincount=50, maxwidth=2.0) #cats = categorize(atoms, dists, idx) #cats[0] pos = atoms.positions # Get all atom pairs: n = len(atoms) pairs = get_pairs(n) # Filter pairs based on atom types: bond = (14,14) pnum = atoms.numbers[pairs] # numbers == (bond[0],bond[1]) or numbers == (bond[1],bond[0]) : mask = np.any(np.column_stack((np.all(pnum == bond, axis=1), np.all(pnum == reversed(bond), axis = 1))),axis=1) del pnum # Calculate distancess: neighbours = [(-1, 2), (-1, 2), (-1, 2)] vectors = atoms.positions[pairs[:,0]] - atoms.positions[pairs[:,1]] tmp = np.zeros((len(vectors), 2)) tmp[:,0] = lensq(vectors) for d0 in range(*neighbours[0]): for d1 in range(*neighbours[1]): for d2 in range(*neighbours[2]): if d0 == d1 == d2 == 0: continue tmp[:,1] = lensq(vectors + np.dot(np.array([d0, d1, d2]), atoms.cell)) tmp.min(axis=1, out=tmp[:,0]) # # vectors må korrigeres for PBC. Sjekk om vi kan få pair list rett ut fra ASE # dists = np.sqrt(tmp[:,0]) del tmp # Filter pairs based on bond lengths: maxdist = 2.8 if maxdist is not None: # add to mask mask = np.all(np.column_stack((mask, dists <= maxdist)), axis = 1) dists = dists[mask] pairs = pairs[mask,:] vectors = vectors[mask,:] import matplotlib.pyplot as plt vec2d = np.zeros((vectors.shape[0],2)) x = np.array([1,0,0]) y = np.array([0,1,0]) vec2d = vectors[:,::2] pos2d = pos[pairs[:,0],::2] print vec2d.shape print pos2d.shape plt.quiver(pos[:,0], pos[:,1], vec2d[:,0], vec2d[:,1]) plt.show()
def get_shortest_bond(self, include_self=False, safe_mode=True, rmax=3.0): """ Returns a tupple containing the shortest bond length in Angstrom, followed by the indices of the two atoms making up the bond Parameters: include_self : bool (default False) Whether to check for bonds between an atom and its _own_ periodic image. This is only needed for very small unit cells, typically with a single atom. safe_mode : bool (default True) Much slower, but safer for non-cubic cells rmax : float (default 3.0) Maximum bond length (in Angstrom) to check for (only used in safe_mode) """ a = self._cell[0] b = self._cell[1] c = self._cell[2] pos = self._positions natoms = pos.shape[0] if natoms == 1: print "Note from get_shortest_bond(): include_self is enabled since only a single atom was found!" include_self = True # Limit to sphere of radius Rc if safe_mode: #if include_self: # print "include_self and safe_mode are not currently compatible. sorry" # return natoms = self.get_num_atoms() a = self._cell[0] b = self._cell[1] c = self._cell[2] # Find distance between opposing faces of the cell: wa = abs(np.dot(a, np.cross(b, c))) / np.linalg.norm(np.cross( b, c)) wb = abs(np.dot(b, np.cross(c, a))) / np.linalg.norm(np.cross( c, a)) wc = abs(np.dot(c, np.cross(a, b))) / np.linalg.norm(np.cross( a, b)) # If half the max radius exceeds one of the face-to-face distances (wa, wb or wc), # we add more atoms in the given direction(s) as necessary. la = 1 + int(2 * rmax / wa) lb = 1 + int(2 * rmax / wb) lc = 1 + int(2 * rmax / wc) print "dim:", la, lb, lc #p2 = self.get_supercell_positions(la,lb,lc, coords='d') pos = np.zeros((natoms * la * lb * lc, 3)) #offsets = np.zeros((natoms*la*lb*lc,3), dtype=np.int) #c = np.diag((1,1,1)) # since we use direct coordinates for i in range(la): for j in range(lb): for k in range(lc): m = i * lb * lc + j * lc + k pos[m * natoms:(m + 1) * natoms] = self._positions + np.array((i, j, k)) #offsets[m*natoms:(m+1)*natoms] = [i, j, k] indices = np.tile(np.arange(natoms), la * lb * lc) paired = np.zeros(natoms, dtype=np.int) minr = np.zeros(natoms) for j in np.arange(natoms): # Center at atom <index>: pos -= pos[j] # Minimum image convention with coordinates in range lb*[-0.5,0.5> pos[:, 0] -= la * (pos[:, 0] * 2 / la).astype('int') pos[:, 1] -= lb * (pos[:, 1] * 2 / lb).astype('int') pos[:, 2] -= lc * (pos[:, 2] * 2 / lc).astype('int') cart = direct_to_cartesian(pos, self._cell) dr = np.sqrt(np.sum(cart**2, 1)) cond = np.logical_and(dr < rmax, dr > 0.0) dr = dr[cond] if dr.shape[0] == 0: print "[Warning]: No neighbours found within %.2f Angstrom of atom %d" % ( rmax, j) minr[j] = 1001.0 continue so = np.argsort(dr) #pos = pos[cond] #offsets = (2*pos).astype('int') ##indices = indices[cond] ## sort: #dr = dr[so] #pos = pos[so] #offsets = offsets[so] #indices = indices[so] #indices, dr, offsets, pos = self.get_neighbours(j) paired[j] = indices[cond][so][0] minr[j] = dr[so][0] #pairs[j,nearest] = #minpair = pairs[j,nearest] #minr = dr[0] #print nearest,shortest minidx = np.argmin(minr) minr = minr[minidx] if minr > 1000.0: print "[Error]: No bonds shorter than %.2f Angstrom found. Please increase rmax" % rmax return (minr, minidx, paired[minidx]) else: # Build array of pair indices: pairs = get_pairs(natoms, include_self=include_self) npairs = pairs.shape[0] # Find displacement vectors for all pairs: x = pos[pairs[:, 0]] - pos[pairs[:, 1]] # Use minimum image convention to threat bonds over PBCs # Note: use safe_mode with tilted unit cells in which the # shortest bond is close to half of one of the cell dimensions x = x - (2 * x).astype('int') X = direct_to_cartesian(x, self._cell) r2 = (X**2).sum(axis=1) r = np.sqrt(r2) meanr2 = np.mean(r2, axis=0) meanr = np.mean(r, axis=0) minidx = np.argmin(r) minpair = pairs[minidx] minr = r[minidx] return (minr, minpair[0], minpair[1])