Commit 5270f858 authored by Charlles Abreu's avatar Charlles Abreu
Browse files

resolved PR #2611 merge conflicts

parents 697ab72e eec9cd69
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Portions copyright (c) 2008-2020 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -31,6 +31,7 @@
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
......@@ -254,6 +255,31 @@ void testInitialTemperature() {
ASSERT_USUALLY_EQUAL_TOL(targetTemperature, temperature, 0.01);
}
void testForceGroups() {
System system;
system.addParticle(1.0);
VerletIntegrator integrator(0.01);
integrator.setIntegrationForceGroups(1<<1);
CustomExternalForce* f1 = new CustomExternalForce("x");
f1->addParticle(0);
f1->setForceGroup(1);
CustomExternalForce* f2 = new CustomExternalForce("y");
f2->addParticle(0);
f2->setForceGroup(2);
system.addForce(f1);
system.addForce(f2);
Context context(system, integrator, platform);
context.setPositions(vector<Vec3>(1));
// Take one step and verify that the position was updated based only on f1.
integrator.step(1);
Vec3 pos = context.getState(State::Positions).getPositions()[0];
ASSERT(pos[0] < 0);
ASSERT(pos[1] == 0);
ASSERT(pos[2] == 0);
}
void runPlatformTests();
int main(int argc, char* argv[]) {
......@@ -264,6 +290,7 @@ int main(int argc, char* argv[]) {
testConstrainedClusters();
testConstrainedMasslessParticles();
testInitialTemperature();
testForceGroups();
runPlatformTests();
}
catch(const exception& e) {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -841,6 +841,7 @@ class ForceField(object):
newSite = deepcopy(site)
newSite.index = indexMap[site.index]
newSite.atoms = [indexMap[i] for i in site.atoms]
newSite.excludeWith = indexMap[site.excludeWith]
newTemplate.virtualSites = [site for site in newTemplate.virtualSites if site.index != newSite.index]
newTemplate.virtualSites.append(newSite)
return newTemplates
......
......@@ -6,7 +6,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-2018 Stanford University and the Authors.
Portions copyright (c) 2012-2020 Stanford University and the Authors.
Authors: Peter Eastman
Contributors:
......@@ -139,8 +139,10 @@ class PDBFile(object):
element = elem.potassium
elif upper.startswith('ZN'):
element = elem.zinc
elif( len( residue ) == 1 and upper.startswith('CA') ):
elif len(residue) == 1 and upper.startswith('CA'):
element = elem.calcium
elif upper.startswith('D') and any(a.name == atomName[1:] for a in residue.iter_atoms()):
pass # A Drude particle
else:
try:
element = elem.get_by_symbol(upper[0])
......@@ -258,7 +260,7 @@ class PDBFile(object):
map[atom.attrib[id]] = name
@staticmethod
def writeFile(topology, positions, file=sys.stdout, keepIds=False, extraParticleIdentifier=' '):
def writeFile(topology, positions, file=sys.stdout, keepIds=False, extraParticleIdentifier='EP'):
"""Write a PDB file containing a single model.
Parameters
......@@ -274,7 +276,7 @@ class PDBFile(object):
rather than generating new ones. Warning: It is up to the caller to
make sure these are valid IDs that satisfy the requirements of the
PDB format. Otherwise, the output file will be invalid.
extraParticleIdentifier : string=' '
extraParticleIdentifier : string='EP'
String to write in the element column of the ATOM records for atoms whose element is None (extra particles)
"""
PDBFile.writeHeader(topology, file)
......@@ -301,7 +303,7 @@ class PDBFile(object):
a*10, b*10, c*10, alpha*RAD_TO_DEG, beta*RAD_TO_DEG, gamma*RAD_TO_DEG), file=file)
@staticmethod
def writeModel(topology, positions, file=sys.stdout, modelIndex=None, keepIds=False, extraParticleIdentifier=' '):
def writeModel(topology, positions, file=sys.stdout, modelIndex=None, keepIds=False, extraParticleIdentifier='EP'):
"""Write out a model to a PDB file.
Parameters
......@@ -321,7 +323,7 @@ class PDBFile(object):
make sure these are valid IDs that satisfy the requirements of the
PDB format. No guarantees are made about what will happen if they
are not, and the output file could be invalid.
extraParticleIdentifier : string=' '
extraParticleIdentifier : string='EP'
String to write in the element column of the ATOM records for atoms whose element is None (extra particles)
"""
......
......@@ -6,7 +6,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-2015 Stanford University and the Authors.
Portions copyright (c) 2012-2020 Stanford University and the Authors.
Authors: Peter Eastman
Contributors:
......@@ -250,7 +250,8 @@ class Simulation(object):
if next[4]:
getEnergy = True
state = self.context.getState(getPositions=getPositions, getVelocities=getVelocities, getForces=getForces,
getEnergy=getEnergy, getParameters=True, enforcePeriodicBox=periodic)
getEnergy=getEnergy, getParameters=True, enforcePeriodicBox=periodic,
groups=self.context.getIntegrator().getIntegrationForceGroups())
for reporter, next in reports:
reporter.report(self, state)
......
......@@ -106,6 +106,33 @@ Parameters:
}
}
%extend OpenMM::Integrator {
%pythoncode %{
def setIntegrationForceGroups(self, groups):
"""Set which force groups to use for integration. By default, all force groups are included.
Parameters
----------
groups : set or int
a set of indices for which force groups to include when integrating the equations of motion.
Alternatively, the groups can be passed as a single unsigned integer interpreted as a bitmask,
in which case group i will be included if (groups&(1<<i)) != 0.
"""
try:
# is the input integer-like?
groups_mask = int(groups)
except TypeError:
if isinstance(groups, set):
groups_mask = functools.reduce(operator.or_,
((1<<x) & 0xffffffff for x in groups))
else:
raise TypeError('%s is neither an int nor set' % groups)
if groups_mask >= 0x80000000:
groups_mask -= 0x100000000
_openmm.Integrator_setIntegrationForceGroups(self, groups_mask)
%}
}
%extend OpenMM::RPMDIntegrator {
%pythoncode %{
def getState(self,
......
......@@ -1019,6 +1019,75 @@ END"""))
# If the check is not done correctly, this will throw an exception.
ff.createSystem(pdb.topology)
def test_CharmmPolar(self):
"""Test the CHARMM polarizable force field."""
pdb = PDBFile('systems/ala_ala_ala_drude.pdb')
pdb.topology.setUnitCellDimensions(Vec3(3, 3, 3))
ff = ForceField('charmm_polar_2019.xml')
system = ff.createSystem(pdb.topology, nonbondedMethod=PME, nonbondedCutoff=1.2*nanometers)
for i,f in enumerate(system.getForces()):
f.setForceGroup(i)
if isinstance(f, NonbondedForce):
f.setPMEParameters(3.4, 64, 64, 64)
integrator = DrudeLangevinIntegrator(300, 1.0, 1.0, 10.0, 0.001)
context = Context(system, integrator, Platform.getPlatformByName('Reference'))
context.setPositions(pdb.positions)
# Compare the energy to values computed by CHARMM. Here is what it outputs:
# ENER ENR: Eval# ENERgy Delta-E GRMS
# ENER INTERN: BONDs ANGLes UREY-b DIHEdrals IMPRopers
# ENER CROSS: CMAPs PMF1D PMF2D PRIMO
# ENER EXTERN: VDWaals ELEC HBONds ASP USER
# ENER EWALD: EWKSum EWSElf EWEXcl EWQCor EWUTil
# ---------- --------- --------- --------- --------- ---------
# ENER> 0 102.83992 0.00000 13.06415
# ENER INTERN> 54.72574 40.21459 11.61009 26.10373 0.14113
# ENER CROSS> -3.37113 0.00000 0.00000 0.00000
# ENER EXTERN> 22.74761 -24.21667 0.00000 0.00000 0.00000
# ENER EWALD> 56.14258 -7279.07968 7197.82192 0.00000 0.00000
# ---------- --------- --------- --------- --------- ---------
# First check the total energy.
energy = context.getState(getEnergy=True).getPotentialEnergy().value_in_unit(kilocalories_per_mole)
self.assertAlmostEqual(102.83992, energy, delta=energy*1e-3)
# Now check individual components. CHARMM and OpenMM split them up a little differently. I've tried to
# match things up, but I think there's still some inconsistency in where forces related to Drude particles
# are categorized. That's why the Coulomb and bonds terms match less accurately than the other terms
# (and less accurately than the total energy, which agrees well).
coulomb = 0
vdw = 0
bonds = 0
angles = 0
propers = 0
impropers = 0
cmap = 0
for i,f in enumerate(system.getForces()):
energy = context.getState(getEnergy=True, groups={i}).getPotentialEnergy().value_in_unit(kilocalories_per_mole)
if isinstance(f, NonbondedForce):
coulomb += energy
elif isinstance(f, CustomNonbondedForce) or isinstance(f, CustomBondForce):
vdw += energy
elif isinstance(f, HarmonicBondForce) or isinstance(f, DrudeForce):
bonds += energy
elif isinstance(f, HarmonicAngleForce):
angles += energy
elif isinstance(f, PeriodicTorsionForce):
propers += energy
elif isinstance(f, CustomTorsionForce):
impropers += energy
elif isinstance(f, CMAPTorsionForce):
cmap += energy
self.assertAlmostEqual(-24.21667+56.14258-7279.07968+7197.82192, coulomb, delta=abs(coulomb)*5e-2) # ELEC+EWKSum+EWSElf+EWEXcl
self.assertAlmostEqual(22.74761, vdw, delta=vdw*1e-3) # VDWaals
self.assertAlmostEqual(54.72574+11.61009, bonds, delta=bonds*2e-2) # BONDs+UREY-b
self.assertAlmostEqual(40.21459, angles, delta=angles*1e-3) # ANGLes
self.assertAlmostEqual(26.10373, propers, delta=propers*1e-3) # DIHEdrals
self.assertAlmostEqual(0.14113, impropers, delta=impropers*1e-3) # IMPRopers
class AmoebaTestForceField(unittest.TestCase):
"""Test the ForceField.createSystem() method with the AMOEBA forcefield."""
......
......@@ -17,7 +17,7 @@ class TestMetadynamics(unittest.TestCase):
cv = CustomBondForce('r')
cv.addBond(0, 1)
bias = BiasVariable(cv, 0.94, 1.06, 0.00431, gridWidth=31)
meta = Metadynamics(system, [bias], 300*kelvin, 2.0, 5.0, 10)
meta = Metadynamics(system, [bias], 300*kelvin, 3.0, 5.0, 10)
integrator = LangevinIntegrator(300*kelvin, 10/picosecond, 0.001*picosecond)
integrator.setRandomNumberSeed(4321)
topology = Topology()
......
......@@ -80,7 +80,7 @@ class TestPdbFile(unittest.TestCase):
output = StringIO()
PDBFile.writeFile(pdb.topology, pdb.positions, output)
input = StringIO(output.getvalue())
pdb = PDBFile(input, extraParticleIdentifier = '')
pdb = PDBFile(input)
for atom in pdb.topology.atoms():
if atom.index > 2:
self.assertEqual(None, atom.element)
......
......@@ -35,7 +35,7 @@ class TestSimulatedTempering(unittest.TestCase):
distances = [[] for i in range(10)]
count = 0
for i in range(7000):
for i in range(20000):
st.step(5)
pos = simulation.context.getState(getPositions=True).getPositions().value_in_unit(nanometers)
r = norm(pos[0]-pos[1])
......
REMARK 1 CREATED WITH OPENMM 7.5, 2020-06-04
ATOM 1 N ALA A 1 0.072 -0.034 -0.113 1.00 0.00 N
ATOM 2 DN ALA A 1 0.024 -0.103 -0.101 1.00 0.00 EP
ATOM 3 H ALA A 1 -0.396 0.850 -0.349 1.00 0.00 H
ATOM 4 H2 ALA A 1 -0.547 -0.623 0.444 1.00 0.00 H
ATOM 5 H3 ALA A 1 0.343 -0.509 -0.974 1.00 0.00 H
ATOM 6 CA ALA A 1 1.286 0.359 0.692 1.00 0.00 C
ATOM 7 DCA ALA A 1 1.247 0.375 0.636 1.00 0.00 EP
ATOM 8 HA ALA A 1 0.730 0.825 1.494 1.00 0.00 H
ATOM 9 C ALA A 1 1.986 1.606 0.031 1.00 0.00 C
ATOM 10 DC ALA A 1 1.956 1.579 0.036 1.00 0.00 EP
ATOM 11 O ALA A 1 1.230 2.563 -0.208 1.00 0.00 O
ATOM 12 DO ALA A 1 1.219 2.525 -0.201 1.00 0.00 EP
ATOM 13 LPOA ALA A 1 0.996 2.412 -0.097 1.00 0.00 EP
ATOM 14 LPOB ALA A 1 1.458 2.722 -0.321 1.00 0.00 EP
ATOM 15 CB ALA A 1 2.135 -0.773 1.297 1.00 0.00 C
ATOM 16 DCB ALA A 1 2.057 -0.772 1.289 1.00 0.00 EP
ATOM 17 HB1 ALA A 1 2.779 -1.237 0.521 1.00 0.00 H
ATOM 18 HB2 ALA A 1 1.483 -1.559 1.736 1.00 0.00 H
ATOM 19 HB3 ALA A 1 2.788 -0.373 2.102 1.00 0.00 H
ATOM 20 N ALA A 2 3.340 1.626 -0.172 1.00 0.00 N
ATOM 21 DN ALA A 2 3.289 1.631 -0.202 1.00 0.00 EP
ATOM 22 H ALA A 2 3.913 0.773 -0.267 1.00 0.00 H
ATOM 23 CA ALA A 2 3.977 2.932 -0.230 1.00 0.00 C
ATOM 24 DCA ALA A 2 3.990 2.909 -0.215 1.00 0.00 EP
ATOM 25 HA ALA A 2 3.675 3.404 0.715 1.00 0.00 H
ATOM 26 C ALA A 2 5.518 2.682 -0.121 1.00 0.00 C
ATOM 27 DC ALA A 2 5.487 2.654 -0.128 1.00 0.00 EP
ATOM 28 O ALA A 2 5.947 1.505 -0.133 1.00 0.00 O
ATOM 29 DO ALA A 2 5.889 1.489 -0.137 1.00 0.00 EP
ATOM 30 LPOA ALA A 2 5.668 1.399 -0.158 1.00 0.00 EP
ATOM 31 LPOB ALA A 2 6.229 1.603 -0.108 1.00 0.00 EP
ATOM 32 CB ALA A 2 3.712 3.828 -1.442 1.00 0.00 C
ATOM 33 DCB ALA A 2 3.662 3.802 -1.434 1.00 0.00 EP
ATOM 34 HB1 ALA A 2 2.636 4.055 -1.572 1.00 0.00 H
ATOM 35 HB2 ALA A 2 4.080 3.339 -2.370 1.00 0.00 H
ATOM 36 HB3 ALA A 2 4.238 4.801 -1.334 1.00 0.00 H
ATOM 37 N ALA A 3 6.281 3.795 -0.031 1.00 0.00 N
ATOM 38 DN ALA A 3 6.275 3.733 -0.037 1.00 0.00 EP
ATOM 39 H ALA A 3 5.825 4.723 0.051 1.00 0.00 H
ATOM 40 CA ALA A 3 7.692 3.798 0.060 1.00 0.00 C
ATOM 41 DCA ALA A 3 7.707 3.802 0.068 1.00 0.00 EP
ATOM 42 HA ALA A 3 8.015 3.302 -0.864 1.00 0.00 H
ATOM 43 C ALA A 3 8.044 5.364 0.125 1.00 0.00 C
ATOM 44 DC ALA A 3 8.018 5.323 0.136 1.00 0.00 EP
ATOM 45 CB ALA A 3 8.274 3.163 1.304 1.00 0.00 C
ATOM 46 DCB ALA A 3 8.233 3.093 1.333 1.00 0.00 EP
ATOM 47 HB1 ALA A 3 8.009 2.087 1.363 1.00 0.00 H
ATOM 48 HB2 ALA A 3 7.899 3.666 2.221 1.00 0.00 H
ATOM 49 HB3 ALA A 3 9.384 3.230 1.300 1.00 0.00 H
ATOM 50 O ALA A 3 7.074 6.193 0.135 1.00 0.00 O
ATOM 51 DOT1 ALA A 3 7.032 6.119 0.127 1.00 0.00 EP
ATOM 52 OXT ALA A 3 9.258 5.664 0.187 1.00 0.00 O
ATOM 53 DOT2 ALA A 3 9.219 5.692 0.188 1.00 0.00 EP
ATOM 54 LPT1 ALA A 3 7.196 6.521 0.158 1.00 0.00 EP
ATOM 55 LPT2 ALA A 3 6.769 6.022 0.114 1.00 0.00 EP
ATOM 56 LPT3 ALA A 3 9.295 6.011 0.208 1.00 0.00 EP
ATOM 57 LPT4 ALA A 3 9.454 5.374 0.178 1.00 0.00 EP
TER 58 ALA A 3
END
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