Source code for ase.constraints.external_force
import numpy as np
from ase.constraints.constraint import FixConstraint, slice2enlist
[docs]
class ExternalForce(FixConstraint):
"""Constraint object for pulling two atoms apart by an external force.
You can combine this constraint for example with FixBondLength but make
sure that *ExternalForce* comes first in the list if there are overlaps
between atom1-2 and atom3-4:
>>> from ase.build import bulk
>>> atoms = bulk('Cu', 'fcc', a=3.6)
>>> atom1, atom2, atom3, atom4 = atoms[:4]
>>> fext = 1.0
>>> con1 = ExternalForce(atom1, atom2, f_ext)
>>> con2 = FixBondLength(atom3, atom4)
>>> atoms.set_constraint([con1, con2])
see ase/test/external_force.py"""
def __init__(self, a1, a2, f_ext):
self.indices = [a1, a2]
self.external_force = f_ext
def get_removed_dof(self, atoms):
return 0
def adjust_positions(self, atoms, new):
pass
def adjust_forces(self, atoms, forces):
dist = np.subtract.reduce(atoms.positions[self.indices])
force = self.external_force * dist / np.linalg.norm(dist)
forces[self.indices] += (force, -force)
def adjust_potential_energy(self, atoms):
dist = np.subtract.reduce(atoms.positions[self.indices])
return -np.linalg.norm(dist) * self.external_force
def index_shuffle(self, atoms, ind):
"""Shuffle the indices of the two atoms in this constraint"""
newa = [-1, -1] # Signal error
for new, old in slice2enlist(ind, len(atoms)):
for i, a in enumerate(self.indices):
if old == a:
newa[i] = new
if newa[0] == -1 or newa[1] == -1:
raise IndexError('Constraint not part of slice')
self.indices = newa
def __repr__(self):
return 'ExternalForce(%d, %d, %f)' % (
self.indices[0],
self.indices[1],
self.external_force,
)
def todict(self):
return {
'name': 'ExternalForce',
'kwargs': {
'a1': self.indices[0],
'a2': self.indices[1],
'f_ext': self.external_force,
},
}