Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
ad7a55b8
Unverified
Commit
ad7a55b8
authored
Oct 25, 2019
by
peastman
Committed by
GitHub
Oct 25, 2019
Browse files
Merge pull request #2447 from peastman/energy
Avoid unnecessary force evaluation when computing kinetic energy
parents
466a826e
88209091
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
52 additions
and
37 deletions
+52
-37
openmmapi/include/openmm/BAOABLangevinIntegrator.h
openmmapi/include/openmm/BAOABLangevinIntegrator.h
+4
-0
openmmapi/include/openmm/BrownianIntegrator.h
openmmapi/include/openmm/BrownianIntegrator.h
+5
-1
openmmapi/include/openmm/CustomIntegrator.h
openmmapi/include/openmm/CustomIntegrator.h
+6
-2
openmmapi/include/openmm/Integrator.h
openmmapi/include/openmm/Integrator.h
+12
-1
openmmapi/src/BAOABLangevinIntegrator.cpp
openmmapi/src/BAOABLangevinIntegrator.cpp
+4
-0
openmmapi/src/BrownianIntegrator.cpp
openmmapi/src/BrownianIntegrator.cpp
+5
-1
openmmapi/src/Context.cpp
openmmapi/src/Context.cpp
+2
-1
openmmapi/src/CustomIntegrator.cpp
openmmapi/src/CustomIntegrator.cpp
+12
-2
platforms/cuda/include/CudaKernels.h
platforms/cuda/include/CudaKernels.h
+1
-1
platforms/cuda/src/CudaKernels.cpp
platforms/cuda/src/CudaKernels.cpp
+0
-12
platforms/opencl/include/OpenCLKernels.h
platforms/opencl/include/OpenCLKernels.h
+1
-1
platforms/opencl/src/OpenCLKernels.cpp
platforms/opencl/src/OpenCLKernels.cpp
+0
-11
platforms/reference/src/SimTKReference/ReferenceCustomDynamics.cpp
.../reference/src/SimTKReference/ReferenceCustomDynamics.cpp
+0
-4
No files found.
openmmapi/include/openmm/BAOABLangevinIntegrator.h
View file @
ad7a55b8
...
@@ -140,6 +140,10 @@ protected:
...
@@ -140,6 +140,10 @@ protected:
* Compute the kinetic energy of the system at the current time.
* Compute the kinetic energy of the system at the current time.
*/
*/
double
computeKineticEnergy
();
double
computeKineticEnergy
();
/**
* Computing kinetic energy for this integrator does not require forces.
*/
bool
kineticEnergyRequiresForce
()
const
;
private:
private:
double
temperature
,
friction
;
double
temperature
,
friction
;
int
randomNumberSeed
;
int
randomNumberSeed
;
...
...
openmmapi/include/openmm/BrownianIntegrator.h
View file @
ad7a55b8
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
2
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
9
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -133,6 +133,10 @@ protected:
...
@@ -133,6 +133,10 @@ protected:
* Compute the kinetic energy of the system at the current time.
* Compute the kinetic energy of the system at the current time.
*/
*/
double
computeKineticEnergy
();
double
computeKineticEnergy
();
/**
* Computing kinetic energy for this integrator does not require forces.
*/
bool
kineticEnergyRequiresForce
()
const
;
private:
private:
double
temperature
,
friction
;
double
temperature
,
friction
;
int
randomNumberSeed
;
int
randomNumberSeed
;
...
...
openmmapi/include/openmm/CustomIntegrator.h
View file @
ad7a55b8
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2011-201
8
Stanford University and the Authors. *
* Portions copyright (c) 2011-201
9
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -627,6 +627,10 @@ protected:
...
@@ -627,6 +627,10 @@ protected:
* Compute the kinetic energy of the system at the current time.
* Compute the kinetic energy of the system at the current time.
*/
*/
double
computeKineticEnergy
();
double
computeKineticEnergy
();
/**
* Get whether computeKineticEnergy() expects forces to have been computed.
*/
bool
kineticEnergyRequiresForce
()
const
;
private:
private:
class
ComputationInfo
;
class
ComputationInfo
;
class
FunctionInfo
;
class
FunctionInfo
;
...
@@ -639,7 +643,7 @@ private:
...
@@ -639,7 +643,7 @@ private:
std
::
string
kineticEnergy
;
std
::
string
kineticEnergy
;
mutable
bool
globalsAreCurrent
;
mutable
bool
globalsAreCurrent
;
int
randomNumberSeed
;
int
randomNumberSeed
;
bool
forcesAreValid
;
bool
forcesAreValid
,
keNeedsForce
;
Kernel
kernel
;
Kernel
kernel
;
};
};
...
...
openmmapi/include/openmm/Integrator.h
View file @
ad7a55b8
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
9
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -120,8 +120,19 @@ protected:
...
@@ -120,8 +120,19 @@ protected:
* Compute the kinetic energy of the system at the current time. This may be different from simply
* Compute the kinetic energy of the system at the current time. This may be different from simply
* mv<sup>2</sup>/2. For example, a leapfrog integrator will store velocities offset by half a step,
* mv<sup>2</sup>/2. For example, a leapfrog integrator will store velocities offset by half a step,
* but the kinetic energy should be computed at the current time, not delayed by half a step.
* but the kinetic energy should be computed at the current time, not delayed by half a step.
*
* If kineticEnergyRequiresForce() returns true, this method can assume that valid forces
* have already been computed.
*/
*/
virtual
double
computeKineticEnergy
()
=
0
;
virtual
double
computeKineticEnergy
()
=
0
;
/**
* Get whether computeKineticEnergy() expects forces to have been computed. The default
* implementation returns true to be safe. Non-leapfrog integrators can override this to
* return false, which makes calling getState() to query the energy less expensive.
*/
virtual
bool
kineticEnergyRequiresForce
()
const
{
return
true
;
}
private:
private:
double
stepSize
,
constraintTol
;
double
stepSize
,
constraintTol
;
};
};
...
...
openmmapi/src/BAOABLangevinIntegrator.cpp
View file @
ad7a55b8
...
@@ -76,6 +76,10 @@ double BAOABLangevinIntegrator::computeKineticEnergy() {
...
@@ -76,6 +76,10 @@ double BAOABLangevinIntegrator::computeKineticEnergy() {
return
kernel
.
getAs
<
IntegrateBAOABStepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
);
return
kernel
.
getAs
<
IntegrateBAOABStepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
);
}
}
bool
BAOABLangevinIntegrator
::
kineticEnergyRequiresForce
()
const
{
return
false
;
}
void
BAOABLangevinIntegrator
::
step
(
int
steps
)
{
void
BAOABLangevinIntegrator
::
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!"
);
...
...
openmmapi/src/BrownianIntegrator.cpp
View file @
ad7a55b8
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
2
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
9
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -71,6 +71,10 @@ double BrownianIntegrator::computeKineticEnergy() {
...
@@ -71,6 +71,10 @@ double BrownianIntegrator::computeKineticEnergy() {
return
kernel
.
getAs
<
IntegrateBrownianStepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
);
return
kernel
.
getAs
<
IntegrateBrownianStepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
);
}
}
bool
BrownianIntegrator
::
kineticEnergyRequiresForce
()
const
{
return
false
;
}
void
BrownianIntegrator
::
step
(
int
steps
)
{
void
BrownianIntegrator
::
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!"
);
...
...
openmmapi/src/Context.cpp
View file @
ad7a55b8
...
@@ -96,8 +96,9 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
...
@@ -96,8 +96,9 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
bool
includeForces
=
types
&
State
::
Forces
;
bool
includeForces
=
types
&
State
::
Forces
;
bool
includeEnergy
=
types
&
State
::
Energy
;
bool
includeEnergy
=
types
&
State
::
Energy
;
bool
includeParameterDerivs
=
types
&
State
::
ParameterDerivatives
;
bool
includeParameterDerivs
=
types
&
State
::
ParameterDerivatives
;
bool
needForcesForEnergy
=
(
includeEnergy
&&
getIntegrator
().
kineticEnergyRequiresForce
());
if
(
includeForces
||
includeEnergy
||
includeParameterDerivs
)
{
if
(
includeForces
||
includeEnergy
||
includeParameterDerivs
)
{
double
energy
=
impl
->
calcForcesAndEnergy
(
includeForces
||
include
Energy
||
includeParameterDerivs
,
includeEnergy
,
groups
);
double
energy
=
impl
->
calcForcesAndEnergy
(
includeForces
||
needForcesFor
Energy
||
includeParameterDerivs
,
includeEnergy
,
groups
);
if
(
includeEnergy
)
if
(
includeEnergy
)
builder
.
setEnergy
(
impl
->
calcKineticEnergy
(),
energy
);
builder
.
setEnergy
(
impl
->
calcKineticEnergy
(),
energy
);
if
(
includeForces
)
{
if
(
includeForces
)
{
...
...
openmmapi/src/CustomIntegrator.cpp
View file @
ad7a55b8
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2011-201
7
Stanford University and the Authors. *
* Portions copyright (c) 2011-201
9
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -35,6 +35,9 @@
...
@@ -35,6 +35,9 @@
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/kernels.h"
#include "openmm/kernels.h"
#include "lepton/CompiledExpression.h"
#include "lepton/ParsedExpression.h"
#include "lepton/Parser.h"
#include <set>
#include <set>
#include <string>
#include <string>
...
@@ -45,7 +48,7 @@ CustomIntegrator::CustomIntegrator(double stepSize) : globalsAreCurrent(true), f
...
@@ -45,7 +48,7 @@ CustomIntegrator::CustomIntegrator(double stepSize) : globalsAreCurrent(true), f
setStepSize
(
stepSize
);
setStepSize
(
stepSize
);
setConstraintTolerance
(
1e-5
);
setConstraintTolerance
(
1e-5
);
setRandomNumberSeed
(
0
);
setRandomNumberSeed
(
0
);
k
ineticEnergy
=
"m*v*v/2"
;
setK
ineticEnergy
Expression
(
"m*v*v/2"
)
;
}
}
CustomIntegrator
::~
CustomIntegrator
()
{
CustomIntegrator
::~
CustomIntegrator
()
{
...
@@ -103,9 +106,14 @@ vector<string> CustomIntegrator::getKernelNames() {
...
@@ -103,9 +106,14 @@ vector<string> CustomIntegrator::getKernelNames() {
}
}
double
CustomIntegrator
::
computeKineticEnergy
()
{
double
CustomIntegrator
::
computeKineticEnergy
()
{
forcesAreValid
=
keNeedsForce
;
return
kernel
.
getAs
<
IntegrateCustomStepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
,
forcesAreValid
);
return
kernel
.
getAs
<
IntegrateCustomStepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
,
forcesAreValid
);
}
}
bool
CustomIntegrator
::
kineticEnergyRequiresForce
()
const
{
return
keNeedsForce
;
}
void
CustomIntegrator
::
step
(
int
steps
)
{
void
CustomIntegrator
::
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!"
);
...
@@ -312,4 +320,6 @@ const string& CustomIntegrator::getKineticEnergyExpression() const {
...
@@ -312,4 +320,6 @@ const string& CustomIntegrator::getKineticEnergyExpression() const {
void
CustomIntegrator
::
setKineticEnergyExpression
(
const
string
&
expression
)
{
void
CustomIntegrator
::
setKineticEnergyExpression
(
const
string
&
expression
)
{
kineticEnergy
=
expression
;
kineticEnergy
=
expression
;
Lepton
::
CompiledExpression
expr
=
Lepton
::
Parser
::
parse
(
kineticEnergy
).
createCompiledExpression
();
keNeedsForce
=
(
expr
.
getVariables
().
find
(
"f"
)
!=
expr
.
getVariables
().
end
());
}
}
platforms/cuda/include/CudaKernels.h
View file @
ad7a55b8
...
@@ -1633,7 +1633,7 @@ private:
...
@@ -1633,7 +1633,7 @@ private:
double
energy
;
double
energy
;
float
energyFloat
;
float
energyFloat
;
int
numGlobalVariables
,
sumWorkGroupSize
;
int
numGlobalVariables
,
sumWorkGroupSize
;
bool
hasInitializedKernels
,
deviceGlobalsAreCurrent
,
modifiesParameters
,
keNeedsForce
,
hasAnyConstraints
,
needsEnergyParamDerivs
;
bool
hasInitializedKernels
,
deviceGlobalsAreCurrent
,
modifiesParameters
,
hasAnyConstraints
,
needsEnergyParamDerivs
;
std
::
vector
<
bool
>
deviceValuesAreCurrent
;
std
::
vector
<
bool
>
deviceValuesAreCurrent
;
mutable
std
::
vector
<
bool
>
localValuesAreCurrent
;
mutable
std
::
vector
<
bool
>
localValuesAreCurrent
;
CudaArray
globalValues
;
CudaArray
globalValues
;
...
...
platforms/cuda/src/CudaKernels.cpp
View file @
ad7a55b8
...
@@ -7957,7 +7957,6 @@ void CudaIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context,
...
@@ -7957,7 +7957,6 @@ void CudaIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context,
kineticEnergyArgs.push_back(&array.getDevicePointer());
kineticEnergyArgs.push_back(&array.getDevicePointer());
for (auto& array : tabulatedFunctions)
for (auto& array : tabulatedFunctions)
kineticEnergyArgs.push_back(&array.getDevicePointer());
kineticEnergyArgs.push_back(&array.getDevicePointer());
keNeedsForce = usesVariable(keExpression, "f");
// Create a second kernel to sum the values.
// Create a second kernel to sum the values.
...
@@ -8213,17 +8212,6 @@ bool CudaIntegrateCustomStepKernel::evaluateCondition(int step) {
...
@@ -8213,17 +8212,6 @@ bool CudaIntegrateCustomStepKernel::evaluateCondition(int step) {
double CudaIntegrateCustomStepKernel::computeKineticEnergy(ContextImpl& context, CustomIntegrator& integrator, bool& forcesAreValid) {
double CudaIntegrateCustomStepKernel::computeKineticEnergy(ContextImpl& context, CustomIntegrator& integrator, bool& forcesAreValid) {
prepareForComputation(context, integrator, forcesAreValid);
prepareForComputation(context, integrator, forcesAreValid);
if (keNeedsForce && !forcesAreValid) {
// Compute the force. We want to then mark that forces are valid, which means also computing
// potential energy if any steps will expect it to be valid too.
bool willNeedEnergy = false;
for (int i = 0; i < integrator.getNumComputations(); i++)
willNeedEnergy |= needsEnergy[i];
energy = context.calcForcesAndEnergy(true, willNeedEnergy, -1);
energyFloat = (float) energy;
forcesAreValid = true;
}
CUdeviceptr posCorrection = (cu.getUseMixedPrecision() ? cu.getPosqCorrection().getDevicePointer() : 0);
CUdeviceptr posCorrection = (cu.getUseMixedPrecision() ? cu.getPosqCorrection().getDevicePointer() : 0);
int randomIndex = 0;
int randomIndex = 0;
kineticEnergyArgs[1] = &posCorrection;
kineticEnergyArgs[1] = &posCorrection;
...
...
platforms/opencl/include/OpenCLKernels.h
View file @
ad7a55b8
...
@@ -1625,7 +1625,7 @@ private:
...
@@ -1625,7 +1625,7 @@ private:
double
energy
;
double
energy
;
float
energyFloat
;
float
energyFloat
;
int
numGlobalVariables
,
sumWorkGroupSize
;
int
numGlobalVariables
,
sumWorkGroupSize
;
bool
hasInitializedKernels
,
deviceGlobalsAreCurrent
,
modifiesParameters
,
keNeedsForce
,
hasAnyConstraints
,
needsEnergyParamDerivs
;
bool
hasInitializedKernels
,
deviceGlobalsAreCurrent
,
modifiesParameters
,
hasAnyConstraints
,
needsEnergyParamDerivs
;
std
::
vector
<
bool
>
deviceValuesAreCurrent
;
std
::
vector
<
bool
>
deviceValuesAreCurrent
;
mutable
std
::
vector
<
bool
>
localValuesAreCurrent
;
mutable
std
::
vector
<
bool
>
localValuesAreCurrent
;
OpenCLArray
globalValues
;
OpenCLArray
globalValues
;
...
...
platforms/opencl/src/OpenCLKernels.cpp
View file @
ad7a55b8
...
@@ -8364,7 +8364,6 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
...
@@ -8364,7 +8364,6 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
kineticEnergyKernel.setArg<cl::Buffer>(index++, array.getDeviceBuffer());
kineticEnergyKernel.setArg<cl::Buffer>(index++, array.getDeviceBuffer());
for (auto& array : tabulatedFunctions)
for (auto& array : tabulatedFunctions)
kineticEnergyKernel.setArg<cl::Buffer>(index++, array.getDeviceBuffer());
kineticEnergyKernel.setArg<cl::Buffer>(index++, array.getDeviceBuffer());
keNeedsForce = usesVariable(keExpression, "f");
// Create a second kernel to sum the values.
// Create a second kernel to sum the values.
...
@@ -8627,16 +8626,6 @@ bool OpenCLIntegrateCustomStepKernel::evaluateCondition(int step) {
...
@@ -8627,16 +8626,6 @@ bool OpenCLIntegrateCustomStepKernel::evaluateCondition(int step) {
double OpenCLIntegrateCustomStepKernel::computeKineticEnergy(ContextImpl& context, CustomIntegrator& integrator, bool& forcesAreValid) {
double OpenCLIntegrateCustomStepKernel::computeKineticEnergy(ContextImpl& context, CustomIntegrator& integrator, bool& forcesAreValid) {
prepareForComputation(context, integrator, forcesAreValid);
prepareForComputation(context, integrator, forcesAreValid);
if (keNeedsForce && !forcesAreValid) {
// Compute the force. We want to then mark that forces are valid, which means also computing
// potential energy if any steps will expect it to be valid too.
bool willNeedEnergy = false;
for (int i = 0; i < integrator.getNumComputations(); i++)
willNeedEnergy |= needsEnergy[i];
energy = context.calcForcesAndEnergy(true, willNeedEnergy, -1);
forcesAreValid = true;
}
cl.clearBuffer(sumBuffer);
cl.clearBuffer(sumBuffer);
kineticEnergyKernel.setArg<cl::Buffer>(8, cl.getIntegrationUtilities().getRandom().getDeviceBuffer());
kineticEnergyKernel.setArg<cl::Buffer>(8, cl.getIntegrationUtilities().getRandom().getDeviceBuffer());
kineticEnergyKernel.setArg<cl_uint>(9, 0);
kineticEnergyKernel.setArg<cl_uint>(9, 0);
...
...
platforms/reference/src/SimTKReference/ReferenceCustomDynamics.cpp
View file @
ad7a55b8
...
@@ -463,10 +463,6 @@ double ReferenceCustomDynamics::computeKineticEnergy(OpenMM::ContextImpl& contex
...
@@ -463,10 +463,6 @@ double ReferenceCustomDynamics::computeKineticEnergy(OpenMM::ContextImpl& contex
globals
.
insert
(
context
.
getParameters
().
begin
(),
context
.
getParameters
().
end
());
globals
.
insert
(
context
.
getParameters
().
begin
(),
context
.
getParameters
().
end
());
for
(
auto
&
global
:
globals
)
for
(
auto
&
global
:
globals
)
expressionSet
.
setVariable
(
expressionSet
.
getVariableIndex
(
global
.
first
),
global
.
second
);
expressionSet
.
setVariable
(
expressionSet
.
getVariableIndex
(
global
.
first
),
global
.
second
);
if
(
kineticEnergyNeedsForce
)
{
energy
=
context
.
calcForcesAndEnergy
(
true
,
true
,
-
1
);
forcesAreValid
=
true
;
}
computePerDof
(
numberOfAtoms
,
sumBuffer
,
atomCoordinates
,
velocities
,
forces
,
masses
,
perDof
,
kineticEnergyExpression
);
computePerDof
(
numberOfAtoms
,
sumBuffer
,
atomCoordinates
,
velocities
,
forces
,
masses
,
perDof
,
kineticEnergyExpression
);
double
sum
=
0.0
;
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
numberOfAtoms
;
j
++
)
for
(
int
j
=
0
;
j
<
numberOfAtoms
;
j
++
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment