Rigid bodies¶
ASE constraint that keeps nodes and linkers rigid during optimisation: cage_isomer_builder.utils.rigid_body.
FixRigidBodies ¶
Bases: FixConstraint
Constrain groups of atoms to move only as rigid bodies.
Each group's reference shape (atom positions relative to its
mass-weighted centroid) never changes; the constrained optimiser may
only translate and rotate each group as a whole. Build one from a
structure with :meth:FixRigidBodies.from_atoms. The constructor takes
the reference data directly (not an Atoms object) so that
todict() and dict2constraint round-trip, as ASE's
Trajectory writer requires.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
groups
|
sequence of sequence of int
|
Atom indices per rigid body. |
required |
group_masses
|
sequence of sequence of float
|
Per-atom mass, aligned with |
required |
group_ref_rel
|
sequence of (N, 3) array-like
|
Reference positions of each group's atoms relative to its
mass-weighted centroid, aligned with |
required |
Examples:
>>> import numpy as np
>>> from ase.build import molecule
>>> from cage_isomer_builder.utils.rigid_body import FixRigidBodies
>>> a, b = molecule("H2O"), molecule("H2O")
>>> b.translate([3.0, 0.0, 0.0])
>>> pair = a + b # two waters, atoms 0-2 and 3-5
>>> constraint = FixRigidBodies.from_atoms(pair, [[0, 1, 2], [3, 4, 5]])
>>> pair.set_constraint(constraint)
>>> new = pair.positions.copy()
>>> new[1] += [0.3, 0.0, 0.0] # try to stretch an O-H bond
>>> pair.set_positions(new) # the constraint keeps each water rigid
>>> round(float(pair.get_distance(0, 1)), 4) == round(float(a.get_distance(0, 1)), 4)
True
Source code in cage_isomer_builder/utils/rigid_body.py
from_atoms
classmethod
¶
Build from a structure, keeping each group's current shape.
Groups with fewer than 2 atoms are dropped: a single atom has no shape to keep.
Examples:
>>> import numpy as np
>>> from ase.build import molecule
>>> from cage_isomer_builder.utils.rigid_body import FixRigidBodies
>>> a, b = molecule("H2O"), molecule("H2O")
>>> b.translate([3.0, 0.0, 0.0])
>>> pair = a + b # two waters, atoms 0-2 and 3-5
>>> constraint = FixRigidBodies.from_atoms(pair, [[0, 1, 2], [3, 4, 5]])
>>> [g.tolist() for g in constraint.group_indices]
[[0, 1, 2], [3, 4, 5]]
Source code in cage_isomer_builder/utils/rigid_body.py
get_removed_dof ¶
Degrees of freedom removed: 3N - 6 per rigid group of N atoms (ASE constraint interface).
Examples:
>>> import numpy as np
>>> from ase.build import molecule
>>> from cage_isomer_builder.utils.rigid_body import FixRigidBodies
>>> a, b = molecule("H2O"), molecule("H2O")
>>> b.translate([3.0, 0.0, 0.0])
>>> pair = a + b # two waters, atoms 0-2 and 3-5
>>> constraint = FixRigidBodies.from_atoms(pair, [[0, 1, 2], [3, 4, 5]])
>>> constraint.get_removed_dof(pair) # 2 waters x (9 - 6)
6
Source code in cage_isomer_builder/utils/rigid_body.py
adjust_positions ¶
Replace new positions in place by the closest rigid-body move of
each group (ASE constraint interface).
Examples:
>>> import numpy as np
>>> from ase.build import molecule
>>> from cage_isomer_builder.utils.rigid_body import FixRigidBodies
>>> a, b = molecule("H2O"), molecule("H2O")
>>> b.translate([3.0, 0.0, 0.0])
>>> pair = a + b # two waters, atoms 0-2 and 3-5
>>> constraint = FixRigidBodies.from_atoms(pair, [[0, 1, 2], [3, 4, 5]])
>>> new = pair.positions.copy()
>>> new[0] += [0.0, 0.0, 0.5] # move one atom only
>>> constraint.adjust_positions(pair, new)
>>> bool(np.isclose(np.linalg.norm(new[0] - new[1]), a.get_distance(0, 1)))
True
Source code in cage_isomer_builder/utils/rigid_body.py
adjust_forces ¶
Replace forces in place by each group's net force and torque, spread back over its atoms as a rigid-body motion (ASE constraint interface).
Examples:
>>> import numpy as np
>>> from ase.build import molecule
>>> from cage_isomer_builder.utils.rigid_body import FixRigidBodies
>>> a, b = molecule("H2O"), molecule("H2O")
>>> b.translate([3.0, 0.0, 0.0])
>>> pair = a + b # two waters, atoms 0-2 and 3-5
>>> constraint = FixRigidBodies.from_atoms(pair, [[0, 1, 2], [3, 4, 5]])
>>> forces = np.zeros((6, 3))
>>> forces[1] = [1.0, 0.0, 0.0] # push one H only
>>> constraint.adjust_forces(pair, forces)
>>> round(float(forces[:3].sum(axis=0)[0]), 6) # the whole water feels the net force
1.0
Source code in cage_isomer_builder/utils/rigid_body.py
todict ¶
Dictionary form, as used by ASE to store the constraint in a trajectory.
Examples:
>>> import numpy as np
>>> from ase.build import molecule
>>> from cage_isomer_builder.utils.rigid_body import FixRigidBodies
>>> a, b = molecule("H2O"), molecule("H2O")
>>> b.translate([3.0, 0.0, 0.0])
>>> pair = a + b # two waters, atoms 0-2 and 3-5
>>> constraint = FixRigidBodies.from_atoms(pair, [[0, 1, 2], [3, 4, 5]])
>>> constraint.todict()["name"]
'FixRigidBodies'