"docs-source/vscode:/vscode.git/clone" did not exist on "7216f935dc97600d2072513d8859950038656391"
Unverified Commit 50efef13 authored by Andy Simmonett's avatar Andy Simmonett
Browse files

Start implementing changes from review - CUDA broken

parent 3251d4e4
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
#include "openmm/VariableLangevinIntegrator.h" #include "openmm/VariableLangevinIntegrator.h"
#include "openmm/VariableVerletIntegrator.h" #include "openmm/VariableVerletIntegrator.h"
#include "openmm/VerletIntegrator.h" #include "openmm/VerletIntegrator.h"
#include "openmm/VelocityVerletIntegrator.h" #include "openmm/NoseHooverIntegrator.h"
#include <iosfwd> #include <iosfwd>
#include <set> #include <set>
#include <string> #include <string>
...@@ -1075,7 +1075,7 @@ public: ...@@ -1075,7 +1075,7 @@ public:
* @param system the System this kernel will be applied to * @param system the System this kernel will be applied to
* @param integrator the VelocityVerletIntegrator this kernel will be used for * @param integrator the VelocityVerletIntegrator this kernel will be used for
*/ */
virtual void initialize(const System& system, const VelocityVerletIntegrator& integrator) = 0; virtual void initialize(const System& system, const NoseHooverIntegrator& integrator) = 0;
/** /**
* Execute the kernel. * Execute the kernel.
* *
...@@ -1084,14 +1084,14 @@ public: ...@@ -1084,14 +1084,14 @@ public:
* @param forcesAreValid a reference to the parent integrator's boolean for keeping * @param forcesAreValid a reference to the parent integrator's boolean for keeping
* track of the validity of the current forces. * track of the validity of the current forces.
*/ */
virtual void execute(ContextImpl& context, const VelocityVerletIntegrator& integrator, bool &forcesAreValid) = 0; virtual void execute(ContextImpl& context, const NoseHooverIntegrator& integrator, bool &forcesAreValid) = 0;
/** /**
* Compute the kinetic energy. * Compute the kinetic energy.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the VelocityVerletIntegrator this kernel is being used for * @param integrator the VelocityVerletIntegrator this kernel is being used for
*/ */
virtual double computeKineticEnergy(ContextImpl& context, const VelocityVerletIntegrator& integrator) = 0; virtual double computeKineticEnergy(ContextImpl& context, const NoseHooverIntegrator& integrator) = 0;
}; };
/** /**
...@@ -1346,11 +1346,11 @@ public: ...@@ -1346,11 +1346,11 @@ public:
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param noseHooverChain the object describing the chain to be propagated. * @param noseHooverChain the object describing the chain to be propagated.
* @param kineticEnergy the kineticEnergy of the particles being thermostated by this chain. * @param kineticEnergy the {center of mass, relative} kineticEnergies of the particles being thermostated by this chain.
* @param timeStep the time step used by the integrator. * @param timeStep the time step used by the integrator.
* @return the velocity scale factor to apply to the particles associated with this heat bath. * @return the velocity scale factor to apply to the particles associated with this heat bath.
*/ */
virtual double propagateChain(ContextImpl& context, const NoseHooverChain &noseHooverChain, double kineticEnergy, double timeStep) = 0; virtual std::pair<double, double> propagateChain(ContextImpl& context, const NoseHooverChain &noseHooverChain, std::pair<double, double> kineticEnergy, double timeStep) = 0;
/** /**
* Execute the kernal that computes the total (kinetic + potential) heat bath energy. * Execute the kernal that computes the total (kinetic + potential) heat bath energy.
* *
...@@ -1367,15 +1367,15 @@ public: ...@@ -1367,15 +1367,15 @@ public:
* @param noseHooverChain the chain whose energy is to be determined. * @param noseHooverChain the chain whose energy is to be determined.
* @param downloadValue whether the computed value should be downloaded and returned. * @param downloadValue whether the computed value should be downloaded and returned.
*/ */
virtual double computeMaskedKineticEnergy(ContextImpl& context, const NoseHooverChain &noseHooverChain, bool downloadValue) = 0; virtual std::pair<double, double> computeMaskedKineticEnergy(ContextImpl& context, const NoseHooverChain &noseHooverChain, bool downloadValue) = 0;
/** /**
* Execute the kernel that scales the velocities of particles associated with a nose hoover chain * Execute the kernel that scales the velocities of particles associated with a nose hoover chain
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined. * @param noseHooverChain the chain whose energy is to be determined.
* @param scaleFactor the multiplicative factor by which velocities are scaled. * @param scaleFactor the multiplicative factor by which {absolute, relative} velocities are scaled.
*/ */
virtual void scaleVelocities(ContextImpl& context, const NoseHooverChain &noseHooverChain, double scaleFactor) = 0; virtual void scaleVelocities(ContextImpl& context, const NoseHooverChain &noseHooverChain, std::pair<double, double> scaleFactor) = 0;
}; };
/** /**
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
#include "openmm/VariableVerletIntegrator.h" #include "openmm/VariableVerletIntegrator.h"
#include "openmm/Vec3.h" #include "openmm/Vec3.h"
#include "openmm/VerletIntegrator.h" #include "openmm/VerletIntegrator.h"
#include "openmm/VelocityVerletIntegrator.h" #include "openmm/NoseHooverIntegrator.h"
#include "openmm/VirtualSite.h" #include "openmm/VirtualSite.h"
#include "openmm/Platform.h" #include "openmm/Platform.h"
#include "openmm/serialization/XmlSerializer.h" #include "openmm/serialization/XmlSerializer.h"
......
...@@ -49,6 +49,12 @@ namespace OpenMM { ...@@ -49,6 +49,12 @@ namespace OpenMM {
* *
* where the total number of timesteps used to propagate the chain in each step is * where the total number of timesteps used to propagate the chain in each step is
* the number of MTS steps multiplied by the number of terms in the Yoshida-Suzuki decomposition. * the number of MTS steps multiplied by the number of terms in the Yoshida-Suzuki decomposition.
*
* Two types of NHC may be created. The first is a simple thermostat that couples with a given subset
* of the atoms within a system, controling their absolute motion. The second is more elaborate and
* can thermostat tethered pairs of atoms and in this case two thermostats are created: one that controls
* the absolute center of mass velocity of each pair and another that controls their motion relative to
* one another.
*/ */
class OPENMM_EXPORT NoseHooverChain { class OPENMM_EXPORT NoseHooverChain {
...@@ -56,23 +62,29 @@ public: ...@@ -56,23 +62,29 @@ public:
/** /**
* Create a NoseHooverChain. * Create a NoseHooverChain.
* *
* @param defaultTemperature the default temperature of the heat bath (in Kelvin) * @param defaultTemperature the default temperature of the heat bath for absolute motion (in Kelvin)
* @param defaultCollisionFrequency the default collision frequency (in 1/ps) * @param defaultRelativeTemperature the default temperature of the heat bath for relative motion(in Kelvin).
* @param defaultNumDOFs the default number of degrees of freedom in the particles that * This is only used if the list of thermostated pairs is not empty.
* interact with this chain * @param defaultCollisionFrequency the default collision frequency for absolute motion (in 1/ps)
* @param defaultChainLength the default length of (number of particles in) this heat bath * @param defaultRelativeCollisionFrequency the default collision frequency for relative motion(in 1/ps).
* @param defaultNumMTS the default number of multi time steps used to propagate this chain * This is only used if the list of thermostated pairs is not empty.
* @param defaultNumYoshidaSuzuki the default number of Yoshida Suzuki steps used to propagate this chain (1, 3, or 5). * @param defaultNumDOFs the default number of degrees of freedom in the particles that
* @param defaultChainID the default chain id used to distinguish this Nose-Hoover chain from others that may * interact with this chain
* be used to control a different set of particles, e.g. for Drude oscillators * @param defaultChainLength the default length of (number of particles in) this heat bath
* @param thermostatedAtoms the list of atoms to be handled by this thermostat * @param defaultNumMTS the default number of multi time steps used to propagate this chain
* @param parentAtoms the list of parent atoms, if this thermostat handles Drude particles. Empty vector otherwise. * @param defaultNumYoshidaSuzuki the default number of Yoshida Suzuki steps used to propagate this chain (1, 3, or 5).
* @param defaultChainID the default chain id used to distinguish this Nose-Hoover chain from others that may
* be used to control a different set of particles, e.g. for Drude oscillators
* @param thermostatedAtoms the list of atoms to be handled by this thermostat
* @param thermostatedPairs the list of connected pairs to be thermostated; their absolute center of mass motion will
* be thermostated independently from their motion relative to one another.
*/ */
NoseHooverChain(double defaultTemperature, double defaultCollisionFrequency, int defaultNumDOFs, int defaultChainLength, NoseHooverChain(double defaultTemperature, double defaultRelativeTemperature, double defaultCollisionFrequency,
double defaultRelativeCollisionFrequency, int defaultNumDOFs, int defaultChainLength,
int defaultNumMTS, int defaultNumYoshidaSuzuki, int defaultChainID, int defaultNumMTS, int defaultNumYoshidaSuzuki, int defaultChainID,
const std::vector<int>& thermostatedAtoms, const std::vector<int>& parentAtoms); const std::vector<int>& thermostatedAtoms, const std::vector< std::pair< int, int > > &thermostatedPairs);
/** /**
* Get the default temperature of the heat bath (in Kelvin). * Get the default temperature of the heat bath for treating absolute particle motion (in Kelvin).
* *
* @return the default temperature of the heat bath, measured in Kelvin. * @return the default temperature of the heat bath, measured in Kelvin.
*/ */
...@@ -80,8 +92,8 @@ public: ...@@ -80,8 +92,8 @@ public:
return defaultTemp; return defaultTemp;
} }
/** /**
* Set the default temperature of the heat bath. This will affect any new Contexts you create, * Set the default temperature of the heat bath for treating absolute particle motion.
* but not ones that already exist. * This will affect any new Contexts you create, but not ones that already exist.
* *
* @param temperature the default temperature of the heat bath (in Kelvin) * @param temperature the default temperature of the heat bath (in Kelvin)
*/ */
...@@ -89,7 +101,25 @@ public: ...@@ -89,7 +101,25 @@ public:
defaultTemp = temperature; defaultTemp = temperature;
} }
/** /**
* Get the default collision frequency (in 1/ps). * Get the default temperature of the heat bath for treating relative particle motion (in Kelvin).
*
* @return the default temperature of the heat bath, measured in Kelvin.
*/
double getDefaultRelativeTemperature() const {
return defaultRelativeTemp;
}
/**
* Set the default temperature of the heat bath for treating relative motion if this thermostat has
* been set up to treat connected pairs of atoms. This will affect any new Contexts you create,
* but not ones that already exist.
*
* @param temperature the default temperature of the heat bath for relative motion (in Kelvin)
*/
void setDefaultRelativeTemperature(double temperature) {
defaultRelativeTemp = temperature;
}
/**
* Get the default collision frequency for treating absolute particle motion (in 1/ps).
* *
* @return the default collision frequency, measured in 1/ps. * @return the default collision frequency, measured in 1/ps.
*/ */
...@@ -97,14 +127,32 @@ public: ...@@ -97,14 +127,32 @@ public:
return defaultFreq; return defaultFreq;
} }
/** /**
* Set the default collision frequency. This will affect any new Contexts you create, * Set the default collision frequency for treating absolute particle motion.
* but not those that already exist. * This will affect any new Contexts you create, but not those that already exist.
* *
* @param frequency the default collision frequency (in 1/ps) * @param frequency the default collision frequency (in 1/ps)
*/ */
void setDefaultCollisionFrequency(double frequency) { void setDefaultCollisionFrequency(double frequency) {
defaultFreq = frequency; defaultFreq = frequency;
} }
/**
* Get the default collision frequency for treating relative particle motion (in 1/ps).
*
* @return the default collision frequency, measured in 1/ps.
*/
double getDefaultRelativeCollisionFrequency() const {
return defaultRelativeFreq;
}
/**
* Set the default collision frequency for treating relative particle motion if this thermostat has
* been set up to handle connected pairs of atoms. This will affect any new Contexts you create,
* but not those that already exist.
*
* @param frequency the default collision frequency (in 1/ps)
*/
void setDefaultRelativeCollisionFrequency(double frequency) {
defaultRelativeFreq = frequency;
}
/** /**
* Get the default number of degrees of freedom in the particles controled by this heat bath. * Get the default number of degrees of freedom in the particles controled by this heat bath.
* *
...@@ -209,26 +257,22 @@ public: ...@@ -209,26 +257,22 @@ public:
thermostatedAtoms = atomIDs; thermostatedAtoms = atomIDs;
} }
/** /**
* In case this thermostat handles the kinetic energy of Drude particles relative to the * Get the list of any connected pairs to be handled by this thermostat.
* atoms that they are attached to, get the atom ids of all parent atoms.
* If this is a regular thermostat, returns an empty vector. * If this is a regular thermostat, returns an empty vector.
* *
* @returns ids of all parent atoms * @returns list of connected pairs.
*/ */
const std::vector<int>& getParentAtoms() const { const std::vector< std::pair< int, int > >& getThermostatedPairs() const {
return parentAtoms; return thermostatedPairs;
} }
/** /**
* In case this thermostat handles the kinetic energy of Drude particles * In case this thermostat handles the kinetic energy of Drude particles
* set the atom IDs of all parent atoms. * set the atom IDs of all parent atoms.
* *
* @param parentIDs * @param pairIDs the list of connected pairs to thermostat.
*/ */
void setParentAtoms(const std::vector<int>& parentIDs){ void setThermostatedPairs(const std::vector< std::pair< int, int > >& pairIDs){
if (not parentIDs.size() == thermostatedAtoms.size()){ thermostatedPairs = pairIDs;
throw OpenMMException("The number of parent atoms has to be the same as the number of thermostated atoms, or zero.");
}
parentAtoms = parentIDs;
} }
/** /**
* Get the default weights used in the Yoshida Suzuki multi time step decomposition (dimensionless) * Get the default weights used in the Yoshida Suzuki multi time step decomposition (dimensionless)
...@@ -246,11 +290,12 @@ public: ...@@ -246,11 +290,12 @@ public:
return false; return false;
} }
private: private:
double defaultTemp, defaultFreq; //, defaultTimeStep; double defaultTemp, defaultFreq, defaultRelativeTemp, defaultRelativeFreq;
int defaultNumDOFs, defaultChainLength, defaultNumMTS, defaultNumYS; int defaultNumDOFs, defaultChainLength, defaultNumMTS, defaultNumYS;
// The suffix used to distinguish NH chains, e.g. for Drude particles vs. regular particles. // The suffix used to distinguish NH chains, e.g. for Drude particles vs. regular particles.
int defaultChainID; int defaultChainID;
std::vector<int> thermostatedAtoms, parentAtoms; std::vector<int> thermostatedAtoms;
std::vector<std::pair<int, int>> thermostatedPairs;
}; };
} // namespace OpenMM } // namespace OpenMM
......
#ifndef OPENMM_VELOCITYVERLETINTEGRATOR_H_ #ifndef OPENMM_NOSEHOOVERINTEGRATOR_H_
#define OPENMM_VELOCITYVERLETINTEGRATOR_H_ #define OPENMM_NOSEHOOVERINTEGRATOR_H_
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* OpenMM * * OpenMM *
...@@ -47,16 +47,32 @@ class System; ...@@ -47,16 +47,32 @@ class System;
* thermostats, using the velocity Verlet propagation algorithm. * thermostats, using the velocity Verlet propagation algorithm.
*/ */
class OPENMM_EXPORT VelocityVerletIntegrator : public Integrator { class OPENMM_EXPORT NoseHooverIntegrator : public Integrator {
public: public:
/** /**
* Create a VelocityVerletIntegrator. * Create a NoseHooverIntegrator. This version creates a bare velocity Verlet integrator
* with no thermostats; any thermostats should be added by calling addThermostat.
* *
* @param stepSize the step size with which to integrate the system (in picoseconds) * @param stepSize the step size with which to integrate the system (in picoseconds)
*/ */
explicit VelocityVerletIntegrator(double stepSize); explicit NoseHooverIntegrator(double stepSize);
/**
* Create a NoseHooverIntegrator.
*
* @param stepSize the step size with which to integrate the system (in picoseconds)
* @param system the system to be thermostated. Note: this must be setup, i.e. all
* particles should have been added, before calling this function.
* @param temperature the target temperature for the system.
* @param collisionFrequency the frequency of the interaction with the heat bath (in 1/ps).
* @param chainLength the number of beads in the Nose-Hoover chain.
* @param numMTS the number of step in the multiple time step chain propagation algorithm.
* @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition
* used in the chain propagation algorithm (must be 1, 3, or 5).
*/
explicit NoseHooverIntegrator(double stepSize, System &system, double temperature, int collisionFrequnency,
int chainLength = 3, int numMTS = 3, int numYoshidaSuzuki = 3);
virtual ~VelocityVerletIntegrator(); virtual ~NoseHooverIntegrator();
/** /**
* Advance a simulation through time by taking a series of time steps. * Advance a simulation through time by taking a series of time steps.
* *
...@@ -64,7 +80,7 @@ public: ...@@ -64,7 +80,7 @@ public:
*/ */
void step(int steps); void step(int steps);
/** /**
* Add a Nose-Hoover Chain thermostat to control the temperature of the system * Add a simple Nose-Hoover Chain thermostat to control the temperature of the full system
* *
* @param system the system to be thermostated. Note: this must be setup, i.e. all * @param system the system to be thermostated. Note: this must be setup, i.e. all
* particles should have been added, before calling this function. * particles should have been added, before calling this function.
...@@ -75,28 +91,38 @@ public: ...@@ -75,28 +91,38 @@ public:
* @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition * @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition
* used in the chain propagation algorithm (must be 1, 3, or 5). * used in the chain propagation algorithm (must be 1, 3, or 5).
*/ */
int addNoseHooverChainThermostat(System& system, double temperature, double collisionFrequency, int addThermostat(System& system, double temperature, double collisionFrequency,
int chainLength, int numMTS, int numYoshidaSuzuki); int chainLength, int numMTS, int numYoshidaSuzuki);
/** /**
* Add a Nose-Hoover Chain thermostat to control the temperature of the system * Add a Nose-Hoover Chain thermostat to control the temperature of a collection of atoms and/or pairs of
* connected atoms within the full system. A list of atoms defining the atoms to be thermostated is
* provided and the thermostat will only control members of that list. Additionally a list of pairs of
* connected atoms may be provided; in this case both the center of mass absolute motion of each pair is
* controlled as well as their motion relative to each other, which is independently thermostated.
* *
* @param system the system to be thermostated. Note: this must be setup, i.e. all * @param system the system to be thermostated. Note: this must be setup, i.e. all
* particles should have been added, before calling this function. * particles should have been added, before calling this function.
* @param mask list of particle ids to be thermostated. * @param thermostatedParticles list of particle ids to be thermostated.
* @param parents either an empty list of a list describing the parent atoms that each thermostated * @param thermostatedPairs a list of pairs of connected atoms whose absolute center of mass motion
* atom is connected to. * and motion relative to one another will be independently thermostated.
* @param temperature the target temperature for the system. * @param temperature the target temperature for each pair's absolute of center of mass motion.
* @param collisionFrequency the frequency of the interaction with the heat bath (in 1/ps). * @param relativeTemperature the target temperature for each pair's relative motion.
* @param collisionFrequency the frequency of the interaction with the heat bath for the
* pairs' center of mass motion (in 1/ps).
* @param relativeCollisionFrequency the frequency of the interaction with the heat bath for the
* pairs' relative motion (in 1/ps).
* @param chainLength the number of beads in the Nose-Hoover chain. * @param chainLength the number of beads in the Nose-Hoover chain.
* @param numMTS the number of step in the multiple time step chain propagation algorithm. * @param numMTS the number of step in the multiple time step chain propagation algorithm.
* @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition * @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition
* used in the chain propagation algorithm (must be 1, 3, or 5). * used in the chain propagation algorithm (must be 1, 3, or 5).
*/ */
int addMaskedNoseHooverChainThermostat(System& system, const std::vector<int>& mask, const std::vector<int>& parents, int addSubsystemThermostat(System& system, const std::vector<int>& thermostatedParticles,
double temperature, double collisionFrequency, const std::vector< std::pair< int, int> >& thermostatedPairs,
int chainLength, int numMTS, int numYoshidaSuzuki); double temperature, double relativeTemperature,
double collisionFrequency, double relativeCollisionFrequency,
int chainLength = 3, int numMTS = 3, int numYoshidaSuzuki = 3);
/** /**
* Get the temperature of the i-th chain (in Kelvin). * Get the temperature of the i-th chain for controling absolute particle motion (in Kelvin).
* *
* @param chainID the index of the Nose-Hoover chain (default=0). * @param chainID the index of the Nose-Hoover chain (default=0).
* *
...@@ -104,14 +130,29 @@ public: ...@@ -104,14 +130,29 @@ public:
*/ */
double getTemperature(int chainID=0) const; double getTemperature(int chainID=0) const;
/** /**
* set the temperature of the i-th chain. * set the (absolute motion) temperature of the i-th chain.
* *
* @param temperature the temperature for the Nose-Hoover chain thermostat (in Kelvin). * @param temperature the temperature for the Nose-Hoover chain thermostat (in Kelvin).
* @param chainID The id of the Nose-Hoover chain for which the temperature is set (default=0). * @param chainID The id of the Nose-Hoover chain for which the temperature is set (default=0).
*/ */
void setTemperature(double temperature, int chainID=0); void setTemperature(double temperature, int chainID=0);
/** /**
* Get the collision frequency of the i-th chain (in 1/picosecond). * Get the temperature of the i-th chain for controling pairs' relative particle motion (in Kelvin).
*
* @param chainID the index of the Nose-Hoover chain (default=0).
*
* @return the temperature.
*/
double getRelativeTemperature(int chainID=0) const;
/**
* set the (relative pair motion) temperature of the i-th chain.
*
* @param temperature the temperature for the Nose-Hoover chain thermostat (in Kelvin).
* @param chainID The id of the Nose-Hoover chain for which the temperature is set (default=0).
*/
void setRelativeTemperature(double temperature, int chainID=0);
/**
* Get the collision frequency for absolute motion of the i-th chain (in 1/picosecond).
* *
* @param chainID the index of the Nose-Hoover chain (default=0). * @param chainID the index of the Nose-Hoover chain (default=0).
* *
...@@ -119,12 +160,27 @@ public: ...@@ -119,12 +160,27 @@ public:
*/ */
double getCollisionFrequency(int chainID=0) const; double getCollisionFrequency(int chainID=0) const;
/** /**
* Set the collision frequency of the i-th chain. * Set the collision frequency for absolute motion of the i-th chain.
* *
* @param frequency the collision frequency in picosecond. * @param frequency the collision frequency in picosecond.
* @param chainID the index of the Nose-Hoover chain (default=0). * @param chainID the index of the Nose-Hoover chain (default=0).
*/ */
void setCollisionFrequency(double frequency, int chainID=0); void setCollisionFrequency(double frequency, int chainID=0);
/**
* Get the collision frequency for pairs' relative motion of the i-th chain (in 1/picosecond).
*
* @param chainID the index of the Nose-Hoover chain (default=0).
*
* @return the collision frequency.
*/
double getRelativeCollisionFrequency(int chainID=0) const;
/**
* Set the collision frequency for pairs' relative motion of the i-th chain.
*
* @param frequency the collision frequency in picosecond.
* @param chainID the index of the Nose-Hoover chain (default=0).
*/
void setRelativeCollisionFrequency(double frequency, int chainID=0);
/** /**
* Compute the total (potential + kinetic) heat bath energy for all heat baths * Compute the total (potential + kinetic) heat bath energy for all heat baths
* associated with this integrator, at the current time. * associated with this integrator, at the current time.
...@@ -154,11 +210,11 @@ protected: ...@@ -154,11 +210,11 @@ protected:
* Advance any Nose-Hoover chains associated with this integrator and determine * Advance any Nose-Hoover chains associated with this integrator and determine
* scale factor for the velocities. * scale factor for the velocities.
* *
* @param kineticEnergy the kinetic energy of the system that the chain is thermostating * @param kineticEnergy the {absolute, relative} kinetic energies of the system that the chain is thermostating
* @param chainID id of the Nose-Hoover-Chain * @param chainID id of the Nose-Hoover-Chain
* @return the scale factor to be applied to the velocities of the particles thermostated by the chain. * @return the scale factor to be applied to the velocities of the particles thermostated by the chain.
*/ */
double propagateChain(double kineticEnergy, int chainID=0); std::pair<double, double> propagateChain(std::pair<double, double> kineticEnergy, int chainID=0);
/** /**
* This will be called by the Context when it is created. It informs the Integrator * This will be called by the Context when it is created. It informs the Integrator
* of what context it will be integrating, and gives it a chance to do any necessary initialization. * of what context it will be integrating, and gives it a chance to do any necessary initialization.
...@@ -186,4 +242,4 @@ protected: ...@@ -186,4 +242,4 @@ protected:
} // namespace OpenMM } // namespace OpenMM
#endif /*OPENMM_VELOCITYVERLETINTEGRATOR_H_*/ #endif /*OPENMM_NOSEHOOVERINTEGRATOR_H_*/
...@@ -34,13 +34,15 @@ ...@@ -34,13 +34,15 @@
using namespace OpenMM; using namespace OpenMM;
NoseHooverChain::NoseHooverChain(double defaultTemperature, double defaultCollisionFrequency, NoseHooverChain::NoseHooverChain(double defaultTemperature, double defaultRelativeTemperature, double defaultCollisionFrequency,
double defaultRelativeCollisionFrequency,
int defaultNumDOFs, int defaultChainLength, int defaultNumMTS, int defaultNumDOFs, int defaultChainLength, int defaultNumMTS,
int defaultNumYoshidaSuzuki, int defaultChainID, int defaultNumYoshidaSuzuki, int defaultChainID,
const std::vector<int>& thermostatedAtoms, const std::vector<int>& parentAtoms): const std::vector<int>& thermostatedAtoms, const std::vector<std::pair<int, int> > &thermostatedPairs):
defaultTemp(defaultTemperature), defaultFreq(defaultCollisionFrequency), defaultNumDOFs(defaultNumDOFs), defaultTemp(defaultTemperature), defaultRelativeTemp(defaultRelativeTemperature), defaultFreq(defaultCollisionFrequency),
defaultRelativeFreq(defaultRelativeCollisionFrequency), defaultNumDOFs(defaultNumDOFs),
defaultChainLength(defaultChainLength), defaultNumMTS(defaultNumMTS), defaultNumYS(defaultNumYoshidaSuzuki), defaultChainLength(defaultChainLength), defaultNumMTS(defaultNumMTS), defaultNumYS(defaultNumYoshidaSuzuki),
defaultChainID(defaultChainID), thermostatedAtoms(thermostatedAtoms), parentAtoms(parentAtoms) defaultChainID(defaultChainID), thermostatedAtoms(thermostatedAtoms), thermostatedPairs(thermostatedPairs)
{} {}
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "openmm/VelocityVerletIntegrator.h" #include "openmm/NoseHooverIntegrator.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/Force.h" #include "openmm/Force.h"
#include "openmm/System.h" #include "openmm/System.h"
...@@ -46,24 +46,28 @@ using namespace OpenMM; ...@@ -46,24 +46,28 @@ using namespace OpenMM;
using std::string; using std::string;
using std::vector; using std::vector;
VelocityVerletIntegrator::VelocityVerletIntegrator(double stepSize): NoseHooverIntegrator::NoseHooverIntegrator(double stepSize):
forcesAreValid(false) forcesAreValid(false)
{ {
setStepSize(stepSize); setStepSize(stepSize);
setConstraintTolerance(1e-5); setConstraintTolerance(1e-5);
} }
NoseHooverIntegrator::NoseHooverIntegrator(double stepSize, System &system, double temperature, int collisionFrequnency,
int chainLength, int numMTS, int numYoshidaSuzuki) : forcesAreValid(false) {
setStepSize(stepSize);
setConstraintTolerance(1e-5);
addThermostat(system, temperature, collisionFrequnency, chainLength, numMTS, numYoshidaSuzuki);
}
VelocityVerletIntegrator::~VelocityVerletIntegrator() {} NoseHooverIntegrator::~NoseHooverIntegrator() {}
double VelocityVerletIntegrator::propagateChain(double kineticEnergy, int chainID) { std::pair<double, double> NoseHooverIntegrator::propagateChain(std::pair<double, double> kineticEnergy, int chainID) {
return nhcKernel.getAs<NoseHooverChainKernel>().propagateChain(*context, noseHooverChains.at(chainID), kineticEnergy, getStepSize()); return nhcKernel.getAs<NoseHooverChainKernel>().propagateChain(*context, noseHooverChains.at(chainID), kineticEnergy, getStepSize());
} }
int VelocityVerletIntegrator::addNoseHooverChainThermostat(System& system, double temperature, double collisionFrequency, int NoseHooverIntegrator::addThermostat(System& system, double temperature, double collisionFrequency,
int chainLength, int numMTS, int numYoshidaSuzuki) { int chainLength, int numMTS, int numYoshidaSuzuki) {
int numForces = system.getNumForces();
std::vector<int> thermostatedParticles; std::vector<int> thermostatedParticles;
std::vector<int> parentParticles;
for(int particle = 0; particle < system.getNumParticles(); ++particle) { for(int particle = 0; particle < system.getNumParticles(); ++particle) {
double mass = system.getParticleMass(particle); double mass = system.getParticleMass(particle);
if ( (mass > 0) && (mass < 0.8) ){ if ( (mass > 0) && (mass < 0.8) ){
...@@ -75,51 +79,62 @@ int VelocityVerletIntegrator::addNoseHooverChainThermostat(System& system, doubl ...@@ -75,51 +79,62 @@ int VelocityVerletIntegrator::addNoseHooverChainThermostat(System& system, doubl
} }
} }
return addMaskedNoseHooverChainThermostat(system, thermostatedParticles, parentParticles, temperature, collisionFrequency, chainLength, numMTS, numYoshidaSuzuki); return addSubsystemThermostat(system, thermostatedParticles, std::vector<std::pair<int, int>>(), temperature, temperature,
collisionFrequency, collisionFrequency, chainLength, numMTS, numYoshidaSuzuki);
} }
int VelocityVerletIntegrator::addMaskedNoseHooverChainThermostat(System& system, const std::vector<int>& thermostatedParticles, const std::vector<int>& parentParticles, int NoseHooverIntegrator::addSubsystemThermostat(System& system, const std::vector<int>& thermostatedParticles,
double temperature, double collisionFrequency, const std::vector< std::pair< int, int> > &thermostatedPairs,
int chainLength, int numMTS, int numYoshidaSuzuki){ double temperature, double relativeTemperature,
const auto & mask = thermostatedParticles; // just an alias double collisionFrequency, double relativeCollisionFrequency,
int chainLength, int numMTS, int numYoshidaSuzuki) {
if (context) { if (context) {
throw OpenMMException("Nose-Hoover chains cannot be added after binding this integrator to a context."); throw OpenMMException("Nose-Hoover chains cannot be added after binding this integrator to a context.");
} }
if ((parentParticles.size() != mask.size()) && (parentParticles.size() != 0)) {
throw OpenMMException("The number of parent particles has to be either equal to the number of thermostated particles (to thermostat relative motion)"
" or zero (to thermostat absolute motion).");
}
// figure out the number of DOFs // figure out the number of DOFs
int nDOF = 3*mask.size(); int nDOF = 3*(thermostatedParticles.size() + thermostatedPairs.size());
for (int constraintNum = 0; constraintNum < system.getNumConstraints(); constraintNum++) { for (int constraintNum = 0; constraintNum < system.getNumConstraints(); constraintNum++) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(constraintNum, particle1, particle2, distance); system.getConstraintParameters(constraintNum, particle1, particle2, distance);
bool particle1_in_mask = (std::find(mask.begin(), mask.end(), particle1) != mask.end()); bool particle1_in_thermostatedParticles = ((std::find(thermostatedParticles.begin(), thermostatedParticles.end(), particle1)
bool particle2_in_mask = (std::find(mask.begin(), mask.end(), particle2) != mask.end()); != thermostatedParticles.end())) ||
(std::find_if(thermostatedPairs.begin(), thermostatedPairs.end(),
[&particle1](const std::pair<int, int>& pair){ return pair.first == particle1 || pair.second == particle1;})
!= thermostatedPairs.end());
bool particle2_in_thermostatedParticles = ((std::find(thermostatedParticles.begin(), thermostatedParticles.end(), particle2)
!= thermostatedParticles.end())) ||
(std::find_if(thermostatedPairs.begin(), thermostatedPairs.end(),
[&particle2](const std::pair<int, int>& pair){ return pair.first == particle2 || pair.second == particle2;})
!= thermostatedPairs.end());
if ((system.getParticleMass(particle1) > 0) && (system.getParticleMass(particle2) > 0)){ if ((system.getParticleMass(particle1) > 0) && (system.getParticleMass(particle2) > 0)){
if ((particle1_in_mask && !particle2_in_mask) || (!particle1_in_mask && particle2_in_mask)){ if ((particle1_in_thermostatedParticles && !particle2_in_thermostatedParticles) ||
(!particle1_in_thermostatedParticles && particle2_in_thermostatedParticles)){
throw OpenMMException("Cannot add only one of particles " + std::to_string(particle1) + " and " + std::to_string(particle2) throw OpenMMException("Cannot add only one of particles " + std::to_string(particle1) + " and " + std::to_string(particle2)
+ " to NoseHooverChain, because they are connected by a constraint."); + " to NoseHooverChain, because they are connected by a constraint.");
} }
if (particle1_in_mask && particle2_in_mask){ if (particle1_in_thermostatedParticles && particle2_in_thermostatedParticles){
nDOF -= 1; nDOF -= 1;
} }
} }
} }
int numForces = system.getNumForces(); int numForces = system.getNumForces();
if (parentParticles.size() == 0){ // remove 3 degrees of freedom from thermostats that act on absolute motions if (thermostatedPairs.size() == 0){ // remove 3 degrees of freedom from thermostats that act on absolute motions
for (int forceNum = 0; forceNum < numForces; ++forceNum) { for (int forceNum = 0; forceNum < numForces; ++forceNum) {
if (dynamic_cast<CMMotionRemover*>(&system.getForce(forceNum))) nDOF -= 3; // if (dynamic_cast<CMMotionRemover*>(&system.getForce(forceNum))) nDOF -= 3;
} }
} }
// make sure that thermostats do not overlap // make sure that thermostats do not overlap
for (auto &other_nhc: noseHooverChains) { for (auto &other_nhc: noseHooverChains) {
for (auto &particle: mask){ for (auto &particle: thermostatedParticles){
bool isParticleInOtherChain = (std::find(other_nhc.getThermostatedAtoms().begin(), bool isParticleInOtherChain = (std::find(other_nhc.getThermostatedAtoms().begin(),
other_nhc.getThermostatedAtoms().end(), other_nhc.getThermostatedAtoms().end(),
particle) == other_nhc.getThermostatedAtoms().begin()); particle) != other_nhc.getThermostatedAtoms().end()) ||
(std::find_if(other_nhc.getThermostatedPairs().begin(),
other_nhc.getThermostatedPairs().end(),
[&particle](const std::pair<int, int>& pair){ return pair.first == particle || pair.second == particle;})
!= other_nhc.getThermostatedPairs().end());
if (isParticleInOtherChain){ if (isParticleInOtherChain){
throw OpenMMException("Found particle " + std::to_string(particle) + "in a different NoseHooverChain, " throw OpenMMException("Found particle " + std::to_string(particle) + "in a different NoseHooverChain, "
"but particles can only be thermostated by one thermostat."); "but particles can only be thermostated by one thermostat.");
...@@ -127,16 +142,19 @@ int VelocityVerletIntegrator::addMaskedNoseHooverChainThermostat(System& system, ...@@ -127,16 +142,19 @@ int VelocityVerletIntegrator::addMaskedNoseHooverChainThermostat(System& system,
} }
} }
// create and add new chain // create and add new chain
int chainID = noseHooverChains.size(); int chainID = 0;
auto nhc = NoseHooverChain(temperature, collisionFrequency, nDOF, chainLength, for(const auto &c : noseHooverChains) {
numMTS, numYoshidaSuzuki, chainID, // We need to account for the fact that a NHC with pairs thermostated has both a relative and an absolute chain
thermostatedParticles, parentParticles); chainID += c.getThermostatedPairs().size() ? 2 : 1;
}
auto nhc = NoseHooverChain(temperature, relativeTemperature, collisionFrequency, relativeCollisionFrequency,
nDOF, chainLength, numMTS, numYoshidaSuzuki, chainID, thermostatedParticles, thermostatedPairs);
noseHooverChains.push_back(nhc); noseHooverChains.push_back(nhc);
return chainID; return chainID;
} }
double VelocityVerletIntegrator::getTemperature(int chainID) const { double NoseHooverIntegrator::getTemperature(int chainID) const {
if (chainID >= noseHooverChains.size()) { if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot get temperature for chainID " + std::to_string(chainID) throw OpenMMException("Cannot get temperature for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator." + ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
...@@ -145,7 +163,7 @@ double VelocityVerletIntegrator::getTemperature(int chainID) const { ...@@ -145,7 +163,7 @@ double VelocityVerletIntegrator::getTemperature(int chainID) const {
return noseHooverChains.at(chainID).getDefaultTemperature(); return noseHooverChains.at(chainID).getDefaultTemperature();
} }
void VelocityVerletIntegrator::setTemperature(double temperature, int chainID){ void NoseHooverIntegrator::setTemperature(double temperature, int chainID){
if (chainID >= noseHooverChains.size()) { if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot set temperature for chainID " + std::to_string(chainID) throw OpenMMException("Cannot set temperature for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator." + ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
...@@ -155,15 +173,35 @@ void VelocityVerletIntegrator::setTemperature(double temperature, int chainID){ ...@@ -155,15 +173,35 @@ void VelocityVerletIntegrator::setTemperature(double temperature, int chainID){
} }
double VelocityVerletIntegrator::getCollisionFrequency(int chainID) const { double NoseHooverIntegrator::getRelativeTemperature(int chainID) const {
if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot get relative temperature for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
);
}
return noseHooverChains.at(chainID).getDefaultRelativeTemperature();
}
void NoseHooverIntegrator::setRelativeTemperature(double temperature, int chainID){
if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot set relative temperature for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
);
}
noseHooverChains.at(chainID).setDefaultRelativeTemperature(temperature);
}
double NoseHooverIntegrator::getCollisionFrequency(int chainID) const {
if (chainID >= noseHooverChains.size()) { if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot get collision frequency for chainID " + std::to_string(chainID) throw OpenMMException("Cannot get collision frequency for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator." + ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
); );
} }
return noseHooverChains.at(chainID).getDefaultCollisionFrequency(); return noseHooverChains.at(chainID).getDefaultCollisionFrequency();
} }
void VelocityVerletIntegrator::setCollisionFrequency(double frequency, int chainID){
void NoseHooverIntegrator::setCollisionFrequency(double frequency, int chainID){
if (chainID >= noseHooverChains.size()) { if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot set collision frequency for chainID " + std::to_string(chainID) throw OpenMMException("Cannot set collision frequency for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator." + ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
...@@ -172,12 +210,31 @@ void VelocityVerletIntegrator::setCollisionFrequency(double frequency, int chain ...@@ -172,12 +210,31 @@ void VelocityVerletIntegrator::setCollisionFrequency(double frequency, int chain
noseHooverChains.at(chainID).setDefaultCollisionFrequency(frequency); noseHooverChains.at(chainID).setDefaultCollisionFrequency(frequency);
} }
double VelocityVerletIntegrator::computeKineticEnergy() { double NoseHooverIntegrator::getRelativeCollisionFrequency(int chainID) const {
if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot get relative collision frequency for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
);
}
return noseHooverChains.at(chainID).getDefaultRelativeCollisionFrequency();
}
void NoseHooverIntegrator::setRelativeCollisionFrequency(double frequency, int chainID){
if (chainID >= noseHooverChains.size()) {
throw OpenMMException("Cannot set relative collision frequency for chainID " + std::to_string(chainID)
+ ". Only " + std::to_string(noseHooverChains.size()) + " have been registered with this integrator."
);
}
noseHooverChains.at(chainID).setDefaultRelativeCollisionFrequency(frequency);
}
double NoseHooverIntegrator::computeKineticEnergy() {
double kE = 0.0; double kE = 0.0;
if(noseHooverChains.size()) { if(noseHooverChains.size()) {
for (const auto &nhc: noseHooverChains){ for (const auto &nhc: noseHooverChains){
if (nhc.getParentAtoms().size() == 0) { if (nhc.getThermostatedPairs().size() == 0) {
kE += nhcKernel.getAs<NoseHooverChainKernel>().computeMaskedKineticEnergy(*context, nhc, true); auto KEs = nhcKernel.getAs<NoseHooverChainKernel>().computeMaskedKineticEnergy(*context, nhc, true);
kE += std::get<0>(KEs);
} }
} }
} else { } else {
...@@ -186,7 +243,7 @@ double VelocityVerletIntegrator::computeKineticEnergy() { ...@@ -186,7 +243,7 @@ double VelocityVerletIntegrator::computeKineticEnergy() {
return kE; return kE;
} }
double VelocityVerletIntegrator::computeHeatBathEnergy() { double NoseHooverIntegrator::computeHeatBathEnergy() {
double energy = 0; double energy = 0;
for(auto &nhc : noseHooverChains) { for(auto &nhc : noseHooverChains) {
energy += nhcKernel.getAs<NoseHooverChainKernel>().computeHeatBathEnergy(*context, nhc); energy += nhcKernel.getAs<NoseHooverChainKernel>().computeHeatBathEnergy(*context, nhc);
...@@ -194,7 +251,7 @@ double VelocityVerletIntegrator::computeHeatBathEnergy() { ...@@ -194,7 +251,7 @@ double VelocityVerletIntegrator::computeHeatBathEnergy() {
return energy; return energy;
} }
void VelocityVerletIntegrator::initialize(ContextImpl& contextRef) { void NoseHooverIntegrator::initialize(ContextImpl& contextRef) {
if (owner != NULL && &contextRef.getOwner() != owner) if (owner != NULL && &contextRef.getOwner() != owner)
throw OpenMMException("This Integrator is already bound to a context"); throw OpenMMException("This Integrator is already bound to a context");
context = &contextRef; context = &contextRef;
...@@ -206,22 +263,22 @@ void VelocityVerletIntegrator::initialize(ContextImpl& contextRef) { ...@@ -206,22 +263,22 @@ void VelocityVerletIntegrator::initialize(ContextImpl& contextRef) {
forcesAreValid = false; forcesAreValid = false;
} }
void VelocityVerletIntegrator::cleanup() { void NoseHooverIntegrator::cleanup() {
vvKernel = Kernel(); vvKernel = Kernel();
nhcKernel = Kernel(); nhcKernel = Kernel();
} }
vector<string> VelocityVerletIntegrator::getKernelNames() { vector<string> NoseHooverIntegrator::getKernelNames() {
std::vector<std::string> names; std::vector<std::string> names;
names.push_back(NoseHooverChainKernel::Name()); names.push_back(NoseHooverChainKernel::Name());
names.push_back(IntegrateVelocityVerletStepKernel::Name()); names.push_back(IntegrateVelocityVerletStepKernel::Name());
return names; return names;
} }
void VelocityVerletIntegrator::step(int steps) { void NoseHooverIntegrator::step(int steps) {
if (context == NULL) if (context == NULL)
throw OpenMMException("This Integrator is not bound to a context!"); throw OpenMMException("This Integrator is not bound to a context!");
double scale, kineticEnergy; std::pair<double, double> scale, kineticEnergy;
for (int i = 0; i < steps; ++i) { for (int i = 0; i < steps; ++i) {
context->updateContextState(); context->updateContextState();
for(auto &nhc : noseHooverChains) { for(auto &nhc : noseHooverChains) {
......
...@@ -1380,7 +1380,7 @@ public: ...@@ -1380,7 +1380,7 @@ public:
* @param system the System this kernel will be applied to * @param system the System this kernel will be applied to
* @param integrator the VelocityVerletIntegrator this kernel will be used for * @param integrator the VelocityVerletIntegrator this kernel will be used for
*/ */
void initialize(const System& system, const VelocityVerletIntegrator& integrator); void initialize(const System& system, const NoseHooverIntegrator& integrator);
/** /**
* Execute the kernel. * Execute the kernel.
* *
...@@ -1389,14 +1389,14 @@ public: ...@@ -1389,14 +1389,14 @@ public:
* @param forcesAreValid a reference to the parent integrator's boolean for keeping * @param forcesAreValid a reference to the parent integrator's boolean for keeping
* track of the validity of the current forces. * track of the validity of the current forces.
*/ */
void execute(ContextImpl& context, const VelocityVerletIntegrator& integrator, bool &forcesAreValid); void execute(ContextImpl& context, const NoseHooverIntegrator& integrator, bool &forcesAreValid);
/** /**
* Compute the kinetic energy. * Compute the kinetic energy.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the VelocityVerletIntegrator this kernel is being used for * @param integrator the VelocityVerletIntegrator this kernel is being used for
*/ */
double computeKineticEnergy(ContextImpl& context, const VelocityVerletIntegrator& integrator); double computeKineticEnergy(ContextImpl& context, const NoseHooverIntegrator& integrator);
private: private:
CudaContext& cu; CudaContext& cu;
CUfunction kernel1, kernel2, kernel3; CUfunction kernel1, kernel2, kernel3;
......
...@@ -7076,7 +7076,7 @@ double CudaIntegrateVerletStepKernel::computeKineticEnergy(ContextImpl& context, ...@@ -7076,7 +7076,7 @@ double CudaIntegrateVerletStepKernel::computeKineticEnergy(ContextImpl& context,
return cu.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize()); return cu.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize());
} }
void CudaIntegrateVelocityVerletStepKernel::initialize(const System& system, const VelocityVerletIntegrator& integrator) { void CudaIntegrateVelocityVerletStepKernel::initialize(const System& system, const NoseHooverIntegrator& integrator) {
cu.getPlatformData().initializeContexts(system); cu.getPlatformData().initializeContexts(system);
cu.setAsCurrent(); cu.setAsCurrent();
map<string, string> defines; map<string, string> defines;
...@@ -7086,7 +7086,7 @@ void CudaIntegrateVelocityVerletStepKernel::initialize(const System& system, con ...@@ -7086,7 +7086,7 @@ void CudaIntegrateVelocityVerletStepKernel::initialize(const System& system, con
kernel3 = cu.getKernel(module, "integrateVelocityVerletPart3"); kernel3 = cu.getKernel(module, "integrateVelocityVerletPart3");
} }
void CudaIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, const VelocityVerletIntegrator& integrator, bool &forcesAreValid) { void CudaIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, const NoseHooverIntegrator& integrator, bool &forcesAreValid) {
cu.setAsCurrent(); cu.setAsCurrent();
CudaIntegrationUtilities& integration = cu.getIntegrationUtilities(); CudaIntegrationUtilities& integration = cu.getIntegrationUtilities();
int numAtoms = cu.getNumAtoms(); int numAtoms = cu.getNumAtoms();
...@@ -7136,7 +7136,7 @@ void CudaIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, const ...@@ -7136,7 +7136,7 @@ void CudaIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, const
cu.reorderAtoms(); cu.reorderAtoms();
} }
double CudaIntegrateVelocityVerletStepKernel::computeKineticEnergy(ContextImpl& context, const VelocityVerletIntegrator& integrator) { double CudaIntegrateVelocityVerletStepKernel::computeKineticEnergy(ContextImpl& context, const NoseHooverIntegrator& integrator) {
return cu.getIntegrationUtilities().computeKineticEnergy(0); return cu.getIntegrationUtilities().computeKineticEnergy(0);
} }
...@@ -8512,7 +8512,7 @@ double CudaNoseHooverChainKernel::computeMaskedKineticEnergy(ContextImpl& contex ...@@ -8512,7 +8512,7 @@ double CudaNoseHooverChainKernel::computeMaskedKineticEnergy(ContextImpl& contex
bool useDouble = cu.getUseDoublePrecision() || cu.getUseMixedPrecision(); bool useDouble = cu.getUseDoublePrecision() || cu.getUseMixedPrecision();
int chainID = nhc.getDefaultChainID(); int chainID = nhc.getDefaultChainID();
const auto & parents = nhc.getParentAtoms(); const auto & parents = nhc.getThermostatedPairs();
const auto & thermostatedAtoms = nhc.getThermostatedAtoms(); const auto & thermostatedAtoms = nhc.getThermostatedAtoms();
auto nAtoms = cu.getPaddedNumAtoms(); auto nAtoms = cu.getPaddedNumAtoms();
if (!masks.count(chainID)) { if (!masks.count(chainID)) {
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "CudaTests.h" #include "CudaTests.h"
#include "TestVelocityVerletIntegrator.h" #include "TestNoseHooverIntegrator.h"
void runPlatformTests() { void runPlatformTests() {
} }
...@@ -1150,7 +1150,7 @@ public: ...@@ -1150,7 +1150,7 @@ public:
* @param system the System this kernel will be applied to * @param system the System this kernel will be applied to
* @param integrator the VelocityVerletIntegrator this kernel will be used for * @param integrator the VelocityVerletIntegrator this kernel will be used for
*/ */
void initialize(const System& system, const VelocityVerletIntegrator& integrator); void initialize(const System& system, const NoseHooverIntegrator& integrator);
/** /**
* Execute the kernel. * Execute the kernel.
* *
...@@ -1159,14 +1159,14 @@ public: ...@@ -1159,14 +1159,14 @@ public:
* @param forcesAreValid a reference to the parent integrator's boolean for keeping * @param forcesAreValid a reference to the parent integrator's boolean for keeping
* track of the validity of the current forces. * track of the validity of the current forces.
*/ */
void execute(ContextImpl& context, const VelocityVerletIntegrator& integrator, bool &forcesAreValid); void execute(ContextImpl& context, const NoseHooverIntegrator& integrator, bool &forcesAreValid);
/** /**
* Compute the kinetic energy. * Compute the kinetic energy.
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param integrator the VelocityVerletIntegrator this kernel is being used for * @param integrator the VelocityVerletIntegrator this kernel is being used for
*/ */
double computeKineticEnergy(ContextImpl& context, const VelocityVerletIntegrator& integrator); double computeKineticEnergy(ContextImpl& context, const NoseHooverIntegrator& integrator);
private: private:
ReferencePlatform::PlatformData& data; ReferencePlatform::PlatformData& data;
ReferenceVelocityVerletDynamics* dynamics; ReferenceVelocityVerletDynamics* dynamics;
...@@ -1446,11 +1446,11 @@ public: ...@@ -1446,11 +1446,11 @@ public:
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param noseHooverChain the object describing the chain to be propagated. * @param noseHooverChain the object describing the chain to be propagated.
* @param kineticEnergy the kineticEnergy of the particles being thermostated by this chain. * @param kineticEnergy the {absolute, relative} kinetic energies of the particles being thermostated by this chain.
* @param timeStep the time step used by the integrator. * @param timeStep the time step used by the integrator.
* @return the velocity scale factor to apply to the particles associated with this heat bath. * @return the velocity scale factors to apply to the {absolute, relative} motion of particles associated with this heat bath.
*/ */
virtual double propagateChain(ContextImpl& context, const NoseHooverChain &nhc, double kineticEnergy, double timeStep); virtual std::pair<double, double> propagateChain(ContextImpl& context, const NoseHooverChain &nhc, std::pair<double, double> kineticEnergy, double timeStep);
/** /**
* Execute the kernal that computes the total (kinetic + potential) heat bath energy. * Execute the kernal that computes the total (kinetic + potential) heat bath energy.
* *
...@@ -1468,16 +1468,16 @@ public: ...@@ -1468,16 +1468,16 @@ public:
* @param downloadValue whether the computed value should be downloaded and returned. * @param downloadValue whether the computed value should be downloaded and returned.
* *
*/ */
virtual double computeMaskedKineticEnergy(ContextImpl& context, const NoseHooverChain &noseHooverChain, bool downloadValue); virtual std::pair<double, double> computeMaskedKineticEnergy(ContextImpl& context, const NoseHooverChain &noseHooverChain, bool downloadValue);
/** /**
* Execute the kernel that scales the velocities of particles associated with a nose hoover chain * Execute the kernel that scales the velocities of particles associated with a nose hoover chain
* *
* @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined. * @param noseHooverChain the chain whose energy is to be determined.
* @param scaleFactor the multiplicative factor by which velocities are scaled. * @param scaleFactor the multiplicative factor by which {absolute, relative} velocities are scaled.
*/ */
virtual void scaleVelocities(ContextImpl& context, const NoseHooverChain &noseHooverChain, double scaleFactor); virtual void scaleVelocities(ContextImpl& context, const NoseHooverChain &noseHooverChain, std::pair<double, double> scaleFactor);
private: private:
......
...@@ -2150,14 +2150,14 @@ ReferenceIntegrateVelocityVerletStepKernel::~ReferenceIntegrateVelocityVerletSte ...@@ -2150,14 +2150,14 @@ ReferenceIntegrateVelocityVerletStepKernel::~ReferenceIntegrateVelocityVerletSte
delete dynamics; delete dynamics;
} }
void ReferenceIntegrateVelocityVerletStepKernel::initialize(const System& system, const VelocityVerletIntegrator& integrator) { void ReferenceIntegrateVelocityVerletStepKernel::initialize(const System& system, const NoseHooverIntegrator& integrator) {
int numParticles = system.getNumParticles(); int numParticles = system.getNumParticles();
masses.resize(numParticles); masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = system.getParticleMass(i); masses[i] = system.getParticleMass(i);
} }
void ReferenceIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, const VelocityVerletIntegrator& integrator, bool &forcesAreValid) { void ReferenceIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, const NoseHooverIntegrator& integrator, bool &forcesAreValid) {
double stepSize = integrator.getStepSize(); double stepSize = integrator.getStepSize();
vector<Vec3>& posData = extractPositions(context); vector<Vec3>& posData = extractPositions(context);
vector<Vec3>& velData = extractVelocities(context); vector<Vec3>& velData = extractVelocities(context);
...@@ -2175,7 +2175,7 @@ void ReferenceIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, c ...@@ -2175,7 +2175,7 @@ void ReferenceIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, c
data.stepCount++; data.stepCount++;
} }
double ReferenceIntegrateVelocityVerletStepKernel::computeKineticEnergy(ContextImpl& context, const VelocityVerletIntegrator& integrator) { double ReferenceIntegrateVelocityVerletStepKernel::computeKineticEnergy(ContextImpl& context, const NoseHooverIntegrator& integrator) {
return computeShiftedKineticEnergy(context, masses, 0); return computeShiftedKineticEnergy(context, masses, 0);
} }
...@@ -2470,8 +2470,10 @@ void ReferenceNoseHooverChainKernel::initialize() { ...@@ -2470,8 +2470,10 @@ void ReferenceNoseHooverChainKernel::initialize() {
//SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) thermostat.getRandomNumberSeed()); //SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) thermostat.getRandomNumberSeed());
} }
double ReferenceNoseHooverChainKernel::propagateChain(ContextImpl& context, const NoseHooverChain &nhc, double kineticEnergy, double timeStep) { std::pair<double, double> ReferenceNoseHooverChainKernel::propagateChain(ContextImpl& context, const NoseHooverChain &nhc, std::pair<double, double> kineticEnergy, double timeStep) {
if (kineticEnergy < 1e-8) return 1.0; // (catches the problem of zero velocities in the first dynamics step, where we have nothing to scale) double absKE = kineticEnergy.first;
double relKE = kineticEnergy.second;
if (absKE < 1e-8) return {1.0, 1.0}; // (catches the problem of zero velocities in the first dynamics step, where we have nothing to scale)
// Get the variables describing the NHC // Get the variables describing the NHC
int chainLength = nhc.getDefaultChainLength(); int chainLength = nhc.getDefaultChainLength();
int chainID = nhc.getDefaultChainID(); int chainID = nhc.getDefaultChainID();
...@@ -2497,10 +2499,34 @@ double ReferenceNoseHooverChainKernel::propagateChain(ContextImpl& context, cons ...@@ -2497,10 +2499,34 @@ double ReferenceNoseHooverChainKernel::propagateChain(ContextImpl& context, cons
if (chainVelocities.size() < chainLength){ if (chainVelocities.size() < chainLength){
chainVelocities.resize(chainLength, 0); chainVelocities.resize(chainLength, 0);
} }
double scale = chainPropagator->propagate(kineticEnergy, chainVelocities, chainPositions, numDOFs, double absScale = chainPropagator->propagate(absKE, chainVelocities, chainPositions, numDOFs,
temperature, collisionFrequency, timeStep, temperature, collisionFrequency, timeStep,
numMTS, nhc.getDefaultYoshidaSuzukiWeights());
double relScale = 0;
int numPairs = nhc.getThermostatedPairs().size();
if(numPairs){
double relativeTemperature = nhc.getDefaultRelativeTemperature();
double relativeCollisionFrequency = nhc.getDefaultRelativeCollisionFrequency();
if (allChainPositions.size() < chainID+2){
allChainPositions.resize(chainID+2);
}
if (allChainVelocities.size() < chainID+2){
allChainVelocities.resize(chainID+2);
}
auto& chainPositions = allChainPositions.at(chainID+1);
auto& chainVelocities = allChainVelocities.at(chainID+1);
if (chainPositions.size() < chainLength){
chainPositions.resize(chainLength, 0);
}
if (chainVelocities.size() < chainLength){
chainVelocities.resize(chainLength, 0);
}
relScale = chainPropagator->propagate(relKE, chainVelocities, chainPositions, 3*numPairs,
relativeTemperature, relativeCollisionFrequency, timeStep,
numMTS, nhc.getDefaultYoshidaSuzukiWeights()); numMTS, nhc.getDefaultYoshidaSuzukiWeights());
return scale;
}
return {absScale, relScale};
} }
double ReferenceNoseHooverChainKernel::computeHeatBathEnergy(ContextImpl& context, const NoseHooverChain &nhc) { double ReferenceNoseHooverChainKernel::computeHeatBathEnergy(ContextImpl& context, const NoseHooverChain &nhc) {
...@@ -2527,9 +2553,9 @@ double ReferenceNoseHooverChainKernel::computeHeatBathEnergy(ContextImpl& contex ...@@ -2527,9 +2553,9 @@ double ReferenceNoseHooverChainKernel::computeHeatBathEnergy(ContextImpl& contex
return kineticEnergy + potentialEnergy; return kineticEnergy + potentialEnergy;
} }
double ReferenceNoseHooverChainKernel::computeMaskedKineticEnergy(ContextImpl& context, const NoseHooverChain &noseHooverChain, bool downloadValue) { std::pair<double, double> ReferenceNoseHooverChainKernel::computeMaskedKineticEnergy(ContextImpl& context, const NoseHooverChain &noseHooverChain, bool downloadValue) {
const std::vector<int>& mask = noseHooverChain.getThermostatedAtoms(); const std::vector<int>& atomsList = noseHooverChain.getThermostatedAtoms();
const std::vector<int>& parents = noseHooverChain.getParentAtoms(); const std::vector<std::pair<int,int>>& pairsList = noseHooverChain.getThermostatedPairs();
std::vector<Vec3>& velocities = extractVelocities(context); std::vector<Vec3>& velocities = extractVelocities(context);
const System& system = context.getSystem(); const System& system = context.getSystem();
int numParticles = system.getNumParticles(); int numParticles = system.getNumParticles();
...@@ -2537,44 +2563,64 @@ double ReferenceNoseHooverChainKernel::computeMaskedKineticEnergy(ContextImpl& c ...@@ -2537,44 +2563,64 @@ double ReferenceNoseHooverChainKernel::computeMaskedKineticEnergy(ContextImpl& c
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = system.getParticleMass(i); masses[i] = system.getParticleMass(i);
double ke = 0; double comKE = 0;
if (parents.size() == 0){ double relKE = 0;
// scale absolute velocities // kinetic energy of individual atoms
for (auto m: mask){ for (const auto &m: atomsList){
ke += 0.5 * masses[m] * velocities[m].dot(velocities[m]); comKE += 0.5 * masses[m] * velocities[m].dot(velocities[m]);
} }
} else { // center of mass kinetic energy of pairs
// scale velocities relative to parent for (const auto &p: pairsList){
assert(parents.size() == mask.size()); double m1 = masses[p.first];
Vec3 velocity; double m2 = masses[p.second];
double mass; Vec3 v1 = velocities[p.first];
for (int i=0; i < mask.size(); i++){ Vec3 v2 = velocities[p.second];
velocity = velocities[mask[i]] - velocities[parents[i]]; double invMass = 1.0 / (m1 + m2);
mass = masses[mask[i]] * masses[parents[i]] / (masses[mask[i]] + masses[parents[i]]); double redMass = m1 * m2 * invMass;
ke += 0.5 * mass * velocity.dot(velocity); double fracM1 = m1 * invMass;
} double fracM2 = m2 * invMass;
Vec3 comVelocity = fracM1 * v1 + fracM2 * v2;
Vec3 relVelocity = v2 - v1;
comKE += 0.5 * (m1 + m2) * comVelocity.dot(comVelocity);
relKE += 0.5 * redMass * relVelocity.dot(relVelocity);
} }
// We ignore the downloadValue argument here and always return the correct value // We ignore the downloadValue argument here and always return the correct value
return ke; return {comKE, relKE};
} }
void ReferenceNoseHooverChainKernel::scaleVelocities(ContextImpl& context, const NoseHooverChain &noseHooverChain, double scaleFactor) { void ReferenceNoseHooverChainKernel::scaleVelocities(ContextImpl& context, const NoseHooverChain &noseHooverChain, std::pair<double, double> scaleFactors) {
const std::vector<int>& mask = noseHooverChain.getThermostatedAtoms(); const auto& atoms = noseHooverChain.getThermostatedAtoms();
const std::vector<int>& parents = noseHooverChain.getParentAtoms(); const auto& pairs = noseHooverChain.getThermostatedPairs();
std::vector<Vec3>& velocities = extractVelocities(context); std::vector<Vec3>& velocities = extractVelocities(context);
double absScale = scaleFactors.first;
double relScale = scaleFactors.second;
if (parents.size() == 0){ const System& system = context.getSystem();
// scale absolute velocities int numParticles = system.getNumParticles();
for (auto m: mask){ std::vector<double> masses(numParticles);
velocities[m] *= scaleFactor; for (int i = 0; i < numParticles; ++i)
} masses[i] = system.getParticleMass(i);
} else { // scale absolute velocities
// scale velocities relative to parent for (const auto &a: atoms){
assert(parents.size() == mask.size()); velocities[a] *= absScale;
for (int i=0; i < mask.size(); i++){ }
velocities[mask[i]] = velocities[parents[i]] + scaleFactor * (velocities[mask[i]] - velocities[parents[i]]); // scale relative velocities and absolute center of mass velocities for each pair
} for (const auto &p: pairs){
int p1 = p.first;
int p2 = p.second;
double m1 = masses[p.first];
double m2 = masses[p.second];
Vec3 v1 = velocities[p.first];
Vec3 v2 = velocities[p.second];
double invMass = 1.0 / (m1 + m2);
double fracM1 = m1 * invMass;
double fracM2 = m2 * invMass;
Vec3 comVelocity = fracM1 * v1 + fracM2 * v2;
Vec3 relVelocity = v2 - v1;
velocities[p1] = absScale * comVelocity - relScale * relVelocity * fracM2;
velocities[p2] = absScale * comVelocity + relScale * relVelocity * fracM1;
} }
} }
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "ReferenceTests.h" #include "ReferenceTests.h"
#include "TestVelocityVerletIntegrator.h" #include "TestNoseHooverIntegrator.h"
void runPlatformTests() { void runPlatformTests() {
} }
...@@ -35,6 +35,6 @@ ...@@ -35,6 +35,6 @@
#include "openmm/DrudeForce.h" #include "openmm/DrudeForce.h"
#include "openmm/DrudeLangevinIntegrator.h" #include "openmm/DrudeLangevinIntegrator.h"
#include "openmm/DrudeSCFIntegrator.h" #include "openmm/DrudeSCFIntegrator.h"
#include "openmm/DrudeVelocityVerletIntegrator.h" #include "openmm/DrudeNIntegrator.h"
#endif /*OPENMM_DRUDE_H_*/ #endif /*OPENMM_DRUDE_H_*/
#ifndef OPENMM_DRUDEVELOCITYVERLETINTEGRATOR_H_ #ifndef OPENMM_DRUDENOSEHOOVERINTEGRATOR_H_
#define OPENMM_DRUDEVELOCITYVERLETINTEGRATOR_H_ #define OPENMM_DRUDENOSEHOOVERINTEGRATOR_H_
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* OpenMM * * OpenMM *
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "openmm/VelocityVerletIntegrator.h" #include "openmm/NoseHooverIntegrator.h"
#include "openmm/Kernel.h" #include "openmm/Kernel.h"
#include "openmm/internal/windowsExportDrude.h" #include "openmm/internal/windowsExportDrude.h"
...@@ -49,33 +49,28 @@ namespace OpenMM { ...@@ -49,33 +49,28 @@ namespace OpenMM {
* particles. * particles.
*/ */
class OPENMM_EXPORT_DRUDE DrudeVelocityVerletIntegrator : public VelocityVerletIntegrator { class OPENMM_EXPORT_DRUDE DrudeNoseHooverIntegrator : public NoseHooverIntegrator {
public: public:
/** /**
* Create a DrudeVelocityVerletIntegrator. * Create a DrudeNoseHooverIntegrator.
* *
* @param stepSize the step size with which to integrator the system (in picoseconds) * @param stepSize the step size with which to integrator the system (in picoseconds)
*/
DrudeVelocityVerletIntegrator(double stepSize);
virtual ~DrudeVelocityVerletIntegrator();
/**
* Add a Nose-Hoover Chain thermostat to control the temperature of the system
*
* @param system the system to be thermostated. Note: this must be setup, i.e. all * @param system the system to be thermostated. Note: this must be setup, i.e. all
* particles should have been added, before calling this function. * particles should have been added, before calling this function.
* @param temperature the target temperature for the system. * @param temperature the target temperature for the system.
* @param collisionFrequency the frequency of the interaction with the heat bath (in 1/ps). * @param drudeTemperature the target temperature for the Drude particles, relative to their parent atom.
* @param temperature the target temperature for the drude particles.. * @param collisionFrequency the frequency of the system's interaction with the heat bath (in 1/ps).
* @param collisionFrequency the frequency of the interaction of the drude particles with the heat bath (in 1/ps). * @param drudeCollisionFrequency the frequency of the drude particles' interaction with the heat bath (in 1/ps).
* @param chainLength the number of beads in the Nose-Hoover chain. * @param chainLength the number of beads in the Nose-Hoover chain.
* @param numMTS the number of step in the multiple time step chain propagation algorithm. * @param numMTS the number of step in the multiple time step chain propagation algorithm.
* @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition * @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition
* used in the chain propagation algorithm (must be 1, 3, or 5). * used in the chain propagation algorithm (must be 1, 3, or 5).
*/ */
int addDrudeNoseHooverChainThermostat(System& system, double temperature, double collisionFrequency, DrudeNoseHooverIntegrator(double stepSize, System &system, double temperature, double drudeTemperature,
double drudeTemperature, double drudeCollisionFrequency, double collisionFrequency, double drudeCollisionFrequency,
int chainLength, int numMTS, int numYoshidaSuzuki); int chainLength = 3, int numMTS = 3, int numYoshidaSuzuki = 3);
virtual ~DrudeNoseHooverIntegrator();
/** /**
* This will be called by the Context when it is created. It informs the Integrator * This will be called by the Context when it is created. It informs the Integrator
* of what context it will be integrating, and gives it a chance to do any necessary initialization. * of what context it will be integrating, and gives it a chance to do any necessary initialization.
...@@ -94,4 +89,4 @@ public: ...@@ -94,4 +89,4 @@ public:
} // namespace OpenMM } // namespace OpenMM
#endif /*OPENMM_DRUDEVELOCITYVERLETINTEGRATOR_H_*/ #endif /*OPENMM_DRUDENOSEHOOVERINTEGRATOR_H_*/
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "openmm/DrudeVelocityVerletIntegrator.h" #include "openmm/DrudeNoseHooverIntegrator.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/OpenMMException.h" #include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
...@@ -46,13 +46,10 @@ using namespace OpenMM; ...@@ -46,13 +46,10 @@ using namespace OpenMM;
using std::string; using std::string;
using std::vector; using std::vector;
DrudeVelocityVerletIntegrator::DrudeVelocityVerletIntegrator(double stepSize) : VelocityVerletIntegrator(stepSize) { } DrudeNoseHooverIntegrator::DrudeNoseHooverIntegrator(double stepSize, System &system, double temperature, double drudeTemperature,
double collisionFrequency, double drudeCollisionFrequency,
DrudeVelocityVerletIntegrator::~DrudeVelocityVerletIntegrator() { } int chainLength, int numMTS, int numYoshidaSuzuki) :
NoseHooverIntegrator(stepSize) {
int DrudeVelocityVerletIntegrator::addDrudeNoseHooverChainThermostat(System& system, double temperature, double collisionFrequency,
double drudeTemperature, double drudeCollisionFrequency,
int chainLength, int numMTS, int numYoshidaSuzuki) {
const DrudeForce* drudeForce = NULL; const DrudeForce* drudeForce = NULL;
for (int i = 0; i < system.getNumForces(); i++) for (int i = 0; i < system.getNumForces(); i++)
if (dynamic_cast<const DrudeForce*>(&system.getForce(i)) != NULL) { if (dynamic_cast<const DrudeForce*>(&system.getForce(i)) != NULL) {
...@@ -63,30 +60,31 @@ int DrudeVelocityVerletIntegrator::addDrudeNoseHooverChainThermostat(System& sys ...@@ -63,30 +60,31 @@ int DrudeVelocityVerletIntegrator::addDrudeNoseHooverChainThermostat(System& sys
} }
if (drudeForce == NULL) if (drudeForce == NULL)
throw OpenMMException("The System does not contain a DrudeForce"); throw OpenMMException("The System does not contain a DrudeForce");
std::set<int> realParticlesSet; std::set<int> realParticlesSet;
vector<int> realParticles, drudeParticles, drudeParents; vector<int> realParticles, drudeParticles, drudeParents;
vector<std::pair<int, int>> drudePairs;
for (int i = 0; i < system.getNumParticles(); i++) { for (int i = 0; i < system.getNumParticles(); i++) {
if (system.getParticleMass(i) > 0.0) realParticlesSet.insert(i); if (system.getParticleMass(i) > 0.0) realParticlesSet.insert(i);
} }
for (int i = 0; i < drudeForce->getNumParticles(); i++) { for (int i = 0; i < drudeForce->getNumParticles(); i++) {
int p, p1, p2, p3, p4; int p, p1, p2, p3, p4;
double charge, polarizability, aniso12, aniso34; double charge, polarizability, aniso12, aniso34;
drudeForce->getParticleParameters(i, p, p1, p2, p3, p4, charge, polarizability, aniso12, aniso34); drudeForce->getParticleParameters(i, p, p1, p2, p3, p4, charge, polarizability, aniso12, aniso34);
realParticlesSet.erase(p); realParticlesSet.erase(p);
drudeParticles.push_back(p); realParticlesSet.erase(p1);
drudeParents.push_back(p1); drudePairs.push_back({p,p1});
} }
for(const auto &p : realParticlesSet) realParticles.push_back(p); for(const auto &p : realParticlesSet) realParticles.push_back(p);
addMaskedNoseHooverChainThermostat(system, realParticles, vector<int>(), temperature, collisionFrequency, addSubsystemThermostat(system, realParticles, drudePairs, temperature, drudeTemperature, collisionFrequency,
chainLength, numMTS, numYoshidaSuzuki); drudeCollisionFrequency, chainLength, numMTS, numYoshidaSuzuki);
addMaskedNoseHooverChainThermostat(system, drudeParticles, drudeParents, drudeTemperature, drudeCollisionFrequency,
chainLength, numMTS, numYoshidaSuzuki);
return noseHooverChains.size() - 1;
} }
void DrudeVelocityVerletIntegrator::initialize(ContextImpl& contextRef) { DrudeNoseHooverIntegrator::~DrudeNoseHooverIntegrator() { }
VelocityVerletIntegrator::initialize(contextRef);
void DrudeNoseHooverIntegrator::initialize(ContextImpl& contextRef) {
NoseHooverIntegrator::initialize(contextRef);
if (owner != NULL && &contextRef.getOwner() != owner) if (owner != NULL && &contextRef.getOwner() != owner)
throw OpenMMException("This Integrator is already bound to a context"); throw OpenMMException("This Integrator is already bound to a context");
const DrudeForce* drudeForce = NULL; const DrudeForce* drudeForce = NULL;
...@@ -113,17 +111,17 @@ void DrudeVelocityVerletIntegrator::initialize(ContextImpl& contextRef) { ...@@ -113,17 +111,17 @@ void DrudeVelocityVerletIntegrator::initialize(ContextImpl& contextRef) {
owner = &contextRef.getOwner(); owner = &contextRef.getOwner();
} }
double DrudeVelocityVerletIntegrator::computeDrudeKineticEnergy() { double DrudeNoseHooverIntegrator::computeDrudeKineticEnergy() {
double kE = 0.0; double kE = 0.0;
for (const auto &nhc: noseHooverChains){ for (const auto &nhc: noseHooverChains){
if (nhc.getParentAtoms().size() != 0) { if (nhc.getThermostatedPairs().size() != 0) {
kE += nhcKernel.getAs<NoseHooverChainKernel>().computeMaskedKineticEnergy(*context, nhc, true); kE += nhcKernel.getAs<NoseHooverChainKernel>().computeMaskedKineticEnergy(*context, nhc, true).second;
} }
} }
return kE; return kE;
} }
double DrudeVelocityVerletIntegrator::computeTotalKineticEnergy() { double DrudeNoseHooverIntegrator::computeTotalKineticEnergy() {
return vvKernel.getAs<IntegrateVelocityVerletStepKernel>().computeKineticEnergy(*context, *this); return vvKernel.getAs<IntegrateVelocityVerletStepKernel>().computeKineticEnergy(*context, *this);
} }
/* -------------------------------------------------------------------------- *
* 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/CMMotionRemover.h"
#include "openmm/DrudeNoseHooverIntegrator.h"
#include "openmm/Context.h"
#include "openmm/State.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/VirtualSite.h"
#include "openmm/NonbondedForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/System.h"
#include "openmm/DrudeForce.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;
//extern "C" OPENMM_EXPORT void registerDrudeReferenceKernelFactories();
extern "C" OPENMM_EXPORT void registerKernelFactories();
Platform& initializePlatform(int argc, char* argv[]);
void testWaterBox(Platform& platform){
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const int gridSize = 3;
const int numMolecules = gridSize*gridSize*gridSize;
const double spacing = 0.8;
const double boxSize = spacing*(gridSize+1);
const double temperature = 300.0;
const double temperatureDrude = 10.0;
System system;
NonbondedForce* nonbonded = new NonbondedForce();
DrudeForce* drude = new DrudeForce();
CMMotionRemover* cmm = new CMMotionRemover(1);
system.addForce(cmm);
system.addForce(nonbonded);
system.addForce(drude);
system.setDefaultPeriodicBoxVectors(Vec3(boxSize, 0, 0), Vec3(0, boxSize, 0), Vec3(0, 0, boxSize));
nonbonded->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
nonbonded->setCutoffDistance(1.2);
nonbonded->setSwitchingDistance(0.8);
for (int i = 0; i < numMolecules; i++) {
int startIndex = system.getNumParticles();
system.addParticle(15.6); // O
system.addParticle(0.4); // D
system.addParticle(1.0); // H1
system.addParticle(1.0); // H2
system.addParticle(0.0); // M
nonbonded->addParticle(1.71636, 0.318395, 0.21094*4.184);
nonbonded->addParticle(-1.71636, 1, 0);
nonbonded->addParticle(0.55733, 1, 0);
nonbonded->addParticle(0.55733, 1, 0);
nonbonded->addParticle(-1.11466, 1, 0);
for (int j = 0; j < 5; j++)
for (int k = 0; k < j; k++)
nonbonded->addException(startIndex+j, startIndex+k, 0, 1, 0);
system.addConstraint(startIndex, startIndex+2, 0.09572);
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, ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184), 1, 1);
}
vector<Vec3> positions;
for (int i = 0; i < gridSize; i++)
for (int j = 0; j < gridSize; j++)
for (int k = 0; k < gridSize; k++) {
Vec3 pos(i*spacing, j*spacing, k*spacing);
positions.push_back(pos);
positions.push_back(pos);
positions.push_back(pos+Vec3(0.09572, 0, 0));
positions.push_back(pos+Vec3(-0.023999, 0.092663, 0));
positions.push_back(pos);
}
int numStandardDof = 3*3*numMolecules - system.getNumConstraints();
int numDrudeDof = 3*numMolecules;
int numDof = numStandardDof+numDrudeDof;
// Simulate it and check the temperature.
int chainLength = 4;
int numMTS = 3;
int numYS = 3;
double frequency = 50.0;
double frequencyDrude = 25.0;
int randomSeed = 100;
DrudeNoseHooverIntegrator integ(0.0005, system, temperature, temperatureDrude,
frequency, frequencyDrude, chainLength, numMTS, numYS);;
Context context(system, integ, platform);
context.setPositions(positions);
context.setVelocitiesToTemperature(temperature, randomSeed);
std::vector<Vec3> velocities = context.getState(State::Velocities).getVelocities();
for (int i = 0; i < numMolecules; i++){
Vec3 noize;
for (int j = 0; j < 3; j++){
noize[j] = float(((i+18311)*(j+18253) * 313419097822414) % 18313) / float(18313);
noize[j] *= sqrt(3 * BOLTZ * temperatureDrude / 0.4);
}
velocities[5*i+1] = velocities[5*i] + noize;
}
context.setVelocities(velocities);
context.applyConstraints(1e-6);
// Equilibrate.
integ.step(5000);
// Compute the internal and center of mass temperatures.
double totalKE = 0;
int numSteps = 100000;
double meanTemp = 0.0;
double meanDrudeTemp = 0.0;
double meanConserved = 0.0;
for (int i = 0; i < numSteps; i++) {
integ.step(1);
State state = context.getState(State::Energy);
double KE = state.getKineticEnergy();
double PE = state.getPotentialEnergy();
double fullKE = integ.computeTotalKineticEnergy();
double drudeKE = integ.computeDrudeKineticEnergy();
KE = fullKE - drudeKE;
double temp = KE/(0.5*numStandardDof*BOLTZ);
double drudeTemp = drudeKE/(0.5*numDrudeDof*BOLTZ);
meanTemp = (i*meanTemp + temp)/(i+1);
meanDrudeTemp = (i*meanDrudeTemp + drudeTemp)/(i+1);
double heatBathEnergy = integ.computeHeatBathEnergy();
double conserved = PE + fullKE + heatBathEnergy;
meanConserved = (i*meanConserved + conserved)/(i+1);
#define DEBUG 1
#if DEBUG
if(i%10 == 0)
std::cout << std::setw(6) << i
<< std::setprecision(8) << std::setw(16) << KE
<< std::setprecision(8) << std::setw(16) << drudeKE
<< std::setprecision(8) << std::setw(16) << meanTemp
<< std::setprecision(8) << std::setw(16) << meanDrudeTemp
<< std::setprecision(8) << std::setw(16) << conserved
<< std::endl;
#endif
totalKE += KE;
// ASSERT(fabs(meanConserved - conserved) < 0.5);
}
totalKE /= numSteps;
// ASSERT_USUALLY_EQUAL_TOL(temperature, meanTemp, 0.02);
// ASSERT_USUALLY_EQUAL_TOL(temperatureDrude, meanDrudeTemp, 0.10);
}
int main(int argc, char* argv[]) {
try {
Platform& platform = initializePlatform(argc, argv);
//registerDrudeReferenceKernelFactories();
//registerKernelFactories();
testWaterBox(platform);
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h" #include "openmm/NonbondedForce.h"
#include "openmm/System.h" #include "openmm/System.h"
#include "openmm/VelocityVerletIntegrator.h" #include "openmm/NoseHooverIntegrator.h"
#include "openmm/VirtualSite.h" #include "openmm/VirtualSite.h"
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h" #include "sfmt/SFMT.h"
...@@ -51,7 +51,7 @@ void testVVSingleBond() { ...@@ -51,7 +51,7 @@ void testVVSingleBond() {
System system; System system;
system.addParticle(2.0); system.addParticle(2.0);
system.addParticle(2.0); system.addParticle(2.0);
VelocityVerletIntegrator integrator(0.01); NoseHooverIntegrator integrator(0.01);
HarmonicBondForce* forceField = new HarmonicBondForce(); HarmonicBondForce* forceField = new HarmonicBondForce();
forceField->addBond(0, 1, 1.5, 1); forceField->addBond(0, 1, 1.5, 1);
system.addForce(forceField); system.addForce(forceField);
...@@ -86,7 +86,7 @@ void testVVConstraints() { ...@@ -86,7 +86,7 @@ void testVVConstraints() {
const int numParticles = 8; const int numParticles = 8;
const int numConstraints = 5; const int numConstraints = 5;
System system; System system;
VelocityVerletIntegrator integrator(0.001); NoseHooverIntegrator integrator(0.001);
integrator.setConstraintTolerance(1e-5); integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce(); NonbondedForce* forceField = new NonbondedForce();
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
...@@ -138,7 +138,7 @@ void testVVConstraints() { ...@@ -138,7 +138,7 @@ void testVVConstraints() {
void testVVConstrainedClusters() { void testVVConstrainedClusters() {
const int numParticles = 7; const int numParticles = 7;
System system; System system;
VelocityVerletIntegrator integrator(0.001); NoseHooverIntegrator integrator(0.001);
integrator.setConstraintTolerance(1e-5); integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce(); NonbondedForce* forceField = new NonbondedForce();
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
...@@ -205,7 +205,7 @@ void testVVConstrainedMasslessParticles() { ...@@ -205,7 +205,7 @@ void testVVConstrainedMasslessParticles() {
vector<Vec3> positions(2); vector<Vec3> positions(2);
positions[0] = Vec3(-1, 0, 0); positions[0] = Vec3(-1, 0, 0);
positions[1] = Vec3(1, 0, 0); positions[1] = Vec3(1, 0, 0);
VelocityVerletIntegrator integrator(0.01); NoseHooverIntegrator integrator(0.01);
bool failed = false; bool failed = false;
try { try {
// This should throw an exception. // This should throw an exception.
...@@ -250,7 +250,7 @@ void testThreeParticleVirtualSite() { ...@@ -250,7 +250,7 @@ void testThreeParticleVirtualSite() {
forceField->addParticle(2, params); forceField->addParticle(2, params);
params[0] = 0.4; params[0] = 0.4;
forceField->addParticle(3, params); forceField->addParticle(3, params);
VelocityVerletIntegrator integrator(0.002); NoseHooverIntegrator integrator(0.002);
Context context(system, integrator, platform); Context context(system, integrator, platform);
vector<Vec3> positions(4); vector<Vec3> positions(4);
positions[0] = Vec3(0, 0, 0); positions[0] = Vec3(0, 0, 0);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include "openmm/internal/AssertionUtilities.h" #include "openmm/internal/AssertionUtilities.h"
#include "openmm/NoseHooverChain.h" #include "openmm/NoseHooverChain.h"
#include "openmm/VelocityVerletIntegrator.h" #include "openmm/NoseHooverIntegrator.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/State.h" #include "openmm/State.h"
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
...@@ -65,8 +65,8 @@ void testHarmonicOscillator() { ...@@ -65,8 +65,8 @@ void testHarmonicOscillator() {
auto harmonic_restraint = new CustomExternalForce("0.5*(x^2+y^2+z^2)"); auto harmonic_restraint = new CustomExternalForce("0.5*(x^2+y^2+z^2)");
harmonic_restraint->addParticle(0); harmonic_restraint->addParticle(0);
system.addForce(harmonic_restraint); system.addForce(harmonic_restraint);
VelocityVerletIntegrator integrator(0.001); NoseHooverIntegrator integrator(0.001);
integrator.addNoseHooverChainThermostat(system, temperature, frequency, chain_length, mts, ys); integrator.addThermostat(system, temperature, frequency, chain_length, mts, ys);
Context context(system, integrator, platform); Context context(system, integrator, platform);
context.setPositions(positions); context.setPositions(positions);
context.setVelocities(velocities); context.setVelocities(velocities);
...@@ -156,15 +156,16 @@ void testDimerBox(bool constrain=true) { ...@@ -156,15 +156,16 @@ void testDimerBox(bool constrain=true) {
} }
} }
} }
bool simpleConstruct = true;
VelocityVerletIntegrator integrator(0.001);
double temperature = 300; // kelvin double temperature = 300; // kelvin
double collisionFrequency = 25; // 1/ps double collisionFrequency = 25; // 1/ps
int numMTS = 3; int numMTS = 3;
int numYS = 3; int numYS = 3;
int chainLength = 5; int chainLength = 5;
integrator.addNoseHooverChainThermostat(system, temperature, collisionFrequency, auto integrator = simpleConstruct ? NoseHooverIntegrator(0.001, system, temperature, collisionFrequency, chainLength, numMTS, numYS)
chainLength, numMTS, numYS); : NoseHooverIntegrator(0.001);
if (!simpleConstruct)
integrator.addThermostat(system, temperature, collisionFrequency, chainLength, numMTS, numYS);
Context context(system, integrator, platform); Context context(system, integrator, platform);
context.setPositions(positions); context.setPositions(positions);
context.setVelocitiesToTemperature(temperature); context.setVelocitiesToTemperature(temperature);
...@@ -212,7 +213,7 @@ void testDimerBox(bool constrain=true) { ...@@ -212,7 +213,7 @@ void testDimerBox(bool constrain=true) {
void testCheckpoints() { void testCheckpoints() {
double timeStep = 0.001; double timeStep = 0.001;
VelocityVerletIntegrator integrator(timeStep), newIntegrator(timeStep); NoseHooverIntegrator integrator(timeStep), newIntegrator(timeStep);
System system; System system;
double mass = 1; double mass = 1;
system.addParticle(mass); system.addParticle(mass);
...@@ -223,17 +224,11 @@ void testCheckpoints() { ...@@ -223,17 +224,11 @@ void testCheckpoints() {
system.addForce(force); system.addForce(force);
double kineticEnergy = 1e6; double kineticEnergy = 1e6;
double temperature=300, collisionFrequency=1, chainLength=3, numMTS=3, numYS=3; double temperature=300, collisionFrequency=1, chainLength=3, numMTS=3, numYS=3;
integrator.addMaskedNoseHooverChainThermostat(system, std::vector<int>(1,0), std::vector<int>(), temperature, collisionFrequency,
chainLength, numMTS, numYS);
newIntegrator.addMaskedNoseHooverChainThermostat(system, std::vector<int>(1,0), std::vector<int>(), temperature, collisionFrequency,
chainLength, numMTS, numYS);
chainLength = 10; chainLength = 10;
integrator.addMaskedNoseHooverChainThermostat(system, std::vector<int>(1,1), std::vector<int>(1,0), integrator.addSubsystemThermostat(system, std::vector<int>(), std::vector<std::pair<int,int>>{{0,1}}, temperature, temperature, collisionFrequency, collisionFrequency,
temperature, collisionFrequency, chainLength, numMTS, numYS);
chainLength, numMTS, numYS); newIntegrator.addSubsystemThermostat(system, std::vector<int>(), std::vector<std::pair<int,int>>{{0,1}}, temperature, temperature, collisionFrequency, collisionFrequency,
newIntegrator.addMaskedNoseHooverChainThermostat(system, std::vector<int>(1,1), std::vector<int>(1,0), chainLength, numMTS, numYS);
temperature, collisionFrequency,
chainLength, numMTS, numYS);
Context context(system, integrator, platform); Context context(system, integrator, platform);
Context newContext(system, newIntegrator, platform); Context newContext(system, newIntegrator, platform);
std::vector<Vec3> positions(2); std::vector<Vec3> positions(2);
......
...@@ -78,7 +78,7 @@ class WrapperGenerator: ...@@ -78,7 +78,7 @@ class WrapperGenerator:
'Vec3 OpenMM::LocalCoordinatesSite::getXWeights', 'Vec3 OpenMM::LocalCoordinatesSite::getXWeights',
'Vec3 OpenMM::LocalCoordinatesSite::getYWeights', 'Vec3 OpenMM::LocalCoordinatesSite::getYWeights',
'std::vector<double> OpenMM::NoseHooverChain::getDefaultYoshidaSuzukiWeights', 'std::vector<double> OpenMM::NoseHooverChain::getDefaultYoshidaSuzukiWeights',
'virtual void OpenMM::VelocityVerletIntegrator::stateChanged', 'virtual void OpenMM::NoseHooverIntegrator::stateChanged',
] ]
self.hideClasses = ['Kernel', 'KernelImpl', 'KernelFactory', 'ContextImpl', 'SerializationNode', 'SerializationProxy'] self.hideClasses = ['Kernel', 'KernelImpl', 'KernelFactory', 'ContextImpl', 'SerializationNode', 'SerializationProxy']
self.nodeByID={} self.nodeByID={}
...@@ -168,6 +168,7 @@ class CHeaderGenerator(WrapperGenerator): ...@@ -168,6 +168,7 @@ class CHeaderGenerator(WrapperGenerator):
'std::vector< std::string >': 'OpenMM_StringArray', 'std::vector< std::string >': 'OpenMM_StringArray',
'std::vector< Vec3 >': 'OpenMM_Vec3Array', 'std::vector< Vec3 >': 'OpenMM_Vec3Array',
'std::vector< std::pair< int, int > >': 'OpenMM_BondArray', '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, double >': 'OpenMM_ParameterArray',
'std::map< std::string, std::string >': 'OpenMM_PropertyArray', 'std::map< std::string, std::string >': 'OpenMM_PropertyArray',
'std::vector< double >': 'OpenMM_DoubleArray', 'std::vector< double >': 'OpenMM_DoubleArray',
......
...@@ -168,6 +168,7 @@ UNITS = { ...@@ -168,6 +168,7 @@ UNITS = {
("*", "getCutoffDistance") : ("unit.nanometers", ()), ("*", "getCutoffDistance") : ("unit.nanometers", ()),
("*", "getSwitchingDistance") : ("unit.nanometers", ()), ("*", "getSwitchingDistance") : ("unit.nanometers", ()),
("*", "getDefaultCollisionFrequency") : ("1/unit.picosecond", ()), ("*", "getDefaultCollisionFrequency") : ("1/unit.picosecond", ()),
("*", "getDefaultRelativeCollisionFrequency") : ("1/unit.picosecond", ()),
("*", "getDefaultPeriodicBoxVectors") ("*", "getDefaultPeriodicBoxVectors")
: (None, ('unit.nanometer', 'unit.nanometer', 'unit.nanometer')), : (None, ('unit.nanometer', 'unit.nanometer', 'unit.nanometer')),
("*", "getDefaultPressure") : ("unit.bar", ()), ("*", "getDefaultPressure") : ("unit.bar", ()),
...@@ -182,6 +183,7 @@ UNITS = { ...@@ -182,6 +183,7 @@ UNITS = {
("*", "setDefaultSurfaceTension") : (None, ("unit.bar*unit.nanometer",)), ("*", "setDefaultSurfaceTension") : (None, ("unit.bar*unit.nanometer",)),
("*", "getDefaultTemperature") : ("unit.kelvin", ()), ("*", "getDefaultTemperature") : ("unit.kelvin", ()),
("*", "setDefaultTemperature") : (None, ("unit.kelvin",)), ("*", "setDefaultTemperature") : (None, ("unit.kelvin",)),
("*", "getDefaultRelativeTemperature") : ("unit.kelvin", ()),
("*", "getErrorTolerance") : (None, ()), ("*", "getErrorTolerance") : (None, ()),
("*", "getEwaldErrorTolerance") : (None, ()), ("*", "getEwaldErrorTolerance") : (None, ()),
("*", "getFriction") : ("1/unit.picosecond", ()), ("*", "getFriction") : ("1/unit.picosecond", ()),
...@@ -468,7 +470,7 @@ UNITS = { ...@@ -468,7 +470,7 @@ UNITS = {
("MonteCarloMembraneBarostat", "getXYMode") : (None, ()), ("MonteCarloMembraneBarostat", "getXYMode") : (None, ()),
("MonteCarloMembraneBarostat", "getZMode") : (None, ()), ("MonteCarloMembraneBarostat", "getZMode") : (None, ()),
("DrudeLangevinIntegrator", "getDrudeFriction") : ("1/unit.picosecond", ()), ("DrudeLangevinIntegrator", "getDrudeFriction") : ("1/unit.picosecond", ()),
("NoseHooverChain", "getParentAtoms") : (None, ()), ("NoseHooverChain", "getThermostatedPairs") : (None, ()),
("NoseHooverChain", "getThermostatedAtoms") : (None, ()), ("NoseHooverChain", "getThermostatedAtoms") : (None, ()),
("NoseHooverChain", "getDefaultYoshidaSuzukiWeights") : (None, ()), ("NoseHooverChain", "getDefaultYoshidaSuzukiWeights") : (None, ()),
("DrudeSCFIntegrator", "getMinimizationErrorTolerance") : ("unit.kilojoules_per_mole/unit.nanometer", ()), ("DrudeSCFIntegrator", "getMinimizationErrorTolerance") : ("unit.kilojoules_per_mole/unit.nanometer", ()),
......
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