Coverage for /builds/kinetik161/ase/ase/geometry/dimensionality/bond_generator.py: 96.43%
28 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
1import numpy as np
3from ase.data import covalent_radii
4from ase.neighborlist import NeighborList
7def get_bond_list(atoms, nl, rs):
8 bonds = []
9 for i in range(len(atoms)):
10 p = atoms.positions[i]
11 indices, offsets = nl.get_neighbors(i)
13 for j, offset in zip(indices, offsets):
14 q = atoms.positions[j] + np.dot(offset, atoms.get_cell())
15 d = np.linalg.norm(p - q)
16 k = d / (rs[i] + rs[j])
17 bonds.append((k, i, j, tuple(offset)))
18 return set(bonds)
21def next_bond(atoms):
22 """
23 Generates bonds (lazily) one at a time, sorted by k-value (low to high).
24 Here, k = d_ij / (r_i + r_j), where d_ij is the bond length and r_i and r_j
25 are the covalent radii of atoms i and j.
27 Parameters:
29 atoms: ASE atoms object
31 Returns: iterator of bonds
32 A bond is a tuple with the following elements:
34 k: float k-value
35 i: float index of first atom
36 j: float index of second atom
37 offset: tuple cell offset of second atom
38 """
39 kmax = 0
40 rs = covalent_radii[atoms.get_atomic_numbers()]
41 seen = set()
42 while 1:
43 # Expand the scope of the neighbor list.
44 kmax += 2
45 nl = NeighborList(kmax * rs, skin=0, self_interaction=False)
46 nl.update(atoms)
48 # Get a list of bonds, sorted by k-value.
49 bonds = get_bond_list(atoms, nl, rs)
50 new_bonds = bonds - seen
51 if len(new_bonds) == 0:
52 break
54 # Yield the bonds which we have not previously generated.
55 seen.update(new_bonds)
56 yield from sorted(new_bonds, key=lambda x: x[0])