File: connected.py

package info (click to toggle)
python-ase 3.26.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,484 kB
  • sloc: python: 148,112; xml: 2,728; makefile: 110; javascript: 47
file content (91 lines) | stat: -rw-r--r-- 2,600 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
from ase.atoms import Atoms
from ase.data import covalent_radii
from ase.neighborlist import NeighborList


def connected_atoms(atoms, index, dmax=None, scale=1.5):
    """Find all atoms connected to atoms[index] and return them."""
    return atoms[connected_indices(atoms, index, dmax, scale)]


def connected_indices(atoms, index, dmax=None, scale=1.5):
    """Find atoms connected to atoms[index] and return their indices.

    If dmax is not None:
    Atoms are defined to be connected if they are nearer than dmax
    to each other.

    If dmax is None:
    Atoms are defined to be connected if they are nearer than the
    sum of their covalent radii * scale to each other.

    """
    if index < 0:
        index = len(atoms) + index

    # set neighbor lists
    if dmax is None:
        # define neighbors according to covalent radii
        radii = scale * covalent_radii[atoms.get_atomic_numbers()]
    else:
        # define neighbors according to distance
        radii = [0.5 * dmax] * len(atoms)
    nl = NeighborList(radii, skin=0, self_interaction=False, bothways=True)
    nl.update(atoms)

    connected = [index] + list(nl.get_neighbors(index)[0])
    isolated = False
    while not isolated:
        isolated = True
        for i in connected:
            for j in nl.get_neighbors(i)[0]:
                if j not in connected:
                    connected.append(j)
                    isolated = False

    return connected


def separate(atoms, **kwargs):
    """Split atoms into separated entities

    Returns:
      List of Atoms object that connected_indices calls connected.
    """
    indices = list(range(len(atoms)))

    separated = []
    while indices:
        my_indcs = connected_indices(atoms, indices[0], **kwargs)
        separated.append(Atoms(cell=atoms.cell, pbc=atoms.pbc))
        for i in my_indcs:
            separated[-1].append(atoms[i])
            del indices[indices.index(i)]

    return separated


def split_bond(atoms, index1, index2, **kwargs):
    """Split atoms by a bond specified by indices

    index1: index of first atom
    index2: index of second atom
    kwargs: kwargs transferred to connected_atoms

    Returns two Atoms objects
    """
    assert index1 != index2
    if index2 > index1:
        shift = 0, 1
    else:
        shift = 1, 0

    atoms_copy = atoms.copy()
    del atoms_copy[index2]
    atoms1 = connected_atoms(atoms_copy, index1 - shift[0], **kwargs)

    atoms_copy = atoms.copy()
    del atoms_copy[index1]
    atoms2 = connected_atoms(atoms_copy, index2 - shift[1], **kwargs)

    return atoms1, atoms2