Unverified Commit 7e72bafb authored by Zheng GONG's avatar Zheng GONG Committed by GitHub
Browse files

Merge pull request #3 from openmm/master

Update from upstream
parents 83b8ea75 f6431a42
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* 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) 2010-2014 Stanford University and the Authors. *
* Authors: Andrew C. Simmonett and Andreas Kraemer
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/serialization/XmlSerializer.h"
#include "openmm/System.h"
#include "openmm/Context.h"
#include <iostream>
#include <sstream>
using namespace OpenMM;
using namespace std;
void assertIntegratorsEqual(const NoseHooverIntegrator& integrator1, const NoseHooverIntegrator& integrator2){
ASSERT_EQUAL(integrator1.getStepSize(), integrator2.getStepSize());
ASSERT_EQUAL(integrator1.getConstraintTolerance(), integrator2.getConstraintTolerance());
ASSERT_EQUAL(integrator1.getMaximumPairDistance(), integrator2.getMaximumPairDistance());
ASSERT_EQUAL(integrator1.getNumThermostats(), integrator2.getNumThermostats());
for (int i = 0; i < integrator1.getNumThermostats(); i++) {
const auto &thermostat1 = integrator1.getThermostat(i);
const auto &thermostat2 = integrator2.getThermostat(i);
ASSERT_EQUAL(thermostat1.getTemperature(), thermostat2.getTemperature());
ASSERT_EQUAL(thermostat1.getCollisionFrequency(), thermostat2.getCollisionFrequency());
ASSERT_EQUAL(thermostat1.getRelativeTemperature(), thermostat2.getRelativeTemperature());
ASSERT_EQUAL(thermostat1.getRelativeCollisionFrequency(), thermostat2.getRelativeCollisionFrequency());
ASSERT_EQUAL(thermostat1.getChainLength(), thermostat2.getChainLength());
ASSERT_EQUAL(thermostat1.getNumMultiTimeSteps(), thermostat2.getNumMultiTimeSteps());
ASSERT_EQUAL(thermostat1.getNumYoshidaSuzukiTimeSteps(), thermostat2.getNumYoshidaSuzukiTimeSteps());
ASSERT_EQUAL(thermostat1.getChainID(), thermostat2.getChainID());
const auto &thermostat1Atoms = thermostat1.getThermostatedAtoms();
const auto &thermostat2Atoms = thermostat2.getThermostatedAtoms();
ASSERT_EQUAL(thermostat1Atoms.size(), thermostat2Atoms.size());
for (int j = 0; j < thermostat1Atoms.size(); ++j) {
ASSERT_EQUAL(thermostat1Atoms[j], thermostat2Atoms[j]);
}
const auto &thermostat1Pairs = thermostat1.getThermostatedPairs();
const auto &thermostat2Pairs = thermostat2.getThermostatedPairs();
ASSERT_EQUAL(thermostat1Pairs.size(), thermostat2Pairs.size());
for (int j = 0; j < thermostat1Pairs.size(); ++j) {
ASSERT_EQUAL(thermostat1Pairs[j].first, thermostat2Pairs[j].first);
ASSERT_EQUAL(thermostat1Pairs[j].second, thermostat2Pairs[j].second);
}
}
}
void testSerialization() {
// Check with custom subsystem thermostats
NoseHooverIntegrator integrator_sub (0.0006);
integrator_sub.setConstraintTolerance(0.0404);
integrator_sub.setMaximumPairDistance(0.0051);
integrator_sub.addSubsystemThermostat(
{0,1,2,3,4,7}, {{0,7}}, 301.1, 1.1, 1.2, 1.3, 9, 2, 5
);
// Serialize and then deserialize it.
stringstream buffer;
XmlSerializer::serialize<NoseHooverIntegrator>(&integrator_sub, "Integrator", buffer);
NoseHooverIntegrator* copy = XmlSerializer::deserialize<NoseHooverIntegrator>(buffer);
assertIntegratorsEqual(integrator_sub, *copy);
// Check with default constructor
System system;
for (int i=0; i<10; i++) system.addParticle(1.0);
NoseHooverIntegrator integrator(331, 1.1, 0.004, 5, 5, 5);
Context context(system, integrator);
// Serialize and then deserialize it.
stringstream buffer2;
XmlSerializer::serialize<NoseHooverIntegrator>(&integrator, "Integrator", buffer2);
copy = XmlSerializer::deserialize<NoseHooverIntegrator>(buffer2);
// for thermostats that apply to the whole system, the particles are not serialized ...
ASSERT_EQUAL(copy->getThermostat(0).getThermostatedAtoms().size(), 0);
// ... but assigned when creating a context.
Context context2(system, *copy);
assertIntegratorsEqual(integrator, *copy);
}
int main() {
try {
testSerialization();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* 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) 2019 Stanford University and the Authors. *
* Authors: Andreas Krämer and Andrew C. Simmonett *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/VirtualSite.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testVVSingleBond() {
System system;
system.addParticle(2.0);
system.addParticle(2.0);
NoseHooverIntegrator integrator(0.01);
HarmonicBondForce* forceField = new HarmonicBondForce();
forceField->addBond(0, 1, 1.5, 1);
system.addForce(forceField);
Context context(system, integrator, platform);
vector<Vec3> positions(2);
positions[0] = Vec3(-1, 0, 0);
positions[1] = Vec3(1, 0, 0);
context.setPositions(positions);
// This is simply a harmonic oscillator, so compare it to the analytical solution.
const double freq = 1.0;
State state = context.getState(State::Energy);
const double initialEnergy = state.getKineticEnergy()+state.getPotentialEnergy();
for (int i = 0; i < 1000; ++i) {
state = context.getState(State::Positions | State::Velocities | State::Energy);
double time = state.getTime();
double expectedDist = 1.5+0.5*std::cos(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
double expectedSpeed = -0.5*freq*std::sin(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedSpeed, 0, 0), state.getVelocities()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedSpeed, 0, 0), state.getVelocities()[1], 0.02);
double energy = state.getKineticEnergy()+state.getPotentialEnergy();
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(1);
}
ASSERT_EQUAL_TOL(10.0, context.getState(0).getTime(), 1e-5);
}
void testVVConstraints() {
const int numParticles = 8;
const int numConstraints = 5;
System system;
NoseHooverIntegrator integrator(0.001);
integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce();
for (int i = 0; i < numParticles; ++i) {
system.addParticle(i%2 == 0 ? 5.0 : 10.0);
forceField->addParticle((i%2 == 0 ? 0.2 : -0.2), 0.5, 5.0);
}
system.addConstraint(0, 1, 1.0);
system.addConstraint(1, 2, 1.0);
system.addConstraint(2, 3, 1.0);
system.addConstraint(4, 5, 1.0);
system.addConstraint(6, 7, 1.0);
system.addForce(forceField);
Context context(system, integrator, platform);
vector<Vec3> positions(numParticles);
vector<Vec3> velocities(numParticles);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int i = 0; i < numParticles; ++i) {
positions[i] = Vec3(i/2, (i+1)/2, 0);
velocities[i] = Vec3(genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5);
}
context.setPositions(positions);
context.setVelocities(velocities);
// Simulate it and see whether the constraints remain satisfied.
double initialEnergy = 0.0;
for (int i = 0; i < 1000; ++i) {
State state = context.getState(State::Positions | State::Energy | State::Velocities | State::Forces);
for (int j = 0; j < numConstraints; ++j) {
int particle1, particle2;
double distance;
system.getConstraintParameters(j, particle1, particle2, distance);
Vec3 p1 = state.getPositions()[particle1];
Vec3 p2 = state.getPositions()[particle2];
double dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2]));
ASSERT_EQUAL_TOL(distance, dist, 1e-4);
}
double energy = state.getPotentialEnergy()+state.getKineticEnergy();
if (i == 1)
initialEnergy = energy;
else if (i > 1)
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(1);
}
}
void testVVConstrainedClusters() {
const int numParticles = 7;
System system;
NoseHooverIntegrator integrator(0.001);
integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce();
for (int i = 0; i < numParticles; ++i) {
system.addParticle(i > 1 ? 1.0 : 10.0);
forceField->addParticle((i%2 == 0 ? 0.2 : -0.2), 0.5, 5.0);
}
system.addConstraint(0, 1, 1.0);
system.addConstraint(0, 2, 1.0);
system.addConstraint(0, 3, 1.0);
system.addConstraint(0, 4, 1.0);
system.addConstraint(1, 5, 1.0);
system.addConstraint(1, 6, 1.0);
system.addConstraint(2, 3, sqrt(2.0));
system.addConstraint(2, 4, sqrt(2.0));
system.addConstraint(3, 4, sqrt(2.0));
system.addConstraint(5, 6, sqrt(2.0));
system.addForce(forceField);
Context context(system, integrator, platform);
vector<Vec3> positions(numParticles);
positions[0] = Vec3(0, 0, 0);
positions[1] = Vec3(1, 0, 0);
positions[2] = Vec3(-1, 0, 0);
positions[3] = Vec3(0, 1, 0);
positions[4] = Vec3(0, 0, 1);
positions[5] = Vec3(2, 0, 0);
positions[6] = Vec3(1, 1, 0);
vector<Vec3> velocities(numParticles);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int i = 0; i < numParticles; ++i)
velocities[i] = Vec3(genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5);
context.setPositions(positions);
context.setVelocities(velocities);
// Simulate it and see whether the constraints remain satisfied.
double initialEnergy = 0.0;
for (int i = 0; i < 1000; ++i) {
State state = context.getState(State::Positions | State::Energy | State::Velocities | State::Forces);
for (int j = 0; j < system.getNumConstraints(); ++j) {
int particle1, particle2;
double distance;
system.getConstraintParameters(j, particle1, particle2, distance);
Vec3 p1 = state.getPositions()[particle1];
Vec3 p2 = state.getPositions()[particle2];
double dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2]));
ASSERT_EQUAL_TOL(distance, dist, 2e-5);
}
double energy = state.getPotentialEnergy()+state.getKineticEnergy();
if (i == 1)
initialEnergy = energy;
else if (i > 1)
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(1);
}
}
void testVVConstrainedMasslessParticles() {
System system;
system.addParticle(0.0);
system.addParticle(1.0);
system.addConstraint(0, 1, 1.5);
vector<Vec3> positions(2);
positions[0] = Vec3(-1, 0, 0);
positions[1] = Vec3(1, 0, 0);
NoseHooverIntegrator integrator(0.01);
bool failed = false;
try {
// This should throw an exception.
Context context(system, integrator, platform);
}
catch (exception& ex) {
failed = true;
}
ASSERT(failed);
// Now make both particles massless, which should work.
system.setParticleMass(1, 0.0);
Context context(system, integrator, platform);
context.setPositions(positions);
context.setVelocitiesToTemperature(300.0);
integrator.step(1);
State state = context.getState(State::Velocities);
ASSERT_EQUAL(0.0, state.getVelocities()[0][0]);
}
/**
* Make sure that virtual sites are updated correctly
*/
void testThreeParticleVirtualSite() {
System system;
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(0.0);
system.setVirtualSite(3, new ThreeParticleAverageSite(0, 1, 2, 0.2, 0.3, 0.5));
CustomExternalForce* forceField = new CustomExternalForce("-a*x");
system.addForce(forceField);
forceField->addPerParticleParameter("a");
vector<double> params(1);
params[0] = 0.1;
forceField->addParticle(0, params);
params[0] = 0.2;
forceField->addParticle(1, params);
params[0] = 0.3;
forceField->addParticle(2, params);
params[0] = 0.4;
forceField->addParticle(3, params);
NoseHooverIntegrator integrator(0.002);
Context context(system, integrator, platform);
vector<Vec3> positions(4);
positions[0] = Vec3(0, 0, 0);
positions[1] = Vec3(1, 0, 0);
positions[2] = Vec3(0, 1, 0);
context.setPositions(positions);
context.applyConstraints(0.0001);
for (int i = 0; i < 1000; i++) {
State state = context.getState(State::Positions | State::Forces);
const vector<Vec3>& pos = state.getPositions();
ASSERT_EQUAL_VEC(pos[0]*0.2+pos[1]*0.3+pos[2]*0.5, pos[3], 1e-5);
ASSERT_EQUAL_VEC(Vec3(0.1+0.4*0.2, 0, 0), state.getForces()[0], 1e-5);
ASSERT_EQUAL_VEC(Vec3(0.2+0.4*0.3, 0, 0), state.getForces()[1], 1e-5);
ASSERT_EQUAL_VEC(Vec3(0.3+0.4*0.5, 0, 0), state.getForces()[2], 1e-5);
integrator.step(1);
}
}
void runPlatformTests();
int main(int argc, char* argv[]) {
try {
initializeTests(argc, argv);
testVVSingleBond();
testVVConstraints();
testVVConstrainedClusters();
testVVConstrainedMasslessParticles();
testThreeParticleVirtualSite();
runPlatformTests();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* 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) 2019 Stanford University and the Authors. *
* Authors: Andreas Krämer and Andrew C. Simmonett *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/NoseHooverChain.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/Context.h"
#include "openmm/State.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/System.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace OpenMM;
using namespace std;
void testHarmonicOscillator() {
const double mass = 1.0;
double temperature = 300;
double frequency = 1;
double mts = 1, ys = 1, chain_length = 3;
System system;
system.addParticle(mass);
vector<Vec3> positions(1);
positions[0] = Vec3(0.5,0.5,0.5);
vector<Vec3> velocities(1);
velocities[0] = Vec3(0, 0, 0);
auto harmonic_restraint = new CustomExternalForce("0.5*(x^2+y^2+z^2)");
harmonic_restraint->addParticle(0);
system.addForce(harmonic_restraint);
NoseHooverIntegrator integrator(0.001);
integrator.addThermostat(temperature, frequency, chain_length, mts, ys);
Context context(system, integrator, platform);
context.setPositions(positions);
context.setVelocities(velocities);
double mean_temperature=0;
// equilibration
integrator.step(2000);
for (size_t i=0; i < 2500; i++){
integrator.step(10);
State state = context.getState(State::Energy | State::Positions | State::Velocities);
double kinetic_energy = state.getKineticEnergy();
double temp = kinetic_energy/(0.5*3*BOLTZ);
mean_temperature = (i*mean_temperature + temp)/(i+1);
double PE = state.getPotentialEnergy();
double time = state.getTime();
double energy = kinetic_energy + PE + integrator.computeHeatBathEnergy();
}
ASSERT_EQUAL_TOL(temperature, mean_temperature, 0.02);
}
int makeDimerBox(System& system, std::vector<Vec3>& positions, bool constrain=true, int numMolecules=20, double bondLength=0.1){
double boxLength = 2; // nm
Vec3 a(boxLength, 0.0, 0.0);
Vec3 b(0.0, boxLength, 0.0);
Vec3 c(0.0, 0.0, boxLength);
double mass = 20;
double bondForceConstant = 30000; //0.001;
int numDOF = 0;
NonbondedForce* forceField = new NonbondedForce();
HarmonicBondForce* bondForce = new HarmonicBondForce();
for(int molecule = 0; molecule < numMolecules; ++molecule) {
int particle1 = system.addParticle(mass);
int particle2 = system.addParticle(mass);
forceField->addParticle(0.0, 0.1, 1.0);
forceField->addParticle(0.0, 0.1, 1.0);
forceField->addException(particle1, particle2, 0, 0, 0);
bondForce->addBond(particle1, particle2, bondLength, bondForceConstant);
numDOF += 6;
if (constrain) {
system.addConstraint(particle1, particle2, bondLength);
numDOF -= 1;
}
}
forceField->setCutoffDistance(.99*boxLength/2);
forceField->setSwitchingDistance(.88*boxLength/2);
forceField->setUseSwitchingFunction(true);
forceField->setUseDispersionCorrection(false);
forceField->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
system.addForce(forceField);
system.addForce(bondForce);
system.setDefaultPeriodicBoxVectors(a, b, c);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int i = 0; i < numMolecules; i++) {
while (true) {
Vec3 pos = Vec3(boxLength*genrand_real2(sfmt), boxLength*genrand_real2(sfmt), boxLength*genrand_real2(sfmt));
Vec3 pos1 = pos + Vec3(0,0, bondLength/2);
Vec3 pos2 = pos + Vec3(0,0,-bondLength/2);
double minDist = 2*boxLength;
for (int j = 0; j < i; j++) {
Vec3 delta = pos1-positions[j];
minDist = std::min(minDist, sqrt(delta.dot(delta)));
delta = pos2-positions[j];
minDist = std::min(minDist, sqrt(delta.dot(delta)));
}
if (minDist > 0.15) {
positions[2*i+0] = pos1;
positions[2*i+1] = pos2;
break;
}
}
}
return numDOF;
}
void testDimerBox(bool constrain=true) {
// Check conservation of system + bath energy for a harmonic oscillator
int numMolecules = 20;
double bondLength = 0.1;
double bondLengthSquared = bondLength * bondLength;
System system;
std::vector<Vec3> positions(numMolecules*2);
int numDOF = makeDimerBox(system, positions, constrain, numMolecules, bondLength);
bool simpleConstruct = true;
double temperature = 300; // kelvin
double collisionFrequency = 200; // 1/ps
int numMTS = 3;
int numYS = 3;
int chainLength = 5;
auto integrator = simpleConstruct ? NoseHooverIntegrator(temperature, collisionFrequency, 0.001, chainLength, numMTS, numYS)
: NoseHooverIntegrator(0.001);
if (!simpleConstruct)
integrator.addThermostat(temperature, collisionFrequency, chainLength, numMTS, numYS);
Context context(system, integrator, platform);
context.setPositions(positions);
context.setVelocitiesToTemperature(temperature);
int nSteps = 1500;
double mean_temp = 0.0;
std::vector<double> energies(nSteps);
for (int i = 0; i < nSteps; ++i) {
integrator.step(1);
State state = context.getState(State::Energy | (constrain ? State::Positions : 0));
if (constrain) {
auto positions = state.getPositions();
for(int i = 0; i < numMolecules; ++i) {
Vec3 delta = positions[2*i+1] - positions[2*i];
double dR2 = delta.dot(delta);
ASSERT_EQUAL_TOL(bondLengthSquared, dR2, 1e-4);
}
}
double KE = state.getKineticEnergy();
double PE = state.getPotentialEnergy();
double time = state.getTime();
double instantaneous_temperature = 2 * KE / (BOLTZ * numDOF);
mean_temp = (i*mean_temp + instantaneous_temperature)/(i+1);
double energy = KE + PE + integrator.computeHeatBathEnergy();
energies[i] = energy;
}
double sum = std::accumulate(energies.begin(), energies.end(), 0.0);
double mean = sum / energies.size();
double sq_sum = std::inner_product(energies.begin(), energies.end(), energies.begin(), 0.0);
double std = std::sqrt(sq_sum / energies.size() - mean * mean);
double relative_std = std / mean;
// Check mean temperature
ASSERT_USUALLY_EQUAL_TOL(temperature, mean_temp, 1e-2);
// Check fluctuation of conserved (total bath + system) energy
ASSERT_USUALLY_EQUAL_TOL(relative_std, 0, 5e-4);
}
void testCheckpoints() {
// Create a system with Drude-like particles to be thermostated as a pair, as well as another
// particle to be thermostated independently, to test all integrator features.
double timeStep = 0.001;
NoseHooverIntegrator integrator(timeStep), newIntegrator(timeStep);
System system;
double mass = 1;
system.addParticle(8*mass);
system.addParticle(mass);
system.addParticle(5*mass);
HarmonicBondForce* force = new HarmonicBondForce();
force->addBond(0, 1, 0.1, 50.0);
force->addBond(0, 2, 0.1, 50.0);
system.addForce(force);
double kineticEnergy = 1e6;
double temperature=300, collisionFrequency=1, chainLength=3, numMTS=3, numYS=3;
chainLength = 10;
integrator.addSubsystemThermostat(std::vector<int>{2}, std::vector<std::pair<int,int>>{{0,1}}, temperature, collisionFrequency, temperature, collisionFrequency,
chainLength, numMTS, numYS);
newIntegrator.addSubsystemThermostat(std::vector<int>{2}, std::vector<std::pair<int,int>>{{0,1}}, temperature, collisionFrequency, temperature, collisionFrequency,
chainLength, numMTS, numYS);
Context context(system, integrator, platform);
Context newContext(system, newIntegrator, platform);
std::vector<Vec3> positions(3);
std::vector<Vec3> velocities(3);
positions[1] = {0.1, 0.0, 0.0};
velocities[1] = {0.1,0.2,-0.2};
positions[2] = {-0.1, 0.001, 0.001};
velocities[2] = {-0.1,0.2,-0.2};
context.setPositions(positions);
context.setVelocities(velocities);
// Run a short simulation and checkpoint..
integrator.step(500);
std::stringstream checkpoint;
context.createCheckpoint(checkpoint);
// Now continue the simulation
integrator.step(5);
// And try the same, starting from the checkpoint
newContext.loadCheckpoint(checkpoint);
newIntegrator.step(5);
State state1 = context.getState(State::Positions | State::Velocities);
State state2 = newContext.getState(State::Positions | State::Velocities);
ASSERT_EQUAL_VEC(state1.getPositions()[0], state2.getPositions()[0], 1e-6);
ASSERT_EQUAL_VEC(state1.getPositions()[1], state2.getPositions()[1], 1e-6);
ASSERT_EQUAL_VEC(state1.getVelocities()[0], state2.getVelocities()[0], 1e-6);
ASSERT_EQUAL_VEC(state1.getVelocities()[1], state2.getVelocities()[1], 1e-6);
}
void testAPIChangeNumParticles() {
bool constrain = true;
int numMolecules = 20;
double bondLength = 0.1;
double bondLengthSquared = bondLength * bondLength;
System system;
std::vector<Vec3> positions(numMolecules*2);
int numDOF = makeDimerBox(system, positions, constrain, numMolecules, bondLength);
}
void runPlatformTests();
int main(int argc, char* argv[]) {
try {
initializeTests(argc, argv);
testHarmonicOscillator();
bool constrain;
constrain = false; testDimerBox(constrain);
constrain = true; testDimerBox(constrain);
testCheckpoints();
runPlatformTests();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
......@@ -76,7 +76,12 @@ class WrapperGenerator:
'static std::vector<std::string> OpenMM::Platform::loadPluginsFromDirectory',
'Vec3 OpenMM::LocalCoordinatesSite::getOriginWeights',
'Vec3 OpenMM::LocalCoordinatesSite::getXWeights',
'Vec3 OpenMM::LocalCoordinatesSite::getYWeights']
'Vec3 OpenMM::LocalCoordinatesSite::getYWeights',
'std::vector<double> OpenMM::NoseHooverChain::getYoshidaSuzukiWeights',
'const std::vector<int>& OpenMM::NoseHooverIntegrator::getAllThermostatedIndividualParticles',
'const std::vector<std::tuple<int, int, double> >& OpenMM::NoseHooverIntegrator::getAllThermostatedPairs',
'virtual void OpenMM::NoseHooverIntegrator::stateChanged'
]
self.hideClasses = ['Kernel', 'KernelImpl', 'KernelFactory', 'ContextImpl', 'SerializationNode', 'SerializationProxy']
self.nodeByID={}
......@@ -165,6 +170,7 @@ class CHeaderGenerator(WrapperGenerator):
'std::vector< std::string >': 'OpenMM_StringArray',
'std::vector< Vec3 >': 'OpenMM_Vec3Array',
'std::vector< std::pair< int, int > >': 'OpenMM_BondArray',
'const std::vector< std::pair< int, int > >': 'OpenMM_BondArray',
'std::map< std::string, double >': 'OpenMM_ParameterArray',
'std::map< std::string, std::string >': 'OpenMM_PropertyArray',
'std::vector< double >': 'OpenMM_DoubleArray',
......
......@@ -184,7 +184,7 @@ def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM,
if not openmm_lib_path:
reportError("Set OPENMM_LIB_PATH to point to the lib directory for OpenMM")
extra_compile_args=[]
extra_compile_args=['-std=c++11']
extra_link_args=[]
if platform.system() == "Windows":
define_macros.append( ('WIN32', None) )
......
......@@ -164,6 +164,7 @@ class CharmmPsfFile(object):
CMAP_FORCE_GROUP = 5
NONBONDED_FORCE_GROUP = 6
GB_FORCE_GROUP = 6
DRUDE_FORCE_GROUP = 7
@_catchindexerror
def __init__(self, psf_name, periodicBoxVectors=None, unitCellDimensions=None):
......@@ -466,6 +467,37 @@ class CharmmPsfFile(object):
else:
self.box_vectors = periodicBoxVectors
def _build_exclusion_list(self):
pair_12_set = set()
pair_13_set = set()
pair_14_set = set()
for bond in self.bond_list:
a1, a2 = bond.atom1, bond.atom2
pair = (min(a1.idx, a2.idx), max(a1.idx, a2.idx),)
pair_12_set.add(pair)
for bond in self.bond_list:
a2, a3 = bond.atom1, bond.atom2
for a1 in a2.bond_partners:
pair = (min(a1.idx, a3.idx), max(a1.idx, a3.idx),)
if a1 != a3:
pair_13_set.add(pair)
for a4 in a3.bond_partners:
pair = (min(a2.idx, a4.idx), max(a2.idx, a4.idx),)
if a2 != a4:
pair_13_set.add(pair)
for bond in self.bond_list:
a2, a3 = bond.atom1, bond.atom2
for a1 in a2.bond_partners:
for a4 in a3.bond_partners:
pair = (min(a1.idx, a4.idx), max(a1.idx, a4.idx),)
if a1 != a4:
pair_14_set.add(pair)
# in case there are 3,4,5-member rings
self.pair_12_list = list(sorted(pair_12_set))
self.pair_13_list = list(sorted(pair_13_set - pair_12_set))
self.pair_14_list = list(sorted(pair_14_set - pair_13_set.union(pair_12_set)))
@staticmethod
def _convert(string, type, message):
"""Converts a string to a specific type, making sure to raise
......@@ -1320,31 +1352,29 @@ class CharmmPsfFile(object):
# now, add the actual force to the system
system.addForce(nbtforce)
# build 1-2, 1-3 and 1-4 pairs from connectivity
if verbose:
print('Build exclusion list...')
self._build_exclusion_list()
if verbose:
print('\tNumber of 1-2 pairs: %i' % len(self.pair_12_list))
print('\tNumber of 1-3 pairs: %i' % len(self.pair_13_list))
print('\tNumber of 1-4 pairs: %i' % len(self.pair_14_list))
# Add 1-4 interactions
excluded_atom_pairs = set() # save these pairs so we don't zero them out
sigma_scale = 2**(-1/6)
nbxmod = abs(params.nbxmod)
if nbxmod == 4:
for ia1, ia4 in self.pair_14_list:
force.addException(ia1, ia4, 0.0, 0.1, 0.0)
if nbxmod == 5:
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
if tor.atom1 in tor.atom4.bond_partners: continue
if tor.atom1 in tor.atom4.angle_partners: continue
key = min((tor.atom1.idx, tor.atom4.idx),
(tor.atom4.idx, tor.atom1.idx))
if key in excluded_atom_pairs: continue # multiterm...
charge_prod = (tor.atom1.charge * tor.atom4.charge)
epsilon = (sqrt(abs(tor.atom1.type.epsilon_14) * ene_conv *
abs(tor.atom4.type.epsilon_14) * ene_conv))
sigma = (tor.atom1.type.rmin_14 + tor.atom4.type.rmin_14) * (
length_conv * sigma_scale)
force.addException(tor.atom1.idx, tor.atom4.idx,
charge_prod, sigma, epsilon)
excluded_atom_pairs.add(
min((tor.atom1.idx, tor.atom4.idx),
(tor.atom4.idx, tor.atom1.idx))
)
for ia1, ia4 in self.pair_14_list:
atom1 = self.atom_list[ia1]
atom4 = self.atom_list[ia4]
charge_prod = (atom1.charge * atom4.charge)
epsilon = sqrt(abs(atom1.type.epsilon_14 * atom4.type.epsilon_14)) * ene_conv
sigma = (atom1.type.rmin_14 + atom4.type.rmin_14) * (length_conv * sigma_scale)
force.addException(ia1, ia4, charge_prod, sigma, epsilon)
# Add excluded atoms
# Drude and lonepairs will be excluded based on their parent atoms
......@@ -1368,33 +1398,24 @@ class CharmmPsfFile(object):
for i in range(len(excludeterm)):
for j in range(i):
force.addException(excludeterm[j], excludeterm[i], 0.0, 0.1, 0.0)
# Exclude all bonds and angles, as well as the lonepair/Drude attached onto them
for atom in self.atom_list:
if nbxmod > 1:
for atom2 in atom.bond_partners:
if atom2.idx > atom.idx:
for excludeatom in [atom.idx]+parent_exclude_list[atom.idx]:
for excludeatom2 in [atom2.idx]+parent_exclude_list[atom2.idx]:
force.addException(excludeatom, excludeatom2, 0.0, 0.1, 0.0)
if nbxmod > 2:
for atom2 in atom.angle_partners:
if atom2.idx > atom.idx:
for excludeatom in [atom.idx]+parent_exclude_list[atom.idx]:
for excludeatom2 in [atom2.idx]+parent_exclude_list[atom2.idx]:
force.addException(excludeatom, excludeatom2, 0.0, 0.1, 0.0)
if nbxmod > 3:
for atom2 in atom.dihedral_partners:
if atom2.idx <= atom.idx: continue
if ((atom.idx, atom2.idx) in excluded_atom_pairs):
continue
force.addException(atom.idx, atom2.idx, 0.0, 0.1, 0.0)
# Exclude 1-2 and 1-3 pairs as well as the lonepair/Drude attached onto them
if nbxmod > 1:
for ia1, ia2 in self.pair_12_list:
for excludeatom in [ia1]+parent_exclude_list[ia1]:
for excludeatom2 in [ia2]+parent_exclude_list[ia2]:
force.addException(excludeatom, excludeatom2, 0.0, 0.1, 0.0)
if nbxmod > 2:
for ia1, ia3 in self.pair_13_list:
for excludeatom in [ia1]+parent_exclude_list[ia1]:
for excludeatom2 in [ia3]+parent_exclude_list[ia3]:
force.addException(excludeatom, excludeatom2, 0.0, 0.1, 0.0)
system.addForce(force)
# Add Drude particles (Drude force)
if has_drude_particle:
if verbose: print('Adding Drude force and Thole screening...')
drudeforce = mm.DrudeForce()
drudeforce.setForceGroup(7)
drudeforce.setForceGroup(self.DRUDE_FORCE_GROUP)
for pair in self.drudepair_list:
parentatom=pair[0]
drudeatom=pair[1]
......@@ -1423,24 +1444,16 @@ class CharmmPsfFile(object):
particleMap = {}
for i in range(drudeforce.getNumParticles()):
particleMap[drudeforce.getParticleParameters(i)[0]] = i
for bond in self.bond_list:
alpha1 = self.drudeconsts_list[bond.atom1.idx][0]
alpha2 = self.drudeconsts_list[bond.atom2.idx][0]
if abs(alpha1) > TINY and abs(alpha2) > TINY: # both are Drude parent atoms
thole1 = self.drudeconsts_list[bond.atom1.idx][1]
thole2 = self.drudeconsts_list[bond.atom2.idx][1]
drude1 = bond.atom1.idx + 1 # CHARMM psf has hard-coded rule that the Drude is next to its parent
drude2 = bond.atom2.idx + 1
drudeforce.addScreenedPair(particleMap[drude1], particleMap[drude2], thole1+thole2)
for ang in self.angle_list:
alpha1 = self.drudeconsts_list[ang.atom1.idx][0]
alpha2 = self.drudeconsts_list[ang.atom3.idx][0]
# Apply thole screening for 1-2 and 1-3 pairs
for ia1, ia2 in self.pair_12_list + self.pair_13_list:
alpha1 = self.drudeconsts_list[ia1][0]
alpha2 = self.drudeconsts_list[ia2][0]
if abs(alpha1) > TINY and abs(alpha2) > TINY: # both are Drude parent atoms
thole1 = self.drudeconsts_list[ang.atom1.idx][1]
thole2 = self.drudeconsts_list[ang.atom3.idx][1]
drude1 = ang.atom1.idx + 1 # CHARMM psf has hard-coded rule that the Drude is next to its parent
drude2 = ang.atom3.idx + 1
thole1 = self.drudeconsts_list[ia1][1]
thole2 = self.drudeconsts_list[ia2][1]
drude1 = ia1 + 1 # CHARMM psf has hard-coded rule that the Drude is next to its parent
drude2 = ia2 + 1
drudeforce.addScreenedPair(particleMap[drude1], particleMap[drude2], thole1+thole2)
# If we needed a CustomNonbondedForce, map all of the exceptions from
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1259,9 +1259,9 @@ class Modeller(object):
adds whole copies of the pre-equilibrated membrane patch, so the box dimensions will always be
integer multiples of the patch size. That may lead to a larger membrane than what you requested.
This method has built in support for POPC and POPE lipids. You can also build other types of
membranes by providing a pre-equilibrated, solvated membrane patch that can be tiled in the XY
plane to form the membrane.
This method has built in support for POPC, POPE, DLPC, DLPE, DMPC, DOPC and DPPC lipids.
You can also build other types of membranes by providing a pre-equilibrated, solvated membrane patch
that can be tiled in the XY plane to form the membrane.
Parameters
----------
......@@ -1289,7 +1289,7 @@ class Modeller(object):
"""
if 'topology' in dir(lipidType) and 'positions' in dir(lipidType):
patch = lipidType
elif lipidType.upper() in ('POPC', 'POPE'):
elif lipidType.upper() in ('POPC', 'POPE', 'DLPC', 'DLPE', 'DMPC', 'DOPC', 'DPPC'):
patch = PDBFile(os.path.join(os.path.dirname(__file__), 'data', lipidType.upper()+'.pdb'))
else:
raise ValueError('Unsupported lipid type: '+lipidType)
......
......@@ -21,6 +21,9 @@ except ImportError:
INDENT = " "
docTags = {'emphasis':'i', 'bold':'b', 'itemizedlist':'ul', 'listitem':'li', 'preformatted':'pre', 'computeroutput':'tt', 'subscript':'sub'}
def is_method_abstract(argstring):
return argstring.split(")")[-1].find("=0") >= 0
def striphtmltags(s):
"""Strip a couple html tags used inside docstrings in the C++ source
to produce something more easily read as plain text.
......@@ -511,7 +514,7 @@ class SwigInputBuilder:
mArgsstring = getText("argsstring", memberNode)
if self.fOutPythonprepend and \
len(paramList) and \
mArgsstring.find('=0') < 0:
not is_method_abstract(mArgsstring):
text = '''
%pythonprepend OpenMM::{shortClassName}::{methName}{mArgsstring} %{{{{{{0}}
%}}}}'''.format(shortClassName=shortClassName, methName=methName, mArgsstring=mArgsstring)
......@@ -529,6 +532,7 @@ class SwigInputBuilder:
% self.__class__.__name__)
raise Exception(s)'''.format(argName=argName)
# Convert input arguments to the proper units, if specified.
if key not in methodsWithOutputArgs:
if key in self.configModule.UNITS:
......@@ -563,9 +567,10 @@ class SwigInputBuilder:
# write pythonappend blocks
if self.fOutPythonappend \
and mArgsstring.find('=0') < 0:
and not is_method_abstract(mArgsstring):
key = (shortClassName, methName)
#print "key %s %s \n" % (shortClassName, methName)
#sys.stdout.write("key %s %s \n" % (shortClassName, methName))
addText=''
returnType = getText("type", memberNode)
......@@ -619,8 +624,15 @@ class SwigInputBuilder:
pType = getText('type', pNode)
except IndexError:
pType = getText('type/ref', pNode)
# parse default arguments
try:
defaultValue = getText('defval', pNode)
except:
defaultValue = ""
if defaultValue != "":
defaultValue = "=%s" %defaultValue
pName = getText('declname', pNode)
self.fOutPythonappend.write("%s%s %s" % (sepChar, pType, pName))
self.fOutPythonappend.write("%s%s %s%s" % (sepChar, pType, pName, defaultValue))
sepChar=', '
if pType.find('&')>=0 and \
......
......@@ -66,6 +66,8 @@ SKIP_METHODS = [('State', 'getPositions'),
('IntegrateVariableLangevinStepKernel',),
('IntegrateVariableVerletStepKernel',),
('IntegrateVerletStepKernel',),
('IntegrateVelocityVerletStepKernel',),
('NoseHooverChainKernel',),
('IntegrateCustomStepKernel',),
('Kernel',),
('KernelFactory',),
......@@ -112,6 +114,8 @@ SKIP_METHODS = [('State', 'getPositions'),
('LocalCoordinatesSite', 'getOriginWeights', 0),
('LocalCoordinatesSite', 'getXWeights', 0),
('LocalCoordinatesSite', 'getYWeights', 0),
("NoseHooverIntegrator", "getAllThermostatedIndividualParticles"),
("NoseHooverIntegrator", "getAllThermostatedPairs"),
]
# The build script assumes method args that are non-const references are
......@@ -180,6 +184,7 @@ UNITS = {
("*", "setDefaultSurfaceTension") : (None, ("unit.bar*unit.nanometer",)),
("*", "getDefaultTemperature") : ("unit.kelvin", ()),
("*", "setDefaultTemperature") : (None, ("unit.kelvin",)),
("*", "getRelativeTemperature") : ("unit.kelvin", ()),
("*", "getErrorTolerance") : (None, ()),
("*", "getEwaldErrorTolerance") : (None, ()),
("*", "getFriction") : ("1/unit.picosecond", ()),
......@@ -213,6 +218,9 @@ UNITS = {
("*", "getTabulatedFunction") : (None, ()),
("*", "getUseDispersionCorrection") : (None, ()),
("*", "getTemperature") : ("unit.kelvin", ()),
("*", "getRelativeTemperature") : ("unit.kelvin", ()),
("*", "getCollisionFrequency") : ( "1/unit.picosecond", ()),
("*", "getRelativeCollisionFrequency") : ( "1/unit.picosecond", ()),
("*", "getUseDispersionCorrection") : (None, ()),
("*", "getWeight") : (None, ()),
("*", "getWeight12") : (None, ()),
......@@ -339,9 +347,11 @@ UNITS = {
("HippoNonbondedForce", "getInducedDipoles") : ( None, ()),
("HippoNonbondedForce", "getLabFramePermanentDipoles") : ( None, ()),
("Context", "getParameter") : (None, ()),
("Context", "getParameters") : (None, ()),
("Context", "getMolecules") : (None, ()),
("Context", "getState") : (None, (None, None, None)),
("CMAPTorsionForce", "getMapParameters") : (None, (None, 'unit.kilojoule_per_mole')),
("CMAPTorsionForce", "getTorsionParameters") : (None, ()),
("CMMotionRemover", "getFrequency") : (None, ()),
......@@ -465,11 +475,28 @@ UNITS = {
("MonteCarloMembraneBarostat", "MonteCarloMembraneBarostat") : (None, ("unit.bar", "unit.bar*unit.nanometer", "unit.kelvin", None, None, None)),
("MonteCarloMembraneBarostat", "getXYMode") : (None, ()),
("MonteCarloMembraneBarostat", "getZMode") : (None, ()),
("DrudeLangevinIntegrator", "getDrudeFriction") : ("1/unit.picosecond", ()),
("DrudeLangevinIntegrator", "getDrudeFriction") : ("unit.picosecond**-1", ()),
("DrudeSCFIntegrator", "getMinimizationErrorTolerance") : ("unit.kilojoules_per_mole/unit.nanometer", ()),
("RPMDIntegrator", "getContractions") : (None, ()),
("RPMDIntegrator", "getTotalEnergy") : ("unit.kilojoules_per_mole", ()),
("RPMDIntegrator", "getState"): (None,(None, None, None, None)),
("RMSDForce", "getReferencePositions") : ("unit.nanometer", ()),
("RMSDForce", "getParticles") : (None, ()),
("NoseHooverChain", "getThermostatedPairs") : (None, ()),
("NoseHooverChain", "getThermostatedAtoms") : (None, ()),
("NoseHooverChain", "getYoshidaSuzukiWeights") : (None, ()),
("NoseHooverIntegrator", "setTemperature") : (None, ("unit.kelvin", None)),
("NoseHooverIntegrator", "setRelativeTemperature") : (None, ("unit.kelvin", None) ),
("NoseHooverIntegrator", "setCollisionFrequency") : (None, ("unit.picosecond**-1", None)),
("NoseHooverIntegrator", "setRelativeCollisionFrequency") : (None, ("unit.picosecond**-1", None)),
("NoseHooverIntegrator", "computeHeatBathEnergy") : ( "unit.kilojoules_per_mole", ()),
("NoseHooverIntegrator", "addThermostat"): (None, ("unit.kelvin", "unit.picosecond**-1", None, None, None)),
("NoseHooverIntegrator", "addSubsystemThermostat"):
(None, (None, None, "unit.kelvin", "unit.picosecond**-1", "unit.kelvin", "unit.picosecond**-1", None, None, None)),
("NoseHooverIntegrator", "getNumThermostats") : (None, ()),
("NoseHooverIntegrator", "getThermostat") : (None, ()),
("NoseHooverIntegrator", "getMaximumPairDistance") : ("unit.nanometer", ()),
("NoseHooverIntegrator", "setMaximumPairDistance") : (None, ("unit.nanometer",)),
("DrudeNoseHooverIntegrator", "getMaxDrudeDistance") : ("unit.nanometer", ()),
("DrudeNoseHooverIntegrator", "setMaxDrudeDistance") : (None, ("unit.nanometer",)),
}
......@@ -682,7 +682,7 @@ class TestAPIUnits(unittest.TestCase):
force.setSolventDielectric(80)
self.assertEqual(force.getSolventDielectric(), 80)
self.assertEqual(force.getSurfaceAreaFactor(),
self.assertAlmostEqualUnit(force.getSurfaceAreaFactor(),
-170.35173066268223*kilojoule_per_mole/nanometer**2) # default
force.setSurfaceAreaFactor(-1.0*kilocalorie_per_mole/angstrom**2)
self.assertAlmostEqualUnit(force.getSurfaceAreaFactor(),
......@@ -1165,6 +1165,60 @@ class TestAPIUnits(unittest.TestCase):
self.assertAlmostEqualUnit(integrator.getFriction(), 0.1/microsecond)
self.assertEqual(integrator.getStepSize(), 1*femtosecond)
def testNoseHooverIntegrator(self):
""" Tests the NoseHooverIntegrator API features """
integrator = NoseHooverIntegrator(300, 0.1, 1)
self.assertEqual(integrator.getTemperature(0), 300*kelvin)
self.assertEqual(integrator.getCollisionFrequency(), 0.1/picosecond)
self.assertEqual(integrator.getStepSize(), 1*picosecond)
integrator = NoseHooverIntegrator(300*kelvin, 0.1/microsecond, 1*femtosecond)
self.assertEqual(integrator.getTemperature(), 300*kelvin)
self.assertAlmostEqualUnit(integrator.getCollisionFrequency(), 0.1/microsecond)
self.assertEqual(integrator.getStepSize(), 1*femtosecond)
self.assertEqual(integrator.computeHeatBathEnergy(), 0.0*kilojoule_per_mole)
# Test setters
integrator.setTemperature(200*kelvin)
self.assertEqual(integrator.getTemperature(), 200*kelvin)
integrator.setCollisionFrequency(0.1/picosecond)
self.assertEqual(integrator.getCollisionFrequency(), 0.1/picosecond)
integrator.setRelativeTemperature(200*kelvin)
self.assertEqual(integrator.getRelativeTemperature(), 200*kelvin)
integrator.setRelativeCollisionFrequency(0.1/picosecond)
self.assertEqual(integrator.getRelativeCollisionFrequency(), 0.1/picosecond)
# Test bare consructor and addThermostat
integrator = NoseHooverIntegrator(1*femtosecond)
self.assertEqual(integrator.getStepSize(), 1*femtosecond)
integrator.addThermostat(300*kelvin, 0.1/microsecond, 3, 3, 3)
self.assertAlmostEqualUnit(integrator.getTemperature(), 300*kelvin)
self.assertAlmostEqualUnit(integrator.getCollisionFrequency(), 0.1/microsecond)
integrator = NoseHooverIntegrator(1*femtosecond)
integrator.addSubsystemThermostat([0], [], 300*kelvin, 0.1/microsecond, 1.0*kelvin, 1.0/microsecond, 3, 3, 3)
self.assertAlmostEqualUnit(integrator.getTemperature(), 300*kelvin)
self.assertAlmostEqualUnit(integrator.getCollisionFrequency(), 0.1/microsecond)
self.assertAlmostEqualUnit(integrator.getRelativeTemperature(), 1.0*kelvin)
self.assertAlmostEqualUnit(integrator.getRelativeCollisionFrequency(), 1.0/microsecond)
def testDrudeNoseHooverIntegrator(self):
""" Tests the DrudeNoseHooverIntegrator API features """
integrator = DrudeNoseHooverIntegrator(300, 0.1, 1.0, 1.0, 1)
self.assertEqual(integrator.getTemperature(0), 300*kelvin)
self.assertEqual(integrator.getCollisionFrequency(), 0.1/picosecond)
self.assertEqual(integrator.getRelativeTemperature(0), 1.0*kelvin)
self.assertEqual(integrator.getRelativeCollisionFrequency(), 1.0/picosecond)
self.assertEqual(integrator.getStepSize(), 1*picosecond)
integrator = DrudeNoseHooverIntegrator(300*kelvin, 0.1/microsecond, 5.0*kelvin, 0.01/microsecond, 1*femtosecond)
self.assertEqual(integrator.getTemperature(), 300*kelvin)
self.assertAlmostEqualUnit(integrator.getCollisionFrequency(), 0.1/microsecond)
self.assertEqual(integrator.getRelativeTemperature(), 5.0*kelvin)
self.assertAlmostEqualUnit(integrator.getRelativeCollisionFrequency(), 0.01/microsecond)
self.assertEqual(integrator.getStepSize(), 1*femtosecond)
def testAndersenThermostat(self):
""" Tests the AndersenThermostat API features """
force = AndersenThermostat(300*kelvin, 1/microsecond)
......
......@@ -349,6 +349,18 @@ class TestCharmmFiles(unittest.TestCase):
energy = context.getState(getEnergy=True).getPotentialEnergy().value_in_unit(kilocalories_per_mole)
self.assertAlmostEqual(energy, modeEnergy[abs(nbxmod)], delta=1e-3*abs(energy))
def test_Nonbonded_Exclusion(self):
"""Test that the 1-2, 1-3 and 1-4 pairs are correctly excluded or scaled."""
psf = CharmmPsfFile('systems/MoS2.psf')
pdb = PDBFile('systems/MoS2.pdb')
params = CharmmParameterSet('systems/MoS2.prm')
system = psf.createSystem(params, nonbondedMethod=NoCutoff)
context = Context(system, VerletIntegrator(1*femtoseconds), Platform.getPlatformByName('Reference'))
context.setPositions(pdb.positions)
energy = context.getState(getEnergy=True).getPotentialEnergy().value_in_unit(kilocalories_per_mole)
# Compare with value computed with NAMD.
self.assertAlmostEqual(energy, -2154.5539, delta=1e-3*abs(energy))
if __name__ == '__main__':
unittest.main()
......
import unittest
import warnings
import tempfile
from datetime import datetime, timedelta
from simtk.openmm import *
......@@ -120,5 +121,36 @@ class TestIntegrators(unittest.TestCase):
context.setPositions(pdb.positions)
integrator.step(10)
def testNoseHooverIntegrator(self):
"""Test partial thermostating in the NoseHooverIntegrator (only API)"""
pdb = PDBFile('systems/alanine-dipeptide-explicit.pdb')
ff = ForceField('amber99sbildn.xml', 'tip3p.xml')
system = ff.createSystem(pdb.topology, cutoffMethod=PME)
integrator = NoseHooverIntegrator(1.0*femtosecond)
integrator.addSubsystemThermostat(list(range(5)), [], 200*kelvin, 1/picosecond, 200*kelvin, 1/picosecond, 3,3,3)
con = Context(system, integrator)
con.setPositions(pdb.positions)
integrator.step(5)
self.assertNotEqual(integrator.computeHeatBathEnergy(), 0.0*kilojoule_per_mole)
def testDrudeNoseHooverIntegrator(self):
"""Test the DrudeNoseHooverIntegrator"""
warnings.filterwarnings('ignore', category=CharmmPSFWarning)
psf = CharmmPsfFile('systems/ala3_solv_drude.psf')
crd = CharmmCrdFile('systems/ala3_solv_drude.crd')
params = CharmmParameterSet('systems/toppar_drude_master_protein_2013e.str')
# Box dimensions (cubic box)
psf.setBox(33.2*angstroms, 33.2*angstroms, 33.2*angstroms)
system = psf.createSystem(params, nonbondedMethod=PME, ewaldErrorTolerance=0.0005)
integrator = DrudeNoseHooverIntegrator(300*kelvin, 1.0/picosecond, 1*kelvin, 10/picosecond, 0.001*picoseconds)
con = Context(system, integrator)
con.setPositions(crd.positions)
integrator.step(5)
self.assertNotEqual(integrator.computeHeatBathEnergy(), 0.0*kilojoule_per_mole)
if __name__ == '__main__':
unittest.main()
timestep 1.0 # fs
# initial config
coordinates MoS2.pdb
temperature 300K
outputname out
# force field params
structure MoS2.psf
parameters MoS2.prm
paraTypeCharmm on
vdwGeometricSigma no
LJcorrection no
exclude scaled1-4
1-4scaling 1.0
switching off
cutoff 100 # A. actually no cutoff
pairlistdist 100
run 20
TITLE created by fftool
REMARK SIMBOX
CRYST1 50.000 50.000 50.000 90.00 90.00 90.00 P 1 1
ATOM 1 Mo01 MoS2 1 36.632 11.332 15.080 1.00 0.00 Mo
ATOM 2 Mo02 MoS2 1 48.105 10.837 4.221 1.00 0.00 Mo
ATOM 3 Mo03 MoS2 1 48.501 1.004 16.589 1.00 0.00 Mo
ATOM 4 Mo04 MoS2 1 39.006 9.266 15.382 1.00 0.00 Mo
ATOM 5 Mo05 MoS2 1 45.811 10.936 6.393 1.00 0.00 Mo
ATOM 6 Mo06 MoS2 1 48.422 2.971 14.116 1.00 0.00 Mo
ATOM 7 Mo07 MoS2 1 48.184 8.870 6.695 1.00 0.00 Mo
ATOM 8 Mo08 MoS2 1 38.927 11.233 12.909 1.00 0.00 Mo
ATOM 9 Mo09 MoS2 1 46.127 3.070 16.287 1.00 0.00 Mo
ATOM 10 Mo10 MoS2 1 41.380 7.201 15.684 1.00 0.00 Mo
ATOM 11 Mo11 MoS2 1 43.516 11.035 8.565 1.00 0.00 Mo
ATOM 12 Mo12 MoS2 1 48.343 4.937 11.642 1.00 0.00 Mo
ATOM 13 Mo13 MoS2 1 48.264 6.904 9.168 1.00 0.00 Mo
ATOM 14 Mo14 MoS2 1 41.221 11.134 10.737 1.00 0.00 Mo
ATOM 15 Mo15 MoS2 1 43.754 5.135 15.986 1.00 0.00 Mo
ATOM 16 Mo16 MoS2 1 36.553 13.298 12.607 1.00 0.00 Mo
ATOM 17 Mo17 MoS2 1 36.237 21.164 2.712 1.00 0.00 Mo
ATOM 18 Mo18 MoS2 1 45.732 12.902 3.919 1.00 0.00 Mo
ATOM 19 Mo19 MoS2 1 41.301 9.167 13.210 1.00 0.00 Mo
ATOM 20 Mo20 MoS2 1 45.890 8.969 8.867 1.00 0.00 Mo
ATOM 21 Mo21 MoS2 1 46.048 5.036 13.814 1.00 0.00 Mo
ATOM 22 Mo22 MoS2 1 43.674 7.102 13.512 1.00 0.00 Mo
ATOM 23 Mo23 MoS2 1 43.595 9.068 11.038 1.00 0.00 Mo
ATOM 24 Mo24 MoS2 1 45.969 7.003 11.340 1.00 0.00 Mo
ATOM 25 Mo25 MoS2 1 36.474 15.265 10.133 1.00 0.00 Mo
ATOM 26 Mo26 MoS2 1 38.610 19.099 3.014 1.00 0.00 Mo
ATOM 27 Mo27 MoS2 1 43.437 13.001 6.091 1.00 0.00 Mo
ATOM 28 Mo28 MoS2 1 43.358 14.968 3.618 1.00 0.00 Mo
ATOM 29 Mo29 MoS2 1 36.316 19.198 5.186 1.00 0.00 Mo
ATOM 30 Mo30 MoS2 1 38.848 13.199 10.435 1.00 0.00 Mo
ATOM 31 Mo31 MoS2 1 36.395 17.231 7.660 1.00 0.00 Mo
ATOM 32 Mo32 MoS2 1 40.984 17.033 3.316 1.00 0.00 Mo
ATOM 33 Mo33 MoS2 1 41.142 13.100 8.263 1.00 0.00 Mo
ATOM 34 Mo34 MoS2 1 38.769 15.166 7.961 1.00 0.00 Mo
ATOM 35 Mo35 MoS2 1 38.689 17.132 5.488 1.00 0.00 Mo
ATOM 36 Mo36 MoS2 1 41.063 15.067 5.790 1.00 0.00 Mo
ATOM 37 S01 MoS2 1 48.074 13.199 4.080 1.00 0.00 S
ATOM 38 S02 MoS2 1 36.601 13.694 14.939 1.00 0.00 S
ATOM 39 S03 MoS2 1 36.205 23.526 2.571 1.00 0.00 S
ATOM 40 S04 MoS2 1 46.502 11.163 2.512 1.00 0.00 S
ATOM 41 S05 MoS2 1 35.029 11.658 13.371 1.00 0.00 S
ATOM 42 S06 MoS2 1 34.633 21.490 1.003 1.00 0.00 S
ATOM 43 S07 MoS2 1 45.700 15.264 3.778 1.00 0.00 S
ATOM 44 S08 MoS2 1 38.895 13.595 12.767 1.00 0.00 S
ATOM 45 S09 MoS2 1 36.284 21.560 5.045 1.00 0.00 S
ATOM 46 S10 MoS2 1 44.128 13.228 2.210 1.00 0.00 S
ATOM 47 S11 MoS2 1 37.323 11.559 11.199 1.00 0.00 S
ATOM 48 S12 MoS2 1 34.712 19.524 3.477 1.00 0.00 S
ATOM 49 S13 MoS2 1 36.522 15.660 12.466 1.00 0.00 S
ATOM 50 S14 MoS2 1 45.779 13.298 6.252 1.00 0.00 S
ATOM 51 S15 MoS2 1 38.579 21.461 2.873 1.00 0.00 S
ATOM 52 S16 MoS2 1 34.950 13.624 10.898 1.00 0.00 S
ATOM 53 S17 MoS2 1 44.207 11.262 4.684 1.00 0.00 S
ATOM 54 S18 MoS2 1 37.007 19.425 1.305 1.00 0.00 S
ATOM 55 S19 MoS2 1 43.326 17.330 3.477 1.00 0.00 S
ATOM 56 S20 MoS2 1 41.190 13.496 10.596 1.00 0.00 S
ATOM 57 S21 MoS2 1 36.363 19.593 7.519 1.00 0.00 S
ATOM 58 S22 MoS2 1 41.754 15.294 1.909 1.00 0.00 S
ATOM 59 S23 MoS2 1 39.618 11.460 9.028 1.00 0.00 S
ATOM 60 S24 MoS2 1 34.791 17.557 5.951 1.00 0.00 S
ATOM 61 S25 MoS2 1 36.442 17.627 9.992 1.00 0.00 S
ATOM 62 S26 MoS2 1 43.484 13.397 8.424 1.00 0.00 S
ATOM 63 S27 MoS2 1 40.952 19.395 3.175 1.00 0.00 S
ATOM 64 S28 MoS2 1 34.870 15.591 8.424 1.00 0.00 S
ATOM 65 S29 MoS2 1 41.912 11.361 6.856 1.00 0.00 S
ATOM 66 S30 MoS2 1 39.380 17.359 1.607 1.00 0.00 S
ATOM 67 S31 MoS2 1 48.153 11.232 6.554 1.00 0.00 S
ATOM 68 S32 MoS2 1 48.469 3.366 16.448 1.00 0.00 S
ATOM 69 S33 MoS2 1 38.974 11.628 15.241 1.00 0.00 S
ATOM 70 S34 MoS2 1 46.581 9.196 4.986 1.00 0.00 S
ATOM 71 S35 MoS2 1 46.897 1.331 14.880 1.00 0.00 S
ATOM 72 S36 MoS2 1 37.402 9.593 13.673 1.00 0.00 S
ATOM 73 S37 MoS2 1 43.405 15.363 5.950 1.00 0.00 S
ATOM 74 S38 MoS2 1 38.816 15.561 10.294 1.00 0.00 S
ATOM 75 S39 MoS2 1 38.658 19.494 5.347 1.00 0.00 S
ATOM 76 S40 MoS2 1 41.833 13.327 4.382 1.00 0.00 S
ATOM 77 S41 MoS2 1 37.244 13.525 8.726 1.00 0.00 S
ATOM 78 S42 MoS2 1 37.086 17.458 3.779 1.00 0.00 S
ATOM 79 S43 MoS2 1 41.032 17.429 5.648 1.00 0.00 S
ATOM 80 S44 MoS2 1 41.111 15.462 8.122 1.00 0.00 S
ATOM 81 S45 MoS2 1 38.737 17.528 7.820 1.00 0.00 S
ATOM 82 S46 MoS2 1 39.460 15.393 4.080 1.00 0.00 S
ATOM 83 S47 MoS2 1 39.539 13.426 6.554 1.00 0.00 S
ATOM 84 S48 MoS2 1 37.165 15.492 6.252 1.00 0.00 S
ATOM 85 S49 MoS2 1 48.232 9.266 9.027 1.00 0.00 S
ATOM 86 S50 MoS2 1 46.096 5.432 16.146 1.00 0.00 S
ATOM 87 S51 MoS2 1 41.269 11.529 13.069 1.00 0.00 S
ATOM 88 S52 MoS2 1 46.660 7.230 7.459 1.00 0.00 S
ATOM 89 S53 MoS2 1 44.524 3.396 14.578 1.00 0.00 S
ATOM 90 S54 MoS2 1 39.697 9.494 11.501 1.00 0.00 S
ATOM 91 S55 MoS2 1 41.348 9.563 15.543 1.00 0.00 S
ATOM 92 S56 MoS2 1 48.390 5.333 13.974 1.00 0.00 S
ATOM 93 S57 MoS2 1 45.858 11.331 8.726 1.00 0.00 S
ATOM 94 S58 MoS2 1 39.776 7.527 13.975 1.00 0.00 S
ATOM 95 S59 MoS2 1 46.818 3.297 12.406 1.00 0.00 S
ATOM 96 S60 MoS2 1 44.286 9.296 7.158 1.00 0.00 S
ATOM 97 S61 MoS2 1 48.311 7.299 11.501 1.00 0.00 S
ATOM 98 S62 MoS2 1 43.722 7.497 15.845 1.00 0.00 S
ATOM 99 S63 MoS2 1 43.564 11.430 10.897 1.00 0.00 S
ATOM 100 S64 MoS2 1 46.739 5.264 9.933 1.00 0.00 S
ATOM 101 S65 MoS2 1 42.150 5.462 14.277 1.00 0.00 S
ATOM 102 S66 MoS2 1 41.992 9.395 9.329 1.00 0.00 S
ATOM 103 S67 MoS2 1 45.937 9.365 11.199 1.00 0.00 S
ATOM 104 S68 MoS2 1 46.017 7.398 13.673 1.00 0.00 S
ATOM 105 S69 MoS2 1 43.643 9.464 13.371 1.00 0.00 S
ATOM 106 S70 MoS2 1 44.365 7.329 9.631 1.00 0.00 S
ATOM 107 S71 MoS2 1 44.445 5.363 12.105 1.00 0.00 S
ATOM 108 S72 MoS2 1 42.071 7.428 11.803 1.00 0.00 S
END
* CHARMM FORCE FIELD GENERATED BY fftool
*
ATOMS
MASS 1 MoS 95.9370
MASS 2 SMo 32.0640
BONDS
MoS SMo 51.422084 2.410000
ANGLES
SMo MoS SMo 141.933556 83.800000
MoS SMo MoS 244.980880 83.800000
DIHEDRALS
NONBONDED
!VLJ = Eps,i,j[(Rmin,i,j/ri,j)**12 - 2(Rmin,i,j/ri,j)**6]
!epsilon: kcal/mole, Eps,i,j = sqrt(eps,i * eps,j)
!Rmin/2: A, Rmin,i,j = Rmin/2,i + Rmin/2,j
!atom ignored epsilon Rmin/2 ignored eps,1-4 Rmin/2,1-4
MoS 0.000000 -0.115918 2.486253 0.000000 -0.057959 2.486253
SMo 0.000000 -0.498327 1.874512 0.000000 -0.249163 1.874512
END
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment