Source code for MMTK.ForceFields.Restraints

# Harmonic restraint terms that can be added to a force field.
#
# Written by Konrad Hinsen
#

"""
Harmonic restraint terms that can be added to any force field

Example::

 from MMTK import *
 from MMTK.ForceFields import Amber99ForceField
 from MMTK.ForceFields.Restraints import HarmonicDistanceRestraint
 
 universe = InfiniteUniverse()
 universe.protein = Protein('bala1')
 force_field = Amber99ForceField() + \
               HarmonicDistanceRestraint(universe.protein[0][1].peptide.N,
                                         universe.protein[0][1].peptide.O,
                                         0.5, 10.)
 universe.setForceField(force_field)
"""

__docformat__ = 'restructuredtext'

from MMTK.ForceFields.ForceField import ForceField
from MMTK_forcefield import HarmonicDistanceTerm, HarmonicAngleTerm, \
                            CosineDihedralTerm
from Scientific import N

[docs]class HarmonicDistanceRestraint(ForceField): """ Harmonic distance restraint between two atoms """ def __init__(self, atom1, atom2, distance, force_constant): """ :param atom1: first atom :type atom1: :class:`~MMTK.ChemicalObjects.Atom` :param atom2: second atom :type atom2: :class:`~MMTK.ChemicalObjects.Atom` :param distance: the distance at which the restraint is zero :type distance: float :param force_constant: the force constant of the restraint term. The functional form of the restraint is force_constant*((r1-r2).length()-distance)**2, where r1 and r2 are the positions of the two atoms. """ self.index1, self.index2 = self.getAtomParameterIndices((atom1, atom2)) self.arguments = (self.index1, self.index2, distance, force_constant) self.distance = distance self.force_constant = force_constant ForceField.__init__(self, 'harmonic distance restraint') def evaluatorParameters(self, universe, subset1, subset2, global_data): if subset1 is not None: s1 = subset1.atomList() s2 = subset2.atomList() if not ((self.atom1 in s1 and self.atom2 in s2) or \ (self.atom1 in s2 and self.atom2 in s1)): raise ValueError("restraint outside subset") return {'harmonic_distance_term': [(self.index1, self.index2, self.distance, self.force_constant)]} def evaluatorTerms(self, universe, subset1, subset2, global_data): params = self.evaluatorParameters(universe, subset1, subset2, global_data)['harmonic_distance_term'] assert len(params) == 1 indices = N.array([params[0][:2]]) parameters = N.array([params[0][2:]]) return [HarmonicDistanceTerm(universe._spec, indices, parameters, self.name)] def description(self): return 'ForceFields.Restraints.' + self.__class__.__name__ + \ `self.arguments`
[docs]class HarmonicAngleRestraint(ForceField): """ Harmonic angle restraint between three atoms """ def __init__(self, atom1, atom2, atom3, angle, force_constant): """ :param atom1: first atom :type atom1: :class:`~MMTK.ChemicalObjects.Atom` :param atom2: second (central) atom :type atom2: :class:`~MMTK.ChemicalObjects.Atom` :param atom3: third atom :type atom3: :class:`~MMTK.ChemicalObjects.Atom` :param angle: the angle at which the restraint is zero :type angle: float :param force_constant: the force constant of the restraint term. The functional form of the restraint is force_constant*(phi-angle)**2, where phi is the angle atom1-atom2-atom3. """ self.index1, self.index2, self.index3 = \ self.getAtomParameterIndices((atom1, atom2, atom3)) self.arguments = (self.index1, self.index2, self.index3, angle, force_constant) self.angle = angle self.force_constant = force_constant ForceField.__init__(self, 'harmonic angle restraint') def evaluatorParameters(self, universe, subset1, subset2, global_data): return {'harmonic_angle_term': [(self.index1, self.index2, self.index3, self.angle, self.force_constant)]} def evaluatorTerms(self, universe, subset1, subset2, global_data): params = self.evaluatorParameters(universe, subset1, subset2, global_data)['harmonic_angle_term'] assert len(params) == 1 indices = N.array([params[0][:3]]) parameters = N.array([params[0][3:]]) return [HarmonicAngleTerm(universe._spec, indices, parameters, self.name)]
[docs]class HarmonicDihedralRestraint(ForceField): """ Harmonic dihedral angle restraint between four atoms """ def __init__(self, atom1, atom2, atom3, atom4, dihedral, force_constant): """ :param atom1: first atom :type atom1: :class:`~MMTK.ChemicalObjects.Atom` :param atom2: second (axis) atom :type atom2: :class:`~MMTK.ChemicalObjects.Atom` :param atom3: third (axis)atom :type atom3: :class:`~MMTK.ChemicalObjects.Atom` :param atom4: fourth atom :type atom4: :class:`~MMTK.ChemicalObjects.Atom` :param dihedral: the dihedral angle at which the restraint is zero :type dihedral: float :param force_constant: the force constant of the restraint term. The functional form of the restraint is force_constant*(phi-abs(dihedral))**2, where phi is the dihedral angle atom1-atom2-atom3-atom4. """ self.index1, self.index2, self.index3, self.index4 = \ self.getAtomParameterIndices((atom1, atom2, atom3, atom4)) self.dihedral = dihedral self.force_constant = force_constant self.arguments = (self.index1, self.index2, self.index3, self.index4, dihedral, force_constant) ForceField.__init__(self, 'harmonic dihedral restraint') def evaluatorParameters(self, universe, subset1, subset2, global_data): return {'cosine_dihedral_term': [(self.index1, self.index2, self.index3, self.index4, 0., self.dihedral, 0., self.force_constant)]} def evaluatorTerms(self, universe, subset1, subset2, global_data): params = self.evaluatorParameters(universe, subset1, subset2, global_data)['cosine_dihedral_term'] assert len(params) == 1 indices = N.array([params[0][:4]]) parameters = N.array([params[0][4:]]) return [CosineDihedralTerm(universe._spec, indices, parameters, self.name)]