"plugins/rpmd/platforms/hip/tests/TestHipRpmd.cpp" did not exist on "3e7616fc783f75e207a3bf5c31659334ad958075"
Commit bceea302 authored by Peter Eastman's avatar Peter Eastman
Browse files

Merge remote-tracking branch 'origin/master' into qc

parents 2e6397b7 a1b2641c
......@@ -524,6 +524,47 @@ void testReordering() {
}
}
/**
* Test a System where multiple virtual sites are all calculated from the same particles.
*/
void testOverlappingSites() {
System system;
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
NonbondedForce* nonbonded = new NonbondedForce();
system.addForce(nonbonded);
nonbonded->addParticle(1.0, 0.0, 0.0);
nonbonded->addParticle(-0.5, 0.0, 0.0);
nonbonded->addParticle(-0.5, 0.0, 0.0);
vector<Vec3> positions;
positions.push_back(Vec3(0, 0, 0));
positions.push_back(Vec3(10, 0, 0));
positions.push_back(Vec3(0, 10, 0));
for (int i = 0; i < 20; i++) {
system.addParticle(0.0);
double u = 0.1*((i+1)%4);
double v = 0.05*i;
system.setVirtualSite(3+i, new ThreeParticleAverageSite(0, 1, 2, u, v, 1-u-v));
nonbonded->addParticle(i%2 == 0 ? -1.0 : 1.0, 0.0, 0.0);
positions.push_back(Vec3());
}
VerletIntegrator i1(0.002);
VerletIntegrator i2(0.002);
Context c1(system, i1, Platform::getPlatformByName("Reference"));
Context c2(system, i2, platform);
c1.setPositions(positions);
c2.setPositions(positions);
c1.applyConstraints(0.0001);
c2.applyConstraints(0.0001);
State s1 = c1.getState(State::Positions | State::Forces);
State s2 = c2.getState(State::Positions | State::Forces);
for (int i = 0; i < system.getNumParticles(); i++)
ASSERT_EQUAL_VEC(s1.getPositions()[i], s2.getPositions()[i], 1e-5);
for (int i = 0; i < 3; i++)
ASSERT_EQUAL_VEC(s1.getForces()[i], s2.getForces()[i], 1e-5);
}
int main(int argc, char* argv[]) {
try {
if (argc > 1)
......@@ -535,6 +576,7 @@ int main(int argc, char* argv[]) {
testLocalCoordinates();
testConservationLaws();
testReordering();
testOverlappingSites();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
......
......@@ -126,13 +126,15 @@ public:
* Set the torsion-torsion grid at the specified index
*
* @param index the index of the torsion-torsion for which to get parameters
* @param grid grid
* @param grid either 3 or 6 values may be specified per grid point. If the derivatives
* are omitted, they are calculated automatically by fitting a 2D spline to
* the energies.
* grid[x][y][0] = x value
* grid[x][y][1] = y value
* grid[x][y][2] = function value
* grid[x][y][3] = dfdx value
* grid[x][y][4] = dfdy value
* grid[x][y][5] = dfd(xy) value
* grid[x][y][2] = energy
* grid[x][y][3] = dEdx value
* grid[x][y][4] = dEdy value
* grid[x][y][5] = dEd(xy) value
*/
void setTorsionTorsionGrid(int index, const std::vector<std::vector<std::vector<double> > >& grid);
......@@ -181,29 +183,7 @@ public:
_spacing[0] = _spacing[1] = 1.0;
}
TorsionTorsionGridInfo(const TorsionTorsionGrid& grid) {
_grid.resize(grid.size());
for(unsigned int kk = 0; kk < grid.size(); kk++){
_grid[kk].resize(grid[kk].size());
for(unsigned int jj = 0; jj < grid[kk].size(); jj++){
_grid[kk][jj].resize(grid[kk][jj].size());
for(unsigned int ii = 0; ii < grid[kk][jj].size(); ii++){
_grid[kk][jj][ii] = grid[kk][jj][ii];
}
}
}
_startValues[0] = _grid[0][0][0];
_startValues[1] = _grid[0][0][1];
_spacing[0] = static_cast<double>(_grid.size()-1)/360.0;
_spacing[1] = static_cast<double>(grid.size()-1)/360.0;
_size[0] = static_cast<int>(grid.size());
_size[1] = static_cast<int>(grid[0].size());
}
TorsionTorsionGridInfo(const TorsionTorsionGrid& grid);
const TorsionTorsionGrid& getTorsionTorsionGrid(void) const {
return _grid;
......
......@@ -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-2009 Stanford University and the Authors. *
* Portions copyright (c) 2008-2014 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
......@@ -33,8 +33,10 @@
#include "openmm/OpenMMException.h"
#include "openmm/AmoebaTorsionTorsionForce.h"
#include "openmm/internal/AmoebaTorsionTorsionForceImpl.h"
#include "openmm/internal/SplineFitter.h"
using namespace OpenMM;
using namespace std;
AmoebaTorsionTorsionForce::AmoebaTorsionTorsionForce() {
}
......@@ -82,3 +84,102 @@ void AmoebaTorsionTorsionForce::setTorsionTorsionGrid(int index, const TorsionTo
ForceImpl* AmoebaTorsionTorsionForce::createImpl() const {
return new AmoebaTorsionTorsionForceImpl(*this);
}
AmoebaTorsionTorsionForce::TorsionTorsionGridInfo::TorsionTorsionGridInfo(const TorsionTorsionGrid& grid) {
if (grid[0][0][0] != grid[1][0][0])
_grid = grid;
else {
// We need to transpose the grid.
int xsize = grid[0].size();
int ysize = grid.size();
_grid.resize(xsize);
for (int i = 0; i < xsize; i++) {
_grid[i].resize(ysize);
for (int j = 0; j < ysize; j++)
_grid[i][j] = grid[j][i];
}
}
_startValues[0] = _grid[0][0][0];
_startValues[1] = _grid[0][0][1];
_spacing[0] = static_cast<double>(_grid.size()-1)/360.0;
_spacing[1] = static_cast<double>(_grid.size()-1)/360.0;
_size[0] = static_cast<int>(_grid.size());
_size[1] = static_cast<int>(_grid[0].size());
if (_grid[0][0].size() == 3) {
// We need to compute the derivatives ourselves. First determine if the grid is periodic.
int xsize = _size[0];
int ysize = _size[1];
bool periodic = true;
for (int i = 0; i < xsize; i++)
if (_grid[i][0][2] != _grid[i][ysize-1][2])
periodic = false;
for (int i = 0; i < ysize; i++)
if (_grid[0][i][2] != _grid[xsize-1][i][2])
periodic = false;
// Compute derivatives with respect to the first angle.
vector<double> x(xsize), y(ysize);
for (int i = 0; i < xsize; i++)
x[i] = _grid[i][0][0];
for (int i = 0; i < ysize; i++)
y[i] = _grid[0][i][1];
vector<double> d1(xsize*ysize), d2(xsize*ysize), d12(xsize*ysize);
vector<double> t(xsize), deriv(xsize);
for (int i = 0; i < ysize; i++) {
for (int j = 0; j < xsize; j++)
t[j] = _grid[j][i][2];
if (periodic)
SplineFitter::createPeriodicSpline(x, t, deriv);
else
SplineFitter::createNaturalSpline(x, t, deriv);
for (int j = 0; j < xsize; j++)
d1[j+xsize*i] = SplineFitter::evaluateSplineDerivative(x, t, deriv, x[j]);
}
// Compute derivatives with respect to the second angle.
t.resize(ysize);
deriv.resize(ysize);
for (int i = 0; i < xsize; i++) {
for (int j = 0; j < ysize; j++)
t[j] = _grid[i][j][2];
if (periodic)
SplineFitter::createPeriodicSpline(y, t, deriv);
else
SplineFitter::createNaturalSpline(y, t, deriv);
for (int j = 0; j < ysize; j++)
d2[i+xsize*j] = SplineFitter::evaluateSplineDerivative(y, t, deriv, y[j]);
}
// Compute cross derivatives.
t.resize(xsize);
deriv.resize(xsize);
for (int i = 0; i < ysize; i++) {
for (int j = 0; j < xsize; j++)
t[j] = d2[j+xsize*i];
if (periodic)
SplineFitter::createPeriodicSpline(x, t, deriv);
else
SplineFitter::createNaturalSpline(x, t, deriv);
for (int j = 0; j < xsize; j++)
d12[j+xsize*i] = SplineFitter::evaluateSplineDerivative(x, t, deriv, x[j]);
}
// Add the derivatives to the grid.
for (int i = 0; i < xsize; i++)
for (int j = 0; j < ysize; j++) {
_grid[i][j].push_back(d1[i+xsize*j]);
_grid[i][j].push_back(d2[i+xsize*j]);
_grid[i][j].push_back(d12[i+xsize*j]);
}
}
}
......@@ -49,7 +49,7 @@ extern "C" OPENMM_EXPORT void registerAmoebaReferenceKernelFactories();
const double TOL = 1e-4;
TorsionTorsionGrid& getTorsionGrid( int gridIndex ) {
TorsionTorsionGrid getTorsionGrid(int gridIndex, bool includeDerivs) {
static double grid[4][625][6] = {
{
......@@ -2557,35 +2557,32 @@ static double grid[4][625][6] = {
{ 165.0000, 180.0000, -0.182999000E+01, 0.377952854E-01, 0.233583295E-01, -0.109828932E-02 },
{ 180.0000, 180.0000, -0.146854000E+01, 0.491175487E-02, 0.195601580E-02, -0.163177030E-02 } } };
// static std::vector< std::vector< std::vector<double> > > TorsionTorsionGrid
static std::vector<TorsionTorsionGrid> grids;
if( grids.size() == 0 ){
grids.resize(4);
for( int ii = 0; ii < 4; ii++ ){
grids[ii].resize( 25 );
for( int jj = 0; jj < 25; jj++ ){
grids[ii][jj].resize(25);
for( int kk = 0; kk < 25; kk++ ){
grids[ii][jj][kk].resize(6);
}
int elementCount = (includeDerivs ? 6 : 3);
std::vector<TorsionTorsionGrid> grids(4);
for( int ii = 0; ii < 4; ii++ ){
grids[ii].resize( 25 );
for( int jj = 0; jj < 25; jj++ ){
grids[ii][jj].resize(25);
for( int kk = 0; kk < 25; kk++ ){
grids[ii][jj][kk].resize(elementCount);
}
int index = 0;
for( int jj = 0; jj < 25; jj++ ){
for( int kk = 0; kk < 25; kk++ ){
int jjIndex = static_cast<int>(((grid[ii][index][0] + 180.0)/15.0)+1.0e-05);
int kkIndex = static_cast<int>(((grid[ii][index][1] + 180.0)/15.0)+1.0e-05);
for( int ll = 0; ll < 6; ll++ ){
grids[ii][kk][jj][ll] = grid[ii][index][ll];
}
index++;
}
int index = 0;
for( int jj = 0; jj < 25; jj++ ){
for( int kk = 0; kk < 25; kk++ ){
int jjIndex = static_cast<int>(((grid[ii][index][0] + 180.0)/15.0)+1.0e-05);
int kkIndex = static_cast<int>(((grid[ii][index][1] + 180.0)/15.0)+1.0e-05);
for( int ll = 0; ll < elementCount; ll++ ){
grids[ii][kk][jj][ll] = grid[ii][index][ll];
}
index++;
}
}
}
return grids[gridIndex];
}
void testTorsionTorsion( FILE* log, int systemId ) {
void testTorsionTorsion(int systemId, bool includeDerivs) {
System system;
int numberOfParticles = 6;
......@@ -2645,11 +2642,11 @@ void testTorsionTorsion( FILE* log, int systemId ) {
expectedEnergy = -3.372536909E+00;
}
amoebaTorsionTorsionForce->addTorsionTorsion( 0, 1, 2, 3, 4, chiralCheckAtomIndex, 0 );
amoebaTorsionTorsionForce->setTorsionTorsionGrid( 0, getTorsionGrid( gridIndex ) );
amoebaTorsionTorsionForce->addTorsionTorsion(0, 1, 2, 3, 4, chiralCheckAtomIndex, 0);
amoebaTorsionTorsionForce->setTorsionTorsionGrid(0, getTorsionGrid(gridIndex, includeDerivs));
system.addForce(amoebaTorsionTorsionForce);
Context context(system, integrator, Platform::getPlatformByName( "Reference"));
Context context(system, integrator, Platform::getPlatformByName("Reference"));
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
......@@ -2662,18 +2659,6 @@ void testTorsionTorsion( FILE* log, int systemId ) {
forces[ii][2] *= conversion;
}
#ifdef AMOEBA_DEBUG
if( log ){
(void) fprintf( log, "computeAmoebaTorsionTorsionForces: expected energy=%14.7e %14.7e\n", expectedEnergy, state.getPotentialEnergy() );
for( unsigned int ii = 0; ii < forces.size(); ii++ ){
(void) fprintf( log, "%6u [%14.7e %14.7e %14.7e] [%14.7e %14.7e %14.7e]\n", ii,
expectedForces[ii][0], expectedForces[ii][1], expectedForces[ii][2],
forces[ii][0], forces[ii][1], forces[ii][2] );
}
(void) fflush( log );
}
#endif
double tolerance = 1.0e-03;
for( unsigned int ii = 0; ii < forces.size(); ii++ ){
ASSERT_EQUAL_VEC( expectedForces[ii], forces[ii], tolerance );
......@@ -2687,10 +2672,8 @@ int main( int numberOfArguments, char* argv[] ) {
try {
std::cout << "TestReferenceAmoebaTorsionTorsionForce running test..." << std::endl;
registerAmoebaReferenceKernelFactories();
//registerAmoebaCudaKernelFactories();
FILE* log = NULL;
testTorsionTorsion( log, 1 );
testTorsionTorsion(1, true);
testTorsionTorsion(1, false);
} catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl;
std::cout << "FAIL - ERROR. Test failed." << std::endl;
......
......@@ -33,8 +33,8 @@
#include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/OSRngSeed.h"
#include "openmm/DrudeKernels.h"
#include <cmath>
#include <ctime>
#include <string>
......@@ -49,7 +49,7 @@ DrudeLangevinIntegrator::DrudeLangevinIntegrator(double temperature, double fric
setDrudeFriction(drudeFrictionCoeff);
setStepSize(stepSize);
setConstraintTolerance(1e-5);
setRandomNumberSeed((int) time(NULL));
setRandomNumberSeed(osrngseed());
}
void DrudeLangevinIntegrator::initialize(ContextImpl& contextRef) {
......
......@@ -33,10 +33,10 @@
#include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/OSRngSeed.h"
#include "openmm/RpmdKernels.h"
#include "SimTKOpenMMRealType.h"
#include <cmath>
#include <ctime>
#include <string>
using namespace OpenMM;
......@@ -48,7 +48,7 @@ RPMDIntegrator::RPMDIntegrator(int numCopies, double temperature, double frictio
setFriction(frictionCoeff);
setStepSize(stepSize);
setConstraintTolerance(1e-5);
setRandomNumberSeed((int) time(NULL));
setRandomNumberSeed(osrngseed());
}
RPMDIntegrator::RPMDIntegrator(int numCopies, double temperature, double frictionCoeff, double stepSize) :
......@@ -57,7 +57,7 @@ RPMDIntegrator::RPMDIntegrator(int numCopies, double temperature, double frictio
setFriction(frictionCoeff);
setStepSize(stepSize);
setConstraintTolerance(1e-5);
setRandomNumberSeed((int) time(NULL));
setRandomNumberSeed(osrngseed());
}
void RPMDIntegrator::initialize(ContextImpl& contextRef) {
......
......@@ -30,6 +30,7 @@
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/CustomNonbondedForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/OpenMMException.h"
#include <iostream>
......@@ -166,10 +167,62 @@ void testReplaceExceptions() {
ASSERT(charge == 5.0);
}
/**
* This is the same as testFindExceptions(), except it tests adding exclusions to a CustomNonbondedForce.
*/
void testFindCustomExclusions() {
CustomNonbondedForce nonbonded("r");
vector<pair<int, int> > bonds;
vector<double> params;
for (int i = 0; i < NUM_ATOMS; i++)
nonbonded.addParticle(params);
// loop over all main-chain atoms (even numbered atoms)
for (int i = 0; i < NUM_ATOMS-1; i += 2)
{
// side-chain bonds
bonds.push_back(pair<int, int>(i, i+1));
// main-chain bonds
if (i < NUM_ATOMS-2) // penultimate atom (NUM_ATOMS-2) has no subsequent main-chain atom
bonds.push_back(pair<int, int>(i, i+2));
}
nonbonded.createExclusionsFromBonds(bonds, 3);
// Build lists of the expected exclusions.
vector<set<int> > expectedExclusions(NUM_ATOMS);
int totalExclusions = 0;
for (int i = 0; i < NUM_ATOMS; i += 2) {
addAtomsToExclusions(i, i+1, expectedExclusions, totalExclusions);
addAtomsToExclusions(i, i+2, expectedExclusions, totalExclusions);
addAtomsToExclusions(i, i+3, expectedExclusions, totalExclusions);
addAtomsToExclusions(i, i+4, expectedExclusions, totalExclusions);
addAtomsToExclusions(i+1, i+2, expectedExclusions, totalExclusions);
addAtomsToExclusions(i, i+5, expectedExclusions, totalExclusions);
addAtomsToExclusions(i, i+6, expectedExclusions, totalExclusions);
addAtomsToExclusions(i+1, i+3, expectedExclusions, totalExclusions);
addAtomsToExclusions(i+1, i+4, expectedExclusions, totalExclusions);
}
for (int i = 0; i < nonbonded.getNumExclusions(); i++) {
int particle1, particle2;
nonbonded.getExclusionParticles(i, particle1, particle2);
}
// Compare them to the exceptions that were generated.
ASSERT_EQUAL(totalExclusions, nonbonded.getNumExclusions());
for (int i = 0; i < nonbonded.getNumExclusions(); i++) {
int particle1, particle2;
nonbonded.getExclusionParticles(i, particle1, particle2);
ASSERT(expectedExclusions[particle1].find(particle2) != expectedExclusions[particle1].end());
}
}
int main() {
try {
testFindExceptions();
testReplaceExceptions();
testFindCustomExclusions();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
......
......@@ -55,8 +55,12 @@ foreach(SUBDIR ${SUBDIRS})
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.xml"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.pdb"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.prmtop"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.parm7"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.rst7"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.ncrst"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.dms"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.top"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.par"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*psf"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/charmm22.*"
)
......
......@@ -6,9 +6,9 @@ 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-2014 Stanford University and the Authors.
Authors: Peter Eastman
Contributors:
Contributors: Jason Swails
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
......@@ -31,87 +31,97 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
__author__ = "Peter Eastman"
__version__ = "1.0"
from functools import wraps
from simtk.openmm.app.internal import amber_file_parser
from simtk.unit import Quantity, nanometers, picoseconds
import warnings
try:
import numpy
import numpy as np
except:
pass
np = None
def numpy_protector(func):
"""
Decorator to emit useful error messages if users try to request numpy
processing if numpy is not available. Raises ImportError if numpy could not
be found
"""
@wraps(func)
def wrapper(self, asNumpy=False):
if asNumpy and np is None:
raise ImportError('Could not import numpy. Cannot set asNumpy=True')
return func(self, asNumpy=asNumpy)
return wrapper
class AmberInpcrdFile(object):
"""AmberInpcrdFile parses an AMBER inpcrd file and loads the data stored in it."""
def __init__(self, file, loadVelocities=False, loadBoxVectors=False):
def __init__(self, file, loadVelocities=None, loadBoxVectors=None):
"""Load an inpcrd file.
An inpcrd file contains atom positions and, optionally, velocities and periodic box dimensions.
Unfortunately, it is sometimes impossible to determine from the file itself exactly what data
it contains. You therefore must specify in advance what data to load. It is stored into this
object's "positions", "velocities", and "boxVectors" fields.
Parameters:
- file (string) the name of the file to load
- loadVelocities (boolean=False) whether to load velocities from the file
- loadBoxVectors (boolean=False) whether to load the periodic box vectors
- loadVelocities (boolean=None) deprecated. Velocities are loaded automatically if present
- loadBoxVectors (boolean=None) deprecated. Box vectors are loaded automatically if present
"""
results = amber_file_parser.readAmberCoordinates(file, read_velocities=loadVelocities, read_box=loadBoxVectors)
if loadVelocities:
## The atom positions read from the inpcrd file
self.positions = results[0]
if loadBoxVectors:
## The periodic box vectors read from the inpcrd file
self.boxVectors = results[1]
## The atom velocities read from the inpcrd file
self.velocities = results[2]
else:
self.velocities = results[1]
elif loadBoxVectors:
self.positions = results[0]
self.boxVectors = results[1]
else:
self.positions = results
self.file = file
if loadVelocities is not None or loadBoxVectors is not None:
warnings.warn('loadVelocities and loadBoxVectors have been '
'deprecated. velocities and box information '
'is loaded automatically if the inpcrd file contains '
'them.', DeprecationWarning)
results = amber_file_parser.readAmberCoordinates(file)
self.positions, self.velocities, self.boxVectors = results
# Cached numpy arrays
self._numpyPositions = None
if loadVelocities:
self._numpyVelocities = None
if loadBoxVectors:
self._numpyBoxVectors = None
self._numpyVelocities = None
self._numpyBoxVectors = None
@numpy_protector
def getPositions(self, asNumpy=False):
"""Get the atomic positions.
Parameters:
- asNumpy (boolean=False) if true, the values are returned as a numpy array instead of a list of Vec3s
"""
"""
if asNumpy:
if self._numpyPositions is None:
self._numpyPositions = Quantity(numpy.array(self.positions.value_in_unit(nanometers)), nanometers)
self._numpyPositions = Quantity(np.array(self.positions.value_in_unit(nanometers)), nanometers)
return self._numpyPositions
return self.positions
@numpy_protector
def getVelocities(self, asNumpy=False):
"""Get the atomic velocities.
Parameters:
- asNumpy (boolean=False) if true, the vectors are returned as numpy arrays instead of Vec3s
"""
"""
if self.velocities is None:
raise AttributeError('velocities not found in %s' % self.file)
if asNumpy:
if self._numpyVelocities is None:
self._numpyVelocities = Quantity(numpy.array(self.velocities.value_in_unit(nanometers/picoseconds)), nanometers/picoseconds)
self._numpyVelocities = Quantity(np.array(self.velocities.value_in_unit(nanometers/picoseconds)), nanometers/picoseconds)
return self._numpyVelocities
return self.velocities
@numpy_protector
def getBoxVectors(self, asNumpy=False):
"""Get the periodic box vectors.
Parameters:
- asNumpy (boolean=False) if true, the values are returned as a numpy array instead of a list of Vec3s
"""
"""
if self.boxVectors is None:
raise AttributeError('Box information not found in %s' % self.file)
if asNumpy:
if self._numpyBoxVectors is None:
self._numpyBoxVectors = []
self._numpyBoxVectors.append(Quantity(numpy.array(self.boxVectors[0].value_in_unit(nanometers)), nanometers))
self._numpyBoxVectors.append(Quantity(numpy.array(self.boxVectors[1].value_in_unit(nanometers)), nanometers))
self._numpyBoxVectors.append(Quantity(numpy.array(self.boxVectors[2].value_in_unit(nanometers)), nanometers))
self._numpyBoxVectors.append(Quantity(np.array(self.boxVectors[0].value_in_unit(nanometers)), nanometers))
self._numpyBoxVectors.append(Quantity(np.array(self.boxVectors[1].value_in_unit(nanometers)), nanometers))
self._numpyBoxVectors.append(Quantity(np.array(self.boxVectors[2].value_in_unit(nanometers)), nanometers))
return self._numpyBoxVectors
return self.boxVectors
......@@ -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 source diff could not be displayed because it is too large. You can view the blob instead.
<ForceField>
<Info>
<Source>amoebapro13_5-2014.prm</Source>
<DateGenerated>2014-05-08</DateGenerated>
<Reference>Yue Shi, Zhen Xia, Jiajing Zhang, Robert Best, Chuanjie Wu, Jay W. Ponder, and Pengyu Ren. Polarizable Atomic Multipole-Based AMOEBA Force Field for Proteins. Journal of Chemical Theory and Computation, 9(9):4046–4063, 2013.</Reference>
</Info>
<AmoebaGeneralizedKirkwoodForce solventDielectric="78.3" soluteDielectric="1.0" includeCavityTerm="1" probeRadius="0.14" surfaceAreaFactor="-170.351730663">
<GeneralizedKirkwood type="1" charge="-0.22483" shct="0.79" />
<GeneralizedKirkwood type="2" charge="-0.09722" shct="0.72" />
<GeneralizedKirkwood type="2" charge="-0.31113" shct="0.72" />
<GeneralizedKirkwood type="2" charge="-0.18217" shct="0.72" />
<GeneralizedKirkwood type="2" charge="-0.06142" shct="0.72" />
<GeneralizedKirkwood type="3" charge="0.79586" shct="0.72" />
<GeneralizedKirkwood type="4" charge="0.13964" shct="0.85" />
<GeneralizedKirkwood type="5" charge="-0.76219" shct="0.85" />
<GeneralizedKirkwood type="6" charge="0.07437" shct="0.85" />
<GeneralizedKirkwood type="7" charge="-0.15418" shct="0.79" />
<GeneralizedKirkwood type="7" charge="-0.14115" shct="0.79" />
<GeneralizedKirkwood type="8" charge="-0.17302" shct="0.72" />
<GeneralizedKirkwood type="8" charge="-0.36199" shct="0.72" />
<GeneralizedKirkwood type="8" charge="-0.11441" shct="0.72" />
<GeneralizedKirkwood type="8" charge="0.04440" shct="0.72" />
<GeneralizedKirkwood type="9" charge="0.81010" shct="0.72" />
<GeneralizedKirkwood type="9" charge="0.85003" shct="0.72" />
<GeneralizedKirkwood type="10" charge="0.12044" shct="0.85" />
<GeneralizedKirkwood type="10" charge="0.12637" shct="0.85" />
<GeneralizedKirkwood type="11" charge="-0.75149" shct="0.85" />
<GeneralizedKirkwood type="11" charge="-0.77014" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.08514" shct="0.85" />
<GeneralizedKirkwood type="12" charge="0.07834" shct="0.85" />
<GeneralizedKirkwood type="13" charge="-0.15959" shct="0.72" />
<GeneralizedKirkwood type="14" charge="0.07420" shct="0.85" />
<GeneralizedKirkwood type="15" charge="-0.06548" shct="0.72" />
<GeneralizedKirkwood type="16" charge="0.07117" shct="0.85" />
<GeneralizedKirkwood type="17" charge="-0.16832" shct="0.72" />
<GeneralizedKirkwood type="18" charge="0.06566" shct="0.85" />
<GeneralizedKirkwood type="19" charge="-0.13173" shct="0.72" />
<GeneralizedKirkwood type="20" charge="0.06916" shct="0.85" />
<GeneralizedKirkwood type="21" charge="-0.02887" shct="0.72" />
<GeneralizedKirkwood type="22" charge="0.08767" shct="0.85" />
<GeneralizedKirkwood type="23" charge="-0.17741" shct="0.72" />
<GeneralizedKirkwood type="24" charge="0.05874" shct="0.85" />
<GeneralizedKirkwood type="25" charge="-0.08555" shct="0.72" />
<GeneralizedKirkwood type="26" charge="0.08230" shct="0.85" />
<GeneralizedKirkwood type="27" charge="-0.11939" shct="0.72" />
<GeneralizedKirkwood type="28" charge="0.07096" shct="0.85" />
<GeneralizedKirkwood type="29" charge="-0.17217" shct="0.72" />
<GeneralizedKirkwood type="30" charge="0.06823" shct="0.85" />
<GeneralizedKirkwood type="31" charge="-0.16882" shct="0.72" />
<GeneralizedKirkwood type="32" charge="0.06001" shct="0.85" />
<GeneralizedKirkwood type="33" charge="0.16229" shct="0.72" />
<GeneralizedKirkwood type="34" charge="0.05600" shct="0.85" />
<GeneralizedKirkwood type="35" charge="-0.44145" shct="0.85" />
<GeneralizedKirkwood type="36" charge="0.23017" shct="0.85" />
<GeneralizedKirkwood type="37" charge="0.10834" shct="0.72" />
<GeneralizedKirkwood type="38" charge="0.06805" shct="0.85" />
<GeneralizedKirkwood type="39" charge="-0.40177" shct="0.85" />
<GeneralizedKirkwood type="40" charge="0.24568" shct="0.85" />
<GeneralizedKirkwood type="41" charge="-0.16081" shct="0.72" />
<GeneralizedKirkwood type="42" charge="0.06784" shct="0.85" />
<GeneralizedKirkwood type="43" charge="-0.30144" shct="0.72" />
<GeneralizedKirkwood type="43" charge="-0.30144" shct="0.72" />
<GeneralizedKirkwood type="43" charge="-0.08027" shct="0.72" />
<GeneralizedKirkwood type="44" charge="0.14381" shct="0.85" />
<GeneralizedKirkwood type="44" charge="0.00975" shct="0.85" />
<GeneralizedKirkwood type="45" charge="-0.03264" shct="0.96" />
<GeneralizedKirkwood type="46" charge="0.10947" shct="0.85" />
<GeneralizedKirkwood type="47" charge="0.07683" shct="0.96" />
<GeneralizedKirkwood type="48" charge="-0.23113" shct="0.72" />
<GeneralizedKirkwood type="49" charge="-0.85155" shct="0.96" />
<GeneralizedKirkwood type="50" charge="-0.13558" shct="0.79" />
<GeneralizedKirkwood type="51" charge="-0.26070" shct="0.72" />
<GeneralizedKirkwood type="52" charge="0.90470" shct="0.72" />
<GeneralizedKirkwood type="53" charge="-0.76984" shct="0.85" />
<GeneralizedKirkwood type="54" charge="0.09550" shct="0.85" />
<GeneralizedKirkwood type="55" charge="-0.13205" shct="0.72" />
<GeneralizedKirkwood type="55" charge="-0.12680" shct="0.72" />
<GeneralizedKirkwood type="56" charge="0.09686" shct="0.85" />
<GeneralizedKirkwood type="56" charge="0.11510" shct="0.85" />
<GeneralizedKirkwood type="57" charge="-0.16591" shct="0.72" />
<GeneralizedKirkwood type="57" charge="-0.14420" shct="0.72" />
<GeneralizedKirkwood type="58" charge="0.08886" shct="0.85" />
<GeneralizedKirkwood type="58" charge="0.12121" shct="0.85" />
<GeneralizedKirkwood type="59" charge="-0.03932" shct="0.72" />
<GeneralizedKirkwood type="60" charge="0.06588" shct="0.85" />
<GeneralizedKirkwood type="61" charge="-0.11216" shct="0.72" />
<GeneralizedKirkwood type="62" charge="0.09205" shct="0.85" />
<GeneralizedKirkwood type="63" charge="-0.04246" shct="0.72" />
<GeneralizedKirkwood type="64" charge="0.04681" shct="0.72" />
<GeneralizedKirkwood type="65" charge="0.00023" shct="0.85" />
<GeneralizedKirkwood type="66" charge="-0.02656" shct="0.72" />
<GeneralizedKirkwood type="67" charge="0.00719" shct="0.85" />
<GeneralizedKirkwood type="68" charge="-0.02866" shct="0.72" />
<GeneralizedKirkwood type="69" charge="0.00685" shct="0.85" />
<GeneralizedKirkwood type="70" charge="-0.10731" shct="0.72" />
<GeneralizedKirkwood type="71" charge="0.09011" shct="0.85" />
<GeneralizedKirkwood type="72" charge="-0.05309" shct="0.72" />
<GeneralizedKirkwood type="73" charge="0.07134" shct="0.72" />
<GeneralizedKirkwood type="74" charge="0.00345" shct="0.85" />
<GeneralizedKirkwood type="75" charge="-0.12512" shct="0.72" />
<GeneralizedKirkwood type="76" charge="0.01090" shct="0.85" />
<GeneralizedKirkwood type="77" charge="0.35744" shct="0.72" />
<GeneralizedKirkwood type="78" charge="-0.46438" shct="0.85" />
<GeneralizedKirkwood type="79" charge="0.22899" shct="0.85" />
<GeneralizedKirkwood type="80" charge="-0.14909" shct="0.72" />
<GeneralizedKirkwood type="81" charge="0.07954" shct="0.85" />
<GeneralizedKirkwood type="82" charge="-0.21590" shct="0.72" />
<GeneralizedKirkwood type="83" charge="-0.04549" shct="0.72" />
<GeneralizedKirkwood type="84" charge="0.01759" shct="0.85" />
<GeneralizedKirkwood type="85" charge="-0.15892" shct="0.72" />
<GeneralizedKirkwood type="86" charge="-0.03324" shct="0.85" />
<GeneralizedKirkwood type="87" charge="0.62054" shct="0.72" />
<GeneralizedKirkwood type="88" charge="-0.91150" shct="0.85" />
<GeneralizedKirkwood type="89" charge="-0.16339" shct="0.72" />
<GeneralizedKirkwood type="90" charge="0.08819" shct="0.85" />
<GeneralizedKirkwood type="91" charge="-0.14846" shct="0.72" />
<GeneralizedKirkwood type="92" charge="0.09676" shct="0.72" />
<GeneralizedKirkwood type="93" charge="0.02989" shct="0.85" />
<GeneralizedKirkwood type="94" charge="0.00548" shct="0.72" />
<GeneralizedKirkwood type="95" charge="-0.03588" shct="0.79" />
<GeneralizedKirkwood type="96" charge="0.08805" shct="0.85" />
<GeneralizedKirkwood type="97" charge="0.27382" shct="0.72" />
<GeneralizedKirkwood type="98" charge="-0.20979" shct="0.72" />
<GeneralizedKirkwood type="99" charge="0.00102" shct="0.85" />
<GeneralizedKirkwood type="100" charge="-0.11296" shct="0.72" />
<GeneralizedKirkwood type="101" charge="0.00446" shct="0.85" />
<GeneralizedKirkwood type="102" charge="0.06902" shct="0.72" />
<GeneralizedKirkwood type="103" charge="0.00474" shct="0.85" />
<GeneralizedKirkwood type="104" charge="-0.01987" shct="0.72" />
<GeneralizedKirkwood type="105" charge="0.00374" shct="0.85" />
<GeneralizedKirkwood type="106" charge="-0.10044" shct="0.72" />
<GeneralizedKirkwood type="107" charge="0.11241" shct="0.85" />
<GeneralizedKirkwood type="108" charge="0.16205" shct="0.72" />
<GeneralizedKirkwood type="109" charge="-0.10600" shct="0.79" />
<GeneralizedKirkwood type="110" charge="0.20247" shct="0.85" />
<GeneralizedKirkwood type="111" charge="0.04476" shct="0.72" />
<GeneralizedKirkwood type="112" charge="0.08897" shct="0.85" />
<GeneralizedKirkwood type="113" charge="0.39335" shct="0.72" />
<GeneralizedKirkwood type="114" charge="0.09278" shct="0.85" />
<GeneralizedKirkwood type="115" charge="-0.08186" shct="0.79" />
<GeneralizedKirkwood type="116" charge="0.14211" shct="0.85" />
<GeneralizedKirkwood type="117" charge="-0.10846" shct="0.72" />
<GeneralizedKirkwood type="118" charge="0.08849" shct="0.85" />
<GeneralizedKirkwood type="119" charge="0.04660" shct="0.72" />
<GeneralizedKirkwood type="120" charge="-0.16996" shct="0.79" />
<GeneralizedKirkwood type="121" charge="0.13110" shct="0.85" />
<GeneralizedKirkwood type="122" charge="0.08866" shct="0.72" />
<GeneralizedKirkwood type="123" charge="0.02049" shct="0.85" />
<GeneralizedKirkwood type="124" charge="0.34991" shct="0.72" />
<GeneralizedKirkwood type="125" charge="0.03404" shct="0.85" />
<GeneralizedKirkwood type="126" charge="-0.50635" shct="0.79" />
<GeneralizedKirkwood type="127" charge="-0.11338" shct="0.72" />
<GeneralizedKirkwood type="128" charge="0.08990" shct="0.85" />
<GeneralizedKirkwood type="129" charge="0.20611" shct="0.72" />
<GeneralizedKirkwood type="130" charge="-0.56975" shct="0.79" />
<GeneralizedKirkwood type="131" charge="-0.02289" shct="0.72" />
<GeneralizedKirkwood type="132" charge="0.03876" shct="0.85" />
<GeneralizedKirkwood type="133" charge="0.33110" shct="0.72" />
<GeneralizedKirkwood type="134" charge="0.03651" shct="0.85" />
<GeneralizedKirkwood type="135" charge="-0.13121" shct="0.79" />
<GeneralizedKirkwood type="136" charge="0.10796" shct="0.85" />
<GeneralizedKirkwood type="137" charge="-0.33682" shct="0.72" />
<GeneralizedKirkwood type="138" charge="0.04965" shct="0.85" />
<GeneralizedKirkwood type="139" charge="1.01811" shct="0.72" />
<GeneralizedKirkwood type="140" charge="-0.85879" shct="0.85" />
<GeneralizedKirkwood type="141" charge="-0.17303" shct="0.72" />
<GeneralizedKirkwood type="142" charge="0.10446" shct="0.85" />
<GeneralizedKirkwood type="143" charge="0.85923" shct="0.72" />
<GeneralizedKirkwood type="144" charge="-0.63514" shct="0.85" />
<GeneralizedKirkwood type="145" charge="-0.43939" shct="0.85" />
<GeneralizedKirkwood type="146" charge="0.24242" shct="0.85" />
<GeneralizedKirkwood type="147" charge="-0.15914" shct="0.72" />
<GeneralizedKirkwood type="148" charge="0.10149" shct="0.85" />
<GeneralizedKirkwood type="149" charge="0.76984" shct="0.72" />
<GeneralizedKirkwood type="150" charge="-0.74313" shct="0.85" />
<GeneralizedKirkwood type="151" charge="-0.28938" shct="0.79" />
<GeneralizedKirkwood type="152" charge="0.14092" shct="0.85" />
<GeneralizedKirkwood type="153" charge="-0.10324" shct="0.72" />
<GeneralizedKirkwood type="154" charge="0.06492" shct="0.85" />
<GeneralizedKirkwood type="155" charge="-0.35416" shct="0.72" />
<GeneralizedKirkwood type="156" charge="0.06420" shct="0.85" />
<GeneralizedKirkwood type="157" charge="1.05691" shct="0.72" />
<GeneralizedKirkwood type="158" charge="-0.89737" shct="0.85" />
<GeneralizedKirkwood type="159" charge="-0.10668" shct="0.72" />
<GeneralizedKirkwood type="160" charge="0.09513" shct="0.85" />
<GeneralizedKirkwood type="161" charge="-0.23637" shct="0.72" />
<GeneralizedKirkwood type="162" charge="0.10600" shct="0.85" />
<GeneralizedKirkwood type="163" charge="0.90086" shct="0.72" />
<GeneralizedKirkwood type="164" charge="-0.60677" shct="0.85" />
<GeneralizedKirkwood type="165" charge="-0.53100" shct="0.85" />
<GeneralizedKirkwood type="166" charge="0.24071" shct="0.85" />
<GeneralizedKirkwood type="167" charge="-0.07575" shct="0.72" />
<GeneralizedKirkwood type="168" charge="0.09458" shct="0.85" />
<GeneralizedKirkwood type="169" charge="-0.27255" shct="0.72" />
<GeneralizedKirkwood type="170" charge="0.10149" shct="0.85" />
<GeneralizedKirkwood type="171" charge="0.76984" shct="0.72" />
<GeneralizedKirkwood type="172" charge="-0.74313" shct="0.85" />
<GeneralizedKirkwood type="173" charge="-0.28938" shct="0.79" />
<GeneralizedKirkwood type="174" charge="0.14092" shct="0.85" />
<GeneralizedKirkwood type="175" charge="-0.14215" shct="0.72" />
<GeneralizedKirkwood type="176" charge="0.08383" shct="0.85" />
<GeneralizedKirkwood type="177" charge="-0.22038" shct="0.72" />
<GeneralizedKirkwood type="178" charge="0.07884" shct="0.85" />
<GeneralizedKirkwood type="179" charge="0.14780" shct="0.96" />
<GeneralizedKirkwood type="180" charge="-0.21776" shct="0.72" />
<GeneralizedKirkwood type="181" charge="0.05672" shct="0.85" />
<GeneralizedKirkwood type="182" charge="-0.08975" shct="0.72" />
<GeneralizedKirkwood type="183" charge="0.08202" shct="0.85" />
<GeneralizedKirkwood type="184" charge="-0.21565" shct="0.72" />
<GeneralizedKirkwood type="185" charge="0.08265" shct="0.85" />
<GeneralizedKirkwood type="186" charge="-0.02245" shct="0.72" />
<GeneralizedKirkwood type="187" charge="0.07982" shct="0.85" />
<GeneralizedKirkwood type="188" charge="-0.01637" shct="0.72" />
<GeneralizedKirkwood type="189" charge="0.09822" shct="0.85" />
<GeneralizedKirkwood type="190" charge="0.10000" shct="0.79" />
<GeneralizedKirkwood type="191" charge="0.20727" shct="0.85" />
<GeneralizedKirkwood type="192" charge="-0.14610" shct="0.72" />
<GeneralizedKirkwood type="193" charge="0.06260" shct="0.85" />
<GeneralizedKirkwood type="194" charge="-0.13934" shct="0.72" />
<GeneralizedKirkwood type="195" charge="0.07212" shct="0.85" />
<GeneralizedKirkwood type="196" charge="-0.12642" shct="0.72" />
<GeneralizedKirkwood type="197" charge="0.06261" shct="0.85" />
<GeneralizedKirkwood type="198" charge="0.04761" shct="0.72" />
<GeneralizedKirkwood type="199" charge="0.02822" shct="0.85" />
<GeneralizedKirkwood type="200" charge="-0.20360" shct="0.79" />
<GeneralizedKirkwood type="201" charge="0.08988" shct="0.85" />
<GeneralizedKirkwood type="202" charge="-0.09097" shct="0.72" />
<GeneralizedKirkwood type="203" charge="0.07770" shct="0.85" />
<GeneralizedKirkwood type="204" charge="-0.21722" shct="0.72" />
<GeneralizedKirkwood type="205" charge="0.08258" shct="0.85" />
<GeneralizedKirkwood type="206" charge="-0.01121" shct="0.72" />
<GeneralizedKirkwood type="207" charge="0.07564" shct="0.85" />
<GeneralizedKirkwood type="208" charge="-0.27936" shct="0.79" />
<GeneralizedKirkwood type="209" charge="0.15532" shct="0.85" />
<GeneralizedKirkwood type="210" charge="0.98761" shct="0.72" />
<GeneralizedKirkwood type="211" charge="-0.29224" shct="0.79" />
<GeneralizedKirkwood type="212" charge="0.15787" shct="0.85" />
<GeneralizedKirkwood type="213" charge="-0.08587" shct="0.72" />
<GeneralizedKirkwood type="214" charge="0.08588" shct="0.85" />
<GeneralizedKirkwood type="215" charge="-0.01858" shct="0.72" />
<GeneralizedKirkwood type="216" charge="0.08368" shct="0.85" />
<GeneralizedKirkwood type="217" charge="-0.01249" shct="0.72" />
<GeneralizedKirkwood type="218" charge="0.10208" shct="0.85" />
<GeneralizedKirkwood type="219" charge="0.10000" shct="0.79" />
<GeneralizedKirkwood type="220" charge="0.20727" shct="0.85" />
<GeneralizedKirkwood type="221" charge="-0.19058" shct="0.72" />
<GeneralizedKirkwood type="222" charge="0.07778" shct="0.85" />
<GeneralizedKirkwood type="223" charge="0.68484" shct="0.72" />
<GeneralizedKirkwood type="224" charge="-0.72760" shct="0.85" />
<GeneralizedKirkwood type="225" charge="-0.30948" shct="0.79" />
<GeneralizedKirkwood type="226" charge="0.15474" shct="0.85" />
<GeneralizedKirkwood type="227" charge="-0.26804" shct="0.79" />
<GeneralizedKirkwood type="228" charge="0.11919" shct="0.85" />
<GeneralizedKirkwood type="229" charge="-0.00970" shct="0.72" />
<GeneralizedKirkwood type="230" charge="0.05285" shct="0.85" />
<GeneralizedKirkwood type="231" charge="0.07891" shct="0.79" />
<GeneralizedKirkwood type="231" charge="0.11164" shct="0.79" />
<GeneralizedKirkwood type="231" charge="0.11164" shct="0.79" />
<GeneralizedKirkwood type="232" charge="0.26670" shct="0.85" />
<GeneralizedKirkwood type="232" charge="0.21240" shct="0.85" />
<GeneralizedKirkwood type="232" charge="0.21240" shct="0.85" />
<GeneralizedKirkwood type="233" charge="1.02670" shct="0.72" />
<GeneralizedKirkwood type="234" charge="-0.88956" shct="0.85" />
<GeneralizedKirkwood type="235" charge="0.92336" shct="0.72" />
<GeneralizedKirkwood type="235" charge="0.83309" shct="0.72" />
<GeneralizedKirkwood type="235" charge="0.83309" shct="0.72" />
<GeneralizedKirkwood type="236" charge="-0.58827" shct="0.85" />
<GeneralizedKirkwood type="236" charge="-0.61662" shct="0.85" />
<GeneralizedKirkwood type="236" charge="-0.61662" shct="0.85" />
<GeneralizedKirkwood type="237" charge="-0.46459" shct="0.85" />
<GeneralizedKirkwood type="238" charge="0.24812" shct="0.85" />
<GeneralizedKirkwood type="239" charge="0.07219" shct="0.79" />
<GeneralizedKirkwood type="240" charge="0.23262" shct="0.85" />
<GeneralizedKirkwood type="241" charge="-0.16428" shct="0.72" />
<GeneralizedKirkwood type="242" charge="0.94625" shct="0.72" />
<GeneralizedKirkwood type="243" charge="-0.74794" shct="0.85" />
<GeneralizedKirkwood type="244" charge="0.12611" shct="0.85" />
<GeneralizedKirkwood type="245" charge="-0.04567" shct="0.72" />
<GeneralizedKirkwood type="246" charge="0.10559" shct="0.85" />
<GeneralizedKirkwood type="247" charge="-0.51966" shct="0.85" />
<GeneralizedKirkwood type="248" charge="0.25983" shct="0.85" />
<GeneralizedKirkwood type="249" charge="1.00000" shct="0.8" />
<GeneralizedKirkwood type="250" charge="1.00000" shct="0.8" />
<GeneralizedKirkwood type="251" charge="1.00000" shct="0.8" />
<GeneralizedKirkwood type="252" charge="1.00000" shct="0.8" />
<GeneralizedKirkwood type="253" charge="1.00000" shct="0.8" />
<GeneralizedKirkwood type="254" charge="2.00000" shct="0.8" />
<GeneralizedKirkwood type="255" charge="2.00000" shct="0.8" />
<GeneralizedKirkwood type="256" charge="2.00000" shct="0.8" />
<GeneralizedKirkwood type="257" charge="2.00000" shct="0.8" />
<GeneralizedKirkwood type="258" charge="-1.00000" shct="0.8" />
</AmoebaGeneralizedKirkwoodForce>
<AmoebaWcaDispersionForce epso="0.46024" epsh="0.056484" rmino="0.17025" rminh="0.13275" awater="33.428" slevy="1.0" dispoff="0.026" shctd="0.81" >
<WcaDispersion class="1" radius="0.1855" epsilon="0.46024" />
<WcaDispersion class="2" radius="0.191" epsilon="0.422584" />
<WcaDispersion class="3" radius="0.191" epsilon="0.443504" />
<WcaDispersion class="4" radius="0.1295" epsilon="0.092048" />
<WcaDispersion class="5" radius="0.165" epsilon="0.468608" />
<WcaDispersion class="6" radius="0.147" epsilon="0.108784" />
<WcaDispersion class="7" radius="0.1825" epsilon="0.422584" />
<WcaDispersion class="8" radius="0.191" epsilon="0.422584" />
<WcaDispersion class="9" radius="0.149" epsilon="0.100416" />
<WcaDispersion class="10" radius="0.17025" epsilon="0.46024" />
<WcaDispersion class="11" radius="0.13275" epsilon="0.056484" />
<WcaDispersion class="12" radius="0.20025" epsilon="1.48532" />
<WcaDispersion class="14" radius="0.21" epsilon="1.48532" />
<WcaDispersion class="13" radius="0.15" epsilon="0.110876" />
<WcaDispersion class="15" radius="0.1855" epsilon="0.46024" />
<WcaDispersion class="16" radius="0.191" epsilon="0.422584" />
<WcaDispersion class="17" radius="0.19" epsilon="0.372376" />
<WcaDispersion class="18" radius="0.149" epsilon="0.108784" />
<WcaDispersion class="19" radius="0.17025" epsilon="0.46024" />
<WcaDispersion class="20" radius="0.13275" epsilon="0.056484" />
<WcaDispersion class="22" radius="0.19" epsilon="0.422584" />
<WcaDispersion class="23" radius="0.149" epsilon="0.108784" />
<WcaDispersion class="24" radius="0.1855" epsilon="0.46024" />
<WcaDispersion class="25" radius="0.1295" epsilon="0.092048" />
<WcaDispersion class="26" radius="0.19" epsilon="0.422584" />
<WcaDispersion class="27" radius="0.149" epsilon="0.108784" />
<WcaDispersion class="28" radius="0.19" epsilon="0.422584" />
<WcaDispersion class="29" radius="0.1855" epsilon="0.46024" />
<WcaDispersion class="30" radius="0.191" epsilon="0.443504" />
<WcaDispersion class="31" radius="0.185" epsilon="0.539736" />
<WcaDispersion class="32" radius="0.191" epsilon="0.443504" />
<WcaDispersion class="33" radius="0.165" epsilon="0.468608" />
<WcaDispersion class="34" radius="0.17025" epsilon="0.46024" />
<WcaDispersion class="35" radius="0.13275" epsilon="0.06276" />
<WcaDispersion class="36" radius="0.191" epsilon="0.422584" />
<WcaDispersion class="37" radius="0.1905" epsilon="0.43932" />
<WcaDispersion class="38" radius="0.124" epsilon="0.054392" />
<WcaDispersion class="39" radius="0.1825" epsilon="0.422584" />
<WcaDispersion class="40" radius="0.191" epsilon="0.422584" />
<WcaDispersion class="41" radius="0.188" epsilon="0.43932" />
<WcaDispersion class="42" radius="0.135" epsilon="0.08368" />
<WcaDispersion class="43" radius="0.17025" epsilon="0.46024" />
<WcaDispersion class="44" radius="0.13275" epsilon="0.056484" />
<WcaDispersion class="45" radius="0.119" epsilon="0.33472" />
<WcaDispersion class="46" radius="0.151" epsilon="1.08784" />
<WcaDispersion class="47" radius="0.1855" epsilon="1.4644" />
<WcaDispersion class="48" radius="0.207" epsilon="1.84096" />
<WcaDispersion class="49" radius="0.2185" epsilon="2.21752" />
<WcaDispersion class="50" radius="0.094" epsilon="0.380744" />
<WcaDispersion class="51" radius="0.147" epsilon="1.2552" />
<WcaDispersion class="52" radius="0.1815" epsilon="1.4644" />
<WcaDispersion class="53" radius="0.134" epsilon="0.928848" />
<WcaDispersion class="54" radius="0.2065" epsilon="1.42256" />
</AmoebaWcaDispersionForce>
</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="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.
......
......@@ -40,15 +40,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#=============================================================================================
import os
import os.path
import re
import math
from math import ceil, cos, sin, asin, sqrt, pi
import warnings
try:
import numpy
import numpy as np
except:
pass
np = None
import simtk.unit as units
import simtk.openmm
......@@ -74,6 +73,9 @@ POINTER_LABELS = """
# Pointer labels (above) as a list, not string.
POINTER_LABEL_LIST = POINTER_LABELS.replace(',', '').split()
VELSCALE = 20.455 # velocity conversion factor to angstroms/picosecond
TINY = 1.0e-8
class PrmtopLoader(object):
"""Parsed AMBER prmtop file.
......@@ -83,14 +85,14 @@ class PrmtopLoader(object):
Parse a prmtop file of alanine dipeptide in implicit solvent.
>>> import os, os.path
>>> import os
>>> directory = os.path.join(os.getenv('YANK_INSTALL_DIR'), 'test', 'systems', 'alanine-dipeptide-gbsa')
>>> prmtop_filename = os.path.join(directory, 'alanine-dipeptide.prmtop')
>>> prmtop = PrmtopLoader(prmtop_filename)
Parse a prmtop file of alanine dipeptide in explicit solvent.
>>> import os, os.path
>>> import os
>>> directory = os.path.join(os.getenv('YANK_INSTALL_DIR'), 'test', 'systems', 'alanine-dipeptide-explicit')
>>> prmtop_filename = os.path.join(directory, 'alanine-dipeptide.prmtop')
>>> prmtop = PrmtopLoader(prmtop_filename)
......@@ -437,7 +439,7 @@ class PrmtopLoader(object):
(rVdwI, epsilonI) = nonbondTerms[iAtom]
(rVdwL, epsilonL) = nonbondTerms[lAtom]
rMin = (rVdwI+rVdwL)
epsilon = math.sqrt(epsilonI*epsilonL)
epsilon = sqrt(epsilonI*epsilonL)
try:
iScee = float(self._raw_data["SCEE_SCALE_FACTOR"][iidx])
except KeyError:
......@@ -708,7 +710,7 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
l2 = bond[1]
# Compute the distance between atoms and add a constraint
length = math.sqrt(l1*l1 + l2*l2 - 2*l1*l2*math.cos(aMin))
length = sqrt(l1*l1 + l2*l2 - 2*l1*l2*cos(aMin))
system.addConstraint(iAtom, kAtom, length)
if flexibleConstraints or not constrained:
force.addAngle(iAtom, jAtom, kAtom, aMin, 2*k)
......@@ -739,10 +741,17 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
# System is periodic.
# Set periodic box vectors for periodic system
(boxBeta, boxX, boxY, boxZ) = prmtop.getBoxBetaAndDimensions()
d0 = units.Quantity(0.0, units.angstroms)
xVec = units.Quantity((boxX, d0, d0))
yVec = units.Quantity((d0, boxY, d0))
zVec = units.Quantity((d0, d0, boxZ))
boxBeta = boxBeta.value_in_unit(units.degrees)
boxX = boxX.value_in_unit(units.angstroms)
boxY = boxY.value_in_unit(units.angstroms)
boxZ = boxZ.value_in_unit(units.angstroms)
tmp = [[0.0, 0.0, 0.0],[0.0, 0.0, 0.0],[0.0, 0.0, 0.0]]
_box_vectors_from_lengths_angles([boxX, boxY, boxZ],
[boxBeta, boxBeta, boxBeta],
tmp)
xVec = units.Quantity(tmp[0], units.angstroms)
yVec = units.Quantity(tmp[1], units.angstroms)
zVec = units.Quantity(tmp[2], units.angstroms)
system.setDefaultPeriodicBoxVectors(xVec, yVec, zVec)
# Set cutoff.
......@@ -848,13 +857,13 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
if len(waterO[res]) == 1 and len(waterH[res]) == 2:
if len(waterEP[res]) == 1:
# Four point water
weightH = distOE[res]/math.sqrt(distOH[res]**2-(0.5*distHH[res])**2)
weightH = distOE[res]/sqrt(distOH[res]**2-(0.5*distHH[res])**2)
system.setVirtualSite(waterEP[res][0], mm.ThreeParticleAverageSite(waterO[res][0], waterH[res][0], waterH[res][1], 1-weightH, weightH/2, weightH/2))
elif len(waterEP[res]) == 2:
# Five point water
weightH = cosOOP*distOE[res]/math.sqrt(distOH[res]**2-(0.5*distHH[res])**2)
angleHOH = 2*math.asin(0.5*distHH[res]/distOH[res])
lenCross = (distOH[res]**2)*math.sin(angleHOH)
weightH = cosOOP*distOE[res]/sqrt(distOH[res]**2-(0.5*distHH[res])**2)
angleHOH = 2*asin(0.5*distHH[res]/distOH[res])
lenCross = (distOH[res]**2)*sin(angleHOH)
weightCross = sinOOP*distOE[res]/lenCross
system.setVirtualSite(waterEP[res][0], mm.OutOfPlaneSite(waterO[res][0], waterH[res][0], waterH[res][1], weightH/2, weightH/2, weightCross))
system.setVirtualSite(waterEP[res][1], mm.OutOfPlaneSite(waterO[res][0], waterH[res][0], waterH[res][1], weightH/2, weightH/2, -weightCross))
......@@ -917,134 +926,395 @@ def readAmberSystem(prmtop_filename=None, prmtop_loader=None, shake=None, gbmode
return system
#=============================================================================================
# AMBER INPCRD loader
# AMBER INPCRD loader classes
#=============================================================================================
def readAmberCoordinates(filename, read_box=False, read_velocities=False, verbose=False, asNumpy=False):
class AmberAsciiRestart(object):
"""
Class responsible for parsing Amber coordinates in the ASCII format.
Automatically detects the presence of velocities or box parameters in the
file.
Parameters
----------
filename : str
Name of the restart file
asNumpy : bool (False)
Load the coordinates, velocities, and box as numpy ndarray objects
Attributes
----------
coordinates : natom x 3 array, Quantity
Particle positions with units of length
velocities : natom x 3 array, Quantity
Particle velocities with units of length per time (None if velocities
are not present in the inpcrd file)
boxVectors : 3 x 3 array, Quantity
Box vectors with units of length (None if no box is present in the
inpcrd file)
time : float, Quantity
Simulation time (None if not present) with units of time
title : str
Title of the inpcrd file
filename : str
Name of the file we are parsing
natom : int
Number of atoms in the inpcrd file
Raises
------
`IOError' if the file does not exist
`TypeError' if the format of the file is not recognized
`ValueError' if not all fields are numbers (for example, if a field is
filled with ****'s)
`IndexError' if the file is empty
`ImportError' if numpy is requested but could not be imported
Example
-------
>>> f = AmberAsciiRestart('alanine-dipeptide.inpcrd')
>>> coordinates = f.coordinates
"""
def __init__(self, filename, asNumpy=False):
# Make sure numpy is available if requested
if asNumpy and np is None:
raise ImportError('asNumpy=True: numpy is not available')
self._asNumpy = asNumpy
self.filename = filename
with open(filename, 'r') as f:
lines = f.readlines()
# Get rid of trailing blank lines
while lines and not lines[-1].strip():
lines.pop()
self._parse(lines)
def __str__(self):
return self.filename
def _parse(self, lines):
""" Parses through the inpcrd file """
global VELSCALE
self.title = lines[0].strip()
self.time = None
try:
words = lines[1].split()
self.natom = int(words[0])
except (IndexError, ValueError):
raise TypeError('Unrecognized file type [%s]' % self.filename)
if len(words) >= 2:
self.time = float(words[1]) * units.picoseconds
if len(lines) == int(ceil(self.natom / 2.0) + 2):
hasbox = hasvels = False
self.boxVectors = self.velocities = None
elif self.natom in (1, 2) and len(lines) == 4:
# This is the _only_ case where line counting does not work -- there
# is either 1 or 2 atoms and there are 4 lines. The 1st 3 lines are
# the title, natom/time, and coordinates. The 4th are almost always
# velocities since Amber does not make it easy to make a periodic
# system with only 2 atoms. If natom is 1, the 4th line is either a
# velocity (3 #'s) or a box (6 #'s). If natom is 2, it is a bit
# ambiguous. However, velocities (which are scaled by 20.445) have a
# ~0% chance of being 60+, so we can pretty easily tell if the last
# line has box dimensions and angles or velocities. I cannot
# envision a _plausible_ scenario where the detection here will fail
# in real life.
line = lines[3]
if self.natom == 1:
tmp = [line[i:i+12] for i in range(0, 72, 12) if line[i:i+12]]
if len(tmp) == 3:
hasvels = True
hasbox = False
self.boxVectors = False
elif len(tmp) == 6:
hasbox = True
hasvels = False
self.velocities = None
else:
raise TypeError('Unrecognized line in restart file %s' %
self.filename)
else:
# Ambiguous case
tmp = [float(line[i:i+12]) >= 60.0 for i in range(0, 72, 12)]
if any(tmp):
hasbox = True
hasvels = False
self.velocities = False
else:
hasvels = True
hasbox = False
self.boxVectors = False
elif len(lines) == int(ceil(self.natom / 2.0) + 3):
hasbox = True
hasvels = False
self.velocities = None
elif len(lines) == int(2 * ceil(self.natom / 2.0) + 2):
hasbox = False
self.boxVectors = None
hasvels = True
elif len(lines) == int(2 * ceil(self.natom / 2.0) + 3):
hasbox = hasvels = True
else:
raise TypeError('Badly formatted restart file. Has %d lines '
'for %d atoms.' % (len(self.lines), self.natom))
if self._asNumpy:
coordinates = np.zeros((self.natom, 3), np.float32)
if hasvels:
velocities = np.zeros((self.natom, 3), np.float32)
if hasbox:
boxVectors = np.zeros((3, 3), np.float32)
else:
coordinates = [[0.0, 0.0, 0.0] for i in range(self.natom)]
if hasvels:
velocities = [[0.0, 0.0, 0.0] for i in range(self.natom)]
if hasbox:
boxVectors = [[0.0, 0.0, 0.0] for i in range(3)]
# Now it's time to parse. Coordinates first
startline = 2
endline = startline + int(ceil(self.natom / 2.0))
idx = 0
for i in range(startline, endline):
line = lines[i]
coordinates[idx][0] = float(line[ 0:12])
coordinates[idx][1] = float(line[12:24])
coordinates[idx][2] = float(line[24:36])
idx += 1
if idx < self.natom:
coordinates[idx][0] = float(line[36:48])
coordinates[idx][1] = float(line[48:60])
coordinates[idx][2] = float(line[60:72])
idx += 1
self.coordinates = units.Quantity(coordinates, units.angstroms)
startline = endline
# Now it's time to parse velocities if we have them
if hasvels:
endline = startline + int(ceil(self.natom / 2.0))
idx = 0
for i in range(startline, endline):
line = lines[i]
velocities[idx][0] = float(line[ 0:12]) * VELSCALE
velocities[idx][1] = float(line[12:24]) * VELSCALE
velocities[idx][2] = float(line[24:36]) * VELSCALE
idx += 1
if idx < self.natom:
velocities[idx][0] = float(line[36:48]) * VELSCALE
velocities[idx][1] = float(line[48:60]) * VELSCALE
velocities[idx][2] = float(line[60:72]) * VELSCALE
idx += 1
startline = endline
self.velocities = units.Quantity(velocities,
units.angstroms/units.picoseconds)
if hasbox:
line = lines[startline]
try:
tmp = [float(line[i:i+12]) for i in range(0, 72, 12)]
except (IndexError, ValueError):
raise ValueError('Could not parse box line in %s' %
self.filename)
lengths = tmp[:3]
angles = tmp[3:]
_box_vectors_from_lengths_angles(lengths, angles, boxVectors)
self.boxVectors = units.Quantity(boxVectors, units.angstroms)
class AmberNetcdfRestart(object):
"""
Amber restart/inpcrd file in the NetCDF format (full double-precision
coordinates, velocities, and unit cell parameters). Reads NetCDF restarts
written by LEaP and pmemd/sander. Requires scipy to parse NetCDF files.
Parameters
----------
filename : str
Name of the restart file
asNumpy : bool (False)
Load the coordinates, velocities, and box as numpy ndarray objects
Attributes
----------
coordinates : natom x 3 array, Quantity
Particle positions with units of length
velocities : natom x 3 array, Quantity
Particle velocities with units of length per time (None if velocities
are not present in the inpcrd file)
boxVectors : 3 x 3 array, Quantity
Box vectors with units of length (None if no box is present in the
inpcrd file)
time : float, Quantity
Simulation time (None if not present) with units of time
title : str
Title of the inpcrd file
filename : str
Name of the file we are parsing
natom : int
Number of atoms in the inpcrd file
Raises
------
`IOError' if the file does not exist
`TypeError' if the file is not a NetCDF v3 file
`ImportError' if scipy is not available
Example
-------
>>> f = AmberNetcdfRestart('alanine-dipeptide.ncrst')
>>> coordinates = f.coordinates
"""
def __init__(self, filename, asNumpy=False):
try:
from scipy.io.netcdf import NetCDFFile
except ImportError:
raise ImportError('scipy is necessary to parse NetCDF restarts')
self.filename = filename
self.velocities = self.boxVectors = self.time = None
# Extract the information from the NetCDF file. We need to make copies
# here because the NetCDF variables are mem-mapped, but is only mapped
# to valid memory while the file handle is open. Since the context
# manager GCs the ncfile handle, the memory for the original variables
# is no longer valid. So copy those arrays while the handle is still
# open. This is unnecessary in scipy v.0.12 and lower because NetCDFFile
# accidentally leaks the file handle, but that was 'fixed' in 0.13. This
# fix taken from MDTraj
ncfile = NetCDFFile(filename, 'r')
try:
self.natom = ncfile.dimensions['atom']
self.coordinates = np.array(ncfile.variables['coordinates'][:])
if 'velocities' in ncfile.variables:
vels = ncfile.variables['velocities']
self.velocities = np.array(vels[:]) * vels.scale_factor
if ('cell_lengths' in ncfile.variables and
'cell_angles' in ncfile.variables):
self.boxVectors = np.zeros((3,3), np.float32)
_box_vectors_from_lengths_angles(
ncfile.variables['cell_lengths'][:],
ncfile.variables['cell_angles'][:],
self.boxVectors,
)
if 'time' in ncfile.variables:
self.time = ncfile.variables['time'].getValue()
finally:
ncfile.close()
# They are already numpy -- convert to list if we don't want numpy
if not asNumpy:
self.coordinates = self.coordinates.tolist()
if self.velocities is not None:
self.velocities = self.velocities.tolist()
if self.boxVectors is not None:
self.boxVectors = self.boxVectors.tolist()
# Now add the units
self.coordinates = units.Quantity(self.coordinates, units.angstroms)
if self.velocities is not None:
self.velocities = units.Quantity(self.velocities,
units.angstroms/units.picoseconds)
if self.boxVectors is not None:
self.boxVectors = units.Quantity(self.boxVectors, units.angstroms)
self.time = units.Quantity(self.time, units.picosecond)
def _box_vectors_from_lengths_angles(lengths, angles, boxVectors):
"""
Converts lengths and angles into a series of box vectors and modifies
boxVectors in-place (it must be a mutable sequence)
Parameters
----------
lengths : 3-element array of floats
Lengths of the 3 periodic box vectors
angles : 3-element array of floats
Angles (in degrees) between the 3 periodic box vectors
boxVectors : mutable 3x3 sequence
"""
alpha = angles[0] * pi / 180.0
beta = angles[1] * pi / 180.0
gamma = angles[2] * pi / 180.0
boxVectors[0][0] = lengths[0]
boxVectors[1][0] = lengths[1] * cos(gamma)
boxVectors[1][1] = lengths[1] * sin(gamma)
boxVectors[2][0] = cx = lengths[2] * cos(beta)
boxVectors[2][1] = cy = lengths[2] * (cos(alpha) - cos(beta) * cos(gamma))
boxVectors[2][2] = sqrt(lengths[2]*lengths[2] - cx*cx - cy*cy)
boxVectors[0][1] = boxVectors[0][2] = boxVectors[1][2] = 0.0
# Now make sure any vector close to zero is zero exactly
for i in range(3):
for j in range(3):
if abs(boxVectors[i][j]) < TINY:
boxVectors[i][j] = 0.0
def readAmberCoordinates(filename, asNumpy=False):
"""
Read atomic coordinates (and optionally, box vectors) from Amber formatted coordinate file.
ARGUMENTS
filename (string) - name of Amber coordinates file to be read in
system (simtk.openmm.System) - System object for which coordinates are to be read
OPTIONAL ARGUMENTS
verbose (boolean) - if True, will print out verbose information about the file being read
asNumpy (boolean) - if True, results will be returned as Numpy arrays instead of lists of Vec3s
RETURNS
coordinates, velocities, boxVectors
The velocities and boxVectors will be None if they are not found in the
restart file
EXAMPLES
Read coordinates in vacuum.
>>> directory = os.path.join(os.getenv('YANK_INSTALL_DIR'), 'test', 'systems', 'alanine-dipeptide-gbsa')
>>> crd_filename = os.path.join(directory, 'alanine-dipeptide.inpcrd')
>>> coordinates = readAmberCoordinates(crd_filename)
>>> coordinates, velocities, box_vectors = readAmberCoordinates(crd_filename)
Read coordinates in solvent.
>>> directory = os.path.join(os.getenv('YANK_INSTALL_DIR'), 'test', 'systems', 'alanine-dipeptide-explicit')
>>> crd_filename = os.path.join(directory, 'alanine-dipeptide.inpcrd')
>>> [coordinates, box_vectors] = readAmberCoordinates(crd_filename, read_box=True)
>>> coordinates, velocities, box_vectors = readAmberCoordinates(crd_filename)
"""
# Open coordinate file for reading.
infile = open(filename, 'r')
# Read title
title = infile.readline().strip()
if verbose: print "title: '%s'" % title
# Read number of atoms
natoms = int(infile.readline().split()[0])
if verbose: print "%d atoms" % natoms
# Allocate storage for coordinates
coordinates = []
# Read coordinates
mm = simtk.openmm
natoms_read = 0
while (natoms_read < natoms):
line = infile.readline()
if len(line) == 0:
raise ValueError("Unexpected end of file while reading coordinates")
line = line.strip()
elements = line.split()
while (len(elements) > 0):
coordinates.append(mm.Vec3(float(elements.pop(0)), float(elements.pop(0)), float(elements.pop(0))))
natoms_read += 1
if asNumpy:
newcoords = numpy.zeros([natoms,3], numpy.float32)
for i in range(len(coordinates)):
for j in range(3):
newcoords[i,j] = coordinates[i][j]
coordinates = newcoords
# Assign units.
coordinates = units.Quantity(coordinates, units.angstroms)
# Read velocities if requested.
velocities = None
if (read_velocities):
# Read velocities
velocities = []
natoms_read = 0
while (natoms_read < natoms):
line = infile.readline()
if len(line) == 0:
raise ValueError("Unexpected end of file while reading velocities")
line = line.strip()
elements = line.split()
while (len(elements) > 0):
velocities.append(20.455*mm.Vec3(float(elements.pop(0)), float(elements.pop(0)), float(elements.pop(0))))
natoms_read += 1
if asNumpy:
newvel = numpy.zeros([natoms,3], numpy.float32)
for i in range(len(velocities)):
for j in range(3):
newvel[i,j] = velocities[i][j]
velocities = newvel
# Assign units.
velocities = units.Quantity(velocities, units.angstroms/units.picoseconds)
# Read box size if present
box_vectors = None
if (read_box):
line = infile.readline()
if len(line) == 0:
raise ValueError("Unexpected end of file while reading box vectors")
line = line.strip()
elements = line.split()
nelements = len(elements)
box_dimensions = [0.0]*nelements
for i in range(nelements):
box_dimensions[i] = float(elements[i])
# TODO: Deal with non-standard box sizes.
if nelements == 6:
if asNumpy:
a = units.Quantity(numpy.array([box_dimensions[0], 0.0, 0.0]), units.angstroms)
b = units.Quantity(numpy.array([0.0, box_dimensions[1], 0.0]), units.angstroms)
c = units.Quantity(numpy.array([0.0, 0.0, box_dimensions[2]]), units.angstroms)
else:
a = units.Quantity(mm.Vec3(box_dimensions[0], 0.0, 0.0), units.angstroms)
b = units.Quantity(mm.Vec3(0.0, box_dimensions[1], 0.0), units.angstroms)
c = units.Quantity(mm.Vec3(0.0, 0.0, box_dimensions[2]), units.angstroms)
box_vectors = [a,b,c]
else:
raise Exception("Don't know what to do with box vectors: %s" % line)
# Close file
infile.close()
if box_vectors and velocities:
return (coordinates, box_vectors, velocities)
if box_vectors:
return (coordinates, box_vectors)
if velocities:
return (coordinates, velocities)
return coordinates
try:
crdfile = AmberNetcdfRestart(filename)
except ImportError:
# See if it's an ASCII file. If so, no need to complain
try:
crdfile = AmberAsciiRestart(filename)
except TypeError:
raise TypeError('Problem parsing %s as an ASCII Amber restart file '
'and scipy could not be imported to try reading as '
'a NetCDF restart file.' % filename)
except (IndexError, ValueError):
raise TypeError('Could not parse Amber ASCII restart file %s' %
filename)
except ImportError:
raise ImportError('Could not find numpy; cannot use asNumpy=True')
except TypeError:
# We had scipy, but this is not a NetCDF v3 file. Try as ASCII now
try:
crdfile = AmberAsciiRestart(filename)
except TypeError:
raise TypeError('Problem parsing %s as an ASCII Amber restart file'
% filename)
except (IndexError, ValueError):
raise TypeError('Could not parse Amber ASCII restart file %s' %
filename)
# Import error cannot happen, since we had scipy which has numpy as a
# prereq. Do not catch that exception (only catch what you intend to
# catch...)
# We got here... one of the file types worked. Return the coordinates,
# velocities, and boxVectors
return crdfile.coordinates, crdfile.velocities, crdfile.boxVectors
#=============================================================================================
# MAIN AND TESTS
......
......@@ -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__)
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
......
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