Commit c7aa1d00 authored by kyleabeauchamp's avatar kyleabeauchamp
Browse files

Merge remote-tracking branch 'upstream/master' into vagrant

parents aea4e454 f7127d33
......@@ -61,7 +61,7 @@ void validateForce(System& system, vector<Vec3>& positions, double expectedEnerg
// Try moving each particle along each axis, and see if the energy changes by the correct amount.
double offset = 1e-3;
double offset = 1e-2;
for (int i = 0; i < system.getNumParticles(); i++)
for (int j = 0; j < 3; j++) {
vector<Vec3> offsetPos = positions;
......@@ -76,9 +76,9 @@ void validateForce(System& system, vector<Vec3>& positions, double expectedEnerg
}
void testSingleParticle() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
......@@ -92,9 +92,9 @@ void testSingleParticle() {
}
void testAnisotropicParticle() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double a1 = 0.8;
const double a2 = 1.1;
const double k1 = k/a1;
......@@ -124,9 +124,9 @@ double computeScreening(double r, double thole, double alpha1, double alpha2) {
}
void testThole() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double thole = 2.5;
System system;
system.addParticle(1.0);
......@@ -157,9 +157,9 @@ void testThole() {
}
void testChangingParameters() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
Platform& platform = Platform::getPlatformByName("CUDA");
// Create the system.
......@@ -184,9 +184,9 @@ void testChangingParameters() {
// Modify the parameters.
const double k2 = 2.2;
const double k2 = ONE_4PI_EPS0*2.2;
const double charge2 = 0.3;
const double alpha2 = charge2*charge2/k2;
const double alpha2 = ONE_4PI_EPS0*charge2*charge2/k2;
drude->setParticleParameters(0, 1, 0, -1, -1, -1, charge2, alpha2, 1, 1);
drude->updateParametersInContext(context);
state = context.getState(State::Energy);
......
......@@ -53,9 +53,9 @@ extern "C" OPENMM_EXPORT void registerDrudeCudaKernelFactories();
void testSinglePair() {
const double temperature = 300.0;
const double temperatureDrude = 10.0;
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double mass1 = 1.0;
const double mass2 = 0.1;
const double totalMass = mass1+mass2;
......@@ -132,7 +132,7 @@ void testWater() {
system.addConstraint(startIndex, startIndex+3, 0.09572);
system.addConstraint(startIndex+2, startIndex+3, 0.15139);
system.setVirtualSite(startIndex+4, new ThreeParticleAverageSite(startIndex, startIndex+2, startIndex+3, 0.786646558, 0.106676721, 0.106676721));
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, 1.71636*1.71636/(100000*4.184), 1, 1);
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184), 1, 1);
}
vector<Vec3> positions;
for (int i = 0; i < gridSize; i++)
......
......@@ -85,7 +85,7 @@ void testWater() {
system.addConstraint(startIndex, startIndex+3, 0.09572);
system.addConstraint(startIndex+2, startIndex+3, 0.15139);
system.setVirtualSite(startIndex+4, new ThreeParticleAverageSite(startIndex, startIndex+2, startIndex+3, 0.786646558, 0.106676721, 0.106676721));
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, 1.71636*1.71636/(100000*4.184), 1, 1);
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184), 1, 1);
}
vector<Vec3> positions;
for (int i = 0; i < gridSize; i++)
......
......@@ -131,9 +131,9 @@ void OpenCLCalcDrudeForceKernel::initialize(const System& system, const DrudeFor
double a1 = (atoms[i][2] == -1 ? 1 : aniso12);
double a2 = (atoms[i][3] == -1 || atoms[i][4] == -1 ? 1 : aniso34);
double a3 = 3-a1-a2;
double k3 = charge*charge/(polarizability*a3);
double k1 = charge*charge/(polarizability*a1) - k3;
double k2 = charge*charge/(polarizability*a2) - k3;
double k3 = ONE_4PI_EPS0*charge*charge/(polarizability*a3);
double k1 = ONE_4PI_EPS0*charge*charge/(polarizability*a1) - k3;
double k2 = ONE_4PI_EPS0*charge*charge/(polarizability*a2) - k3;
if (atoms[i][2] == -1) {
atoms[i][2] = 0;
k1 = 0;
......@@ -202,9 +202,9 @@ void OpenCLCalcDrudeForceKernel::copyParametersToContext(ContextImpl& context, c
double a1 = (p2 == -1 ? 1 : aniso12);
double a2 = (p3 == -1 || p4 == -1 ? 1 : aniso34);
double a3 = 3-a1-a2;
double k3 = charge*charge/(polarizability*a3);
double k1 = charge*charge/(polarizability*a1) - k3;
double k2 = charge*charge/(polarizability*a2) - k3;
double k3 = ONE_4PI_EPS0*charge*charge/(polarizability*a3);
double k1 = ONE_4PI_EPS0*charge*charge/(polarizability*a1) - k3;
double k2 = ONE_4PI_EPS0*charge*charge/(polarizability*a2) - k3;
if (p2 == -1)
k1 = 0;
if (p3 == -1 || p4 == -1)
......
......@@ -13,7 +13,7 @@ real u = drudeParams.x*r;
real screening = 1-(1+0.5f*u)*EXP(-u);
real pairEnergy = drudeParams.y*screening*rInv;
energy += pairEnergy;
real4 f = delta*(pairEnergy*rInv*rInv);
real4 f = delta*(drudeParams.y*rInv*rInv)*(screening*rInv-0.5f*(1+u)*EXP(-u)*drudeParams.x);
force1 += f;
force3 -= f;
......@@ -26,7 +26,7 @@ u = drudeParams.x*r;
screening = 1-(1+0.5f*u)*EXP(-u);
pairEnergy = -drudeParams.y*screening*rInv;
energy += pairEnergy;
f = delta*(pairEnergy*rInv*rInv);
f = delta*(-drudeParams.y*rInv*rInv)*(screening*rInv-0.5f*(1+u)*EXP(-u)*drudeParams.x);
force1 += f;
force4 -= f;
......@@ -39,7 +39,7 @@ u = drudeParams.x*r;
screening = 1-(1+0.5f*u)*EXP(-u);
pairEnergy = -drudeParams.y*screening*rInv;
energy += pairEnergy;
f = delta*(pairEnergy*rInv*rInv);
f = delta*(-drudeParams.y*rInv*rInv)*(screening*rInv-0.5f*(1+u)*EXP(-u)*drudeParams.x);
force2 += f;
force3 -= f;
......@@ -52,6 +52,6 @@ u = drudeParams.x*r;
screening = 1-(1+0.5f*u)*EXP(-u);
pairEnergy = drudeParams.y*screening*rInv;
energy += pairEnergy;
f = delta*(pairEnergy*rInv*rInv);
f = delta*(drudeParams.y*rInv*rInv)*(screening*rInv-0.5f*(1+u)*EXP(-u)*drudeParams.x);
force2 += f;
force4 -= f;
......@@ -61,7 +61,7 @@ void validateForce(System& system, vector<Vec3>& positions, double expectedEnerg
// Try moving each particle along each axis, and see if the energy changes by the correct amount.
double offset = 1e-3;
double offset = 1e-2;
for (int i = 0; i < system.getNumParticles(); i++)
for (int j = 0; j < 3; j++) {
vector<Vec3> offsetPos = positions;
......@@ -76,9 +76,9 @@ void validateForce(System& system, vector<Vec3>& positions, double expectedEnerg
}
void testSingleParticle() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
......@@ -92,9 +92,9 @@ void testSingleParticle() {
}
void testAnisotropicParticle() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double a1 = 0.8;
const double a2 = 1.1;
const double k1 = k/a1;
......@@ -124,9 +124,9 @@ double computeScreening(double r, double thole, double alpha1, double alpha2) {
}
void testThole() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double thole = 2.5;
System system;
system.addParticle(1.0);
......@@ -157,9 +157,9 @@ void testThole() {
}
void testChangingParameters() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
Platform& platform = Platform::getPlatformByName("OpenCL");
// Create the system.
......@@ -184,9 +184,9 @@ void testChangingParameters() {
// Modify the parameters.
const double k2 = 2.2;
const double k2 = ONE_4PI_EPS0*2.2;
const double charge2 = 0.3;
const double alpha2 = charge2*charge2/k2;
const double alpha2 = ONE_4PI_EPS0*charge2*charge2/k2;
drude->setParticleParameters(0, 1, 0, -1, -1, -1, charge2, alpha2, 1, 1);
drude->updateParametersInContext(context);
state = context.getState(State::Energy);
......
......@@ -53,9 +53,9 @@ extern "C" OPENMM_EXPORT void registerDrudeOpenCLKernelFactories();
void testSinglePair() {
const double temperature = 300.0;
const double temperatureDrude = 10.0;
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double mass1 = 1.0;
const double mass2 = 0.1;
const double totalMass = mass1+mass2;
......@@ -132,7 +132,7 @@ void testWater() {
system.addConstraint(startIndex, startIndex+3, 0.09572);
system.addConstraint(startIndex+2, startIndex+3, 0.15139);
system.setVirtualSite(startIndex+4, new ThreeParticleAverageSite(startIndex, startIndex+2, startIndex+3, 0.786646558, 0.106676721, 0.106676721));
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, 1.71636*1.71636/(100000*4.184), 1, 1);
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184), 1, 1);
}
vector<Vec3> positions;
for (int i = 0; i < gridSize; i++)
......
......@@ -85,7 +85,7 @@ void testWater() {
system.addConstraint(startIndex, startIndex+3, 0.09572);
system.addConstraint(startIndex+2, startIndex+3, 0.15139);
system.setVirtualSite(startIndex+4, new ThreeParticleAverageSite(startIndex, startIndex+2, startIndex+3, 0.786646558, 0.106676721, 0.106676721));
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, 1.71636*1.71636/(100000*4.184), 1, 1);
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184), 1, 1);
}
vector<Vec3> positions;
for (int i = 0; i < gridSize; i++)
......
......@@ -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) 2011-2013 Stanford University and the Authors. *
* Portions copyright (c) 2011-2014 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -136,9 +136,9 @@ double ReferenceCalcDrudeForceKernel::execute(ContextImpl& context, bool include
RealOpenMM a1 = (p2 == -1 ? 1 : aniso12[i]);
RealOpenMM a2 = (p3 == -1 || p4 == -1 ? 1 : aniso34[i]);
RealOpenMM a3 = 3-a1-a2;
RealOpenMM k3 = charge[i]*charge[i]/(polarizability[i]*a3);
RealOpenMM k1 = charge[i]*charge[i]/(polarizability[i]*a1) - k3;
RealOpenMM k2 = charge[i]*charge[i]/(polarizability[i]*a2) - k3;
RealOpenMM k3 = ONE_4PI_EPS0*charge[i]*charge[i]/(polarizability[i]*a3);
RealOpenMM k1 = ONE_4PI_EPS0*charge[i]*charge[i]/(polarizability[i]*a1) - k3;
RealOpenMM k2 = ONE_4PI_EPS0*charge[i]*charge[i]/(polarizability[i]*a2) - k3;
// Compute the isotropic force.
......@@ -188,6 +188,7 @@ double ReferenceCalcDrudeForceKernel::execute(ContextImpl& context, bool include
int dipole2 = pair2[i];
int dipole1Particles[] = {particle[dipole1], particle1[dipole1]};
int dipole2Particles[] = {particle[dipole2], particle1[dipole2]};
RealOpenMM uscale = pairThole[i]/pow(polarizability[dipole1]*polarizability[dipole2], 1.0/6.0);
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++) {
int p1 = dipole1Particles[j];
......@@ -195,10 +196,10 @@ double ReferenceCalcDrudeForceKernel::execute(ContextImpl& context, bool include
RealOpenMM chargeProduct = charge[dipole1]*charge[dipole2]*(j == k ? 1 : -1);
RealVec delta = pos[p1]-pos[p2];
RealOpenMM r = sqrt(delta.dot(delta));
RealOpenMM u = r*pairThole[i]/pow(polarizability[dipole1]*polarizability[dipole2], 1.0/6.0);
RealOpenMM u = r*uscale;
RealOpenMM screening = 1.0 - (1.0+0.5*u)*exp(-u);
energy += ONE_4PI_EPS0*chargeProduct*screening/r;
RealVec f = delta*(ONE_4PI_EPS0*chargeProduct*screening/(r*r*r));
RealVec f = delta*(ONE_4PI_EPS0*chargeProduct/(r*r))*(screening/r-0.5*(1+u)*exp(-u)*uscale);
force[p1] += f;
force[p2] -= f;
}
......@@ -461,4 +462,4 @@ void ReferenceIntegrateDrudeSCFStepKernel::minimize(ContextImpl& context, double
lbfgsfloatval_t fx;
MinimizerData data(context, drudeParticles);
lbfgs(numDrudeParticles*3, minimizerPos, &fx, evaluate, NULL, &data, &minimizerParams);
}
\ No newline at end of file
}
......@@ -71,14 +71,14 @@ void validateForce(System& system, vector<Vec3>& positions, double expectedEnerg
offsetPos[i][j] = positions[i][j]+offset;
context.setPositions(offsetPos);
double e2 = context.getState(State::Energy | State::Forces).getPotentialEnergy();
ASSERT_EQUAL_TOL(state.getForces()[i][j], (e1-e2)/(2*offset), 1e-3);
ASSERT_EQUAL_TOL(state.getForces()[i][j], (e1-e2)/(2*offset), 1e-5);
}
}
void testSingleParticle() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
......@@ -92,9 +92,9 @@ void testSingleParticle() {
}
void testAnisotropicParticle() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double a1 = 0.8;
const double a2 = 1.1;
const double k1 = k/a1;
......@@ -124,9 +124,9 @@ double computeScreening(double r, double thole, double alpha1, double alpha2) {
}
void testThole() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double thole = 2.5;
System system;
system.addParticle(1.0);
......@@ -157,9 +157,9 @@ void testThole() {
}
void testChangingParameters() {
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
Platform& platform = Platform::getPlatformByName("Reference");
// Create the system.
......@@ -184,9 +184,9 @@ void testChangingParameters() {
// Modify the parameters.
const double k2 = 2.2;
const double k2 = ONE_4PI_EPS0*2.2;
const double charge2 = 0.3;
const double alpha2 = charge2*charge2/k2;
const double alpha2 = ONE_4PI_EPS0*charge2*charge2/k2;
drude->setParticleParameters(0, 1, 0, -1, -1, -1, charge2, alpha2, 1, 1);
drude->updateParametersInContext(context);
state = context.getState(State::Energy);
......
......@@ -53,9 +53,9 @@ extern "C" OPENMM_EXPORT void registerDrudeReferenceKernelFactories();
void testSinglePair() {
const double temperature = 300.0;
const double temperatureDrude = 10.0;
const double k = 1.5;
const double k = ONE_4PI_EPS0*1.5;
const double charge = 0.1;
const double alpha = charge*charge/k;
const double alpha = ONE_4PI_EPS0*charge*charge/k;
const double mass1 = 1.0;
const double mass2 = 0.1;
const double totalMass = mass1+mass2;
......@@ -132,7 +132,7 @@ void testWater() {
system.addConstraint(startIndex, startIndex+3, 0.09572);
system.addConstraint(startIndex+2, startIndex+3, 0.15139);
system.setVirtualSite(startIndex+4, new ThreeParticleAverageSite(startIndex, startIndex+2, startIndex+3, 0.786646558, 0.106676721, 0.106676721));
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, 1.71636*1.71636/(100000*4.184), 1, 1);
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184), 1, 1);
}
vector<Vec3> positions;
for (int i = 0; i < gridSize; i++)
......
......@@ -85,7 +85,7 @@ void testWater() {
system.addConstraint(startIndex, startIndex+3, 0.09572);
system.addConstraint(startIndex+2, startIndex+3, 0.15139);
system.setVirtualSite(startIndex+4, new ThreeParticleAverageSite(startIndex, startIndex+2, startIndex+3, 0.786646558, 0.106676721, 0.106676721));
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, 1.71636*1.71636/(100000*4.184), 1, 1);
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184), 1, 1);
}
vector<Vec3> positions;
for (int i = 0; i < gridSize; i++)
......
......@@ -55,12 +55,16 @@ 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}/*.prm"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.inpcrd"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*.crd"
"${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}/*.str"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/*psf"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/charmm22.*"
)
......
......@@ -28,7 +28,7 @@ from desmonddmsfile import DesmondDMSFile
from checkpointreporter import CheckpointReporter
from charmmcrdfiles import CharmmCrdFile, CharmmRstFile
from charmmparameterset import CharmmParameterSet
from charmmpsffile import CharmmPsfFile
from charmmpsffile import CharmmPsfFile, CharmmPSFWarning
# Enumerated values
......
......@@ -13,7 +13,7 @@ Copyright (c) 2014 the Authors
Author: Jason M. Swails
Contributors:
Date: April 18, 2014
Date: July 17, 2014
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
......@@ -123,6 +123,8 @@ class CharmmParameterSet(object):
elif arg.endswith('.str'):
strs.append(arg)
elif arg.endswith('.inp'):
# Only consider the file name (since the directory is likely
# "toppar" and will screw up file type detection)
fname = os.path.split(arg)[1]
if 'par' in fname:
pars.append(arg)
......@@ -436,11 +438,29 @@ class CharmmParameterSet(object):
try:
at1 = words[0]
at2 = words[1]
emin = conv(words[2], float, 'NBFIX Emin')
emin = abs(conv(words[2], float, 'NBFIX Emin'))
rmin = conv(words[3], float, 'NBFIX Rmin')
try:
emin14 = abs(conv(words[4], float, 'NBFIX Emin 1-4'))
rmin14 = conv(words[5], float, 'NBFIX Rmin 1-4')
except IndexError:
emin14 = rmin14 = None
try:
self.atom_types_str[at1].add_nbfix(at2, rmin, emin,
rmin14, emin14)
self.atom_types_str[at2].add_nbfix(at1, rmin, emin,
rmin14, emin14)
except KeyError:
# Some stream files define NBFIX terms with an atom that
# is defined in another toppar file that does not
# necessarily have to be loaded. As a result, not every
# NBFIX found here will necessarily need to be applied.
# If we can't find a particular atom type, don't bother
# adding that nbfix and press on
pass
except IndexError:
raise CharmmFileError('Could not parse NBFIX terms.')
self.nbfix_types[(min(at1, at2), max(at1, at2))] = (emin, rmin)
self.nbfix_types[(min(at1, at2), max(at1, at2))] = (rmin, emin)
# Now we're done. Load the nonbonded types into the relevant AtomType
# instances. In order for this to work, all keys in nonbonded_types
# must be in the self.atom_types_str dict. Raise a RuntimeError if this
......
......@@ -995,11 +995,25 @@ class CharmmPsfFile(object):
u.kilojoule_per_mole)
ene_conv = dihe_frc_conv
# Create the system
# Create the system and determine if any of our atoms have NBFIX (and
# therefore requires a CustomNonbondedForce instead)
typenames = set()
system = mm.System()
if verbose: print('Adding particles...')
for atom in self.atom_list:
typenames.add(atom.type.name)
system.addParticle(atom.mass)
has_nbfix_terms = False
typenames = list(typenames)
try:
for i, typename in enumerate(typenames):
typ = params.atom_types_str[typename]
for j in range(i, len(typenames)):
if typenames[j] in typ.nbfix:
has_nbfix_terms = True
raise StopIteration
except StopIteration:
pass
# Set up the constraints
if verbose and (constraints is not None and not rigidWater):
print('Adding constraints...')
......@@ -1240,9 +1254,85 @@ class CharmmPsfFile(object):
# Add per-particle nonbonded parameters (LJ params)
sigma_scale = 2**(-1/6) * 2
for i, atm in enumerate(self.atom_list):
force.addParticle(atm.charge, sigma_scale*atm.type.rmin*length_conv,
abs(atm.type.epsilon*ene_conv))
if not has_nbfix_terms:
for atm in self.atom_list:
force.addParticle(atm.charge, sigma_scale*atm.type.rmin*length_conv,
abs(atm.type.epsilon*ene_conv))
else:
for atm in self.atom_list:
force.addParticle(atm.charge, 1.0, 0.0)
# Now add the custom nonbonded force that implements NBFIX. First
# thing we need to do is condense our number of types
lj_idx_list = [0 for atom in self.atom_list]
lj_radii, lj_depths = [], []
num_lj_types = 0
lj_type_list = []
for i, atom in enumerate(self.atom_list):
atom = atom.type
if lj_idx_list[i]: continue # already assigned
num_lj_types += 1
lj_idx_list[i] = num_lj_types
ljtype = (atom.rmin, atom.epsilon)
lj_type_list.append(atom)
lj_radii.append(atom.rmin)
lj_depths.append(atom.epsilon)
for j in range(i+1, len(self.atom_list)):
atom2 = self.atom_list[j].type
if lj_idx_list[j] > 0: continue # already assigned
if atom2 is atom:
lj_idx_list[j] = num_lj_types
elif not atom.nbfix:
# Only non-NBFIXed atom types can be compressed
ljtype2 = (atom2.rmin, atom2.epsilon)
if ljtype == ljtype2:
lj_idx_list[j] = num_lj_types
# Now everything is assigned. Create the A-coefficient and
# B-coefficient arrays
acoef = [0 for i in range(num_lj_types*num_lj_types)]
bcoef = acoef[:]
for i in range(num_lj_types):
for j in range(num_lj_types):
namej = lj_type_list[j].name
try:
rij, wdij, rij14, wdij14 = lj_type_list[i].nbfix[namej]
except KeyError:
rij = (lj_radii[i] + lj_radii[j]) * length_conv
wdij = sqrt(lj_depths[i] * lj_depths[j]) * ene_conv
else:
rij *= length_conv
wdij *= ene_conv
acoef[i+num_lj_types*j] = sqrt(wdij) * rij**6
bcoef[i+num_lj_types*j] = 2 * wdij * rij**6
cforce = mm.CustomNonbondedForce('(a/r6)^2-b/r6; r6=r^6;'
'a=acoef(type1, type2);'
'b=bcoef(type1, type2)')
cforce.addTabulatedFunction('acoef',
mm.Discrete2DFunction(num_lj_types, num_lj_types, acoef))
cforce.addTabulatedFunction('bcoef',
mm.Discrete2DFunction(num_lj_types, num_lj_types, bcoef))
cforce.addPerParticleParameter('type')
cforce.setForceGroup(self.NONBONDED_FORCE_GROUP)
if (nonbondedMethod is ff.PME or nonbondedMethod is ff.Ewald or
nonbondedMethod is ff.CutoffPeriodic):
cforce.setNonbondedMethod(cforce.CutoffPeriodic)
cforce.setCutoffDistance(nonbondedCutoff)
cforce.setUseLongRangeCorrection(True)
elif nonbondedMethod is ff.NoCutoff:
cforce.setNonbondedMethod(cforce.NoCutoff)
elif nonbondedMethod is ff.CutoffNonPeriodic:
cforce.setNonbondedMethod(cforce.CutoffNonPeriodic)
cforce.setCutoffDistance(nonbondedCutoff)
else:
raise ValueError('Unrecognized nonbonded method')
if switchDistance and nonbondedMethod is not ff.NoCutoff:
# make sure it's legal
if switchDistance >= nonbondedCutoff:
raise ValueError('switchDistance is too large compared '
'to the cutoff!')
cforce.setUseSwitchingFunction(True)
cforce.setSwitchingDistance(switchDistance)
for i in lj_idx_list:
cforce.addParticle((i - 1,)) # adjust for indexing from 0
# Add 1-4 interactions
excluded_atom_pairs = set() # save these pairs so we don't zero them out
......@@ -1283,6 +1373,13 @@ class CharmmPsfFile(object):
continue
force.addException(atom.idx, atom2.idx, 0.0, 0.1, 0.0)
system.addForce(force)
# If we needed a CustomNonbondedForce, map all of the exceptions from
# the NonbondedForce to the CustomNonbondedForce
if has_nbfix_terms:
for i in range(force.getNumExceptions()):
ii, jj, q, eps, sig = force.getExceptionParameters(i)
cforce.addExclusion(ii, jj)
system.addForce(cforce)
# Add GB model if we're doing one
if implicitSolvent is not None:
......
This diff is collapsed.
......@@ -30,7 +30,7 @@
<Atom type="swm4ndp-OD" charge="-1.71636" sigma="1" epsilon="0"/>
</NonbondedForce>
<DrudeForce>
<Particle type1="swm4ndp-OD" type2="swm4ndp-O" charge="-1.71636" polarizability="7.040850e-6" thole="1.3"/>
<Particle type1="swm4ndp-OD" type2="swm4ndp-O" charge="-1.71636" polarizability="0.000978253" thole="1.3"/>
</DrudeForce>
</ForceField>
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