"platforms/vscode:/vscode.git/clone" did not exist on "390e0a6b194ce995599f3e41b1beb1a0d82c6d1c"
Commit 956df416 authored by peastman's avatar peastman Committed by GitHub
Browse files

Merge pull request #1915 from peastman/nbfix

Fixed bug in LennardJonesGenerator
parents 57f3be7e 9f25f4fa
...@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of ...@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org. Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2012-2016 Stanford University and the Authors. Portions copyright (c) 2012-2017 Stanford University and the Authors.
Authors: Peter Eastman, Mark Friedrichs Authors: Peter Eastman, Mark Friedrichs
Contributors: Contributors:
...@@ -2365,35 +2365,41 @@ class LennardJonesGenerator(object): ...@@ -2365,35 +2365,41 @@ class LennardJonesGenerator(object):
generator.registerNBFIX(Nbfix.attrib) generator.registerNBFIX(Nbfix.attrib)
def createForce(self, sys, data, nonbondedMethod, nonbondedCutoff, args): def createForce(self, sys, data, nonbondedMethod, nonbondedCutoff, args):
# First derive the lookup tables # First derive the lookup tables. We need to include entries for every type
# that a) appears in the system and b) has unique parameters.
nbfixTypeSet = set().union(*self.nbfixTypes) nbfixTypeSet = set().union(*self.nbfixTypes)
ljIndexList = [None]*len(data.atoms) allTypes = set(data.atomType[atom] for atom in data.atoms)
numLjTypes = 0 mergedTypes = []
ljTypeList = [] mergedTypeParams = []
typeMap = {} paramsToMergedType = {}
for i, atom in enumerate(data.atoms): typeToMergedType = {}
atype = data.atomType[atom] for t in allTypes:
values = tuple(self.ljTypes.getAtomParameters(atom, data)) typeParams = self.ljTypes.paramsForType[t]
if values in typeMap and atype not in nbfixTypeSet: params = (typeParams['sigma'], typeParams['epsilon'])
# Only non-NBFIX types can be compressed if t in nbfixTypeSet:
ljIndexList[i] = typeMap[values] # NBFIX types cannot be merged.
else: typeToMergedType[t] = len(mergedTypes)
typeMap[values] = numLjTypes mergedTypes.append(t)
ljIndexList[i] = numLjTypes mergedTypeParams.append(params)
numLjTypes += 1 elif params in paramsToMergedType:
ljTypeList.append(atype) # We can merge this with another type.
reverseMap = [0]*len(typeMap) typeToMergedType[t] = paramsToMergedType[params]
for typeValue in typeMap: else:
reverseMap[typeMap[typeValue]] = typeValue # This is a new type.
typeToMergedType[t] = len(mergedTypes)
paramsToMergedType[params] = len(mergedTypes)
mergedTypes.append(t)
mergedTypeParams.append(params)
# Now everything is assigned. Create the A- and B-coefficient arrays # Now everything is assigned. Create the A- and B-coefficient arrays
numLjTypes = len(mergedTypes)
acoef = [0]*(numLjTypes*numLjTypes) acoef = [0]*(numLjTypes*numLjTypes)
bcoef = acoef[:] bcoef = acoef[:]
for m in range(numLjTypes): for m in range(numLjTypes):
for n in range(numLjTypes): for n in range(numLjTypes):
pair = (ljTypeList[m], ljTypeList[n]) pair = (mergedTypes[m], mergedTypes[n])
if pair in self.nbfixTypes: if pair in self.nbfixTypes:
epsilon = self.nbfixTypes[pair][1] epsilon = self.nbfixTypes[pair][1]
sigma = self.nbfixTypes[pair][0] sigma = self.nbfixTypes[pair][0]
...@@ -2402,9 +2408,9 @@ class LennardJonesGenerator(object): ...@@ -2402,9 +2408,9 @@ class LennardJonesGenerator(object):
bcoef[m+numLjTypes*n] = 4*epsilon*sigma6 bcoef[m+numLjTypes*n] = 4*epsilon*sigma6
continue continue
else: else:
sigma = 0.5*(reverseMap[m][0]+reverseMap[n][0]) sigma = 0.5*(mergedTypeParams[m][0]+mergedTypeParams[n][0])
sigma6 = sigma**6 sigma6 = sigma**6
epsilon = math.sqrt(reverseMap[m][-1]*reverseMap[n][-1]) epsilon = math.sqrt(mergedTypeParams[m][1]*mergedTypeParams[n][1])
acoef[m+numLjTypes*n] = 4*epsilon*sigma6*sigma6 acoef[m+numLjTypes*n] = 4*epsilon*sigma6*sigma6
bcoef[m+numLjTypes*n] = 4*epsilon*sigma6 bcoef[m+numLjTypes*n] = 4*epsilon*sigma6
...@@ -2423,8 +2429,8 @@ class LennardJonesGenerator(object): ...@@ -2423,8 +2429,8 @@ class LennardJonesGenerator(object):
# Add the particles # Add the particles
for i in ljIndexList: for atom in data.atoms:
self.force.addParticle((i,)) self.force.addParticle((typeToMergedType[data.atomType[atom]],))
self.force.setUseLongRangeCorrection(True) self.force.setUseLongRangeCorrection(True)
self.force.setCutoffDistance(nonbondedCutoff) self.force.setCutoffDistance(nonbondedCutoff)
sys.addForce(self.force) sys.addForce(self.force)
......
...@@ -762,7 +762,7 @@ class TestForceField(unittest.TestCase): ...@@ -762,7 +762,7 @@ class TestForceField(unittest.TestCase):
<Atom type="B" sigma="2" epsilon="0.2"/> <Atom type="B" sigma="2" epsilon="0.2"/>
<Atom type="C" sigma="3" epsilon="0.3"/> <Atom type="C" sigma="3" epsilon="0.3"/>
<Atom type="D" sigma="4" epsilon="0.4"/> <Atom type="D" sigma="4" epsilon="0.4"/>
<Atom type="E" sigma="5" epsilon="0.5"/> <Atom type="E" sigma="4" epsilon="0.4"/>
<NBFixPair type1="A" type2="D" sigma="2.5" epsilon="1.1"/> <NBFixPair type1="A" type2="D" sigma="2.5" epsilon="1.1"/>
<NBFixPair type1="A" type2="E" sigma="3.5" epsilon="1.5"/> <NBFixPair type1="A" type2="E" sigma="3.5" epsilon="1.5"/>
</LennardJonesForce> </LennardJonesForce>
...@@ -778,7 +778,7 @@ class TestForceField(unittest.TestCase): ...@@ -778,7 +778,7 @@ class TestForceField(unittest.TestCase):
context.setPositions(positions) context.setPositions(positions)
def ljEnergy(sigma, epsilon, r): def ljEnergy(sigma, epsilon, r):
return 4*epsilon*((sigma/r)**12-(sigma/r)**6) return 4*epsilon*((sigma/r)**12-(sigma/r)**6)
expected = 0.3*ljEnergy(2.5, 1.1, 3) + 0.3*ljEnergy(3.5, sqrt(0.1), 3) + ljEnergy(3.5, 1.5, 4) expected = 0.3*ljEnergy(2.5, 1.1, 3) + 0.3*ljEnergy(3.0, sqrt(0.08), 3) + ljEnergy(3.5, 1.5, 4)
self.assertAlmostEqual(expected, context.getState(getEnergy=True).getPotentialEnergy().value_in_unit(kilojoules_per_mole)) self.assertAlmostEqual(expected, context.getState(getEnergy=True).getPotentialEnergy().value_in_unit(kilojoules_per_mole))
def test_IgnoreExternalBonds(self): def test_IgnoreExternalBonds(self):
......
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