Skip to content

Commit 0644f05

Browse files
authored
computeDrudeTemperature (openmm#3512)
* computeDrudeTemperature * cleanup * revert drude temperature computation in DrudeNoseHoover
1 parent a6cd8c2 commit 0644f05

File tree

8 files changed

+63
-10
lines changed

8 files changed

+63
-10
lines changed

plugins/drude/openmmapi/include/openmm/DrudeLangevinIntegrator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ class OPENMM_EXPORT_DRUDE DrudeLangevinIntegrator : public DrudeIntegrator {
126126
* getTemperature().
127127
*/
128128
double computeSystemTemperature();
129+
/**
130+
* Compute the instantaneous temperature of the Drude system, measured in Kelvin.
131+
* This is calculated based on the kinetic energy of the internal motion of Drude pairs
132+
* and should remain close to the prescribed Drude temperature.
133+
*/
134+
double computeDrudeTemperature();
129135
protected:
130136
/**
131137
* This will be called by the Context when it is created. It informs the Integrator

plugins/drude/openmmapi/include/openmm/DrudeNoseHooverIntegrator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ class OPENMM_EXPORT_DRUDE DrudeNoseHooverIntegrator : public NoseHooverIntegrato
106106
* getTemperature().
107107
*/
108108
double computeSystemTemperature();
109+
/**
110+
* Compute the instantaneous temperature of the Drude system, measured in Kelvin.
111+
* This is calculated based on the kinetic energy of the internal motion of Drude pairs
112+
* and should remain close to the prescribed Drude temperature.
113+
*/
114+
double computeDrudeTemperature();
109115
protected:
110116
/**
111117
* Return a list of velocities normally distributed around a target temperature, with the Drude

plugins/drude/openmmapi/src/DrudeHelpers.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,16 @@ vector<Vec3> assignDrudeVelocities(const System &system, double temperature, dou
127127
return velocities;
128128
}
129129

130-
double computeSystemTemperatureFromVelocities(const System& system, const vector<Vec3>& velocities) {
130+
131+
/**
132+
* Computes the instantaneous temperatures of the system and the internal Drude motion and returns a pair (T_system, T_drude)
133+
*/
134+
pair<double, double> computeTemperaturesFromVelocities(const System& system, const vector<Vec3>& velocities) {
131135
vector<int> normalParticles;
132136
vector<pair<int, int> > pairParticles;
133137
findParticlesAndPairs(system, normalParticles, pairParticles);
134-
double energy = 0.0;
135-
int dof = 0;
138+
double energy = 0.0, drudeEnergy = 0;
139+
int dof = 0, drudeDof = 0;
136140

137141
// Kinetic energy and degrees of freedom from normal particles.
138142

@@ -151,10 +155,14 @@ double computeSystemTemperatureFromVelocities(const System& system, const vector
151155
int p2 = pair.second;
152156
double mass1 = system.getParticleMass(p1);
153157
double mass2 = system.getParticleMass(p2);
158+
double reducedMass = (mass1*mass2)/(mass1+mass2);
154159
if (mass1 != 0 || mass2 != 0) {
155160
Vec3 momentum = mass1*velocities[p1] + mass2*velocities[p2];
156161
energy += momentum.dot(momentum)/(mass1+mass2);
157-
dof += 3;
162+
Vec3 drudeVelocity = velocities[p1] - velocities[p2];
163+
drudeEnergy += reducedMass*drudeVelocity.dot(drudeVelocity);
164+
dof += 3;
165+
drudeDof += 3;
158166
}
159167
}
160168

@@ -176,7 +184,10 @@ double computeSystemTemperatureFromVelocities(const System& system, const vector
176184
break;
177185
}
178186
energy *= 0.5;
179-
return 2*energy/(dof*BOLTZ);
187+
drudeEnergy *= 0.5;
188+
if (drudeDof == 0)
189+
drudeDof = 1; // so that the drude temperature is reported as 0
190+
return make_pair<double, double>(2*energy/(dof*BOLTZ), 2*drudeEnergy/(drudeDof*BOLTZ));
180191
}
181192

182193
}

plugins/drude/openmmapi/src/DrudeLangevinIntegrator.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@
4242
using namespace OpenMM;
4343
using std::string;
4444
using std::vector;
45+
using std::pair;
4546

4647
namespace OpenMM {
47-
double computeSystemTemperatureFromVelocities(const System& system, const vector<Vec3>& velocities);
48+
pair<double, double> computeTemperaturesFromVelocities(const System& system, const vector<Vec3>& velocities);
4849
}
4950

5051
DrudeLangevinIntegrator::DrudeLangevinIntegrator(double temperature, double frictionCoeff, double drudeTemperature, double drudeFrictionCoeff, double stepSize) : DrudeIntegrator(stepSize) {
@@ -126,5 +127,15 @@ double DrudeLangevinIntegrator::computeSystemTemperature() {
126127
context->calcForcesAndEnergy(true, false, getIntegrationForceGroups());
127128
vector<Vec3> velocities;
128129
context->computeShiftedVelocities(getVelocityTimeOffset(), velocities);
129-
return computeSystemTemperatureFromVelocities(context->getSystem(), velocities);
130+
return computeTemperaturesFromVelocities(context->getSystem(), velocities).first;
130131
}
132+
133+
double DrudeLangevinIntegrator::computeDrudeTemperature() {
134+
if (context == NULL)
135+
throw OpenMMException("This Integrator is not bound to a context!");
136+
context->calcForcesAndEnergy(true, false, getIntegrationForceGroups());
137+
vector<Vec3> velocities;
138+
context->computeShiftedVelocities(getVelocityTimeOffset(), velocities);
139+
return computeTemperaturesFromVelocities(context->getSystem(), velocities).second;
140+
}
141+

plugins/drude/openmmapi/src/DrudeNoseHooverIntegrator.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* -------------------------------------------------------------------------- */
3131

3232
#include "openmm/DrudeNoseHooverIntegrator.h"
33+
#include "SimTKOpenMMRealType.h"
3334
#include "openmm/Context.h"
3435
#include "openmm/OpenMMException.h"
3536
#include "openmm/internal/ContextImpl.h"
@@ -45,12 +46,14 @@
4546
using namespace OpenMM;
4647
using std::string;
4748
using std::vector;
49+
using std::pair;
4850

4951
namespace OpenMM {
5052
extern std::vector<Vec3> assignDrudeVelocities(const System &system, double temperature, double drudeTemperature, int randomSeed);
51-
double computeSystemTemperatureFromVelocities(const System& system, const vector<Vec3>& velocities);
53+
pair<double, double> computeTemperaturesFromVelocities(const System& system, const vector<Vec3>& velocities);
5254
}
5355

56+
5457
DrudeNoseHooverIntegrator::DrudeNoseHooverIntegrator(double temperature, double collisionFrequency,
5558
double drudeTemperature, double drudeCollisionFrequency,
5659
double stepSize, int chainLength, int numMTS, int numYoshidaSuzuki) :
@@ -151,8 +154,20 @@ double DrudeNoseHooverIntegrator::computeSystemTemperature() {
151154
context->calcForcesAndEnergy(true, false, getIntegrationForceGroups());
152155
vector<Vec3> velocities;
153156
context->computeShiftedVelocities(getVelocityTimeOffset(), velocities);
154-
return computeSystemTemperatureFromVelocities(context->getSystem(), velocities);
157+
return computeTemperaturesFromVelocities(context->getSystem(), velocities).first;
158+
}
159+
160+
double DrudeNoseHooverIntegrator::computeDrudeTemperature() {
161+
if (context == NULL)
162+
throw OpenMMException("This Integrator is not bound to a context!");
163+
double kE = computeDrudeKineticEnergy();
164+
size_t num_dofs = 0;
165+
for (const auto &nhc: noseHooverChains){
166+
num_dofs += 3 * nhc.getThermostatedPairs().size();
167+
}
168+
return kE/(0.5 * num_dofs * BOLTZ);
155169
}
170+
156171
std::vector<Vec3> DrudeNoseHooverIntegrator::getVelocitiesForTemperature(const System &system, double temperature,
157172
int randomSeedIn) const {
158173
return assignDrudeVelocities(system, temperature, drudeTemperature, randomSeedIn);

plugins/drude/tests/TestDrudeLangevinIntegrator.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ void testSinglePair() {
8484
Vec3 velCM = vel[0]*(mass1/totalMass) + vel[1]*(mass2/totalMass);
8585
keCM += 0.5*totalMass*velCM.dot(velCM);
8686
Vec3 velInternal = vel[0]-vel[1];
87-
keInternal += 0.5*reducedMass*velInternal.dot(velInternal);
87+
double _keInternal = 0.5*reducedMass*velInternal.dot(velInternal);
88+
keInternal += _keInternal;
89+
ASSERT_EQUAL_TOL(integ.computeDrudeTemperature(), _keInternal/(3*0.5*BOLTZ), 1e-6);
8890
Vec3 delta = state.getPositions()[0]-state.getPositions()[1];
8991
double distance = sqrt(delta.dot(delta));
9092
ASSERT(distance <= maxDistance*(1+1e-6));

plugins/drude/tests/TestDrudeNoseHoover.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ void testWaterBox() {
167167
double drudeKE = integ.computeDrudeKineticEnergy();
168168
double temp = KE/(0.5*numStandardDof*BOLTZ);
169169
double drudeTemp = drudeKE/(0.5*numDrudeDof*BOLTZ);
170+
ASSERT_EQUAL_TOL(drudeTemp, integ.computeDrudeTemperature(), 1e-6);
170171
meanTemp = (i*meanTemp + temp)/(i+1);
171172
meanDrudeTemp = (i*meanDrudeTemp + drudeTemp)/(i+1);
172173
double heatBathEnergy = integ.computeHeatBathEnergy();

wrappers/python/src/swig_doxygen/swigInputConfig.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@
226226
("*", "getGlobalParameterDefaultValue") : (None, ()),
227227
("*", "getPermutationMode") : (None, ()),
228228
("*", "computeSystemTemperature") : ("unit.kelvin", ()),
229+
("*", "computeDrudeTemperature") : ("unit.kelvin", ()),
229230
("LocalCoordinatesSite", "getOriginWeights") : (None, ()),
230231
("LocalCoordinatesSite", "getXWeights") : (None, ()),
231232
("LocalCoordinatesSite", "getYWeights") : (None, ()),

0 commit comments

Comments
 (0)