Commit 8df54762 authored by Lee-Ping Wang's avatar Lee-Ping Wang
Browse files

Merge branch 'master' of github.com:leeping/openmm

parents 3cb25ad8 59854c5e
......@@ -41,9 +41,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
import os
import os.path
import copy
import re
import math
import warnings
try:
import numpy
......@@ -52,6 +52,7 @@ except:
import simtk.unit as units
import simtk.openmm
from simtk.openmm.app import element as elem
import customgbforces as customgb
#=============================================================================================
......@@ -428,15 +429,25 @@ class PrmtopLoader(object):
charges=self.getCharges()
nonbondTerms = self.getNonbondTerms()
for ii in range(0,len(dihedralPointers),5):
if int(dihedralPointers[ii+2])>0 and int(dihedralPointers[ii+3])>0:
iAtom = int(dihedralPointers[ii])//3
lAtom = int(dihedralPointers[ii+3])//3
chargeProd = charges[iAtom]*charges[lAtom]
(rVdwI, epsilonI) = nonbondTerms[iAtom]
(rVdwL, epsilonL) = nonbondTerms[lAtom]
rMin = (rVdwI+rVdwL)
epsilon = math.sqrt(epsilonI*epsilonL)
returnList.append((iAtom, lAtom, chargeProd, rMin, epsilon))
if int(dihedralPointers[ii+2])>0 and int(dihedralPointers[ii+3])>0:
iAtom = int(dihedralPointers[ii])//3
lAtom = int(dihedralPointers[ii+3])//3
iidx = int(dihedralPointers[ii+4]) - 1
chargeProd = charges[iAtom]*charges[lAtom]
(rVdwI, epsilonI) = nonbondTerms[iAtom]
(rVdwL, epsilonL) = nonbondTerms[lAtom]
rMin = (rVdwI+rVdwL)
epsilon = math.sqrt(epsilonI*epsilonL)
try:
iScee = float(self._raw_data["SCEE_SCALE_FACTOR"][iidx])
except KeyError:
iScee = 1.2
try:
iScnb = float(self._raw_data["SCNB_SCALE_FACTOR"][iidx])
except KeyError:
iScnb = 2.0
returnList.append((iAtom, lAtom, chargeProd, rMin, epsilon, iScee, iScnb))
return returnList
def getExcludedAtoms(self):
......@@ -462,34 +473,74 @@ class PrmtopLoader(object):
self._excludedAtoms.append(atomList)
return self._excludedAtoms
def getGBParms(self, symbls=None):
def getGBParms(self, gbmodel, elements):
"""Return list giving GB params, Radius and screening factor"""
try:
return self._gb_List
except AttributeError:
pass
self._gb_List=[]
radii=self._raw_data["RADII"]
screen=self._raw_data["SCREEN"]
gb_List=[]
radii=[float(r) for r in self._raw_data["RADII"]]
screen=[float(s) for s in self._raw_data["SCREEN"]]
if gbmodel == 'GBn2':
alpha = [0 for i in self._raw_data['RADII']]
beta = [0 for i in self._raw_data['RADII']]
gamma = [0 for i in self._raw_data['RADII']]
# Update screening parameters for GBn if specified
if symbls:
for (i, symbl) in enumerate(symbls):
if symbl[0] == ('c' or 'C'):
if gbmodel == 'GBn':
if elements is None:
raise Exception('GBn model requires element information')
for i, element in enumerate(elements):
if element is elem.carbon:
screen[i] = 0.48435382330
elif symbl[0] == ('h' or 'H'):
elif element is elem.hydrogen:
screen[i] = 1.09085413633
elif symbl[0] == ('n' or 'N'):
elif element is elem.nitrogen:
screen[i] = 0.700147318409
elif symbl[0] == ('o' or 'O'):
elif element is elem.oxygen:
screen[i] = 1.06557401132
elif symbl[0] == ('s' or 'S'):
elif element is elem.sulfur:
screen[i] = 0.602256336067
else:
screen[i] = 0.5
if gbmodel == 'GBn2':
if elements is None:
raise Exception('GBn2 model requires element information')
for i, element in enumerate(elements):
if element is elem.carbon:
screen[i] = 1.058554
alpha[i] = 0.733756
beta[i] = 0.506378
gamma[i] = 0.205844
elif element is elem.hydrogen:
screen[i] = 1.425952
alpha[i] = 0.788440
beta[i] = 0.798699
gamma[i] = 0.437334
elif element is elem.nitrogen:
screen[i] = 0.733599
alpha[i] = 0.503364
beta[i] = 0.316828
gamma[i] = 0.192915
elif element is elem.oxygen:
screen[i] = 1.061039
alpha[i] = 0.867814
beta[i] = 0.876635
gamma[i] = 0.387882
elif element is elem.sulfur:
screen[i] = -0.703469
alpha[i] = 0.867814
beta[i] = 0.876635
gamma[i] = 0.387882
else: # not optimized
screen[i] = 0.5
alpha[i] = 1.0
beta[i] = 0.8
gamma[i] = 4.85
lengthConversionFactor = units.angstrom.conversion_factor_to(units.nanometer)
for iAtom in range(len(radii)):
self._gb_List.append((float(radii[iAtom])*lengthConversionFactor, float(screen[iAtom])))
return self._gb_List
if gbmodel == 'GBn2':
for rad, scr, alp, bet, gam in zip(radii, screen, alpha, beta, gamma):
gb_List.append((rad*lengthConversionFactor, scr, alp, bet, gam))
else:
for rad, scr in zip(radii, screen):
gb_List.append((rad*lengthConversionFactor, scr))
return gb_List
def getBoxBetaAndDimensions(self):
"""Return periodic boundary box beta angle and dimensions"""
......@@ -502,11 +553,21 @@ class PrmtopLoader(object):
units.Quantity(y, units.angstrom),
units.Quantity(z, units.angstrom))
@property
def has_scee_scnb(self):
return ("SCEE_SCALE_FACTOR" in self._raw_data and "SCNB_SCALE_FACTOR" in self._raw_data)
@property
def has_atomic_number(self):
return 'ATOMIC_NUMBER' in self._raw_data
#=============================================================================================
# AMBER System builder (based on, but not identical to, systemManager from 'zander')
#=============================================================================================
def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmodel=None, soluteDielectric=1.0, solventDielectric=78.5, nonbondedCutoff=None, nonbondedMethod='NoCutoff', scee=1.2, scnb=2.0, mm=None, verbose=False, EwaldErrorTolerance=None, flexibleConstraints=True, rigidWater=True):
def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmodel=None, soluteDielectric=1.0, solventDielectric=78.5,
nonbondedCutoff=None, nonbondedMethod='NoCutoff', scee=None, scnb=None, mm=None, verbose=False,
EwaldErrorTolerance=None, flexibleConstraints=True, rigidWater=True, elements=None):
"""
Create an OpenMM System from an Amber prmtop file.
......@@ -520,8 +581,8 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
soluteDielectric (float) - The solute dielectric constant to use in the implicit solvent model (default: 1.0)
solventDielectric (float) - The solvent dielectric constant to use in the implicit solvent model (default: 78.5)
nonbondedCutoff (float) - if specified, will set nonbondedCutoff (default: None)
scnb (float) - 1-4 Lennard-Jones scaling factor (default: 1.2)
scee (float) - 1-4 electrostatics scaling factor (default: 2.0)
scnb (float) - 1-4 Lennard-Jones scaling factor (default: taken from prmtop or 1.2 if not present there)
scee (float) - 1-4 electrostatics scaling factor (default: taken from prmtop or 2.0 if not present there)
mm - if specified, this module will be used in place of pyopenmm (default: None)
verbose (boolean) - if True, print out information on progress (default: False)
flexibleConstraints (boolean) - if True, flexible bonds will be added in addition ot constrained bonds
......@@ -571,6 +632,10 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
if prmtop.getIfBox()>1:
raise Exception("only standard periodic boxes are currently supported")
if prmtop.has_scee_scnb and (scee is not None or scnb is not None):
warnings.warn("1-4 scaling parameters in topology file are being ignored. "
"This is not recommended unless you know what you are doing.")
# Use pyopenmm implementation of OpenMM by default.
if mm is None:
mm = simtk.openmm
......@@ -615,7 +680,7 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
if shake == 'h-angles':
numConstrainedBonds = system.getNumConstraints()
atomConstraints = [[]]*system.getNumParticles()
for i in range(system.getNumConstraints()):
for i in range(numConstrainedBonds):
c = system.getConstraintParameters(i)
distance = c[2].value_in_unit(units.nanometer)
atomConstraints[c[0]].append((c[1], distance))
......@@ -712,9 +777,12 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
# Add 1-4 Interactions
excludedAtomPairs = set()
sigmaScale = 2**(-1./6.)
for (iAtom, lAtom, chargeProd, rMin, epsilon) in prmtop.get14Interactions():
chargeProd /= scee
epsilon /= scnb
_scee, _scnb = scee, scnb
for (iAtom, lAtom, chargeProd, rMin, epsilon, iScee, iScnb) in prmtop.get14Interactions():
if scee is None: _scee = iScee
if scnb is None: _scnb = iScnb
chargeProd /= _scee
epsilon /= _scnb
sigma = rMin * sigmaScale
force.addException(iAtom, lAtom, chargeProd, sigma, epsilon)
excludedAtomPairs.add(min((iAtom, lAtom), (lAtom, iAtom)))
......@@ -792,25 +860,32 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
if gbmodel is not None:
if verbose: print "Adding GB parameters..."
charges = prmtop.getCharges()
symbls = None
if gbmodel == 'GBn':
symbls = prmtop.getAtomTypes()
gb_parms = prmtop.getGBParms(symbls)
cutoff = None
if nonbondedMethod != 'NoCutoff':
cutoff = nonbondedCutoff
if units.is_quantity(cutoff):
cutoff = cutoff.value_in_unit(units.nanometers)
gb_parms = prmtop.getGBParms(gbmodel, elements)
if gbmodel == 'HCT':
gb = customgb.GBSAHCTForce(solventDielectric, soluteDielectric, 'ACE')
gb = customgb.GBSAHCTForce(solventDielectric, soluteDielectric, 'ACE', cutoff)
elif gbmodel == 'OBC1':
gb = customgb.GBSAOBC1Force(solventDielectric, soluteDielectric, 'ACE')
gb = customgb.GBSAOBC1Force(solventDielectric, soluteDielectric, 'ACE', cutoff)
elif gbmodel == 'OBC2':
gb = mm.GBSAOBCForce()
gb.setSoluteDielectric(soluteDielectric)
gb.setSolventDielectric(solventDielectric)
elif gbmodel == 'GBn':
gb = customgb.GBSAGBnForce(solventDielectric, soluteDielectric, 'ACE')
gb = customgb.GBSAGBnForce(solventDielectric, soluteDielectric, 'ACE', cutoff)
elif gbmodel == 'GBn2':
gb = customgb.GBSAGBn2Force(solventDielectric, soluteDielectric, 'ACE', cutoff)
else:
raise Exception("Illegal value specified for implicit solvent model")
for iAtom in range(prmtop.getNumAtoms()):
if gbmodel == 'OBC2':
gb.addParticle(charges[iAtom], gb_parms[iAtom][0], gb_parms[iAtom][1])
elif gbmodel == 'GBn2':
gb.addParticle([charges[iAtom], gb_parms[iAtom][0], gb_parms[iAtom][1],
gb_parms[iAtom][2], gb_parms[iAtom][3], gb_parms[iAtom][4]])
else:
gb.addParticle([charges[iAtom], gb_parms[iAtom][0], gb_parms[iAtom][1]])
system.addForce(gb)
......@@ -824,6 +899,8 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
gb.setCutoffDistance(nonbondedCutoff)
else:
raise Exception("Illegal nonbonded method for use with GBSA")
# This applies the reaction field dielectric to the NonbondedForce
# created above. Do not bind force to another name before this!
force.setReactionFieldDielectric(1.0)
# TODO: Add GBVI terms?
......
......@@ -8,7 +8,7 @@ Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2012 University of Virginia and the Authors.
Authors: Christoph Klein, Michael R. Shirts
Contributors:
Contributors: Jason M. Swails
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
......@@ -29,8 +29,9 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
from __future__ import division
from simtk.openmm import CustomGBForce
import sys, pdb, pickle
d0=[2.26685,2.32548,2.38397,2.44235,2.50057,2.55867,2.61663,2.67444,
2.73212,2.78965,2.84705,2.9043,2.96141,3.0184,3.07524,3.13196,
......@@ -188,20 +189,35 @@ for i in range (len(d0)):
m0[i]=m0[i]*10
def _createEnergyTerms(force, SA, cutoff):
# Add the energy terms to the CustomGBForce. These are identical for all the GB models.
force.addEnergyTerm("-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B", CustomGBForce.SingleParticle)
if SA=='ACE':
force.addEnergyTerm("28.3919551*(radius+0.14)^2*(radius/B)^6", CustomGBForce.SingleParticle)
elif SA is not None:
raise ValueError('Unknown surface area method: '+SA)
if cutoff is None:
force.addEnergyTerm("-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))", CustomGBForce.ParticlePairNoExclusions)
else:
force.addEnergyTerm("-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2*(1/f-"+str(1/cutoff)+");"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))", CustomGBForce.ParticlePairNoExclusions)
"""
Amber Equivalent: igb = 1
"""
def GBSAHCTForce(solventDielectric=78.5, soluteDielectric=1, SA=None):
def GBSAHCTForce(solventDielectric=78.5, soluteDielectric=1, SA=None, cutoff=None):
custom = CustomGBForce()
custom.addPerParticleParameter("q");
custom.addPerParticleParameter("radius");
custom.addPerParticleParameter("scale");
custom.addGlobalParameter("solventDielectric", solventDielectric);
custom.addGlobalParameter("soluteDielectric", soluteDielectric);
custom.addPerParticleParameter("q")
custom.addPerParticleParameter("radius")
custom.addPerParticleParameter("scale")
custom.addGlobalParameter("solventDielectric", solventDielectric)
custom.addGlobalParameter("soluteDielectric", soluteDielectric)
custom.addGlobalParameter("offset", 0.009)
custom.addComputedValue("I", "step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(r-sr2^2/r)*(1/(U^2)-1/(L^2))+0.5*log(L/U)/r);"
"U=r+sr2;"
......@@ -212,30 +228,21 @@ def GBSAHCTForce(solventDielectric=78.5, soluteDielectric=1, SA=None):
custom.addComputedValue("B", "1/(1/or-I);"
"or=radius-offset", CustomGBForce.SingleParticle)
custom.addEnergyTerm("-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B", CustomGBForce.SingleParticle)
if SA=='ACE':
custom.addEnergyTerm("28.3919551*(radius+0.14)^2*(radius/B)^6", CustomGBForce.SingleParticle)
elif SA is not None:
raise ValueError('Unknown surface area method: '+SA)
custom.addEnergyTerm("-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))", CustomGBForce.ParticlePairNoExclusions)
_createEnergyTerms(custom, SA, cutoff)
return custom
"""
Amber Equivalents: igb = 2
"""
def GBSAOBC1Force(solventDielectric=78.5, soluteDielectric=1, SA=None):
def GBSAOBC1Force(solventDielectric=78.5, soluteDielectric=1, SA=None, cutoff=None):
custom = CustomGBForce()
custom.addPerParticleParameter("q");
custom.addPerParticleParameter("radius");
custom.addPerParticleParameter("scale");
custom.addGlobalParameter("solventDielectric", solventDielectric);
custom.addGlobalParameter("soluteDielectric", soluteDielectric);
custom.addPerParticleParameter("q")
custom.addPerParticleParameter("radius")
custom.addPerParticleParameter("scale")
custom.addGlobalParameter("solventDielectric", solventDielectric)
custom.addGlobalParameter("soluteDielectric", soluteDielectric)
custom.addGlobalParameter("offset", 0.009)
custom.addComputedValue("I", "step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(r-sr2^2/r)*(1/(U^2)-1/(L^2))+0.5*log(L/U)/r);"
"U=r+sr2;"
......@@ -246,29 +253,21 @@ def GBSAOBC1Force(solventDielectric=78.5, soluteDielectric=1, SA=None):
custom.addComputedValue("B", "1/(1/or-tanh(0.8*psi+2.909125*psi^3)/radius);"
"psi=I*or; or=radius-offset", CustomGBForce.SingleParticle)
custom.addEnergyTerm("-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B", CustomGBForce.SingleParticle)
if SA=='ACE':
custom.addEnergyTerm("28.3919551*(radius+0.14)^2*(radius/B)^6", CustomGBForce.SingleParticle)
elif SA is not None:
raise ValueError('Unknown surface area method: '+SA)
custom.addEnergyTerm("-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))", CustomGBForce.ParticlePairNoExclusions)
_createEnergyTerms(custom, SA, cutoff)
return custom
"""
Amber Equivalents: igb = 5
"""
def GBSAOBC2Force(solventDielectric=78.5, soluteDielectric=1, SA=None):
def GBSAOBC2Force(solventDielectric=78.5, soluteDielectric=1, SA=None, cutoff=None):
custom = CustomGBForce()
custom.addPerParticleParameter("q");
custom.addPerParticleParameter("radius");
custom.addPerParticleParameter("scale");
custom.addGlobalParameter("solventDielectric", solventDielectric);
custom.addGlobalParameter("soluteDielectric", soluteDielectric);
custom.addPerParticleParameter("q")
custom.addPerParticleParameter("radius")
custom.addPerParticleParameter("scale")
custom.addGlobalParameter("solventDielectric", solventDielectric)
custom.addGlobalParameter("soluteDielectric", soluteDielectric)
custom.addGlobalParameter("offset", 0.009)
custom.addComputedValue("I", "step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(r-sr2^2/r)*(1/(U^2)-1/(L^2))+0.5*log(L/U)/r);"
"U=r+sr2;"
......@@ -279,21 +278,13 @@ def GBSAOBC2Force(solventDielectric=78.5, soluteDielectric=1, SA=None):
custom.addComputedValue("B", "1/(1/or-tanh(psi-0.8*psi^2+4.85*psi^3)/radius);"
"psi=I*or; or=radius-offset", CustomGBForce.SingleParticle)
custom.addEnergyTerm("-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B", CustomGBForce.SingleParticle)
if SA=='ACE':
custom.addEnergyTerm("28.3919551*(radius+0.14)^2*(radius/B)^6", CustomGBForce.SingleParticle)
elif SA is not None:
raise ValueError('Unknown surface area method: '+SA)
custom.addEnergyTerm("-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))", CustomGBForce.ParticlePairNoExclusions)
_createEnergyTerms(custom, SA, cutoff)
return custom
"""
Amber Equivalents: igb = 7
"""
def GBSAGBnForce(solventDielectric=78.5, soluteDielectric=1, SA=None):
def GBSAGBnForce(solventDielectric=78.5, soluteDielectric=1, SA=None, cutoff=None):
"""
......@@ -306,12 +297,12 @@ def GBSAGBnForce(solventDielectric=78.5, soluteDielectric=1, SA=None):
custom = CustomGBForce()
custom.addPerParticleParameter("q");
custom.addPerParticleParameter("radius");
custom.addPerParticleParameter("scale");
custom.addPerParticleParameter("q")
custom.addPerParticleParameter("radius")
custom.addPerParticleParameter("scale")
custom.addGlobalParameter("solventDielectric", solventDielectric);
custom.addGlobalParameter("soluteDielectric", soluteDielectric);
custom.addGlobalParameter("solventDielectric", solventDielectric)
custom.addGlobalParameter("soluteDielectric", soluteDielectric)
custom.addGlobalParameter("offset", 0.009)
custom.addGlobalParameter("neckScale", 0.361825)
custom.addGlobalParameter("neckCut", 0.68)
......@@ -331,13 +322,52 @@ def GBSAGBnForce(solventDielectric=78.5, soluteDielectric=1, SA=None):
custom.addComputedValue("B", "1/(1/or-tanh(1.09511284*psi-1.907992938*psi^2+2.50798245*psi^3)/radius);"
"psi=I*or; or=radius-offset", CustomGBForce.SingleParticle)
_createEnergyTerms(custom, SA, cutoff)
return custom
custom.addEnergyTerm("-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B", CustomGBForce.SingleParticle)
if SA=='ACE':
custom.addEnergyTerm("28.3919551*(radius+0.14)^2*(radius/B)^6", CustomGBForce.SingleParticle)
elif SA is not None:
raise ValueError('Unknown surface area method: '+SA)
custom.addEnergyTerm("-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))", CustomGBForce.ParticlePairNoExclusions)
"""
Amber Equivalents: igb = 8
"""
def GBSAGBn2Force(solventDielectric=78.5, soluteDielectric=1, SA=None, cutoff=None):
"""
Indexing for tables:
input: radius1, radius2
index = (radius2*200-20)*21 + (radius1*200-20)
output: index of desired value in row-by-row, 1D version of Tables 3 & 4
"""
custom = CustomGBForce()
custom.addPerParticleParameter("q")
custom.addPerParticleParameter("radius")
custom.addPerParticleParameter("scale")
custom.addPerParticleParameter("alpha")
custom.addPerParticleParameter("beta")
custom.addPerParticleParameter("gamma")
custom.addGlobalParameter("solventDielectric", solventDielectric)
custom.addGlobalParameter("soluteDielectric", soluteDielectric)
custom.addGlobalParameter("offset", 0.0195141)
custom.addGlobalParameter("neckScale", 0.826836)
custom.addGlobalParameter("neckCut", 0.68)
custom.addFunction("getd0", d0, 0, 440)
custom.addFunction("getm0", m0, 0, 440)
custom.addComputedValue("I", "Ivdw+neckScale*Ineck;"
"Ineck=step(radius1+radius2+neckCut-r)*getm0(index)/(1+100*(r-getd0(index))^2+0.3*1000000*(r-getd0(index))^6);"
"index = (radius2*200-20)*21 + (radius1*200-20);"
"Ivdw=step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(r-sr2^2/r)*(1/(U^2)-1/(L^2))+0.5*log(L/U)/r);"
"U=r+sr2;"
"L=max(or1, D);"
"D=abs(r-sr2);"
"sr2 = scale2*or2;"
"or1 = radius1-offset; or2 = radius2-offset", CustomGBForce.ParticlePairNoExclusions)
custom.addComputedValue("B", "1/(1/or-tanh(alpha*psi-beta*psi^2+gamma*psi^3)/radius);"
"psi=I*or; or=radius-offset", CustomGBForce.SingleParticle)
_createEnergyTerms(custom, SA, cutoff)
return custom
......@@ -8,7 +8,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2012 Stanford University and the Authors.
Portions copyright (c) 2012-2013 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
......@@ -138,6 +138,8 @@ class PdbStructure(object):
self.default_model = None
self.models_by_number = {}
self._unit_cell_dimensions = None
self.sequences = []
self.modified_residues = []
# read file
self._load(input_stream)
......@@ -172,6 +174,13 @@ class PdbStructure(object):
except:
pass
self._current_model.connects.append(atoms)
elif (pdb_line.find("SEQRES") == 0):
chain_id = pdb_line[11]
if len(self.sequences) == 0 or chain_id != self.sequences[-1].chain_id:
self.sequences.append(Sequence(chain_id))
self.sequences[-1].residues.extend(pdb_line[19:].split())
elif (pdb_line.find("MODRES") == 0):
self.modified_residues.append(ModifiedResidue(pdb_line[16], int(pdb_line[18:22]), pdb_line[12:15].strip(), pdb_line[24:27].strip()))
self._finalize()
def write(self, output_stream=sys.stdout):
......@@ -266,6 +275,21 @@ class PdbStructure(object):
return self._unit_cell_dimensions
class Sequence(object):
"""Sequence holds the sequence of a chain, as specified by SEQRES records."""
def __init__(self, chain_id):
self.chain_id = chain_id
self.residues = []
class ModifiedResidue(object):
"""ModifiedResidue holds information about a modified residue, as specified by a MODRES record."""
def __init__(self, chain_id, number, residue_name, standard_name):
self.chain_id = chain_id
self.number = number
self.residue_name = residue_name
self.standard_name = standard_name
class Model(object):
"""Model holds one model of a PDB structure.
......@@ -412,7 +436,7 @@ class Chain(object):
self._finalize()
def get_residue(self, residue_number, insertion_code=' '):
return residues_by_num_icode[str(residue_number) + insertion_code]
return self.residues_by_num_icode[str(residue_number) + insertion_code]
def __contains__(self, residue_number):
return self.residues_by_number.__contains__(residue_number)
......@@ -892,7 +916,6 @@ if __name__=='__main__':
import doctest, sys
doctest.testmod(sys.modules[__name__])
import sys
import os
import gzip
import re
......
......@@ -37,7 +37,7 @@ from simtk.openmm.app import Topology, PDBFile, ForceField
from simtk.openmm.app.forcefield import HAngles, _createResidueSignature, _matchResidue, DrudeGenerator
from simtk.openmm.app.topology import Residue
from simtk.openmm.vec3 import Vec3
from simtk.openmm import System, Context, NonbondedForce, VerletIntegrator, LocalEnergyMinimizer
from simtk.openmm import System, Context, NonbondedForce, CustomNonbondedForce, HarmonicBondForce, HarmonicAngleForce, VerletIntegrator, LocalEnergyMinimizer
from simtk.unit import nanometer, molar, elementary_charge, amu, gram, liter, degree, sqrt, acos, is_quantity, dot, norm
import element as elem
import os
......@@ -519,7 +519,7 @@ class Modeller(object):
terminal = hydrogen.attrib['terminal']
data.hydrogens.append(Modeller._Hydrogen(hydrogen.attrib['name'], hydrogen.attrib['parent'], maxph, atomVariants, terminal))
def addHydrogens(self, forcefield, pH=7.0, variants=None, platform=None):
def addHydrogens(self, forcefield=None, pH=7.0, variants=None, platform=None):
"""Add missing hydrogens to the model.
Some residues can exist in multiple forms depending on the pH and properties of the local environment. These
......@@ -561,7 +561,8 @@ class Modeller(object):
additional definitions for other residue types.
Parameters:
- forcefield (ForceField) the ForceField to use for determining the positions of hydrogens
- forcefield (ForceField=None) the ForceField to use for determining the positions of hydrogens. If this is None,
positions will be picked which are generally reasonable but not optimized for any particular ForceField.
- pH (float=7.0) the pH based on which to select variants
- variants (list=None) an optional list of variants to use. If this is specified, its length must equal the number
of residues in the model. variants[i] is the name of the variant to use for residue i (indexed starting at 0).
......@@ -753,14 +754,45 @@ class Modeller(object):
if bond[0] in newAtoms and bond[1] in newAtoms:
newTopology.addBond(newAtoms[bond[0]], newAtoms[bond[1]])
# The hydrogens were added at random positions. Now use the ForceField to fix them up.
system = forcefield.createSystem(newTopology, rigidWater=False)
atoms = list(newTopology.atoms())
for i in range(system.getNumParticles()):
if atoms[i].element != elem.hydrogen:
# This is a heavy atom, so make it immobile.
system.setParticleMass(i, 0)
# The hydrogens were added at random positions. Now perform an energy minimization to fix them up.
if forcefield is not None:
# Use the ForceField the user specified.
system = forcefield.createSystem(newTopology, rigidWater=False)
atoms = list(newTopology.atoms())
for i in range(system.getNumParticles()):
if atoms[i].element != elem.hydrogen:
# This is a heavy atom, so make it immobile.
system.setParticleMass(i, 0)
else:
# Create a System that restrains the distance of each hydrogen from its parent atom
# and causes hydrogens to spread out evenly.
system = System()
nonbonded = CustomNonbondedForce('1/((r/0.1)^4+1)')
bonds = HarmonicBondForce()
angles = HarmonicAngleForce()
system.addForce(nonbonded)
system.addForce(bonds)
system.addForce(angles)
for atom in newTopology.atoms():
nonbonded.addParticle([])
if atom.element != elem.hydrogen:
system.addParticle(0.0)
else:
system.addParticle(1.0)
for atom1, atom2 in newTopology.bonds():
if atom1.element == elem.hydrogen or atom2.element == elem.hydrogen:
bonds.addBond(atom1.index, atom2.index, 0.1, 100000.0)
for residue in newTopology.residues():
if residue.name == 'HOH':
atoms = list(residue.atoms())
oindex = [i for i in range(len(atoms)) if atoms[i].element == elem.oxygen]
if len(atoms) == 3 and len(oindex) == 1:
hindex = list(set([0,1,2])-set(oindex))
angles.addAngle(atoms[hindex[0]].index, atoms[oindex[0]].index, atoms[hindex[1]].index, 1.824, 836.8)
if platform is None:
context = Context(system, VerletIntegrator(0.0))
else:
......
......@@ -36,7 +36,8 @@ import sys
import math
import xml.etree.ElementTree as etree
from copy import copy
from simtk.openmm import Vec3
from datetime import date
from simtk.openmm import Vec3, Platform
from simtk.openmm.app.internal.pdbstructure import PdbStructure
from simtk.openmm.app import Topology
from simtk.unit import nanometers, angstroms, is_quantity, norm, Quantity
......@@ -70,7 +71,13 @@ class PDBFile(object):
# Load the PDB file
pdb = PdbStructure(open(file), load_all_models=True)
if isinstance(file, PdbStructure):
pdb = file
else:
inputfile = file
if isinstance(file, str):
inputfile = open(file)
pdb = PdbStructure(inputfile, load_all_models=True)
PDBFile._loadNameReplacementTables()
# Build the topology
......@@ -140,7 +147,8 @@ class PDBFile(object):
for connect in pdb.models[0].connects:
i = connect[0]
for j in connect[1:]:
connectBonds.append((atomByNumber[i], atomByNumber[j]))
if i in atomByNumber and j in atomByNumber:
connectBonds.append((atomByNumber[i], atomByNumber[j]))
if len(connectBonds) > 0:
# Only add bonds that don't already exist.
existingBonds = set(top.bonds())
......@@ -235,6 +243,7 @@ class PDBFile(object):
- topology (Topology) The Topology defining the molecular system being written
- file (file=stdout) A file to write the file to
"""
print >>file, "REMARK 1 CREATED WITH OPENMM %s, %s" % (Platform.getOpenMMVersion(), str(date.today()))
boxSize = topology.getUnitCellDimensions()
if boxSize is not None:
size = boxSize.value_in_unit(angstroms)
......@@ -278,11 +287,15 @@ class PDBFile(object):
else:
atomName = atom.name
coords = positions[posIndex]
line = "ATOM %5d %-4s %3s %s%4d %s%s%s 1.00 0.00" % (
if atom.element is not None:
symbol = atom.element.symbol
else:
symbol = ' '
line = "ATOM %5d %-4s %3s %s%4d %s%s%s 1.00 0.00 %2s " % (
atomIndex%100000, atomName, resName, chainName,
(resIndex+1)%10000, _format_83(coords[0]),
_format_83(coords[1]), _format_83(coords[2]))
assert len(line) == 66, 'Fixed width overflow detected'
_format_83(coords[1]), _format_83(coords[2]), symbol)
assert len(line) == 80, 'Fixed width overflow detected'
print >>file, line
posIndex += 1
atomIndex += 1
......@@ -300,6 +313,56 @@ class PDBFile(object):
- topology (Topology) The Topology defining the molecular system being written
- file (file=stdout) A file to write the file to
"""
# Identify bonds that should be listed as CONECT records.
standardResidues = ['ALA', 'ASN', 'CYS', 'GLU', 'HIS', 'LEU', 'MET', 'PRO', 'THR', 'TYR',
'ARG', 'ASP', 'GLN', 'GLY', 'ILE', 'LYS', 'PHE', 'SER', 'TRP', 'VAL',
'A', 'G', 'C', 'U', 'I', 'DA', 'DG', 'DC', 'DT', 'DI', 'HOH']
conectBonds = []
for atom1, atom2 in topology.bonds():
if atom1.residue.name not in standardResidues or atom2.residue.name not in standardResidues:
conectBonds.append((atom1, atom2))
elif atom1.name == 'SG' and atom2.name == 'SG' and atom1.residue.name == 'CYS' and atom2.residue.name == 'CYS':
conectBonds.append((atom1, atom2))
if len(conectBonds) > 0:
# Work out the index used in the PDB file for each atom.
atomIndex = {}
nextAtomIndex = 0
prevChain = None
for chain in topology.chains():
for atom in chain.atoms():
if atom.residue.chain != prevChain:
nextAtomIndex += 1
prevChain = atom.residue.chain
atomIndex[atom] = nextAtomIndex
nextAtomIndex += 1
# Record which other atoms each atom is bonded to.
atomBonds = {}
for atom1, atom2 in conectBonds:
index1 = atomIndex[atom1]
index2 = atomIndex[atom2]
if index1 not in atomBonds:
atomBonds[index1] = []
if index2 not in atomBonds:
atomBonds[index2] = []
atomBonds[index1].append(index2)
atomBonds[index2].append(index1)
# Write the CONECT records.
for index1 in sorted(atomBonds):
bonded = atomBonds[index1]
while len(bonded) > 4:
print >>file, "CONECT%5d%5d%5d%5d" % (index1, bonded[0], bonded[1], bonded[2])
del bonded[:4]
line = "CONECT%5d" % index1
for index2 in bonded:
line = "%s%5d" % (line, index2)
print >>file, line
print >>file, "END"
......
......@@ -79,5 +79,6 @@ class PDBReporter(object):
self._nextModel += 1
def __del__(self):
PDBFile.writeFooter(self._topology, self._out)
if self._topology is not None:
PDBFile.writeFooter(self._topology, self._out)
self._out.close()
......@@ -31,9 +31,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
__author__ = "Peter Eastman"
__version__ = "1.0"
import bz2
import gzip
import simtk.openmm as mm
import simtk.unit as unit
from simtk.openmm.app import PDBFile
import math
class StateDataReporter(object):
......@@ -67,7 +68,14 @@ class StateDataReporter(object):
self._reportInterval = reportInterval
self._openedFile = isinstance(file, str)
if self._openedFile:
self._out = open(file, 'w', 0)
# Detect the desired compression scheme from the filename extension
# and open all files unbuffered
if file.endswith('.gz'):
self._out = gzip.GzipFile(fileobj=open(file, 'wb', 0))
elif file.endswith('.bz2'):
self._out = bz2.BZ2File(file, 'w', 0)
else:
self._out = open(file, 'w', 0)
else:
self._out = file
self._step = step
......@@ -109,7 +117,10 @@ class StateDataReporter(object):
self._initializeConstants(simulation)
headers = self._constructHeaders()
print >>self._out, '#"%s"' % ('"'+self._separator+'"').join(headers)
self._out.flush()
try:
self._out.flush()
except AttributeError:
pass
self._hasInitialized = True
# Check for errors.
......@@ -120,7 +131,10 @@ class StateDataReporter(object):
# Write the values.
print >>self._out, self._separator.join(str(v) for v in values)
self._out.flush()
try:
self._out.flush()
except AttributeError:
pass
def _constructReportValues(self, simulation, state):
"""Query the simulation for the current state of our observables of interest.
......
......@@ -616,6 +616,7 @@ EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */tests/* \
*/openmmapi/src/* \
*/internal/* \
*/.svn/* \
*OpenMMFortranModule.f90 \
*OpenMMCWrapper.h
......
#!/bin/env python
#!/usr/bin/env python
#
#
......
......@@ -14,20 +14,7 @@ DOC_STRINGS = {("Context", "setPositions") :
# Do not generate wrappers for the following methods.
# Indexed by (className, [methodName [, numParams]])
SKIP_METHODS = [('State',),
('Stream',),
('Vec3',),
('AmoebaGeneralizedKirkwoodForceImpl',),
('AmoebaAngleForceImpl',),
('AmoebaBondForceImpl',),
('AmoebaInPlaneAngleForceImpl',),
('AmoebaMultipoleForceImpl',),
('AmoebaOutOfPlaneBendForceImpl',),
('AmoebaPiTorsionForceImpl',),
('AmoebaStretchBendForceImpl',),
('AmoebaTorsionTorsionForceImpl',),
('AmoebaVdwForceImpl',),
('AmoebaWcaDispersionForceImpl',),
('AndersenThermostatImpl',),
('AngleInfo',),
('ApplyAndersenThermostatKernel',),
('ApplyConstraintsKernel',),
......@@ -63,30 +50,14 @@ SKIP_METHODS = [('State',),
('CalcNonbondedForceKernel',),
('CalcPeriodicTorsionForceKernel',),
('CalcRBTorsionForceKernel',),
('CMAPTorsionForceImpl',),
('CMMotionRemoverImpl',),
('ComputationInfo',),
('ConstraintInfo',),
('ContextImpl',),
('CudaKernelFactory',),
('CudaStreamFactory',),
('CustomAngleForceImpl',),
('CustomBondForceImpl',),
('CustomCompoundBondForceImpl',),
('CustomExternalForceImpl',),
('CustomGBForceImpl',),
('CustomHbondForceImpl',),
('CustomNonbondedForceImpl',),
('CustomTorsionForceImpl',),
('ExceptionInfo',),
('ExclusionInfo',),
('ForceImpl',),
('FunctionInfo',),
('GBSAOBCForceImpl',),
('GBVIForceImpl',),
('GlobalParameterInfo',),
('HarmonicAngleForceImpl',),
('HarmonicBondForceImpl',),
('InitializeForcesKernel',),
('IntegrateBrownianStepKernel',),
('IntegrateLangevinStepKernel',),
......@@ -97,24 +68,18 @@ SKIP_METHODS = [('State',),
('Kernel',),
('KernelFactory',),
('KernelImpl',),
('MonteCarloBarostatImpl',),
('MonteCarloAnisotropicBarostatImpl',),
('MultipoleInfo',),
('NonbondedForceImpl',),
('OutOfPlaneBendInfo',),
('ParameterInfo',),
('ParticleInfo',),
('PeriodicTorsionForceImpl',),
('PeriodicTorsionInfo',),
('PerParticleParameterInfo',),
('PiTorsionInfo',),
('PlatformData',),
('RBTorsionForceImpl',),
('RBTorsionInfo',),
('RemoveCMMotionKernel',),
('SplineFitter',),
('StreamFactory',),
('StreamImpl',),
('StretchBendInfo',),
('TorsionInfo',),
('TorsionTorsionGridInfo',),
......@@ -139,7 +104,6 @@ SKIP_METHODS = [('State',),
('Platform', 'registerKernelFactory'),
('IntegrateRPMDStepKernel',),
('RPMDIntegrator', 'getState'),
('DrudeForceImpl',),
('CalcDrudeForceKernel',),
('IntegrateDrudeLangevinStepKernel',),
('IntegrateDrudeSCFStepKernel',),
......@@ -159,6 +123,8 @@ NO_OUTPUT_ARGS = [('LocalEnergyMinimizer', 'minimize', 'context'),
('AmoebaMultipoleForce', 'addParticle', 'molecularDipole'),
('AmoebaMultipoleForce', 'addParticle', 'molecularQuadrupole'),
('AmoebaMultipoleForce', 'setCovalentMap', 'covalentAtoms'),
('AmoebaMultipoleForce', 'getElectrostaticPotential', 'context'),
('AmoebaMultipoleForce', 'getInducedDipoles', 'context'),
]
# SWIG assumes the target language shadow class owns the C++ class
......@@ -283,6 +249,7 @@ UNITS = {
#("AmoebaMultipoleForce", "getElectrostaticPotential") : ( None, ('unit.kilojoule_per_mole')),
#("AmoebaMultipoleForce", "getElectrostaticPotential") : ( ('unit.kilojoule_per_mole'), ()),
("AmoebaMultipoleForce", "getElectrostaticPotential") : ( None, ()),
("AmoebaMultipoleForce", "getInducedDipoles") : ( None, ()),
("AmoebaMultipoleForce", "getSystemMultipoleMoments") : ( None, ()),
("AmoebaOutOfPlaneBendForce", "getNumOutOfPlaneBends") : ( None, ()),
......
......@@ -7,15 +7,21 @@
int enforcePeriodic,
int groups) {
State state;
Py_BEGIN_ALLOW_THREADS
PyThreadState* _savePythonThreadState = PyEval_SaveThread();
int types = 0;
if (getPositions) types |= State::Positions;
if (getVelocities) types |= State::Velocities;
if (getForces) types |= State::Forces;
if (getEnergy) types |= State::Energy;
if (getParameters) types |= State::Parameters;
state = self->getState(types, enforcePeriodic, groups);
Py_END_ALLOW_THREADS
try {
state = self->getState(types, enforcePeriodic, groups);
}
catch (...) {
PyEval_RestoreThread(_savePythonThreadState);
throw;
}
PyEval_RestoreThread(_savePythonThreadState);
return _convertStateToLists(state);
}
......@@ -150,15 +156,21 @@ Parameters:
int enforcePeriodic,
int groups) {
State state;
Py_BEGIN_ALLOW_THREADS
PyThreadState* _savePythonThreadState = PyEval_SaveThread();
int types = 0;
if (getPositions) types |= State::Positions;
if (getVelocities) types |= State::Velocities;
if (getForces) types |= State::Forces;
if (getEnergy) types |= State::Energy;
if (getParameters) types |= State::Parameters;
state = self->getState(copy, types, enforcePeriodic, groups);
Py_END_ALLOW_THREADS
try {
state = self->getState(copy, types, enforcePeriodic, groups);
}
catch (...) {
PyEval_RestoreThread(_savePythonThreadState);
throw;
}
PyEval_RestoreThread(_savePythonThreadState);
return _convertStateToLists(state);
}
......
/* Convert python list of tuples to C++ std::vector of Vec3 objects */
%typemap(in) std::vector<Vec3>& (std::vector<OpenMM::Vec3> vVec) {
%typemap(in) const std::vector<Vec3>& (std::vector<OpenMM::Vec3> vVec) {
// typemap -- %typemap(in) std::vector<Vec3>& (std::vector<OpenMM::Vec3> vVec)
int i, pLength, itemLength;
double x, y, z;
......@@ -34,6 +34,32 @@
$1 = &vVec;
}
/* The following two typemaps cause a non-const vector<Vec3>& to become a return value. */
%typemap(in, numinputs=0) std::vector<Vec3>& (std::vector<Vec3> temp) {
$1 = &temp;
}
%typemap(argout) std::vector<Vec3>& {
int i, n;
PyObject *pyList;
n=(*$1).size();
pyList=PyList_New(n);
PyObject* mm = PyImport_AddModule("simtk.openmm");
PyObject* vec3 = PyObject_GetAttrString(mm, "Vec3");
for (i=0; i<n; i++) {
OpenMM::Vec3& v = (*$1).at(i);
PyObject* args = Py_BuildValue("(d,d,d)", v[0], v[1], v[2]);
PyObject* pyVec = PyObject_CallObject(vec3, args);
Py_DECREF(args);
PyList_SET_ITEM(pyList, i, pyVec);
}
$result = pyList;
}
/* const vector<Vec3> should NOT become an output. */
%typemap(argout) const std::vector<Vec3>& {
}
/* Convert python tuple to C++ Vec3 object*/
%typemap(typecheck) Vec3 {
......
......@@ -3,6 +3,7 @@ from validateConstraints import *
from simtk.openmm.app import *
from simtk.openmm import *
from simtk.unit import *
import simtk.openmm.app.element as elem
class TestAmberPrmtopFile(unittest.TestCase):
......@@ -93,42 +94,59 @@ class TestAmberPrmtopFile(unittest.TestCase):
self.assertTrue(any(isinstance(f, force_type) for f in forces))
def test_ImplicitSolventParameters(self):
"""Test that solventDielectric and soluteDielectric are passed correctly
for the different types of implicit solvent.
"""
"""Test that parameters are set correctly for the different types of implicit solvent."""
methodMap = {NoCutoff:NonbondedForce.NoCutoff,
CutoffNonPeriodic:NonbondedForce.CutoffNonPeriodic}
for implicitSolvent_value in [HCT, OBC1, OBC2, GBn]:
system = self.prmtop2.createSystem(implicitSolvent=implicitSolvent_value,
solventDielectric=50.0,
soluteDielectric = 0.9)
found_matching_solvent_dielectric=False
found_matching_solute_dielectric=False
if implicitSolvent_value in set([HCT, OBC1, GBn]):
for force in system.getForces():
if isinstance(force, CustomGBForce):
for j in range(force.getNumGlobalParameters()):
if (force.getGlobalParameterName(j) == 'solventDielectric' and
force.getGlobalParameterDefaultValue(j) == 50.0):
for method in methodMap:
system = self.prmtop2.createSystem(implicitSolvent=implicitSolvent_value,
solventDielectric=50.0, soluteDielectric=0.9, nonbondedMethod=method)
found_matching_solvent_dielectric=False
found_matching_solute_dielectric=False
if implicitSolvent_value in set([HCT, OBC1, GBn]):
for force in system.getForces():
if isinstance(force, CustomGBForce):
self.assertEqual(force.getNonbondedMethod(), methodMap[method])
for j in range(force.getNumGlobalParameters()):
if (force.getGlobalParameterName(j) == 'solventDielectric' and
force.getGlobalParameterDefaultValue(j) == 50.0):
found_matching_solvent_dielectric = True
if (force.getGlobalParameterName(j) == 'soluteDielectric' and
force.getGlobalParameterDefaultValue(j) == 0.9):
found_matching_solute_dielectric = True
if isinstance(force, NonbondedForce):
self.assertEqual(force.getReactionFieldDielectric(), 1.0)
self.assertEqual(force.getNonbondedMethod(), methodMap[method])
self.assertTrue(found_matching_solvent_dielectric and
found_matching_solute_dielectric)
else:
for force in system.getForces():
if isinstance(force, GBSAOBCForce):
self.assertEqual(force.getNonbondedMethod(), methodMap[method])
if force.getSolventDielectric() == 50.0:
found_matching_solvent_dielectric = True
if (force.getGlobalParameterName(j) == 'soluteDielectric' and
force.getGlobalParameterDefaultValue(j) == 0.9):
if force.getSoluteDielectric() == 0.9:
found_matching_solute_dielectric = True
if isinstance(force, NonbondedForce):
self.assertEqual(force.getReactionFieldDielectric(), 1.0)
self.assertTrue(found_matching_solvent_dielectric and
found_matching_solute_dielectric)
else:
for force in system.getForces():
if isinstance(force, GBSAOBCForce):
if force.getSolventDielectric() == 50.0:
found_matching_solvent_dielectric = True
if force.getSoluteDielectric() == 0.9:
found_matching_solute_dielectric = True
if isinstance(force, NonbondedForce):
self.assertEqual(force.getReactionFieldDielectric(), 1.0)
self.assertTrue(found_matching_solvent_dielectric and
found_matching_solute_dielectric)
if isinstance(force, NonbondedForce):
self.assertEqual(force.getReactionFieldDielectric(), 1.0)
self.assertEqual(force.getNonbondedMethod(), methodMap[method])
self.assertTrue(found_matching_solvent_dielectric and
found_matching_solute_dielectric)
def test_HydrogenMass(self):
"""Test that altering the mass of hydrogens works correctly."""
topology = self.prmtop1.topology
hydrogenMass = 4*amu
system1 = self.prmtop1.createSystem()
system2 = self.prmtop1.createSystem(hydrogenMass=hydrogenMass)
for atom in topology.atoms():
if atom.element == elem.hydrogen:
self.assertNotEqual(hydrogenMass, system1.getParticleMass(atom.index))
self.assertEqual(hydrogenMass, system2.getParticleMass(atom.index))
totalMass1 = sum([system1.getParticleMass(i) for i in range(system1.getNumParticles())]).value_in_unit(amu)
totalMass2 = sum([system2.getParticleMass(i) for i in range(system2.getNumParticles())]).value_in_unit(amu)
self.assertAlmostEqual(totalMass1, totalMass2)
if __name__ == '__main__':
unittest.main()
import os
import unittest
from simtk.openmm.app import *
from simtk.openmm import *
from simtk.unit import *
import simtk.openmm.app.element as elem
class TestDesmondDMSFile(unittest.TestCase):
def setUp(self):
"""Set up the tests by loading the input files."""
# alanine dipeptide with explicit water
path = os.path.join(os.path.dirname(__file__), 'systems/alanine-dipeptide-explicit-amber99SBILDN-tip3p.dms')
self.dms = DesmondDMSFile(path)
def test_NonbondedMethod(self):
"""Test all five options for the nonbondedMethod parameter."""
methodMap = {NoCutoff:NonbondedForce.NoCutoff,
CutoffNonPeriodic:NonbondedForce.CutoffNonPeriodic,
CutoffPeriodic:NonbondedForce.CutoffPeriodic,
Ewald:NonbondedForce.Ewald, PME: NonbondedForce.PME}
for method in methodMap:
system = self.dms.createSystem(nonbondedMethod=method)
forces = system.getForces()
self.assertTrue(any(isinstance(f, NonbondedForce) and
f.getNonbondedMethod()==methodMap[method]
for f in forces))
def test_Cutoff(self):
"""Test to make sure the nonbondedCutoff parameter is passed correctly."""
for method in [CutoffNonPeriodic, CutoffPeriodic, Ewald, PME]:
system = self.dms.createSystem(nonbondedMethod=method,
nonbondedCutoff=2*nanometer)
cutoff_distance = 0.0*nanometer
cutoff_check = 2.0*nanometer
for force in system.getForces():
if isinstance(force, NonbondedForce):
cutoff_distance = force.getCutoffDistance()
self.assertEqual(cutoff_distance, cutoff_check)
def test_EwaldErrorTolerance(self):
"""Test to make sure the ewaldErrorTolerance parameter is passed correctly."""
for method in [Ewald, PME]:
system = self.dms.createSystem(nonbondedMethod=method,
ewaldErrorTolerance=1e-6)
tolerance = 0
tolerance_check = 1e-6
for force in system.getForces():
if isinstance(force, NonbondedForce):
tolerance = force.getEwaldErrorTolerance()
self.assertEqual(tolerance, tolerance_check)
def test_RemoveCMMotion(self):
"""Test both options (True and False) for the removeCMMotion parameter."""
for b in [True, False]:
system = self.dms.createSystem(removeCMMotion=b)
self.assertEqual(any(isinstance(f, CMMotionRemover) for f in system.getForces()), b)
def test_HydrogenMass(self):
"""Test that altering the mass of hydrogens works correctly."""
topology = self.dms.topology
hydrogenMass = 4*amu
system1 = self.dms.createSystem()
system2 = self.dms.createSystem(hydrogenMass=hydrogenMass)
for atom in topology.atoms():
if atom.element == elem.hydrogen:
self.assertNotEqual(hydrogenMass, system1.getParticleMass(atom.index))
self.assertEqual(hydrogenMass, system2.getParticleMass(atom.index))
totalMass1 = sum([system1.getParticleMass(i) for i in range(system1.getNumParticles())]).value_in_unit(amu)
totalMass2 = sum([system2.getParticleMass(i) for i in range(system2.getNumParticles())]).value_in_unit(amu)
self.assertAlmostEqual(totalMass1, totalMass2)
......@@ -3,6 +3,7 @@ from validateConstraints import *
from simtk.openmm.app import *
from simtk.openmm import *
from simtk.unit import *
import simtk.openmm.app.element as elem
class TestForceField(unittest.TestCase):
"""Test the ForceField.createSystem() method."""
......@@ -104,6 +105,20 @@ class TestForceField(unittest.TestCase):
self.assertTrue(found_matching_solvent_dielectric and
found_matching_solute_dielectric)
def test_HydrogenMass(self):
"""Test that altering the mass of hydrogens works correctly."""
topology = self.pdb1.topology
hydrogenMass = 4*amu
system1 = self.forcefield1.createSystem(topology)
system2 = self.forcefield1.createSystem(topology, hydrogenMass=hydrogenMass)
for atom in topology.atoms():
if atom.element == elem.hydrogen:
self.assertNotEqual(hydrogenMass, system1.getParticleMass(atom.index))
self.assertEqual(hydrogenMass, system2.getParticleMass(atom.index))
totalMass1 = sum([system1.getParticleMass(i) for i in range(system1.getNumParticles())]).value_in_unit(amu)
totalMass2 = sum([system2.getParticleMass(i) for i in range(system2.getNumParticles())]).value_in_unit(amu)
self.assertAlmostEqual(totalMass1, totalMass2)
if __name__ == '__main__':
......
......@@ -3,6 +3,7 @@ from validateConstraints import *
from simtk.openmm.app import *
from simtk.openmm import *
from simtk.unit import *
import simtk.openmm.app.element as elem
class TestGromacsTopFile(unittest.TestCase):
......@@ -103,6 +104,21 @@ class TestGromacsTopFile(unittest.TestCase):
self.assertTrue(found_matching_solvent_dielectric and
found_matching_solute_dielectric)
def test_HydrogenMass(self):
"""Test that altering the mass of hydrogens works correctly."""
topology = self.top1.topology
hydrogenMass = 4*amu
system1 = self.top1.createSystem()
system2 = self.top1.createSystem(hydrogenMass=hydrogenMass)
for atom in topology.atoms():
if atom.element == elem.hydrogen:
self.assertNotEqual(hydrogenMass, system1.getParticleMass(atom.index))
self.assertEqual(hydrogenMass, system2.getParticleMass(atom.index))
totalMass1 = sum([system1.getParticleMass(i) for i in range(system1.getNumParticles())]).value_in_unit(amu)
totalMass2 = sum([system2.getParticleMass(i) for i in range(system2.getNumParticles())]).value_in_unit(amu)
self.assertAlmostEqual(totalMass1, totalMass2)
if __name__ == '__main__':
unittest.main()
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment