"platforms/cpu/tests/TestCpuSettle.cpp" did not exist on "bb8c2c6f4934bf21e13a69d3ec1f4fd0b31b00bd"
Commit 51e51c3b authored by John Chodera (MSKCC)'s avatar John Chodera (MSKCC)
Browse files

Merge remote-tracking branch 'upstream/master'

parents bc240d4a 373c3878
......@@ -13,7 +13,7 @@ Copyright (c) 2014 the Authors
Author: Jason Deckman
Contributors: Jason M. Swails
Date: April 19, 2014
Date: June 6, 2014
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
......@@ -105,7 +105,7 @@ class CharmmCrdFile(object):
self.resname.append(line[2])
self.attype.append(line[3])
pos = Vec3(float(line[4]), float(line[5]), float(line[6]))
self.positions.append(pos * u.angstroms)
self.positions.append(pos)
self.segid.append(line[7])
self.resid.append(int(line[8]))
self.weighting.append(float(line[9]))
......@@ -120,6 +120,10 @@ class CharmmCrdFile(object):
except (ValueError, IndexError), e:
raise CharmmFileError('Error parsing CHARMM coordinate file')
# Apply units to the positions now. Do it this way to allow for
# (possible) numpy functionality in the future.
self.positions = u.Quantity(self.positions, u.angstroms)
class CharmmRstFile(object):
"""
Reads and parses data, velocities and coordinates from a CHARMM restart
......@@ -209,8 +213,9 @@ class CharmmRstFile(object):
self.velocities = [v * ONE_TIMESCALE for v in self.velocities]
# Add units to positions and velocities
self.positions *= u.angstroms
self.velocities *= u.angstroms / u.picoseconds
self.positions = u.Quantity(self.positions, u.angstroms)
self.positionsold = u.Quantity(self.positionsold, u.angstroms)
self.velocities = u.Quantity(self.velocities, u.angstroms/u.picoseconds)
def _scan(self, handle, str, r=0): # read lines in file until str is found
scanning = True
......
......@@ -241,6 +241,10 @@ class CharmmParameterSet(object):
if line.startswith('HBOND'):
section = None
continue
# It seems like files? sections? can be terminated with 'END'
if line.startswith('END'): # should this be case-insensitive?
section = None
continue
# If we have no section, skip
if section is None: continue
# Now handle each section specifically
......
......@@ -90,6 +90,7 @@ class CharmmPsfFile(object):
- bond_list
- angle_list
- dihedral_list
- dihedral_parameter_list
- improper_list
- cmap_list
- donor_list # hbonds donors?
......@@ -349,6 +350,7 @@ class CharmmPsfFile(object):
self.bond_list = bond_list
self.angle_list = angle_list
self.dihedral_list = dihedral_list
self.dihedral_parameter_list = TrackedList()
self.improper_list = improper_list
self.cmap_list = cmap_list
self.donor_list = donor_list
......@@ -599,9 +601,9 @@ class CharmmPsfFile(object):
central atoms in impropers) and see if that matches. Wild-cards
will apply ONLY if specific parameters cannot be found.
- This method will expand the dihedral_list attribute by adding a
separate Dihedral object for each term for types that have a
multi-term expansion
- This method will expand the dihedral_parameter_list attribute by
adding a separate Dihedral object for each term for types that
have a multi-term expansion
"""
# First load the atom types
types_are_int = False
......@@ -643,12 +645,9 @@ class CharmmPsfFile(object):
self.urey_bradley_list.append(ub)
except KeyError:
raise MissingParameter('Missing angle type for %r' % ang)
# Next load all of the dihedrals. This is a little trickier since we
# need to back up the existing dihedral list and replace it with a
# longer one that has only one Fourier term per Dihedral instance.
dihedral_list = self.dihedral_list
self.dihedral_list = TrackedList()
for dih in dihedral_list:
# Next load all of the dihedrals.
self.dihedral_parameter_list = TrackedList()
for dih in self.dihedral_list:
# Store the atoms
a1, a2, a3, a4 = dih.atom1, dih.atom2, dih.atom3, dih.atom4
at1, at2, at3, at4 = a1.attype, a2.attype, a3.attype, a4.attype
......@@ -662,14 +661,14 @@ class CharmmPsfFile(object):
'%r' % dih)
dtlist = parmset.dihedral_types[key]
for i, dt in enumerate(dtlist):
self.dihedral_list.append(Dihedral(a1, a2, a3, a4, dt))
self.dihedral_parameter_list.append(Dihedral(a1,a2,a3,a4,dt))
# See if we include the end-group interactions for this
# dihedral. We do IFF it is the last or only dihedral term and
# it is NOT in the angle/bond partners
if i != len(dtlist) - 1:
self.dihedral_list[-1].end_groups_active = False
self.dihedral_parameter_list[-1].end_groups_active = False
elif a1 in a4.bond_partners or a1 in a4.angle_partners:
self.dihedral_list[-1].end_groups_active = False
self.dihedral_parameter_list[-1].end_groups_active = False
# Now do the impropers
for imp in self.improper_list:
# Store the atoms
......@@ -755,6 +754,12 @@ class CharmmPsfFile(object):
- alpha, beta, gamma (floats, optional) : Angles between the
periodic cells.
"""
try:
# Since we are setting the box, delete the cached box lengths if we
# have them to make sure they are recomputed if desired.
del self._boxLengths
except AttributeError:
pass
self.box_vectors = _box_vectors_from_lengths_angles(a, b, c,
alpha, beta, gamma)
# If we already have a _topology instance, then we have possibly changed
......@@ -952,8 +957,6 @@ class CharmmPsfFile(object):
- flexibleConstraints (bool=True) Are our constraints flexible or not?
- verbose (bool=False) Optionally prints out a running progress report
"""
# back up the dihedral list
dihedral_list = self.dihedral_list
# Load the parameter set
self.loadParameters(params.condense())
hasbox = self.topology.getUnitCellDimensions() is not None
......@@ -1103,7 +1106,7 @@ class CharmmPsfFile(object):
if verbose: print('Adding torsions...')
force = mm.PeriodicTorsionForce()
force.setForceGroup(self.DIHEDRAL_FORCE_GROUP)
for tor in self.dihedral_list:
for tor in self.dihedral_parameter_list:
force.addTorsion(tor.atom1.idx, tor.atom2.idx, tor.atom3.idx,
tor.atom4.idx, tor.dihedral_type.per,
tor.dihedral_type.phase*pi/180,
......@@ -1235,7 +1238,7 @@ class CharmmPsfFile(object):
# Add 1-4 interactions
excluded_atom_pairs = set() # save these pairs so we don't zero them out
sigma_scale = 2**(-1/6)
for tor in self.dihedral_list:
for tor in self.dihedral_parameter_list:
# First check to see if atoms 1 and 4 are already excluded because
# they are 1-2 or 1-3 pairs (would happen in 6-member rings or
# fewer). Then check that they're not already added as exclusions
......@@ -1355,9 +1358,6 @@ class CharmmPsfFile(object):
# Cache our system for easy access
self._system = system
# Restore the dihedral list to allow reparametrization later
self.dihedral_list = dihedral_list
return system
@property
......@@ -1422,9 +1422,30 @@ class CharmmPsfFile(object):
@property
def boxLengths(self):
""" Return tuple of 3 units """
try:
# See if we have a cached version
return self._boxLengths
except AttributeError:
pass
if self.box_vectors is not None:
return (self.box_vectors[0][0], self.box_vectors[0][1],
self.box_vectors[0][2])
# Get the lengths of each vector
if u.is_quantity(self.box_vectors):
# Unlikely -- each vector is like a quantity
vecs = self.box_vectors.value_in_unit(u.nanometers)
elif u.is_quantity(self.box_vectors[0]):
# Assume all box vectors are quantities
vecs = [x.value_in_unit(u.nanometers) for x in self.box_vectors]
else:
# Assume nanometers
vecs = self.box_vectors
a = sqrt(vecs[0][0]*vecs[0][0] + vecs[0][1]*vecs[0][1] +
vecs[0][2]*vecs[0][2])
b = sqrt(vecs[1][0]*vecs[1][0] + vecs[1][1]*vecs[1][1] +
vecs[1][2]*vecs[1][2])
c = sqrt(vecs[2][0]*vecs[2][0] + vecs[2][1]*vecs[2][1] +
vecs[2][2]*vecs[2][2])
self._boxLengths = (a, b, c) * u.nanometers
return self._boxLengths
return None
@boxLengths.setter
......@@ -1440,6 +1461,12 @@ class CharmmPsfFile(object):
@boxVectors.setter
def boxVectors(self, stuff):
""" Sets the box vectors """
try:
# We may be changing the box, so delete the cached box lengths to
# make sure they are recomputed if desired
del self._boxLengths
except AttributeError:
pass
self.box_vectors = stuff
def deleteCmap(self):
......
This diff is collapsed.
This diff is collapsed.
<ForceField>
<Info>
<DateGenerated>2014-05-28</DateGenerated>
<Reference>Lee-Ping Wang, Todd J. Martinez and Vijay S. Pande. Building force fields - an automatic, systematic and reproducible approach. Journal of Physical Chemistry Letters, 2014, 5, pp 1885-1891. DOI:10.1021/jz500737m</Reference>
</Info>
<AtomTypes>
<Type name="tip3p-fb-O" class="OW" element="O" mass="15.99943"/>
<Type name="tip3p-fb-H" class="HW" element="H" mass="1.007947"/>
</AtomTypes>
<Residues>
<Residue name="HOH">
<Atom name="O" type="tip3p-fb-O"/>
<Atom name="H1" type="tip3p-fb-H"/>
<Atom name="H2" type="tip3p-fb-H"/>
<Bond from="0" to="1"/>
<Bond from="0" to="2"/>
</Residue>
</Residues>
<HarmonicBondForce>
<Bond class1="OW" class2="HW" length="0.101181082494" k="462750.4"/>
</HarmonicBondForce>
<HarmonicAngleForce>
<Angle class1="HW" class2="OW" class3="HW" angle="1.88754640288" k="836.8"/>
</HarmonicAngleForce>
<NonbondedForce coulomb14scale="0.833333" lj14scale="0.5">
<Atom type="tip3p-fb-O" charge="-0.848448690103" sigma="0.317796456355" epsilon="0.652143528104" />
<Atom type="tip3p-fb-H" charge="0.4242243450515" sigma="1" epsilon="0" />
</NonbondedForce>
</ForceField>
<ForceField>
<Info>
<DateGenerated>2014-05-28</DateGenerated>
<Reference>Lee-Ping Wang, Todd J. Martinez and Vijay S. Pande. Building force fields - an automatic, systematic and reproducible approach. Journal of Physical Chemistry Letters, 2014, 5, pp 1885-1891. DOI:10.1021/jz500737m</Reference>
</Info>
<AtomTypes>
<Type name="tip4p-fb-O" class="OW" element="O" mass="15.99943"/>
<Type name="tip4p-fb-H" class="HW" element="H" mass="1.007947"/>
<Type name="tip4p-fb-M" class="MW" mass="0"/>
</AtomTypes>
<Residues>
<Residue name="HOH">
<Atom name="O" type="tip4p-fb-O"/>
<Atom name="H1" type="tip4p-fb-H"/>
<Atom name="H2" type="tip4p-fb-H"/>
<Atom name="M" type="tip4p-fb-M"/>
<VirtualSite type="average3" index="3" atom1="0" atom2="1" atom3="2" weight1="8.203146574531e-01" weight2="8.984267127345e-02" weight3="8.984267127345e-02" />
<Bond from="0" to="1"/>
<Bond from="0" to="2"/>
</Residue>
</Residues>
<HarmonicBondForce>
<Bond class1="OW" class2="HW" length="0.09572" k="462750.4"/>
</HarmonicBondForce>
<HarmonicAngleForce>
<Angle class1="HW" class2="OW" class3="HW" angle="1.82421813418" k="836.8"/>
</HarmonicAngleForce>
<NonbondedForce coulomb14scale="0.833333" lj14scale="0.5">
<Atom type="tip4p-fb-O" charge="0" sigma="3.165552430462e-01" epsilon="7.492790213533e-01" />
<Atom type="tip4p-fb-H" charge="5.258681106763e-01" sigma="1" epsilon="0" />
<Atom type="tip4p-fb-M" charge="-1.0517362213526e+00" sigma="1" epsilon="0" />
</NonbondedForce>
</ForceField>
......@@ -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-2013 Stanford University and the Authors.
Portions copyright (c) 2012-2014 Stanford University and the Authors.
Authors: Peter Eastman, Mark Friedrichs
Contributors:
......@@ -1485,6 +1485,104 @@ class CustomTorsionGenerator:
parsers["CustomTorsionForce"] = CustomTorsionGenerator.parseElement
## @private
class CustomNonbondedGenerator:
"""A CustomNonbondedGenerator constructs a CustomNonbondedForce."""
def __init__(self, energy, bondCutoff):
self.energy = energy
self.bondCutoff = bondCutoff
self.typeMap = {}
self.globalParams = {}
self.perParticleParams = []
self.functions = []
@staticmethod
def parseElement(element, ff):
generator = CustomNonbondedGenerator(element.attrib['energy'], int(element.attrib['bondCutoff']))
ff._forces.append(generator)
for param in element.findall('GlobalParameter'):
generator.globalParams[param.attrib['name']] = float(param.attrib['defaultValue'])
for param in element.findall('PerParticleParameter'):
generator.perParticleParams.append(param.attrib['name'])
for atom in element.findall('Atom'):
types = ff._findAtomTypes(atom, 1)
if None not in types:
values = [float(atom.attrib[param]) for param in generator.perParticleParams]
for t in types[0]:
generator.typeMap[t] = values
def createForce(self, sys, data, nonbondedMethod, nonbondedCutoff, args):
methodMap = {NoCutoff:mm.CustomNonbondedForce.NoCutoff,
CutoffNonPeriodic:mm.CustomNonbondedForce.CutoffNonPeriodic,
CutoffPeriodic:mm.CustomNonbondedForce.CutoffPeriodic}
if nonbondedMethod not in methodMap:
raise ValueError('Illegal nonbonded method for CustomNonbondedForce')
force = mm.CustomNonbondedForce(self.energy)
for param in self.globalParams:
force.addGlobalParameter(param, self.globalParams[param])
for param in self.perParticleParams:
force.addPerParticleParameter(param)
for (name, type, values, params) in self.functions:
if type == 'Continuous1D':
force.addTabulatedFunction(name, mm.Continuous1DFunction(values, params['min'], params['max']))
elif type == 'Continuous2D':
force.addTabulatedFunction(name, mm.Continuous2DFunction(params['xsize'], params['ysize'], values, params['xmin'], params['xmax'], params['ymin'], params['ymax']))
elif type == 'Continuous3D':
force.addTabulatedFunction(name, mm.Continuous2DFunction(params['xsize'], params['ysize'], params['zsize'], values, params['xmin'], params['xmax'], params['ymin'], params['ymax'], params['zmin'], params['zmax']))
elif type == 'Discrete1D':
force.addTabulatedFunction(name, mm.Discrete1DFunction(values))
elif type == 'Discrete2D':
force.addTabulatedFunction(name, mm.Discrete2DFunction(params['xsize'], params['ysize'], values))
elif type == 'Discrete3D':
force.addTabulatedFunction(name, mm.Discrete2DFunction(params['xsize'], params['ysize'], params['zsize'], values))
for atom in data.atoms:
t = data.atomType[atom]
if t in self.typeMap:
values = self.typeMap[t]
force.addParticle(self.typeMap[t])
else:
raise ValueError('No CustomNonbonded parameters defined for atom type '+t)
force.setNonbondedMethod(methodMap[nonbondedMethod])
force.setCutoffDistance(nonbondedCutoff)
sys.addForce(force)
def postprocessSystem(self, sys, data, args):
# Create exceptions based on bonds, virtual sites, and Drude particles.
if self.bondCutoff == 0:
return
bondIndices = []
for bond in data.bonds:
bondIndices.append((bond.atom1, bond.atom2))
for i in range(sys.getNumParticles()):
if sys.isVirtualSite(i):
site = sys.getVirtualSite(i)
for j in range(site.getNumParticles()):
bondIndices.append((i, site.getParticle(j)))
drude = [f for f in sys.getForces() if isinstance(f, mm.DrudeForce)]
if len(drude) > 0:
drude = drude[0]
# For purposes of creating exceptions, a Drude particle is "bonded" to anything
# its parent atom is bonded to.
drudeMap = {}
for i in range(drude.getNumParticles()):
params = drude.getParticleParameters(i)
drudeMap[params[1]] = params[0]
for atom1, atom2 in bondIndices:
drude1 = drudeMap[atom1] if atom1 in drudeMap else None
drude2 = drudeMap[atom2] if atom2 in drudeMap else None
if drude1 is not None:
bondIndices.append((drude1, atom2))
if drude2 is not None:
bondIndices.append((drude1, drude2))
if drude2 is not None:
bondIndices.append((atom1, drude2))
nonbonded = [f for f in sys.getForces() if isinstance(f, mm.CustomNonbondedForce)][0]
nonbonded.createExclusionsFromBonds(bondIndices, self.bondCutoff)
parsers["CustomNonbondedForce"] = CustomNonbondedGenerator.parseElement
## @private
class CustomGBGenerator:
"""A CustomGBGenerator constructs a CustomGBForce."""
......@@ -1493,7 +1591,6 @@ class CustomGBGenerator:
self.typeMap = {}
self.globalParams = {}
self.perParticleParams = []
self.paramValues = []
self.computedValues = []
self.energyTerms = []
self.functions = []
......@@ -2517,9 +2614,10 @@ class AmoebaTorsionTorsionGenerator:
gridRow.append(float(gridEntry.attrib['angle1']))
gridRow.append(float(gridEntry.attrib['angle2']))
gridRow.append(float(gridEntry.attrib['f']))
gridRow.append(float(gridEntry.attrib['fx']))
gridRow.append(float(gridEntry.attrib['fy']))
gridRow.append(float(gridEntry.attrib['fxy']))
if 'fx' in gridEntry.attrib:
gridRow.append(float(gridEntry.attrib['fx']))
gridRow.append(float(gridEntry.attrib['fy']))
gridRow.append(float(gridEntry.attrib['fxy']))
gridCol.append(gridRow)
gridColIndex += 1
......
......@@ -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-2013 Stanford University and the Authors.
Portions copyright (c) 2012-2014 Stanford University and the Authors.
Authors: Peter Eastman
Contributors:
......@@ -745,6 +745,12 @@ class GromacsTopFile(object):
atom1params = nb.getParticleParameters(baseAtomIndex+atoms[0])
atom2params = nb.getParticleParameters(baseAtomIndex+atoms[1])
exceptions.append((baseAtomIndex+atoms[0], baseAtomIndex+atoms[1], atom1params[0]*atom2params[0]*fudgeQQ, params[0], params[1]))
for fields in moleculeType.exclusions:
atoms = [int(x)-1 for x in fields]
for atom in atoms[1:]:
if atom > atoms[0]:
exceptions.append((baseAtomIndex+atoms[0], baseAtomIndex+atom, 0, 0, 0))
# Create nonbonded exceptions.
......
......@@ -421,8 +421,10 @@ class ResidueList(list):
if self._last_residue is None:
res = self._last_residue = Residue(resname, resnum)
list.append(self, res)
elif self._last_residue != (resname, resnum):
if self._last_residue.idx == resnum:
elif (self._last_residue != (resname, resnum) or
system != self._last_residue.system):
if (self._last_residue.idx == resnum and
system == self._last_residue.system):
lresname = self._last_residue.resname
warnings.warn('Residue %d split into separate residues %s '
'and %s' % (resnum, lresname, resname),
......@@ -1063,7 +1065,6 @@ class TrackedList(list):
__delitem__ = _tracking(list.__delitem__)
append = _tracking(list.append)
extend = _tracking(list.extend)
__delslice__ = _tracking(list.__delslice__)
__setitem__ = _tracking(list.__setitem__)
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
......
......@@ -263,7 +263,7 @@ class Modeller(object):
- positiveIon (string='Na+') the type of positive ion to add. Allowed values are 'Cs+', 'K+', 'Li+', 'Na+', and 'Rb+'
- negativeIon (string='Cl-') the type of negative ion to add. Allowed values are 'Cl-', 'Br-', 'F-', and 'I-'. Be aware
that not all force fields support all ion types.
- ionicString (concentration=0*molar) the total concentration of ions (both positive and negative) to add. This
- ionicStrength (concentration=0*molar) the total concentration of ions (both positive and negative) to add. This
does not include ions that are added to neutralize the system.
"""
# Pick a unit cell size.
......@@ -952,14 +952,14 @@ class Modeller(object):
# This is a virtual site. Compute its position by the correct rule.
if site.type == 'average2':
position = site.weights[0]*templateAtomPositions[index+site.atoms[0]] + site.weights[1]*templateAtomPositions[index+site.atoms[1]]
position = site.weights[0]*templateAtomPositions[site.atoms[0]] + site.weights[1]*templateAtomPositions[site.atoms[1]]
elif site.type == 'average3':
position = site.weights[0]*templateAtomPositions[index+site.atoms[0]] + site.weights[1]*templateAtomPositions[index+site.atoms[1]] + site.weights[2]*templateAtomPositions[index+site.atoms[2]]
position = site.weights[0]*templateAtomPositions[site.atoms[0]] + site.weights[1]*templateAtomPositions[site.atoms[1]] + site.weights[2]*templateAtomPositions[site.atoms[2]]
elif site.type == 'outOfPlane':
v1 = templateAtomPositions[index+site.atoms[1]] - templateAtomPositions[index+site.atoms[0]]
v2 = templateAtomPositions[index+site.atoms[2]] - templateAtomPositions[index+site.atoms[0]]
v1 = templateAtomPositions[site.atoms[1]] - templateAtomPositions[site.atoms[0]]
v2 = templateAtomPositions[site.atoms[2]] - templateAtomPositions[site.atoms[0]]
cross = Vec3(v1[1]*v2[2]-v1[2]*v2[1], v1[2]*v2[0]-v1[0]*v2[2], v1[0]*v2[1]-v1[1]*v2[0])
position = templateAtomPositions[index+site.atoms[0]] + site.weights[0]*v1 + site.weights[1]*v2 + site.weights[2]*cross
position = templateAtomPositions[site.atoms[0]] + site.weights[0]*v1 + site.weights[1]*v2 + site.weights[2]*cross
if position is None and atom.type in drudeTypeMap:
# This is a Drude particle. Put it on top of its parent atom.
......
......@@ -272,7 +272,7 @@ UNITS = {
("AmoebaPiTorsionForce", "getPiTorsionParameters") : ( None, (None, None, None, None, None, None, 'unit.kilojoule_per_mole')),
("AmoebaStretchBendForce", "getNumStretchBends") : ( None, ()),
("AmoebaStretchBendForce", "getStretchBendParameters") : ( None, (None, None, None, 'unit.nanometer', 'unit.nanometer', 'unit.radian', 'unit.kilojoule_per_mole/unit.nanometer')),
("AmoebaStretchBendForce", "getStretchBendParameters") : ( None, (None, None, None, 'unit.nanometer', 'unit.nanometer', 'unit.radian', 'unit.kilojoule_per_mole/unit.nanometer/unit.degree')),
("AmoebaTorsionTorsionForce", "getNumTorsionTorsions") : ( None, ()),
("AmoebaTorsionTorsionForce", "getNumTorsionTorsionGrids") : ( None, ()),
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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