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
0b5d58d7
Commit
0b5d58d7
authored
May 27, 2020
by
Charlles Abreu
Browse files
Conflict resolution in TestSplineFilter.cpp
parents
9026dbe7
b0d13582
Changes
105
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
700 additions
and
750 deletions
+700
-750
platforms/opencl/src/OpenCLPlatform.cpp
platforms/opencl/src/OpenCLPlatform.cpp
+1
-2
platforms/opencl/src/OpenCLSort.cpp
platforms/opencl/src/OpenCLSort.cpp
+79
-72
platforms/opencl/tests/TestOpenCLNoseHooverThermostat.cpp
platforms/opencl/tests/TestOpenCLNoseHooverThermostat.cpp
+0
-36
platforms/reference/include/ReferenceKernels.h
platforms/reference/include/ReferenceKernels.h
+51
-61
platforms/reference/include/ReferenceNoseHooverDynamics.h
platforms/reference/include/ReferenceNoseHooverDynamics.h
+35
-13
platforms/reference/include/ReferencePlatform.h
platforms/reference/include/ReferencePlatform.h
+0
-2
platforms/reference/src/ReferenceKernelFactory.cpp
platforms/reference/src/ReferenceKernelFactory.cpp
+2
-4
platforms/reference/src/ReferenceKernels.cpp
platforms/reference/src/ReferenceKernels.cpp
+224
-234
platforms/reference/src/ReferencePlatform.cpp
platforms/reference/src/ReferencePlatform.cpp
+1
-6
platforms/reference/src/SimTKReference/ReferenceCMAPTorsionIxn.cpp
.../reference/src/SimTKReference/ReferenceCMAPTorsionIxn.cpp
+3
-3
platforms/reference/src/SimTKReference/ReferenceNoseHooverChain.cpp
...reference/src/SimTKReference/ReferenceNoseHooverChain.cpp
+8
-8
platforms/reference/src/SimTKReference/ReferenceNoseHooverDynamics.cpp
...erence/src/SimTKReference/ReferenceNoseHooverDynamics.cpp
+48
-103
platforms/reference/tests/TestReferenceNoseHooverThermostat.cpp
...rms/reference/tests/TestReferenceNoseHooverThermostat.cpp
+0
-36
plugins/cpupme/src/CpuPmeKernels.cpp
plugins/cpupme/src/CpuPmeKernels.cpp
+171
-159
plugins/drude/openmmapi/include/openmm/DrudeNoseHooverIntegrator.h
...rude/openmmapi/include/openmm/DrudeNoseHooverIntegrator.h
+1
-1
plugins/drude/openmmapi/src/DrudeNoseHooverIntegrator.cpp
plugins/drude/openmmapi/src/DrudeNoseHooverIntegrator.cpp
+4
-6
plugins/drude/serialization/src/DrudeNoseHooverIntegratorProxy.cpp
...rude/serialization/src/DrudeNoseHooverIntegratorProxy.cpp
+1
-1
plugins/drude/tests/TestDrudeNoseHoover.h
plugins/drude/tests/TestDrudeNoseHoover.h
+10
-1
tests/TestCompoundIntegrator.h
tests/TestCompoundIntegrator.h
+33
-1
tests/TestCustomIntegrator.h
tests/TestCustomIntegrator.h
+28
-1
No files found.
platforms/opencl/src/OpenCLPlatform.cpp
View file @
0b5d58d7
...
...
@@ -87,7 +87,7 @@ OpenCLPlatform::OpenCLPlatform() {
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcGayBerneForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
Integrate
VelocityVerlet
StepKernel
::
Name
(),
factory
);
registerKernelFactory
(
Integrate
NoseHoover
StepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinMiddleStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateBrownianStepKernel
::
Name
(),
factory
);
...
...
@@ -95,7 +95,6 @@ OpenCLPlatform::OpenCLPlatform() {
registerKernelFactory
(
IntegrateVariableLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateCustomStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
ApplyAndersenThermostatKernel
::
Name
(),
factory
);
registerKernelFactory
(
NoseHooverChainKernel
::
Name
(),
factory
);
registerKernelFactory
(
ApplyMonteCarloBarostatKernel
::
Name
(),
factory
);
registerKernelFactory
(
RemoveCMMotionKernel
::
Name
(),
factory
);
platformProperties
.
push_back
(
OpenCLDeviceIndex
());
...
...
platforms/opencl/src/OpenCLSort.cpp
View file @
0b5d58d7
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010-20
18
Stanford University and the Authors. *
* Portions copyright (c) 2010-20
20
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -64,10 +64,11 @@ OpenCLSort::OpenCLSort(OpenCLContext& context, SortTrait* trait, unsigned int le
unsigned
int
maxPositionsSize
=
std
::
min
(
maxGroupSize
,
(
unsigned
int
)
computeBucketPositionsKernel
.
getWorkGroupInfo
<
CL_KERNEL_WORK_GROUP_SIZE
>
(
context
.
getDevice
()));
int
maxLocalBuffer
=
(
maxSharedMem
/
trait
->
getDataSize
())
/
2
;
unsigned
int
maxShortList
=
min
(
8192
,
max
(
maxLocalBuffer
,
(
int
)
OpenCLContext
::
ThreadBlockSize
*
context
.
getNumThreadBlocks
()));
// On Qualcomm's OpenCL, it's essential to check against CL_KERNEL_WORK_GROUP_SIZE. Otherwise you get a crash.
// But AMD's OpenCL returns an inappropriately small value for it that is much shorter than the actual
// maximum, so including the check hurts performance. For the moment I'm going to just comment it out.
// If we officially support Qualcomm in the future, we'll need to do something better.
// The following line checks CL_KERNEL_WORK_GROUP_SIZE to make sure we don't create too large a workgroup.
// Unfortunately, AMD's OpenCL returns an inappropriately small value for it that is much shorter than the actual
// maximum, so including the check hurts performance. For the moment I'm just leaving it commented out.
// If the workgroup size turns out to be too large, we catch the exception and switch back to the standard
// sorting kernels.
//maxShortList = min(maxShortList, shortListKernel.getWorkGroupInfo<CL_KERNEL_WORK_GROUP_SIZE>(context.getDevice()));
isShortList
=
(
length
<=
maxShortList
);
string
vendor
=
context
.
getDevice
().
getInfo
<
CL_DEVICE_VENDOR
>
();
...
...
@@ -92,12 +93,10 @@ OpenCLSort::OpenCLSort(OpenCLContext& context, SortTrait* trait, unsigned int le
// Create workspace arrays.
if
(
!
isShortList
)
{
dataRange
.
initialize
(
context
,
2
,
trait
->
getKeySize
(),
"sortDataRange"
);
bucketOffset
.
initialize
<
cl_uint
>
(
context
,
numBuckets
,
"bucketOffset"
);
bucketOfElement
.
initialize
<
cl_uint
>
(
context
,
length
,
"bucketOfElement"
);
offsetInBucket
.
initialize
<
cl_uint
>
(
context
,
length
,
"offsetInBucket"
);
}
dataRange
.
initialize
(
context
,
2
,
trait
->
getKeySize
(),
"sortDataRange"
);
bucketOffset
.
initialize
<
cl_uint
>
(
context
,
numBuckets
,
"bucketOffset"
);
bucketOfElement
.
initialize
<
cl_uint
>
(
context
,
length
,
"bucketOfElement"
);
offsetInBucket
.
initialize
<
cl_uint
>
(
context
,
length
,
"offsetInBucket"
);
buckets
.
initialize
(
context
,
length
,
trait
->
getDataSize
(),
"buckets"
);
}
...
...
@@ -113,68 +112,76 @@ void OpenCLSort::sort(OpenCLArray& data) {
if
(
isShortList
)
{
// We can use a simpler sort kernel that does the entire operation in one kernel.
if
(
useShortList2
)
{
shortList2Kernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
shortList2Kernel
.
setArg
<
cl
::
Buffer
>
(
1
,
buckets
.
getDeviceBuffer
());
shortList2Kernel
.
setArg
<
cl_int
>
(
2
,
dataLength
);
context
.
executeKernel
(
shortList2Kernel
,
dataLength
);
buckets
.
copyTo
(
data
);
try
{
if
(
useShortList2
)
{
shortList2Kernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
shortList2Kernel
.
setArg
<
cl
::
Buffer
>
(
1
,
buckets
.
getDeviceBuffer
());
shortList2Kernel
.
setArg
<
cl_int
>
(
2
,
dataLength
);
context
.
executeKernel
(
shortList2Kernel
,
dataLength
);
buckets
.
copyTo
(
data
);
}
else
{
shortListKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
shortListKernel
.
setArg
<
cl_uint
>
(
1
,
dataLength
);
shortListKernel
.
setArg
(
2
,
dataLength
*
trait
->
getDataSize
(),
NULL
);
context
.
executeKernel
(
shortListKernel
,
sortKernelSize
,
sortKernelSize
);
}
return
;
}
else
{
shortListKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
shortListKernel
.
setArg
<
cl_uint
>
(
1
,
dataLength
);
shortListKernel
.
setArg
(
2
,
dataLength
*
trait
->
getDataSize
(),
NULL
);
context
.
executeKernel
(
shortListKernel
,
sortKernelSize
,
sortKernelSize
)
;
catch
(
exception
&
ex
)
{
// This can happen if we chose too large a size for the kernel. Switch
// over to the standard sorting method.
isShortList
=
false
;
}
}
else
{
// Compute the range of data values.
unsigned
int
numBuckets
=
bucketOffset
.
getSize
();
computeRangeKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
computeRangeKernel
.
setArg
<
cl_uint
>
(
1
,
data
.
getSize
());
computeRangeKernel
.
setArg
<
cl
::
Buffer
>
(
2
,
dataRange
.
getDeviceBuffer
());
computeRangeKernel
.
setArg
(
3
,
rangeKernelSize
*
trait
->
getKeySize
(),
NULL
);
computeRangeKernel
.
setArg
(
4
,
rangeKernelSize
*
trait
->
getKeySize
(),
NULL
);
computeRangeKernel
.
setArg
<
cl_int
>
(
5
,
numBuckets
);
computeRangeKernel
.
setArg
<
cl
::
Buffer
>
(
6
,
bucketOffset
.
getDeviceBuffer
());
context
.
executeKernel
(
computeRangeKernel
,
rangeKernelSize
,
rangeKernelSize
);
// Assign array elements to buckets.
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl_int
>
(
1
,
data
.
getSize
());
assignElementsKernel
.
setArg
<
cl_int
>
(
2
,
numBuckets
);
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
3
,
dataRange
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
4
,
bucketOffset
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
5
,
bucketOfElement
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
6
,
offsetInBucket
.
getDeviceBuffer
());
context
.
executeKernel
(
assignElementsKernel
,
data
.
getSize
());
// Compute the position of each bucket.
computeBucketPositionsKernel
.
setArg
<
cl_int
>
(
0
,
numBuckets
);
computeBucketPositionsKernel
.
setArg
<
cl
::
Buffer
>
(
1
,
bucketOffset
.
getDeviceBuffer
());
computeBucketPositionsKernel
.
setArg
(
2
,
positionsKernelSize
*
sizeof
(
cl_int
),
NULL
);
context
.
executeKernel
(
computeBucketPositionsKernel
,
positionsKernelSize
,
positionsKernelSize
);
// Copy the data into the buckets.
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
1
,
buckets
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl_int
>
(
2
,
data
.
getSize
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
3
,
bucketOffset
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
4
,
bucketOfElement
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
5
,
offsetInBucket
.
getDeviceBuffer
());
context
.
executeKernel
(
copyToBucketsKernel
,
data
.
getSize
());
// Sort each bucket.
sortBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
sortBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
1
,
buckets
.
getDeviceBuffer
());
sortBucketsKernel
.
setArg
<
cl_int
>
(
2
,
numBuckets
);
sortBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
3
,
bucketOffset
.
getDeviceBuffer
());
sortBucketsKernel
.
setArg
(
4
,
sortKernelSize
*
trait
->
getDataSize
(),
NULL
);
context
.
executeKernel
(
sortBucketsKernel
,
((
data
.
getSize
()
+
sortKernelSize
-
1
)
/
sortKernelSize
)
*
sortKernelSize
,
sortKernelSize
);
}
// Compute the range of data values.
unsigned
int
numBuckets
=
bucketOffset
.
getSize
();
computeRangeKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
computeRangeKernel
.
setArg
<
cl_uint
>
(
1
,
data
.
getSize
());
computeRangeKernel
.
setArg
<
cl
::
Buffer
>
(
2
,
dataRange
.
getDeviceBuffer
());
computeRangeKernel
.
setArg
(
3
,
rangeKernelSize
*
trait
->
getKeySize
(),
NULL
);
computeRangeKernel
.
setArg
(
4
,
rangeKernelSize
*
trait
->
getKeySize
(),
NULL
);
computeRangeKernel
.
setArg
<
cl_int
>
(
5
,
numBuckets
);
computeRangeKernel
.
setArg
<
cl
::
Buffer
>
(
6
,
bucketOffset
.
getDeviceBuffer
());
context
.
executeKernel
(
computeRangeKernel
,
rangeKernelSize
,
rangeKernelSize
);
// Assign array elements to buckets.
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl_int
>
(
1
,
data
.
getSize
());
assignElementsKernel
.
setArg
<
cl_int
>
(
2
,
numBuckets
);
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
3
,
dataRange
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
4
,
bucketOffset
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
5
,
bucketOfElement
.
getDeviceBuffer
());
assignElementsKernel
.
setArg
<
cl
::
Buffer
>
(
6
,
offsetInBucket
.
getDeviceBuffer
());
context
.
executeKernel
(
assignElementsKernel
,
data
.
getSize
());
// Compute the position of each bucket.
computeBucketPositionsKernel
.
setArg
<
cl_int
>
(
0
,
numBuckets
);
computeBucketPositionsKernel
.
setArg
<
cl
::
Buffer
>
(
1
,
bucketOffset
.
getDeviceBuffer
());
computeBucketPositionsKernel
.
setArg
(
2
,
positionsKernelSize
*
sizeof
(
cl_int
),
NULL
);
context
.
executeKernel
(
computeBucketPositionsKernel
,
positionsKernelSize
,
positionsKernelSize
);
// Copy the data into the buckets.
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
1
,
buckets
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl_int
>
(
2
,
data
.
getSize
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
3
,
bucketOffset
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
4
,
bucketOfElement
.
getDeviceBuffer
());
copyToBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
5
,
offsetInBucket
.
getDeviceBuffer
());
context
.
executeKernel
(
copyToBucketsKernel
,
data
.
getSize
());
// Sort each bucket.
sortBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
data
.
getDeviceBuffer
());
sortBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
1
,
buckets
.
getDeviceBuffer
());
sortBucketsKernel
.
setArg
<
cl_int
>
(
2
,
numBuckets
);
sortBucketsKernel
.
setArg
<
cl
::
Buffer
>
(
3
,
bucketOffset
.
getDeviceBuffer
());
sortBucketsKernel
.
setArg
(
4
,
sortKernelSize
*
trait
->
getDataSize
(),
NULL
);
context
.
executeKernel
(
sortBucketsKernel
,
((
data
.
getSize
()
+
sortKernelSize
-
1
)
/
sortKernelSize
)
*
sortKernelSize
,
sortKernelSize
);
}
platforms/opencl/tests/TestOpenCLNoseHooverThermostat.cpp
deleted
100644 → 0
View file @
9026dbe7
/* -------------------------------------------------------------------------- *
* 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 "OpenCLTests.h"
#include "TestNoseHooverThermostat.h"
void
runPlatformTests
()
{
}
platforms/reference/include/ReferenceKernels.h
View file @
0b5d58d7
...
...
@@ -61,7 +61,7 @@ class ReferenceStochasticDynamics;
class
ReferenceConstraintAlgorithm
;
class
ReferenceNoseHooverChain
;
class
ReferenceMonteCarloBarostat
;
class
Reference
VelocityVerlet
Dynamics
;
class
Reference
NoseHoover
Dynamics
;
class
ReferenceVariableStochasticDynamics
;
class
ReferenceVariableVerletDynamics
;
class
ReferenceVerletDynamics
;
...
...
@@ -1139,12 +1139,12 @@ private:
/**
* This kernel is invoked by NoseHooverIntegrator to take one time step.
*/
class
ReferenceIntegrate
VelocityVerlet
StepKernel
:
public
Integrate
VelocityVerlet
StepKernel
{
class
ReferenceIntegrate
NoseHoover
StepKernel
:
public
Integrate
NoseHoover
StepKernel
{
public:
ReferenceIntegrate
VelocityVerlet
StepKernel
(
std
::
string
name
,
const
Platform
&
platform
,
ReferencePlatform
::
PlatformData
&
data
)
:
Integrate
VelocityVerlet
StepKernel
(
name
,
platform
),
ReferenceIntegrate
NoseHoover
StepKernel
(
std
::
string
name
,
const
Platform
&
platform
,
ReferencePlatform
::
PlatformData
&
data
)
:
Integrate
NoseHoover
StepKernel
(
name
,
platform
),
data
(
data
),
dynamics
(
0
)
{
}
~
ReferenceIntegrate
VelocityVerlet
StepKernel
();
~
ReferenceIntegrate
NoseHoover
StepKernel
();
/**
* Initialize the kernel.
*
...
...
@@ -1168,10 +1168,56 @@ public:
* @param integrator the NoseHooverIntegrator this kernel is being used for
*/
double
computeKineticEnergy
(
ContextImpl
&
context
,
const
NoseHooverIntegrator
&
integrator
);
/**
* Execute the kernel that propagates the Nose Hoover chain and determines the velocity scale factor.
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the object describing the chain to be propagated.
* @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.
* @return the velocity scale factor to apply to the particles associated with this heat bath.
*/
std
::
pair
<
double
,
double
>
propagateChain
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
,
std
::
pair
<
double
,
double
>
kineticEnergy
,
double
timeStep
);
/**
* Execute the kernal that computes the total (kinetic + potential) heat bath energy.
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined.
* @return the total heat bath energy.
*/
double
computeHeatBathEnergy
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
);
/**
* Execute the kernel that computes the kinetic energy for a subset of atoms,
* or the relative kinetic energy of Drude particles with respect to their parent atoms
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined.
* @param downloadValue whether the computed value should be downloaded and returned.
*/
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
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined.
* @param scaleFactor the multiplicative factor by which {absolute, relative} velocities are scaled.
*/
void
scaleVelocities
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
,
std
::
pair
<
double
,
double
>
scaleFactor
);
/**
* Write the chain states to a checkpoint.
*/
void
createCheckpoint
(
ContextImpl
&
context
,
std
::
ostream
&
stream
)
const
;
/**
* Load the chain states from a checkpoint.
*/
void
loadCheckpoint
(
ContextImpl
&
context
,
std
::
istream
&
stream
);
private:
ReferencePlatform
::
PlatformData
&
data
;
ReferenceVelocityVerletDynamics
*
dynamics
;
ReferenceNoseHooverChain
*
chainPropagator
;
ReferenceNoseHooverDynamics
*
dynamics
;
std
::
vector
<
double
>
masses
;
std
::
vector
<
std
::
vector
<
double
>
>
chainPositions
;
std
::
vector
<
std
::
vector
<
double
>
>
chainVelocities
;
double
prevStepSize
;
};
...
...
@@ -1466,62 +1512,6 @@ private:
std
::
vector
<
double
>
masses
;
};
/**
* This kernel is invoked by NoseHooverChain at the start of each time step to adjust the thermostat
* and update the associated particle velocities.
*/
class
ReferenceNoseHooverChainKernel
:
public
NoseHooverChainKernel
{
public:
ReferenceNoseHooverChainKernel
(
std
::
string
name
,
const
Platform
&
platform
)
:
NoseHooverChainKernel
(
name
,
platform
),
chainPropagator
(
0
)
{
}
~
ReferenceNoseHooverChainKernel
();
/**
* Initialize the kernel.
*/
virtual
void
initialize
();
/**
* Execute the kernel that propagates the Nose Hoover chain and determines the velocity scale factor.
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the object describing the chain to be propagated.
* @param kineticEnergy the {absolute, relative} kinetic energies of the particles being thermostated by this chain.
* @param timeStep the time step used by the integrator.
* @return the velocity scale factors to apply to the {absolute, relative} motion of particles associated with this heat bath.
*/
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.
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined.
* @return the total heat bath energy.
*/
virtual
double
computeHeatBathEnergy
(
ContextImpl
&
context
,
const
NoseHooverChain
&
nhc
);
/**
* Execute the kernel that computes the kinetic energy for a subset of atoms,
* or the relative kinetic energy of Drude particles with respect to their parent atoms
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined.
* @param downloadValue whether the computed value should be downloaded and returned.
*
*/
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
*
* @param context the context in which to execute this kernel
* @param noseHooverChain the chain whose energy is to be determined.
* @param scaleFactor the multiplicative factor by which {absolute, relative} velocities are scaled.
*/
virtual
void
scaleVelocities
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
,
std
::
pair
<
double
,
double
>
scaleFactor
);
private:
ReferenceNoseHooverChain
*
chainPropagator
;
};
/**
* This kernel is invoked by MonteCarloBarostat to adjust the periodic box volume
*/
...
...
platforms/reference/include/Reference
VelocityVerlet
Dynamics.h
→
platforms/reference/include/Reference
NoseHoover
Dynamics.h
View file @
0b5d58d7
/* Portions copyright (c) 2006-20
1
2 Stanford University and Simbios.
* Contributors: Pande Group
/* Portions copyright (c) 2006-202
0
Stanford University and Simbios.
* Contributors:
Andy Simmonett, Peter Eastman,
Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
...
...
@@ -22,21 +22,24 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __Reference
VelocityVerlet
Dynamics_H__
#define __Reference
VelocityVerlet
Dynamics_H__
#ifndef __Reference
NoseHoover
Dynamics_H__
#define __Reference
NoseHoover
Dynamics_H__
#include "ReferenceDynamics.h"
#include <tuple>
namespace
OpenMM
{
class
ContextImpl
;
class
Reference
VelocityVerlet
Dynamics
:
public
ReferenceDynamics
{
class
Reference
NoseHoover
Dynamics
:
public
ReferenceDynamics
{
private:
std
::
vector
<
OpenMM
::
Vec3
>
xPrime
;
std
::
vector
<
OpenMM
::
Vec3
>
oldx
;
std
::
vector
<
double
>
inverseMasses
;
int
numberOfAtoms
;
public:
/**---------------------------------------------------------------------------------------
...
...
@@ -50,7 +53,7 @@ class ReferenceVelocityVerletDynamics : public ReferenceDynamics {
--------------------------------------------------------------------------------------- */
Reference
VelocityVerlet
Dynamics
(
int
numberOfAtoms
,
double
deltaT
);
Reference
NoseHoover
Dynamics
(
int
numberOfAtoms
,
double
deltaT
);
/**---------------------------------------------------------------------------------------
...
...
@@ -58,11 +61,11 @@ class ReferenceVelocityVerletDynamics : public ReferenceDynamics {
--------------------------------------------------------------------------------------- */
~
Reference
VelocityVerlet
Dynamics
();
~
Reference
NoseHoover
Dynamics
();
/**---------------------------------------------------------------------------------------
Updat
e
Perform the first half of a step using the leapfrog LF-Middle schem
e
@param system the System to be integrated
@param atomCoordinates atom coordinates
...
...
@@ -77,12 +80,31 @@ class ReferenceVelocityVerletDynamics : public ReferenceDynamics {
--------------------------------------------------------------------------------------- */
void
update
(
OpenMM
::
ContextImpl
&
context
,
const
OpenMM
::
System
&
system
,
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
Vec3
>&
velocities
,
std
::
vector
<
OpenMM
::
Vec3
>&
forces
,
std
::
vector
<
double
>&
masses
,
double
tolerance
,
bool
&
forcesAreValid
,
const
std
::
vector
<
int
>
&
allAtoms
,
const
std
::
vector
<
std
::
tuple
<
int
,
int
,
double
>>
&
allPairs
,
double
maxPairDistance
);
void
step1
(
OpenMM
::
ContextImpl
&
context
,
const
OpenMM
::
System
&
system
,
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
Vec3
>&
velocities
,
std
::
vector
<
OpenMM
::
Vec3
>&
forces
,
std
::
vector
<
double
>&
masses
,
double
tolerance
,
bool
&
forcesAreValid
,
const
std
::
vector
<
int
>
&
allAtoms
,
const
std
::
vector
<
std
::
tuple
<
int
,
int
,
double
>>
&
allPairs
,
double
maxPairDistance
);
/**---------------------------------------------------------------------------------------
Perform the second half of a step using the leapfrog LF-Middle scheme
@param system the System to be integrated
@param atomCoordinates atom coordinates
@param velocities velocities
@param forces forces
@param masses atom masses
@param tolerance the constraint tolerance
@param forcesAreValid whether the forces are valid (duh!)
@param allAtoms a list of all atoms not involved in a Drude-like pair
@param allPairs a list of all Drude-like pairs, and their KT values, in the system
@param maxPairDistance the maximum separation allowed for a Drude-like pair
--------------------------------------------------------------------------------------- */
void
step2
(
OpenMM
::
ContextImpl
&
context
,
const
OpenMM
::
System
&
system
,
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
Vec3
>&
velocities
,
std
::
vector
<
OpenMM
::
Vec3
>&
forces
,
std
::
vector
<
double
>&
masses
,
double
tolerance
,
bool
&
forcesAreValid
,
const
std
::
vector
<
int
>
&
allAtoms
,
const
std
::
vector
<
std
::
tuple
<
int
,
int
,
double
>>
&
allPairs
,
double
maxPairDistance
);
};
}
// namespace OpenMM
#endif // __Reference
VelocityVerlet
Dynamics_H__
#endif // __Reference
NoseHoover
Dynamics_H__
platforms/reference/include/ReferencePlatform.h
View file @
0b5d58d7
...
...
@@ -72,8 +72,6 @@ public:
Vec3
*
periodicBoxVectors
;
ReferenceConstraints
*
constraints
;
std
::
map
<
std
::
string
,
double
>*
energyParameterDerivatives
;
std
::
vector
<
std
::
vector
<
double
>>*
noseHooverPositions
;
std
::
vector
<
std
::
vector
<
double
>>*
noseHooverVelocities
;
};
}
// namespace OpenMM
...
...
platforms/reference/src/ReferenceKernelFactory.cpp
View file @
0b5d58d7
...
...
@@ -88,10 +88,8 @@ KernelImpl* ReferenceKernelFactory::createKernelImpl(std::string name, const Pla
return
new
ReferenceCalcGayBerneForceKernel
(
name
,
platform
);
if
(
name
==
IntegrateVerletStepKernel
::
Name
())
return
new
ReferenceIntegrateVerletStepKernel
(
name
,
platform
,
data
);
if
(
name
==
IntegrateVelocityVerletStepKernel
::
Name
())
return
new
ReferenceIntegrateVelocityVerletStepKernel
(
name
,
platform
,
data
);
if
(
name
==
NoseHooverChainKernel
::
Name
())
return
new
ReferenceNoseHooverChainKernel
(
name
,
platform
);
if
(
name
==
IntegrateNoseHooverStepKernel
::
Name
())
return
new
ReferenceIntegrateNoseHooverStepKernel
(
name
,
platform
,
data
);
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
return
new
ReferenceIntegrateLangevinStepKernel
(
name
,
platform
,
data
);
if
(
name
==
IntegrateLangevinMiddleStepKernel
::
Name
())
...
...
platforms/reference/src/ReferenceKernels.cpp
View file @
0b5d58d7
...
...
@@ -57,6 +57,7 @@
#include "ReferenceLJCoulombIxn.h"
#include "ReferenceMonteCarloBarostat.h"
#include "ReferenceNoseHooverChain.h"
#include "ReferenceNoseHooverDynamics.h"
#include "ReferenceProperDihedralBond.h"
#include "ReferenceRbDihedralBond.h"
#include "ReferenceRMSDForce.h"
...
...
@@ -64,7 +65,6 @@
#include "ReferenceTabulatedFunction.h"
#include "ReferenceVariableStochasticDynamics.h"
#include "ReferenceVariableVerletDynamics.h"
#include "ReferenceVelocityVerletDynamics.h"
#include "ReferenceVerletDynamics.h"
#include "ReferenceVirtualSites.h"
#include "openmm/CMMotionRemover.h"
...
...
@@ -127,15 +127,6 @@ static map<string, double>& extractEnergyParameterDerivatives(ContextImpl& conte
return
*
data
->
energyParameterDerivatives
;
}
static
vector
<
vector
<
double
>
>&
extractNoseHooverPositions
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
((
vector
<
vector
<
double
>
>*
)
data
->
noseHooverPositions
);
}
static
vector
<
vector
<
double
>
>&
extractNoseHooverVelocities
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
((
vector
<
vector
<
double
>
>*
)
data
->
noseHooverVelocities
);
}
/**
* Make sure an expression doesn't use any undefined variables.
*/
...
...
@@ -297,20 +288,6 @@ void ReferenceUpdateStateDataKernel::createCheckpoint(ContextImpl& context, ostr
stream
.
write
((
char
*
)
&
velData
[
0
],
sizeof
(
Vec3
)
*
velData
.
size
());
Vec3
*
vectors
=
extractBoxVectors
(
context
);
stream
.
write
((
char
*
)
vectors
,
3
*
sizeof
(
Vec3
));
auto
&
allNoseHooverPositions
=
extractNoseHooverPositions
(
context
);
auto
&
allNoseHooverVelocities
=
extractNoseHooverVelocities
(
context
);
size_t
numChains
=
allNoseHooverPositions
.
size
();
assert
(
numChains
==
allNoseHooverVelocities
.
size
());
stream
.
write
((
char
*
)
&
numChains
,
sizeof
(
size_t
));
for
(
size_t
i
=
0
;
i
<
numChains
;
i
++
){
auto
&
noseHooverPositions
=
allNoseHooverPositions
.
at
(
i
);
auto
&
noseHooverVelocities
=
allNoseHooverVelocities
.
at
(
i
);
size_t
numBeads
=
noseHooverPositions
.
size
();
assert
(
numBeads
==
noseHooverVelocities
.
size
());
stream
.
write
((
char
*
)
&
numBeads
,
sizeof
(
size_t
));
stream
.
write
((
char
*
)
noseHooverPositions
.
data
(),
sizeof
(
double
)
*
numBeads
);
stream
.
write
((
char
*
)
noseHooverVelocities
.
data
(),
sizeof
(
double
)
*
numBeads
);
}
SimTKOpenMMUtilities
::
createCheckpoint
(
stream
);
}
...
...
@@ -326,21 +303,6 @@ void ReferenceUpdateStateDataKernel::loadCheckpoint(ContextImpl& context, istrea
stream
.
read
((
char
*
)
&
velData
[
0
],
sizeof
(
Vec3
)
*
velData
.
size
());
Vec3
*
vectors
=
extractBoxVectors
(
context
);
stream
.
read
((
char
*
)
vectors
,
3
*
sizeof
(
Vec3
));
size_t
numChains
,
numBeads
;
auto
&
allNoseHooverPositions
=
extractNoseHooverPositions
(
context
);
auto
&
allNoseHooverVelocities
=
extractNoseHooverVelocities
(
context
);
stream
.
read
((
char
*
)
&
numChains
,
sizeof
(
size_t
));
allNoseHooverPositions
.
clear
();
allNoseHooverVelocities
.
clear
();
for
(
size_t
i
=
0
;
i
<
numChains
;
i
++
){
stream
.
read
((
char
*
)
&
numBeads
,
sizeof
(
size_t
));
std
::
vector
<
double
>
noseHooverPositions
(
numBeads
);
std
::
vector
<
double
>
noseHooverVelocities
(
numBeads
);
stream
.
read
((
char
*
)
&
noseHooverPositions
[
0
],
sizeof
(
double
)
*
numBeads
);
stream
.
read
((
char
*
)
&
noseHooverVelocities
[
0
],
sizeof
(
double
)
*
numBeads
);
allNoseHooverPositions
.
push_back
(
noseHooverPositions
);
allNoseHooverVelocities
.
push_back
(
noseHooverVelocities
);
}
SimTKOpenMMUtilities
::
loadCheckpoint
(
stream
);
}
...
...
@@ -2153,19 +2115,22 @@ double ReferenceIntegrateVerletStepKernel::computeKineticEnergy(ContextImpl& con
return
computeShiftedKineticEnergy
(
context
,
masses
,
0.5
*
integrator
.
getStepSize
());
}
ReferenceIntegrateVelocityVerletStepKernel
::~
ReferenceIntegrateVelocityVerletStepKernel
()
{
ReferenceIntegrateNoseHooverStepKernel
::~
ReferenceIntegrateNoseHooverStepKernel
()
{
if
(
chainPropagator
)
delete
chainPropagator
;
if
(
dynamics
)
delete
dynamics
;
}
void
ReferenceIntegrate
VelocityVerlet
StepKernel
::
initialize
(
const
System
&
system
,
const
NoseHooverIntegrator
&
integrator
)
{
void
ReferenceIntegrate
NoseHoover
StepKernel
::
initialize
(
const
System
&
system
,
const
NoseHooverIntegrator
&
integrator
)
{
int
numParticles
=
system
.
getNumParticles
();
masses
.
resize
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
masses
[
i
]
=
system
.
getParticleMass
(
i
);
this
->
chainPropagator
=
new
ReferenceNoseHooverChain
();
}
void
ReferenceIntegrate
VelocityVerlet
StepKernel
::
execute
(
ContextImpl
&
context
,
const
NoseHooverIntegrator
&
integrator
,
bool
&
forcesAreValid
)
{
void
ReferenceIntegrate
NoseHoover
StepKernel
::
execute
(
ContextImpl
&
context
,
const
NoseHooverIntegrator
&
integrator
,
bool
&
forcesAreValid
)
{
double
stepSize
=
integrator
.
getStepSize
();
vector
<
Vec3
>&
posData
=
extractPositions
(
context
);
vector
<
Vec3
>&
velData
=
extractVelocities
(
context
);
...
...
@@ -2174,20 +2139,234 @@ void ReferenceIntegrateVelocityVerletStepKernel::execute(ContextImpl& context, c
// Recreate the computation objects with the new parameters.
if
(
dynamics
)
delete
dynamics
;
dynamics
=
new
Reference
VelocityVerlet
Dynamics
(
context
.
getSystem
().
getNumParticles
(),
stepSize
);
dynamics
=
new
Reference
NoseHoover
Dynamics
(
context
.
getSystem
().
getNumParticles
(),
stepSize
);
dynamics
->
setReferenceConstraintAlgorithm
(
&
extractConstraints
(
context
));
prevStepSize
=
stepSize
;
}
dynamics
->
update
(
context
,
context
.
getSystem
(),
posData
,
velData
,
forceData
,
masses
,
integrator
.
getConstraintTolerance
(),
forcesAreValid
,
dynamics
->
step1
(
context
,
context
.
getSystem
(),
posData
,
velData
,
forceData
,
masses
,
integrator
.
getConstraintTolerance
(),
forcesAreValid
,
integrator
.
getAllThermostatedIndividualParticles
(),
integrator
.
getAllThermostatedPairs
(),
integrator
.
getMaximumPairDistance
());
int
numChains
=
integrator
.
getNumThermostats
();
for
(
int
chain
=
0
;
chain
<
numChains
;
++
chain
)
{
const
auto
&
thermostatChain
=
integrator
.
getThermostat
(
chain
);
std
::
pair
<
double
,
double
>
KEs
=
computeMaskedKineticEnergy
(
context
,
thermostatChain
,
true
);
std
::
pair
<
double
,
double
>
scaleFactors
=
propagateChain
(
context
,
thermostatChain
,
KEs
,
stepSize
);
scaleVelocities
(
context
,
thermostatChain
,
scaleFactors
);
}
dynamics
->
step2
(
context
,
context
.
getSystem
(),
posData
,
velData
,
forceData
,
masses
,
integrator
.
getConstraintTolerance
(),
forcesAreValid
,
integrator
.
getAllThermostatedIndividualParticles
(),
integrator
.
getAllThermostatedPairs
(),
integrator
.
getMaximumPairDistance
());
data
.
time
+=
stepSize
;
data
.
stepCount
++
;
}
double
ReferenceIntegrate
VelocityVerlet
StepKernel
::
computeKineticEnergy
(
ContextImpl
&
context
,
const
NoseHooverIntegrator
&
integrator
)
{
double
ReferenceIntegrate
NoseHoover
StepKernel
::
computeKineticEnergy
(
ContextImpl
&
context
,
const
NoseHooverIntegrator
&
integrator
)
{
return
computeShiftedKineticEnergy
(
context
,
masses
,
0
);
}
std
::
pair
<
double
,
double
>
ReferenceIntegrateNoseHooverStepKernel
::
propagateChain
(
ContextImpl
&
context
,
const
NoseHooverChain
&
nhc
,
std
::
pair
<
double
,
double
>
kineticEnergy
,
double
timeStep
)
{
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
int
chainLength
=
nhc
.
getChainLength
();
int
chainID
=
nhc
.
getChainID
();
int
numDOFs
=
nhc
.
getNumDegreesOfFreedom
();
int
numMTS
=
nhc
.
getNumMultiTimeSteps
();
int
nAtoms
=
nhc
.
getThermostatedAtoms
().
size
();
double
absScale
=
0
;
if
(
nAtoms
)
{
if
(
chainPositions
.
size
()
<
2
*
chainID
+
1
){
chainPositions
.
resize
(
2
*
chainID
+
1
);
}
if
(
chainVelocities
.
size
()
<
2
*
chainID
+
1
){
chainVelocities
.
resize
(
2
*
chainID
+
1
);
}
auto
&
positions
=
chainPositions
.
at
(
2
*
chainID
);
auto
&
velocities
=
chainVelocities
.
at
(
2
*
chainID
);
if
(
positions
.
size
()
<
chainLength
){
positions
.
resize
(
chainLength
,
0
);
}
if
(
velocities
.
size
()
<
chainLength
){
velocities
.
resize
(
chainLength
,
0
);
}
double
temperature
=
nhc
.
getTemperature
();
double
collisionFrequency
=
nhc
.
getCollisionFrequency
();
absScale
=
chainPropagator
->
propagate
(
absKE
,
velocities
,
positions
,
numDOFs
,
temperature
,
collisionFrequency
,
timeStep
,
numMTS
,
nhc
.
getYoshidaSuzukiWeights
());
}
double
relScale
=
0
;
int
nPairs
=
nhc
.
getThermostatedPairs
().
size
();
if
(
nPairs
)
{
if
(
chainPositions
.
size
()
<
2
*
chainID
+
2
){
chainPositions
.
resize
(
2
*
chainID
+
2
);
}
if
(
chainVelocities
.
size
()
<
2
*
chainID
+
2
){
chainVelocities
.
resize
(
2
*
chainID
+
2
);
}
auto
&
positions
=
chainPositions
.
at
(
2
*
chainID
+
1
);
auto
&
velocities
=
chainVelocities
.
at
(
2
*
chainID
+
1
);
if
(
positions
.
size
()
<
chainLength
){
positions
.
resize
(
chainLength
,
0
);
}
if
(
velocities
.
size
()
<
chainLength
){
velocities
.
resize
(
chainLength
,
0
);
}
double
temperature
=
nhc
.
getRelativeTemperature
();
double
collisionFrequency
=
nhc
.
getRelativeCollisionFrequency
();
relScale
=
chainPropagator
->
propagate
(
relKE
,
velocities
,
positions
,
3
*
nPairs
,
temperature
,
collisionFrequency
,
timeStep
,
numMTS
,
nhc
.
getYoshidaSuzukiWeights
());
}
return
{
absScale
,
relScale
};
}
double
ReferenceIntegrateNoseHooverStepKernel
::
computeHeatBathEnergy
(
ContextImpl
&
context
,
const
NoseHooverChain
&
nhc
)
{
double
potentialEnergy
=
0
;
double
kineticEnergy
=
0
;
int
chainLength
=
nhc
.
getChainLength
();
int
chainID
=
nhc
.
getChainID
();
int
nAtoms
=
nhc
.
getThermostatedAtoms
().
size
();
int
nPairs
=
nhc
.
getThermostatedPairs
().
size
();
if
(
nAtoms
)
{
double
temperature
=
nhc
.
getTemperature
();
double
collisionFrequency
=
nhc
.
getCollisionFrequency
();
double
kT
=
temperature
*
BOLTZ
;
int
numDOFs
=
nhc
.
getNumDegreesOfFreedom
();
for
(
int
i
=
0
;
i
<
chainLength
;
++
i
)
{
double
prefac
=
i
?
1
:
numDOFs
;
double
mass
=
prefac
*
kT
/
(
collisionFrequency
*
collisionFrequency
);
double
velocity
=
chainVelocities
[
2
*
chainID
][
i
];
// The kinetic energy of this bead
kineticEnergy
+=
0.5
*
mass
*
velocity
*
velocity
;
// The potential energy of this bead
double
position
=
chainPositions
[
2
*
chainID
][
i
];
potentialEnergy
+=
prefac
*
kT
*
position
;
}
}
if
(
nPairs
)
{
double
temperature
=
nhc
.
getRelativeTemperature
();
double
collisionFrequency
=
nhc
.
getRelativeCollisionFrequency
();
double
kT
=
temperature
*
BOLTZ
;
int
numDOFs
=
3
*
nPairs
;
for
(
int
i
=
0
;
i
<
chainLength
;
++
i
)
{
double
prefac
=
i
?
1
:
numDOFs
;
double
mass
=
prefac
*
kT
/
(
collisionFrequency
*
collisionFrequency
);
double
velocity
=
chainVelocities
[
2
*
chainID
+
1
][
i
];
// The kinetic energy of this bead
kineticEnergy
+=
0.5
*
mass
*
velocity
*
velocity
;
// The potential energy of this bead
double
position
=
chainPositions
[
2
*
chainID
+
1
][
i
];
potentialEnergy
+=
prefac
*
kT
*
position
;
}
}
return
kineticEnergy
+
potentialEnergy
;
}
std
::
pair
<
double
,
double
>
ReferenceIntegrateNoseHooverStepKernel
::
computeMaskedKineticEnergy
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
,
bool
downloadValue
)
{
const
std
::
vector
<
int
>&
atomsList
=
noseHooverChain
.
getThermostatedAtoms
();
const
std
::
vector
<
std
::
pair
<
int
,
int
>>&
pairsList
=
noseHooverChain
.
getThermostatedPairs
();
std
::
vector
<
Vec3
>&
velocities
=
extractVelocities
(
context
);
const
System
&
system
=
context
.
getSystem
();
int
numParticles
=
system
.
getNumParticles
();
std
::
vector
<
double
>
masses
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
masses
[
i
]
=
system
.
getParticleMass
(
i
);
double
comKE
=
0
;
double
relKE
=
0
;
// kinetic energy of individual atoms
for
(
const
auto
&
m
:
atomsList
){
comKE
+=
0.5
*
masses
[
m
]
*
velocities
[
m
].
dot
(
velocities
[
m
]);
}
// center of mass kinetic energy of pairs
for
(
const
auto
&
p
:
pairsList
){
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
redMass
=
m1
*
m2
*
invMass
;
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
return
{
comKE
,
relKE
};
}
void
ReferenceIntegrateNoseHooverStepKernel
::
scaleVelocities
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
,
std
::
pair
<
double
,
double
>
scaleFactors
)
{
const
auto
&
atoms
=
noseHooverChain
.
getThermostatedAtoms
();
const
auto
&
pairs
=
noseHooverChain
.
getThermostatedPairs
();
std
::
vector
<
Vec3
>&
velocities
=
extractVelocities
(
context
);
double
absScale
=
scaleFactors
.
first
;
double
relScale
=
scaleFactors
.
second
;
const
System
&
system
=
context
.
getSystem
();
int
numParticles
=
system
.
getNumParticles
();
std
::
vector
<
double
>
masses
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
masses
[
i
]
=
system
.
getParticleMass
(
i
);
// scale absolute velocities
for
(
const
auto
&
a
:
atoms
){
velocities
[
a
]
*=
absScale
;
}
// 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
;
}
}
void
ReferenceIntegrateNoseHooverStepKernel
::
createCheckpoint
(
ContextImpl
&
context
,
ostream
&
stream
)
const
{
size_t
numChains
=
chainPositions
.
size
();
assert
(
numChains
==
chainVelocities
.
size
());
stream
.
write
((
char
*
)
&
numChains
,
sizeof
(
size_t
));
for
(
size_t
i
=
0
;
i
<
numChains
;
i
++
){
auto
&
noseHooverPositions
=
chainPositions
.
at
(
i
);
auto
&
noseHooverVelocities
=
chainVelocities
.
at
(
i
);
size_t
numBeads
=
noseHooverPositions
.
size
();
assert
(
numBeads
==
noseHooverVelocities
.
size
());
stream
.
write
((
char
*
)
&
numBeads
,
sizeof
(
size_t
));
stream
.
write
((
char
*
)
noseHooverPositions
.
data
(),
sizeof
(
double
)
*
numBeads
);
stream
.
write
((
char
*
)
noseHooverVelocities
.
data
(),
sizeof
(
double
)
*
numBeads
);
}
}
void
ReferenceIntegrateNoseHooverStepKernel
::
loadCheckpoint
(
ContextImpl
&
context
,
istream
&
stream
)
{
size_t
numChains
,
numBeads
;
stream
.
read
((
char
*
)
&
numChains
,
sizeof
(
size_t
));
chainPositions
.
clear
();
chainVelocities
.
clear
();
for
(
size_t
i
=
0
;
i
<
numChains
;
i
++
){
stream
.
read
((
char
*
)
&
numBeads
,
sizeof
(
size_t
));
std
::
vector
<
double
>
noseHooverPositions
(
numBeads
);
std
::
vector
<
double
>
noseHooverVelocities
(
numBeads
);
stream
.
read
((
char
*
)
&
noseHooverPositions
[
0
],
sizeof
(
double
)
*
numBeads
);
stream
.
read
((
char
*
)
&
noseHooverVelocities
[
0
],
sizeof
(
double
)
*
numBeads
);
chainPositions
.
push_back
(
noseHooverPositions
);
chainVelocities
.
push_back
(
noseHooverVelocities
);
}
}
ReferenceIntegrateLangevinStepKernel
::~
ReferenceIntegrateLangevinStepKernel
()
{
if
(
dynamics
)
delete
dynamics
;
...
...
@@ -2512,195 +2691,6 @@ void ReferenceApplyAndersenThermostatKernel::execute(ContextImpl& context) {
context
.
getIntegrator
().
getStepSize
());
}
ReferenceNoseHooverChainKernel
::~
ReferenceNoseHooverChainKernel
()
{
if
(
chainPropagator
)
delete
chainPropagator
;
}
void
ReferenceNoseHooverChainKernel
::
initialize
()
{
this
->
chainPropagator
=
new
ReferenceNoseHooverChain
();
//SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) thermostat.getRandomNumberSeed());
}
std
::
pair
<
double
,
double
>
ReferenceNoseHooverChainKernel
::
propagateChain
(
ContextImpl
&
context
,
const
NoseHooverChain
&
nhc
,
std
::
pair
<
double
,
double
>
kineticEnergy
,
double
timeStep
)
{
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
int
chainLength
=
nhc
.
getChainLength
();
int
chainID
=
nhc
.
getChainID
();
int
numDOFs
=
nhc
.
getNumDegreesOfFreedom
();
int
numMTS
=
nhc
.
getNumMultiTimeSteps
();
// Get the state of the NHC from the context
auto
&
allChainPositions
=
extractNoseHooverPositions
(
context
);
auto
&
allChainVelocities
=
extractNoseHooverVelocities
(
context
);
int
nAtoms
=
nhc
.
getThermostatedAtoms
().
size
();
double
absScale
=
0
;
if
(
nAtoms
)
{
if
(
allChainPositions
.
size
()
<
2
*
chainID
+
1
){
allChainPositions
.
resize
(
2
*
chainID
+
1
);
}
if
(
allChainVelocities
.
size
()
<
2
*
chainID
+
1
){
allChainVelocities
.
resize
(
2
*
chainID
+
1
);
}
auto
&
chainPositions
=
allChainPositions
.
at
(
2
*
chainID
);
auto
&
chainVelocities
=
allChainVelocities
.
at
(
2
*
chainID
);
if
(
chainPositions
.
size
()
<
chainLength
){
chainPositions
.
resize
(
chainLength
,
0
);
}
if
(
chainVelocities
.
size
()
<
chainLength
){
chainVelocities
.
resize
(
chainLength
,
0
);
}
double
temperature
=
nhc
.
getTemperature
();
double
collisionFrequency
=
nhc
.
getCollisionFrequency
();
absScale
=
chainPropagator
->
propagate
(
absKE
,
chainVelocities
,
chainPositions
,
numDOFs
,
temperature
,
collisionFrequency
,
timeStep
,
numMTS
,
nhc
.
getYoshidaSuzukiWeights
());
}
double
relScale
=
0
;
int
nPairs
=
nhc
.
getThermostatedPairs
().
size
();
if
(
nPairs
)
{
if
(
allChainPositions
.
size
()
<
2
*
chainID
+
2
){
allChainPositions
.
resize
(
2
*
chainID
+
2
);
}
if
(
allChainVelocities
.
size
()
<
2
*
chainID
+
2
){
allChainVelocities
.
resize
(
2
*
chainID
+
2
);
}
auto
&
chainPositions
=
allChainPositions
.
at
(
2
*
chainID
+
1
);
auto
&
chainVelocities
=
allChainVelocities
.
at
(
2
*
chainID
+
1
);
if
(
chainPositions
.
size
()
<
chainLength
){
chainPositions
.
resize
(
chainLength
,
0
);
}
if
(
chainVelocities
.
size
()
<
chainLength
){
chainVelocities
.
resize
(
chainLength
,
0
);
}
double
temperature
=
nhc
.
getRelativeTemperature
();
double
collisionFrequency
=
nhc
.
getRelativeCollisionFrequency
();
relScale
=
chainPropagator
->
propagate
(
relKE
,
chainVelocities
,
chainPositions
,
3
*
nPairs
,
temperature
,
collisionFrequency
,
timeStep
,
numMTS
,
nhc
.
getYoshidaSuzukiWeights
());
}
return
{
absScale
,
relScale
};
}
double
ReferenceNoseHooverChainKernel
::
computeHeatBathEnergy
(
ContextImpl
&
context
,
const
NoseHooverChain
&
nhc
)
{
double
potentialEnergy
=
0
;
double
kineticEnergy
=
0
;
int
chainLength
=
nhc
.
getChainLength
();
int
chainID
=
nhc
.
getChainID
();
int
nAtoms
=
nhc
.
getThermostatedAtoms
().
size
();
int
nPairs
=
nhc
.
getThermostatedPairs
().
size
();
auto
&
nhcPositions
=
extractNoseHooverPositions
(
context
);
auto
&
nhcVelocities
=
extractNoseHooverVelocities
(
context
);
if
(
nAtoms
)
{
double
temperature
=
nhc
.
getTemperature
();
double
collisionFrequency
=
nhc
.
getCollisionFrequency
();
double
kT
=
temperature
*
BOLTZ
;
int
numDOFs
=
nhc
.
getNumDegreesOfFreedom
();
for
(
int
i
=
0
;
i
<
chainLength
;
++
i
)
{
double
prefac
=
i
?
1
:
numDOFs
;
double
mass
=
prefac
*
kT
/
(
collisionFrequency
*
collisionFrequency
);
double
velocity
=
nhcVelocities
[
2
*
chainID
][
i
];
// The kinetic energy of this bead
kineticEnergy
+=
0.5
*
mass
*
velocity
*
velocity
;
// The potential energy of this bead
double
position
=
nhcPositions
[
2
*
chainID
][
i
];
potentialEnergy
+=
prefac
*
kT
*
position
;
}
}
if
(
nPairs
)
{
double
temperature
=
nhc
.
getRelativeTemperature
();
double
collisionFrequency
=
nhc
.
getRelativeCollisionFrequency
();
double
kT
=
temperature
*
BOLTZ
;
int
numDOFs
=
3
*
nPairs
;
for
(
int
i
=
0
;
i
<
chainLength
;
++
i
)
{
double
prefac
=
i
?
1
:
numDOFs
;
double
mass
=
prefac
*
kT
/
(
collisionFrequency
*
collisionFrequency
);
double
velocity
=
nhcVelocities
[
2
*
chainID
+
1
][
i
];
// The kinetic energy of this bead
kineticEnergy
+=
0.5
*
mass
*
velocity
*
velocity
;
// The potential energy of this bead
double
position
=
nhcPositions
[
2
*
chainID
+
1
][
i
];
potentialEnergy
+=
prefac
*
kT
*
position
;
}
}
return
kineticEnergy
+
potentialEnergy
;
}
std
::
pair
<
double
,
double
>
ReferenceNoseHooverChainKernel
::
computeMaskedKineticEnergy
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
,
bool
downloadValue
)
{
const
std
::
vector
<
int
>&
atomsList
=
noseHooverChain
.
getThermostatedAtoms
();
const
std
::
vector
<
std
::
pair
<
int
,
int
>>&
pairsList
=
noseHooverChain
.
getThermostatedPairs
();
std
::
vector
<
Vec3
>&
velocities
=
extractVelocities
(
context
);
const
System
&
system
=
context
.
getSystem
();
int
numParticles
=
system
.
getNumParticles
();
std
::
vector
<
double
>
masses
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
masses
[
i
]
=
system
.
getParticleMass
(
i
);
double
comKE
=
0
;
double
relKE
=
0
;
// kinetic energy of individual atoms
for
(
const
auto
&
m
:
atomsList
){
comKE
+=
0.5
*
masses
[
m
]
*
velocities
[
m
].
dot
(
velocities
[
m
]);
}
// center of mass kinetic energy of pairs
for
(
const
auto
&
p
:
pairsList
){
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
redMass
=
m1
*
m2
*
invMass
;
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
return
{
comKE
,
relKE
};
}
void
ReferenceNoseHooverChainKernel
::
scaleVelocities
(
ContextImpl
&
context
,
const
NoseHooverChain
&
noseHooverChain
,
std
::
pair
<
double
,
double
>
scaleFactors
)
{
const
auto
&
atoms
=
noseHooverChain
.
getThermostatedAtoms
();
const
auto
&
pairs
=
noseHooverChain
.
getThermostatedPairs
();
std
::
vector
<
Vec3
>&
velocities
=
extractVelocities
(
context
);
double
absScale
=
scaleFactors
.
first
;
double
relScale
=
scaleFactors
.
second
;
const
System
&
system
=
context
.
getSystem
();
int
numParticles
=
system
.
getNumParticles
();
std
::
vector
<
double
>
masses
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
masses
[
i
]
=
system
.
getParticleMass
(
i
);
// scale absolute velocities
for
(
const
auto
&
a
:
atoms
){
velocities
[
a
]
*=
absScale
;
}
// 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
;
}
}
ReferenceApplyMonteCarloBarostatKernel
::~
ReferenceApplyMonteCarloBarostatKernel
()
{
if
(
barostat
)
delete
barostat
;
...
...
platforms/reference/src/ReferencePlatform.cpp
View file @
0b5d58d7
...
...
@@ -66,8 +66,7 @@ ReferencePlatform::ReferencePlatform() {
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcGayBerneForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVelocityVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
NoseHooverChainKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateNoseHooverStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinMiddleStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateBrownianStepKernel
::
Name
(),
factory
);
...
...
@@ -104,8 +103,6 @@ ReferencePlatform::PlatformData::PlatformData(const System& system) : time(0.0),
periodicBoxVectors
=
new
Vec3
[
3
];
constraints
=
new
ReferenceConstraints
(
system
);
energyParameterDerivatives
=
new
map
<
string
,
double
>
();
noseHooverPositions
=
new
vector
<
vector
<
double
>
>
();
noseHooverVelocities
=
new
vector
<
vector
<
double
>
>
();
}
ReferencePlatform
::
PlatformData
::~
PlatformData
()
{
...
...
@@ -116,6 +113,4 @@ ReferencePlatform::PlatformData::~PlatformData() {
delete
[]
periodicBoxVectors
;
delete
constraints
;
delete
energyParameterDerivatives
;
delete
noseHooverPositions
;
delete
noseHooverVelocities
;
}
platforms/reference/src/SimTKReference/ReferenceCMAPTorsionIxn.cpp
View file @
0b5d58d7
/* Portions copyright (c) 2010-20
16
Stanford University and Simbios.
/* Portions copyright (c) 2010-20
20
Stanford University and Simbios.
* Contributors: Peter Eastman
*
* Permission is hereby granted, free of charge, to any person obtaining
...
...
@@ -133,8 +133,8 @@ void ReferenceCMAPTorsionIxn::calculateOneIxn(int index, vector<Vec3>& atomCoord
int
size
=
(
int
)
sqrt
(
coeff
[
map
].
size
());
double
delta
=
2
*
M_PI
/
size
;
int
s
=
(
int
)
(
angleA
/
delta
);
int
t
=
(
int
)
(
angleB
/
delta
);
int
s
=
(
int
)
fmin
(
angleA
/
delta
,
size
-
1
);
int
t
=
(
int
)
fmin
(
angleB
/
delta
,
size
-
1
);
const
vector
<
double
>&
c
=
coeff
[
map
][
s
+
size
*
t
];
double
da
=
angleA
/
delta
-
s
;
double
db
=
angleB
/
delta
-
t
;
...
...
platforms/reference/src/SimTKReference/ReferenceNoseHooverChain.cpp
View file @
0b5d58d7
...
...
@@ -68,27 +68,27 @@ double ReferenceNoseHooverChain::propagate(double kineticEnergy, vector<double>&
for
(
int
mts
=
0
;
mts
<
numMTS
;
++
mts
)
{
for
(
const
auto
&
ys
:
YSWeights
)
{
double
wdt
=
ys
*
timeStep
/
numMTS
;
chainVelocities
.
back
()
+=
0.
2
5
*
wdt
*
chainForces
.
back
();
chainVelocities
.
back
()
+=
0.5
*
wdt
*
chainForces
.
back
();
for
(
int
bead
=
chainLength
-
2
;
bead
>=
0
;
--
bead
)
{
double
aa
=
exp
(
-
0.
1
25
*
wdt
*
chainVelocities
[
bead
+
1
]);
chainVelocities
[
bead
]
=
aa
*
(
chainVelocities
[
bead
]
*
aa
+
0.
2
5
*
wdt
*
chainForces
[
bead
]);
double
aa
=
exp
(
-
0.25
*
wdt
*
chainVelocities
[
bead
+
1
]);
chainVelocities
[
bead
]
=
aa
*
(
chainVelocities
[
bead
]
*
aa
+
0.5
*
wdt
*
chainForces
[
bead
]);
}
// update particle velocities
double
aa
=
exp
(
-
0.5
*
wdt
*
chainVelocities
[
0
]);
double
aa
=
exp
(
-
wdt
*
chainVelocities
[
0
]);
scale
*=
aa
;
// update the thermostat positions
for
(
int
bead
=
0
;
bead
<
chainLength
;
++
bead
)
{
chainPositions
[
bead
]
+=
0.5
*
chainVelocities
[
bead
]
*
wdt
;
chainPositions
[
bead
]
+=
chainVelocities
[
bead
]
*
wdt
;
}
// update the forces
chainForces
[
0
]
=
(
scale
*
scale
*
KE2
-
numDOFs
*
kT
)
/
chainMasses
[
0
];
// update thermostat velocities
for
(
int
bead
=
0
;
bead
<
chainLength
-
1
;
++
bead
)
{
double
aa
=
exp
(
-
0.
1
25
*
wdt
*
chainVelocities
[
bead
+
1
]);
chainVelocities
[
bead
]
=
aa
*
(
aa
*
chainVelocities
[
bead
]
+
0.
2
5
*
wdt
*
chainForces
[
bead
]);
double
aa
=
exp
(
-
0.25
*
wdt
*
chainVelocities
[
bead
+
1
]);
chainVelocities
[
bead
]
=
aa
*
(
aa
*
chainVelocities
[
bead
]
+
0.5
*
wdt
*
chainForces
[
bead
]);
chainForces
[
bead
+
1
]
=
(
chainMasses
[
bead
]
*
chainVelocities
[
bead
]
*
chainVelocities
[
bead
]
-
kT
)
/
chainMasses
[
bead
+
1
];
}
chainVelocities
[
chainLength
-
1
]
+=
0.
2
5
*
wdt
*
chainForces
.
back
();
chainVelocities
[
chainLength
-
1
]
+=
0.5
*
wdt
*
chainForces
.
back
();
}
// YS loop
}
// MTS loop
return
scale
;
...
...
platforms/reference/src/SimTKReference/Reference
VelocityVerlet
Dynamics.cpp
→
platforms/reference/src/SimTKReference/Reference
NoseHoover
Dynamics.cpp
View file @
0b5d58d7
/* Portions copyright (c) 2006-20
13
Stanford University and Simbios.
* Contributors: Peter Eastman, Pande Group
/* Portions copyright (c) 2006-20
20
Stanford University and Simbios.
* Contributors:
Andy Simmonett,
Peter Eastman, Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
...
...
@@ -29,7 +29,7 @@
#include "openmm/OpenMMException.h"
#include "SimTKOpenMMUtilities.h"
#include "openmm/internal/ContextImpl.h"
#include "Reference
VelocityVerlet
Dynamics.h"
#include "Reference
NoseHoover
Dynamics.h"
#include "ReferenceVirtualSites.h"
#include <cstdio>
...
...
@@ -37,49 +37,18 @@
using
std
::
vector
;
using
namespace
OpenMM
;
/**---------------------------------------------------------------------------------------
ReferenceVelocityVerletDynamics constructor
@param numberOfAtoms number of atoms
@param deltaT delta t for dynamics
@param friction friction coefficient
@param temperature temperature
--------------------------------------------------------------------------------------- */
ReferenceVelocityVerletDynamics
::
ReferenceVelocityVerletDynamics
(
int
numberOfAtoms
,
double
deltaT
)
:
ReferenceDynamics
(
numberOfAtoms
,
deltaT
,
0.0
)
{
ReferenceNoseHooverDynamics
::
ReferenceNoseHooverDynamics
(
int
numberOfAtomsIn
,
double
deltaT
)
:
ReferenceDynamics
(
numberOfAtomsIn
,
deltaT
,
0.0
)
{
numberOfAtoms
=
numberOfAtomsIn
;
xPrime
.
resize
(
numberOfAtoms
);
inverseMasses
.
resize
(
numberOfAtoms
);
oldx
.
resize
(
numberOfAtoms
);
}
/**---------------------------------------------------------------------------------------
ReferenceVelocityVerletDynamics destructor
--------------------------------------------------------------------------------------- */
ReferenceVelocityVerletDynamics
::~
ReferenceVelocityVerletDynamics
()
{
ReferenceNoseHooverDynamics
::~
ReferenceNoseHooverDynamics
()
{
}
/**---------------------------------------------------------------------------------------
Update -- driver routine for performing Velocity Verlet dynamics update of coordinates
and velocities
@param system the System to be integrated
@param atomCoordinates atom coordinates
@param velocities velocities
@param forces forces
@param masses atom masses
@param atomList list of all atoms not involved in a Drude-like pair
@param pairList list of all Drude-like pairs
@param maxPairDistance the maximum separation of any Drude-like pairs
--------------------------------------------------------------------------------------- */
void
ReferenceVelocityVerletDynamics
::
update
(
OpenMM
::
ContextImpl
&
context
,
const
OpenMM
::
System
&
system
,
vector
<
Vec3
>&
atomCoordinates
,
void
ReferenceNoseHooverDynamics
::
step1
(
OpenMM
::
ContextImpl
&
context
,
const
OpenMM
::
System
&
system
,
vector
<
Vec3
>&
atomCoordinates
,
vector
<
Vec3
>&
velocities
,
vector
<
Vec3
>&
forces
,
vector
<
double
>&
masses
,
double
tolerance
,
bool
&
forcesAreValid
,
const
std
::
vector
<
int
>
&
atomList
,
const
std
::
vector
<
std
::
tuple
<
int
,
int
,
double
>>
&
pairList
,
...
...
@@ -88,10 +57,8 @@ void ReferenceVelocityVerletDynamics::update(OpenMM::ContextImpl &context, const
// first-time-through initialization
if
(
!
forcesAreValid
)
context
.
calcForcesAndEnergy
(
true
,
false
);
int
numberOfAtoms
=
system
.
getNumParticles
();
if
(
getTimeStep
()
==
0
)
{
// invert masses
for
(
int
ii
=
0
;
ii
<
numberOfAtoms
;
ii
++
)
{
if
(
masses
[
ii
]
==
0.0
)
inverseMasses
[
ii
]
=
0.0
;
...
...
@@ -100,22 +67,20 @@ void ReferenceVelocityVerletDynamics::update(OpenMM::ContextImpl &context, const
}
}
//// Perform the integration.
const
double
halfdt
=
0.5
*
getDeltaT
();
// Regular atoms
for
(
const
auto
&
atom
:
atomList
)
{
if
(
masses
[
atom
]
!=
0.0
)
{
velocities
[
atom
]
+=
0.5
*
inverseMasses
[
atom
]
*
forces
[
atom
]
*
getDeltaT
();
xPrime
[
atom
]
=
atomCoordinates
[
atom
];
atomCoordinates
[
atom
]
+=
velocities
[
atom
]
*
getDeltaT
();
velocities
[
atom
]
+=
inverseMasses
[
atom
]
*
forces
[
atom
]
*
getDeltaT
();
}
}
// Connected particles
for
(
const
auto
&
pair
:
pairList
)
{
const
auto
&
atom1
=
std
::
get
<
0
>
(
pair
);
const
auto
&
atom2
=
std
::
get
<
1
>
(
pair
);
double
m1
=
system
.
getParticleMass
(
atom1
)
;
double
m2
=
system
.
getParticleMass
(
atom2
)
;
double
m1
=
masses
[
atom1
]
;
double
m2
=
masses
[
atom2
]
;
double
mass1fract
=
m1
/
(
m1
+
m2
);
double
mass2fract
=
m2
/
(
m1
+
m2
);
double
invRedMass
=
(
m1
*
m2
!=
0.0
)
?
(
m1
+
m2
)
/
(
m1
*
m2
)
:
0.0
;
...
...
@@ -124,26 +89,52 @@ void ReferenceVelocityVerletDynamics::update(OpenMM::ContextImpl &context, const
Vec3
relVel
=
velocities
[
atom2
]
-
velocities
[
atom1
];
Vec3
comForce
=
forces
[
atom1
]
+
forces
[
atom2
];
Vec3
relForce
=
mass1fract
*
forces
[
atom2
]
-
mass2fract
*
forces
[
atom1
];
comVel
+=
0.5
*
comForce
*
getDeltaT
()
*
invTotMass
;
relVel
+=
0.5
*
relForce
*
getDeltaT
()
*
invRedMass
;
comVel
+=
comForce
*
getDeltaT
()
*
invTotMass
;
relVel
+=
relForce
*
getDeltaT
()
*
invRedMass
;
if
(
m1
!=
0.0
)
{
velocities
[
atom1
]
=
comVel
-
relVel
*
mass2fract
;
xPrime
[
atom1
]
=
atomCoordinates
[
atom1
];
atomCoordinates
[
atom1
]
+=
velocities
[
atom1
]
*
getDeltaT
();
}
if
(
m2
!=
0.0
)
{
velocities
[
atom2
]
=
comVel
+
relVel
*
mass1fract
;
xPrime
[
atom2
]
=
atomCoordinates
[
atom2
];
atomCoordinates
[
atom2
]
+=
velocities
[
atom2
]
*
getDeltaT
();
}
}
//
ReferenceConstraintAlgorithm
*
referenceConstraintAlgorithm
=
getReferenceConstraintAlgorithm
();
if
(
referenceConstraintAlgorithm
)
{
referenceConstraintAlgorithm
->
applyToVelocities
(
atomCoordinates
,
velocities
,
inverseMasses
,
tolerance
);
}
for
(
int
atom
=
0
;
atom
<
numberOfAtoms
;
++
atom
)
{
if
(
masses
[
atom
]
!=
0.0
)
{
xPrime
[
atom
]
=
atomCoordinates
[
atom
]
+
velocities
[
atom
]
*
halfdt
;
}
}
}
void
ReferenceNoseHooverDynamics
::
step2
(
OpenMM
::
ContextImpl
&
context
,
const
OpenMM
::
System
&
system
,
vector
<
Vec3
>&
atomCoordinates
,
vector
<
Vec3
>&
velocities
,
vector
<
Vec3
>&
forces
,
vector
<
double
>&
masses
,
double
tolerance
,
bool
&
forcesAreValid
,
const
std
::
vector
<
int
>
&
atomList
,
const
std
::
vector
<
std
::
tuple
<
int
,
int
,
double
>>
&
pairList
,
double
maxPairDistance
)
{
const
double
halfdt
=
0.5
*
getDeltaT
();
for
(
int
atom
=
0
;
atom
<
numberOfAtoms
;
++
atom
)
{
if
(
masses
[
atom
]
!=
0.0
)
{
xPrime
[
atom
]
+=
velocities
[
atom
]
*
halfdt
;
oldx
[
atom
]
=
xPrime
[
atom
];
}
}
ReferenceConstraintAlgorithm
*
referenceConstraintAlgorithm
=
getReferenceConstraintAlgorithm
();
if
(
referenceConstraintAlgorithm
)
referenceConstraintAlgorithm
->
apply
(
xPrime
,
atomCoordinates
,
inverseMasses
,
tolerance
);
referenceConstraintAlgorithm
->
apply
(
atomCoordinates
,
xPrime
,
inverseMasses
,
tolerance
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
{
if
(
inverseMasses
[
i
]
!=
0.0
)
{
velocities
[
i
]
+=
(
xPrime
[
i
]
-
oldx
[
i
])
/
getDeltaT
();
atomCoordinates
[
i
]
=
xPrime
[
i
];
}
}
// Apply hard wall constraints.
if
(
maxPairDistance
>
0
)
{
...
...
@@ -157,9 +148,6 @@ void ReferenceVelocityVerletDynamics::update(OpenMM::ContextImpl &context, const
if
(
rInv
*
maxPairDistance
<
1.0
)
{
// The constraint has been violated, so make the inter-particle distance "bounce"
// off the hard wall.
//if (rInv*maxPairDistance < 0.5)
// throw OpenMMException("Drude particle moved too far beyond hard wall constraint");
// TODO: Review this - I commented it out to make the NoseHooverThermostat test work
Vec3
bondDir
=
delta
*
rInv
;
Vec3
vel1
=
velocities
[
atom1
];
Vec3
vel2
=
velocities
[
atom2
];
...
...
@@ -213,50 +201,7 @@ void ReferenceVelocityVerletDynamics::update(OpenMM::ContextImpl &context, const
}
}
/* end of hard wall constraint part */
ReferenceVirtualSites
::
computePositions
(
system
,
atomCoordinates
);
context
.
calcForcesAndEnergy
(
true
,
false
);
forcesAreValid
=
true
;
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
++
i
)
{
if
(
masses
[
i
]
!=
0.0
)
for
(
int
j
=
0
;
j
<
3
;
++
j
)
{
xPrime
[
i
][
j
]
+=
velocities
[
i
][
j
]
*
getDeltaT
();
}
}
// Update the positions and velocities.
// Regular atoms
for
(
const
auto
&
atom
:
atomList
)
{
if
(
masses
[
atom
]
!=
0.0
)
{
velocities
[
atom
]
+=
0.5
*
inverseMasses
[
atom
]
*
forces
[
atom
]
*
getDeltaT
()
+
(
atomCoordinates
[
atom
]
-
xPrime
[
atom
])
/
getDeltaT
();
}
}
// Connected particles
for
(
const
auto
&
pair
:
pairList
)
{
const
auto
&
atom1
=
std
::
get
<
0
>
(
pair
);
const
auto
&
atom2
=
std
::
get
<
1
>
(
pair
);
double
m1
=
system
.
getParticleMass
(
atom1
);
double
m2
=
system
.
getParticleMass
(
atom2
);
double
mass1fract
=
m1
/
(
m1
+
m2
);
double
mass2fract
=
m2
/
(
m1
+
m2
);
double
invRedMass
=
(
m1
*
m2
!=
0.0
)
?
(
m1
+
m2
)
/
(
m1
*
m2
)
:
0.0
;
double
invTotMass
=
(
m1
+
m2
!=
0.0
)
?
1.0
/
(
m1
+
m2
)
:
0.0
;
Vec3
comVel
=
velocities
[
atom1
]
*
mass1fract
+
velocities
[
atom2
]
*
mass2fract
;
Vec3
relVel
=
velocities
[
atom2
]
-
velocities
[
atom1
];
Vec3
comForce
=
forces
[
atom1
]
+
forces
[
atom2
];
Vec3
relForce
=
mass1fract
*
forces
[
atom2
]
-
mass2fract
*
forces
[
atom1
];
comVel
+=
0.5
*
comForce
*
getDeltaT
()
*
invTotMass
;
relVel
+=
0.5
*
relForce
*
getDeltaT
()
*
invRedMass
;
if
(
m1
!=
0.0
)
{
velocities
[
atom1
]
=
comVel
-
relVel
*
mass2fract
+
(
atomCoordinates
[
atom1
]
-
xPrime
[
atom1
])
/
getDeltaT
();
}
if
(
m2
!=
0.0
)
{
velocities
[
atom2
]
=
comVel
+
relVel
*
mass1fract
+
(
atomCoordinates
[
atom2
]
-
xPrime
[
atom2
])
/
getDeltaT
();
}
}
if
(
referenceConstraintAlgorithm
)
referenceConstraintAlgorithm
->
applyToVelocities
(
atomCoordinates
,
velocities
,
inverseMasses
,
tolerance
);
ReferenceVirtualSites
::
computePositions
(
context
.
getSystem
(),
atomCoordinates
);
incrementTimeStep
();
}
platforms/reference/tests/TestReferenceNoseHooverThermostat.cpp
deleted
100644 → 0
View file @
9026dbe7
/* -------------------------------------------------------------------------- *
* 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 "ReferenceTests.h"
#include "TestNoseHooverThermostat.h"
void
runPlatformTests
()
{
}
plugins/cpupme/src/CpuPmeKernels.cpp
View file @
0b5d58d7
...
...
@@ -66,96 +66,102 @@ static void spreadCharge(float* posq, float* grid, int gridx, int gridy, int gri
float
posInBox
[
4
]
=
{
0
,
0
,
0
,
0
};
memset
(
grid
,
0
,
sizeof
(
float
)
*
gridx
*
gridy
*
gridz
);
int
i
=
threadIndex
;
const
int
groupSize
=
max
(
1
,
numParticles
/
(
10
*
numThreads
));
int
start
=
groupSize
*
threadIndex
;
while
(
true
)
{
if
(
!
deterministic
)
i
=
atomicCounter
++
;
if
(
i
>=
numParticles
)
start
=
atomicCounter
.
fetch_add
(
groupSize
);
if
(
start
>=
numParticles
)
break
;
// Find the position relative to the nearest grid point.
fvec4
pos
(
&
posq
[
4
*
i
]);
(
pos
-
boxSize
*
floor
(
pos
*
invBoxSize
)).
store
(
posInBox
);
fvec4
t
=
posInBox
[
0
]
*
recipBoxVec0
+
posInBox
[
1
]
*
recipBoxVec1
+
posInBox
[
2
]
*
recipBoxVec2
;
t
=
(
t
-
floor
(
t
))
*
gridSize
;
ivec4
ti
=
t
;
fvec4
dr
=
t
-
ti
;
ivec4
gridIndex
=
ti
-
(
gridSizeInt
&
ti
==
gridSizeInt
);
// Compute the B-spline coefficients.
fvec4
data
[
PME_ORDER
];
data
[
PME_ORDER
-
1
]
=
0.0
f
;
data
[
1
]
=
dr
;
data
[
0
]
=
one
-
dr
;
for
(
int
j
=
3
;
j
<
PME_ORDER
;
j
++
)
{
fvec4
div
(
1.0
f
/
(
j
-
1
));
data
[
j
-
1
]
=
div
*
dr
*
data
[
j
-
2
];
for
(
int
k
=
1
;
k
<
j
-
1
;
k
++
)
data
[
j
-
k
-
1
]
=
div
*
((
dr
+
k
)
*
data
[
j
-
k
-
2
]
+
(
fvec4
(
j
-
k
)
-
dr
)
*
data
[
j
-
k
-
1
]);
data
[
0
]
=
div
*
(
one
-
dr
)
*
data
[
0
];
}
data
[
PME_ORDER
-
1
]
=
scale
*
dr
*
data
[
PME_ORDER
-
2
];
for
(
int
j
=
1
;
j
<
(
PME_ORDER
-
1
);
j
++
)
data
[
PME_ORDER
-
j
-
1
]
=
scale
*
((
dr
+
j
)
*
data
[
PME_ORDER
-
j
-
2
]
+
(
fvec4
(
PME_ORDER
-
j
)
-
dr
)
*
data
[
PME_ORDER
-
j
-
1
]);
data
[
0
]
=
scale
*
(
one
-
dr
)
*
data
[
0
];
// Spread the charges.
int
gridIndexX
=
gridIndex
[
0
];
int
gridIndexY
=
gridIndex
[
1
];
int
gridIndexZ
=
gridIndex
[
2
];
if
(
gridIndexX
<
0
)
return
;
// This happens when a simulation blows up and coordinates become NaN.
int
zindex
[
PME_ORDER
];
for
(
int
j
=
0
;
j
<
PME_ORDER
;
j
++
)
{
zindex
[
j
]
=
gridIndexZ
+
j
;
zindex
[
j
]
-=
(
zindex
[
j
]
>=
gridz
?
gridz
:
0
);
}
float
charge
=
epsilonFactor
*
posq
[
4
*
i
+
3
];
fvec4
zdata0to3
(
data
[
0
][
2
],
data
[
1
][
2
],
data
[
2
][
2
],
data
[
3
][
2
]);
float
zdata4
=
data
[
4
][
2
];
if
(
gridIndexZ
+
4
<
gridz
)
{
for
(
int
ix
=
0
;
ix
<
PME_ORDER
;
ix
++
)
{
int
xbase
=
gridIndexX
+
ix
;
xbase
-=
(
xbase
>=
gridx
?
gridx
:
0
);
xbase
=
xbase
*
gridy
*
gridz
;
float
xdata
=
charge
*
data
[
ix
][
0
];
for
(
int
iy
=
0
;
iy
<
PME_ORDER
;
iy
++
)
{
int
ybase
=
gridIndexY
+
iy
;
ybase
-=
(
ybase
>=
gridy
?
gridy
:
0
);
ybase
=
xbase
+
ybase
*
gridz
;
float
multiplier
=
xdata
*
data
[
iy
][
1
];
fvec4
add0to3
=
zdata0to3
*
multiplier
;
(
fvec4
(
&
grid
[
ybase
+
gridIndexZ
])
+
add0to3
).
store
(
&
grid
[
ybase
+
gridIndexZ
]);
grid
[
ybase
+
zindex
[
4
]]
+=
multiplier
*
zdata4
;
int
end
=
min
(
start
+
groupSize
,
numParticles
);
for
(
int
i
=
start
;
i
<
end
;
++
i
)
{
// Find the position relative to the nearest grid point.
fvec4
pos
(
&
posq
[
4
*
i
]);
(
pos
-
boxSize
*
floor
(
pos
*
invBoxSize
)).
store
(
posInBox
);
fvec4
t
=
posInBox
[
0
]
*
recipBoxVec0
+
posInBox
[
1
]
*
recipBoxVec1
+
posInBox
[
2
]
*
recipBoxVec2
;
t
=
(
t
-
floor
(
t
))
*
gridSize
;
ivec4
ti
=
t
;
fvec4
dr
=
t
-
ti
;
ivec4
gridIndex
=
ti
-
(
gridSizeInt
&
ti
==
gridSizeInt
);
// Compute the B-spline coefficients.
fvec4
data
[
PME_ORDER
];
data
[
PME_ORDER
-
1
]
=
0.0
f
;
data
[
1
]
=
dr
;
data
[
0
]
=
one
-
dr
;
for
(
int
j
=
3
;
j
<
PME_ORDER
;
j
++
)
{
fvec4
div
(
1.0
f
/
(
j
-
1
));
data
[
j
-
1
]
=
div
*
dr
*
data
[
j
-
2
];
for
(
int
k
=
1
;
k
<
j
-
1
;
k
++
)
data
[
j
-
k
-
1
]
=
div
*
((
dr
+
k
)
*
data
[
j
-
k
-
2
]
+
(
fvec4
(
j
-
k
)
-
dr
)
*
data
[
j
-
k
-
1
]);
data
[
0
]
=
div
*
(
one
-
dr
)
*
data
[
0
];
}
data
[
PME_ORDER
-
1
]
=
scale
*
dr
*
data
[
PME_ORDER
-
2
];
for
(
int
j
=
1
;
j
<
(
PME_ORDER
-
1
);
j
++
)
data
[
PME_ORDER
-
j
-
1
]
=
scale
*
((
dr
+
j
)
*
data
[
PME_ORDER
-
j
-
2
]
+
(
fvec4
(
PME_ORDER
-
j
)
-
dr
)
*
data
[
PME_ORDER
-
j
-
1
]);
data
[
0
]
=
scale
*
(
one
-
dr
)
*
data
[
0
];
// Spread the charges.
int
gridIndexX
=
gridIndex
[
0
];
int
gridIndexY
=
gridIndex
[
1
];
int
gridIndexZ
=
gridIndex
[
2
];
if
(
gridIndexX
<
0
)
return
;
// This happens when a simulation blows up and coordinates become NaN.
int
zindex
[
PME_ORDER
];
for
(
int
j
=
0
;
j
<
PME_ORDER
;
j
++
)
{
zindex
[
j
]
=
gridIndexZ
+
j
;
zindex
[
j
]
-=
(
zindex
[
j
]
>=
gridz
?
gridz
:
0
);
}
float
charge
=
epsilonFactor
*
posq
[
4
*
i
+
3
];
fvec4
zdata0to3
(
data
[
0
][
2
],
data
[
1
][
2
],
data
[
2
][
2
],
data
[
3
][
2
]);
float
zdata4
=
data
[
4
][
2
];
if
(
gridIndexZ
+
4
<
gridz
)
{
for
(
int
ix
=
0
;
ix
<
PME_ORDER
;
ix
++
)
{
int
xbase
=
gridIndexX
+
ix
;
xbase
-=
(
xbase
>=
gridx
?
gridx
:
0
);
xbase
=
xbase
*
gridy
*
gridz
;
float
xdata
=
charge
*
data
[
ix
][
0
];
for
(
int
iy
=
0
;
iy
<
PME_ORDER
;
iy
++
)
{
int
ybase
=
gridIndexY
+
iy
;
ybase
-=
(
ybase
>=
gridy
?
gridy
:
0
);
ybase
=
xbase
+
ybase
*
gridz
;
float
multiplier
=
xdata
*
data
[
iy
][
1
];
fvec4
add0to3
=
zdata0to3
*
multiplier
;
(
fvec4
(
&
grid
[
ybase
+
gridIndexZ
])
+
add0to3
).
store
(
&
grid
[
ybase
+
gridIndexZ
]);
grid
[
ybase
+
zindex
[
4
]]
+=
multiplier
*
zdata4
;
}
}
}
}
else
{
for
(
int
ix
=
0
;
ix
<
PME_ORDER
;
ix
++
)
{
int
xbase
=
grid
IndexX
+
ix
;
xbase
-
=
(
xbase
>=
gridx
?
gridx
:
0
)
;
xbase
=
xbase
*
gridy
*
gridz
;
float
xdata
=
charge
*
data
[
ix
][
0
];
for
(
int
iy
=
0
;
iy
<
PME_ORDER
;
iy
++
)
{
int
ybase
=
gridIndexY
+
iy
;
ybase
-
=
(
y
base
>=
gridy
?
gridy
:
0
)
;
ybase
=
xbase
+
ybase
*
gridz
;
float
multiplier
=
xdata
*
data
[
iy
][
1
]
;
fvec4
add0to3
=
zdata0to3
*
multiplier
;
add0to3
.
store
(
temp
)
;
grid
[
ybase
+
zindex
[
0
]]
+=
temp
[
0
];
grid
[
ybase
+
zindex
[
1
]]
+=
temp
[
1
];
grid
[
ybase
+
zindex
[
2
]]
+=
temp
[
2
];
grid
[
ybase
+
zindex
[
3
]]
+=
temp
[
3
]
;
grid
[
ybase
+
zindex
[
4
]]
+=
multiplier
*
zdata4
;
else
{
for
(
int
ix
=
0
;
ix
<
PME_ORDER
;
ix
++
)
{
int
xbase
=
gridIndexX
+
ix
;
xbase
-=
(
xbase
>
=
grid
x
?
gridx
:
0
)
;
xbase
=
xbase
*
gridy
*
gridz
;
float
xdata
=
charge
*
data
[
ix
][
0
]
;
for
(
int
iy
=
0
;
iy
<
PME_ORDER
;
iy
++
)
{
int
ybase
=
gridIndexY
+
iy
;
ybase
-=
(
ybase
>=
gridy
?
gridy
:
0
)
;
ybase
=
x
base
+
ybase
*
gridz
;
float
multiplier
=
xdata
*
data
[
iy
][
1
]
;
fvec4
add0to3
=
zdata0to3
*
multiplier
;
add0to3
.
store
(
temp
)
;
grid
[
ybase
+
zindex
[
0
]]
+=
temp
[
0
]
;
grid
[
ybase
+
zindex
[
1
]]
+=
temp
[
1
];
grid
[
ybase
+
zindex
[
2
]]
+=
temp
[
2
];
grid
[
ybase
+
zindex
[
3
]]
+=
temp
[
3
];
grid
[
ybase
+
zindex
[
4
]]
+=
multiplier
*
zdata4
;
}
}
}
}
if
(
deterministic
)
i
+=
numThreads
;
start
+=
groupSize
*
numThreads
;
}
}
...
...
@@ -310,7 +316,7 @@ static void reciprocalConvolution(int start, int end, fftwf_complex* grid, vecto
}
}
static
void
interpolateForces
(
float
*
posq
,
float
*
force
,
float
*
grid
,
int
gridx
,
int
gridy
,
int
gridz
,
int
numParticles
,
Vec3
*
periodicBoxVectors
,
Vec3
*
recipBoxVectors
,
atomic
<
int
>&
atomicCounter
,
const
float
epsilonFactor
)
{
static
void
interpolateForces
(
float
*
posq
,
float
*
force
,
float
*
grid
,
int
gridx
,
int
gridy
,
int
gridz
,
int
numParticles
,
Vec3
*
periodicBoxVectors
,
Vec3
*
recipBoxVectors
,
atomic
<
int
>&
atomicCounter
,
const
float
epsilonFactor
,
int
numThreads
)
{
fvec4
boxSize
((
float
)
periodicBoxVectors
[
0
][
0
],
(
float
)
periodicBoxVectors
[
1
][
1
],
(
float
)
periodicBoxVectors
[
2
][
2
],
0
);
fvec4
invBoxSize
((
float
)
recipBoxVectors
[
0
][
0
],
(
float
)
recipBoxVectors
[
1
][
1
],
(
float
)
recipBoxVectors
[
2
][
2
],
0
);
fvec4
recipBoxVec0
((
float
)
recipBoxVectors
[
0
][
0
],
(
float
)
recipBoxVectors
[
0
][
1
],
(
float
)
recipBoxVectors
[
0
][
2
],
0
);
...
...
@@ -320,88 +326,94 @@ static void interpolateForces(float* posq, float* force, float* grid, int gridx,
ivec4
gridSizeInt
(
gridx
,
gridy
,
gridz
,
0
);
fvec4
one
(
1
);
fvec4
scale
(
1.0
f
/
(
PME_ORDER
-
1
));
const
int
groupSize
=
max
(
1
,
numParticles
/
(
10
*
numThreads
));
while
(
true
)
{
int
i
=
atomicCounter
++
;
if
(
i
>=
numParticles
)
int
start
=
atomicCounter
.
fetch_add
(
groupSize
)
;
if
(
start
>=
numParticles
)
break
;
// Find the position relative to the nearest grid point.
fvec4
pos
(
&
posq
[
4
*
i
]);
float
posInBox
[
4
];
(
pos
-
boxSize
*
floor
(
pos
*
invBoxSize
)).
store
(
posInBox
);
fvec4
t
=
posInBox
[
0
]
*
recipBoxVec0
+
posInBox
[
1
]
*
recipBoxVec1
+
posInBox
[
2
]
*
recipBoxVec2
;
t
=
(
t
-
floor
(
t
))
*
gridSize
;
ivec4
ti
=
t
;
fvec4
dr
=
t
-
ti
;
ivec4
gridIndex
=
ti
-
(
gridSizeInt
&
ti
==
gridSizeInt
);
// Compute the B-spline coefficients.
fvec4
data
[
PME_ORDER
];
fvec4
ddata
[
PME_ORDER
];
data
[
PME_ORDER
-
1
]
=
0.0
f
;
data
[
1
]
=
dr
;
data
[
0
]
=
one
-
dr
;
for
(
int
j
=
3
;
j
<
PME_ORDER
;
j
++
)
{
fvec4
div
(
1.0
f
/
(
j
-
1
));
data
[
j
-
1
]
=
div
*
dr
*
data
[
j
-
2
];
for
(
int
k
=
1
;
k
<
j
-
1
;
k
++
)
data
[
j
-
k
-
1
]
=
div
*
((
dr
+
k
)
*
data
[
j
-
k
-
2
]
+
(
fvec4
(
j
-
k
)
-
dr
)
*
data
[
j
-
k
-
1
]);
data
[
0
]
=
div
*
(
one
-
dr
)
*
data
[
0
];
}
ddata
[
0
]
=
-
data
[
0
];
for
(
int
j
=
1
;
j
<
PME_ORDER
;
j
++
)
ddata
[
j
]
=
data
[
j
-
1
]
-
data
[
j
];
data
[
PME_ORDER
-
1
]
=
scale
*
dr
*
data
[
PME_ORDER
-
2
];
for
(
int
j
=
1
;
j
<
(
PME_ORDER
-
1
);
j
++
)
data
[
PME_ORDER
-
j
-
1
]
=
scale
*
((
dr
+
j
)
*
data
[
PME_ORDER
-
j
-
2
]
+
(
fvec4
(
PME_ORDER
-
j
)
-
dr
)
*
data
[
PME_ORDER
-
j
-
1
]);
data
[
0
]
=
scale
*
(
one
-
dr
)
*
data
[
0
];
// Compute the force on this atom.
int
gridIndexX
=
gridIndex
[
0
];
int
gridIndexY
=
gridIndex
[
1
];
int
gridIndexZ
=
gridIndex
[
2
];
if
(
gridIndexX
<
0
)
return
;
// This happens when a simulation blows up and coordinates become NaN.
int
zindex
[
PME_ORDER
];
for
(
int
j
=
0
;
j
<
PME_ORDER
;
j
++
)
{
zindex
[
j
]
=
gridIndexZ
+
j
;
zindex
[
j
]
-=
(
zindex
[
j
]
>=
gridz
?
gridz
:
0
);
}
fvec4
zdata
[
PME_ORDER
];
for
(
int
j
=
0
;
j
<
PME_ORDER
;
j
++
)
zdata
[
j
]
=
fvec4
(
data
[
j
][
2
],
data
[
j
][
2
],
ddata
[
j
][
2
],
0
);
fvec4
f
=
0.0
f
;
for
(
int
ix
=
0
;
ix
<
PME_ORDER
;
ix
++
)
{
int
xbase
=
gridIndexX
+
ix
;
xbase
-=
(
xbase
>=
gridx
?
gridx
:
0
);
xbase
=
xbase
*
gridy
*
gridz
;
float
dx
=
data
[
ix
][
0
];
float
ddx
=
ddata
[
ix
][
0
];
fvec4
xdata
(
ddx
,
dx
,
dx
,
0
);
for
(
int
iy
=
0
;
iy
<
PME_ORDER
;
iy
++
)
{
int
ybase
=
gridIndexY
+
iy
;
ybase
-=
(
ybase
>=
gridy
?
gridy
:
0
);
ybase
=
xbase
+
ybase
*
gridz
;
float
dy
=
data
[
iy
][
1
];
float
ddy
=
ddata
[
iy
][
1
];
fvec4
xydata
=
xdata
*
fvec4
(
dy
,
ddy
,
dy
,
0
);
for
(
int
iz
=
0
;
iz
<
PME_ORDER
;
iz
++
)
{
fvec4
gridValue
(
grid
[
ybase
+
zindex
[
iz
]]);
f
=
f
+
xydata
*
zdata
[
iz
]
*
gridValue
;
int
end
=
min
(
start
+
groupSize
,
numParticles
);
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
// Find the position relative to the nearest grid point.
fvec4
pos
(
&
posq
[
4
*
i
]);
float
posInBox
[
4
];
(
pos
-
boxSize
*
floor
(
pos
*
invBoxSize
)).
store
(
posInBox
);
fvec4
t
=
posInBox
[
0
]
*
recipBoxVec0
+
posInBox
[
1
]
*
recipBoxVec1
+
posInBox
[
2
]
*
recipBoxVec2
;
t
=
(
t
-
floor
(
t
))
*
gridSize
;
ivec4
ti
=
t
;
fvec4
dr
=
t
-
ti
;
ivec4
gridIndex
=
ti
-
(
gridSizeInt
&
ti
==
gridSizeInt
);
// Compute the B-spline coefficients.
fvec4
data
[
PME_ORDER
];
fvec4
ddata
[
PME_ORDER
];
data
[
PME_ORDER
-
1
]
=
0.0
f
;
data
[
1
]
=
dr
;
data
[
0
]
=
one
-
dr
;
for
(
int
j
=
3
;
j
<
PME_ORDER
;
j
++
)
{
fvec4
div
(
1.0
f
/
(
j
-
1
));
data
[
j
-
1
]
=
div
*
dr
*
data
[
j
-
2
];
for
(
int
k
=
1
;
k
<
j
-
1
;
k
++
)
data
[
j
-
k
-
1
]
=
div
*
((
dr
+
k
)
*
data
[
j
-
k
-
2
]
+
(
fvec4
(
j
-
k
)
-
dr
)
*
data
[
j
-
k
-
1
]);
data
[
0
]
=
div
*
(
one
-
dr
)
*
data
[
0
];
}
ddata
[
0
]
=
-
data
[
0
];
for
(
int
j
=
1
;
j
<
PME_ORDER
;
j
++
)
ddata
[
j
]
=
data
[
j
-
1
]
-
data
[
j
];
data
[
PME_ORDER
-
1
]
=
scale
*
dr
*
data
[
PME_ORDER
-
2
];
for
(
int
j
=
1
;
j
<
(
PME_ORDER
-
1
);
j
++
)
data
[
PME_ORDER
-
j
-
1
]
=
scale
*
((
dr
+
j
)
*
data
[
PME_ORDER
-
j
-
2
]
+
(
fvec4
(
PME_ORDER
-
j
)
-
dr
)
*
data
[
PME_ORDER
-
j
-
1
]);
data
[
0
]
=
scale
*
(
one
-
dr
)
*
data
[
0
];
// Compute the force on this atom.
int
gridIndexX
=
gridIndex
[
0
];
int
gridIndexY
=
gridIndex
[
1
];
int
gridIndexZ
=
gridIndex
[
2
];
if
(
gridIndexX
<
0
)
return
;
// This happens when a simulation blows up and coordinates become NaN.
int
zindex
[
PME_ORDER
];
for
(
int
j
=
0
;
j
<
PME_ORDER
;
j
++
)
{
zindex
[
j
]
=
gridIndexZ
+
j
;
zindex
[
j
]
-=
(
zindex
[
j
]
>=
gridz
?
gridz
:
0
);
}
fvec4
zdata
[
PME_ORDER
];
for
(
int
j
=
0
;
j
<
PME_ORDER
;
j
++
)
zdata
[
j
]
=
fvec4
(
data
[
j
][
2
],
data
[
j
][
2
],
ddata
[
j
][
2
],
0
);
fvec4
f
=
0.0
f
;
for
(
int
ix
=
0
;
ix
<
PME_ORDER
;
ix
++
)
{
int
xbase
=
gridIndexX
+
ix
;
xbase
-=
(
xbase
>=
gridx
?
gridx
:
0
);
xbase
=
xbase
*
gridy
*
gridz
;
float
dx
=
data
[
ix
][
0
];
float
ddx
=
ddata
[
ix
][
0
];
fvec4
xdata
(
ddx
,
dx
,
dx
,
0
);
for
(
int
iy
=
0
;
iy
<
PME_ORDER
;
iy
++
)
{
int
ybase
=
gridIndexY
+
iy
;
ybase
-=
(
ybase
>=
gridy
?
gridy
:
0
);
ybase
=
xbase
+
ybase
*
gridz
;
float
dy
=
data
[
iy
][
1
];
float
ddy
=
ddata
[
iy
][
1
];
fvec4
xydata
=
xdata
*
fvec4
(
dy
,
ddy
,
dy
,
0
);
for
(
int
iz
=
0
;
iz
<
PME_ORDER
;
iz
++
)
{
fvec4
gridValue
(
grid
[
ybase
+
zindex
[
iz
]]);
f
=
f
+
xydata
*
zdata
[
iz
]
*
gridValue
;
}
}
}
f
*=
-
epsilonFactor
*
posq
[
4
*
i
+
3
];
float
fc
[
4
];
f
.
store
(
fc
);
force
[
4
*
i
+
0
]
=
fc
[
0
]
*
gridx
*
(
float
)
recipBoxVectors
[
0
][
0
];
force
[
4
*
i
+
1
]
=
fc
[
0
]
*
gridx
*
(
float
)
recipBoxVectors
[
1
][
0
]
+
fc
[
1
]
*
gridy
*
(
float
)
recipBoxVectors
[
1
][
1
];
force
[
4
*
i
+
2
]
=
fc
[
0
]
*
gridx
*
(
float
)
recipBoxVectors
[
2
][
0
]
+
fc
[
1
]
*
gridy
*
(
float
)
recipBoxVectors
[
2
][
1
]
+
fc
[
2
]
*
gridz
*
(
float
)
recipBoxVectors
[
2
][
2
];
}
f
*=
-
epsilonFactor
*
posq
[
4
*
i
+
3
];
float
fc
[
4
];
f
.
store
(
fc
);
force
[
4
*
i
+
0
]
=
fc
[
0
]
*
gridx
*
(
float
)
recipBoxVectors
[
0
][
0
];
force
[
4
*
i
+
1
]
=
fc
[
0
]
*
gridx
*
(
float
)
recipBoxVectors
[
1
][
0
]
+
fc
[
1
]
*
gridy
*
(
float
)
recipBoxVectors
[
1
][
1
];
force
[
4
*
i
+
2
]
=
fc
[
0
]
*
gridx
*
(
float
)
recipBoxVectors
[
2
][
0
]
+
fc
[
1
]
*
gridy
*
(
float
)
recipBoxVectors
[
2
][
1
]
+
fc
[
2
]
*
gridz
*
(
float
)
recipBoxVectors
[
2
][
2
];
}
}
...
...
@@ -606,7 +618,7 @@ void CpuCalcPmeReciprocalForceKernel::runWorkerThread(ThreadPool& threads, int i
}
reciprocalConvolution
(
complexStart
,
complexEnd
,
complexGrid
,
recipEterm
);
threads
.
syncThreads
();
interpolateForces
(
posq
,
&
force
[
0
],
realGrid
,
gridx
,
gridy
,
gridz
,
numParticles
,
periodicBoxVectors
,
recipBoxVectors
,
atomicCounter
,
epsilonFactor
);
interpolateForces
(
posq
,
&
force
[
0
],
realGrid
,
gridx
,
gridy
,
gridz
,
numParticles
,
periodicBoxVectors
,
recipBoxVectors
,
atomicCounter
,
epsilonFactor
,
numThreads
);
}
void
CpuCalcPmeReciprocalForceKernel
::
beginComputation
(
IO
&
io
,
const
Vec3
*
periodicBoxVectors
,
bool
includeEnergy
)
{
...
...
@@ -900,7 +912,7 @@ void CpuCalcDispersionPmeReciprocalForceKernel::runWorkerThread(ThreadPool& thre
complexStart
=
(
index
*
complexSize
)
/
numThreads
;
reciprocalConvolution
(
complexStart
,
complexEnd
,
complexGrid
,
recipEterm
);
threads
.
syncThreads
();
interpolateForces
(
posq
,
&
force
[
0
],
realGrid
,
gridx
,
gridy
,
gridz
,
numParticles
,
periodicBoxVectors
,
recipBoxVectors
,
atomicCounter
,
epsilonFactor
);
interpolateForces
(
posq
,
&
force
[
0
],
realGrid
,
gridx
,
gridy
,
gridz
,
numParticles
,
periodicBoxVectors
,
recipBoxVectors
,
atomicCounter
,
epsilonFactor
,
numThreads
);
}
void
CpuCalcDispersionPmeReciprocalForceKernel
::
beginComputation
(
CalcPmeReciprocalForceKernel
::
IO
&
io
,
const
Vec3
*
periodicBoxVectors
,
bool
includeEnergy
)
{
...
...
plugins/drude/openmmapi/include/openmm/DrudeNoseHooverIntegrator.h
View file @
0b5d58d7
...
...
@@ -66,7 +66,7 @@ public:
*/
DrudeNoseHooverIntegrator
(
double
temperature
,
double
collisionFrequency
,
double
drudeTemperature
,
double
drudeCollisionFrequency
,
double
stepSize
,
int
chainLength
=
3
,
int
numMTS
=
3
,
int
numYoshidaSuzuki
=
3
);
int
chainLength
=
3
,
int
numMTS
=
3
,
int
numYoshidaSuzuki
=
7
);
virtual
~
DrudeNoseHooverIntegrator
();
/**
...
...
plugins/drude/openmmapi/src/DrudeNoseHooverIntegrator.cpp
View file @
0b5d58d7
...
...
@@ -82,10 +82,8 @@ void DrudeNoseHooverIntegrator::initialize(ContextImpl& contextRef) {
context
=
&
contextRef
;
owner
=
&
contextRef
.
getOwner
();
vvKernel
=
context
->
getPlatform
().
createKernel
(
IntegrateVelocityVerletStepKernel
::
Name
(),
contextRef
);
vvKernel
.
getAs
<
IntegrateVelocityVerletStepKernel
>
().
initialize
(
contextRef
.
getSystem
(),
*
this
);
nhcKernel
=
context
->
getPlatform
().
createKernel
(
NoseHooverChainKernel
::
Name
(),
contextRef
);
nhcKernel
.
getAs
<
NoseHooverChainKernel
>
().
initialize
();
kernel
=
context
->
getPlatform
().
createKernel
(
IntegrateNoseHooverStepKernel
::
Name
(),
contextRef
);
kernel
.
getAs
<
IntegrateNoseHooverStepKernel
>
().
initialize
(
contextRef
.
getSystem
(),
*
this
);
forcesAreValid
=
false
;
// check for drude particles and build the Nose-Hoover Chains
...
...
@@ -138,14 +136,14 @@ double DrudeNoseHooverIntegrator::computeDrudeKineticEnergy() {
double
kE
=
0.0
;
for
(
const
auto
&
nhc
:
noseHooverChains
){
if
(
nhc
.
getThermostatedPairs
().
size
()
!=
0
)
{
kE
+=
nhcK
ernel
.
getAs
<
NoseHoover
Chain
Kernel
>
().
computeMaskedKineticEnergy
(
*
context
,
nhc
,
true
).
second
;
kE
+=
k
ernel
.
getAs
<
Integrate
NoseHoover
Step
Kernel
>
().
computeMaskedKineticEnergy
(
*
context
,
nhc
,
true
).
second
;
}
}
return
kE
;
}
double
DrudeNoseHooverIntegrator
::
computeTotalKineticEnergy
()
{
return
vvK
ernel
.
getAs
<
Integrate
VelocityVerlet
StepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
);
return
k
ernel
.
getAs
<
Integrate
NoseHoover
StepKernel
>
().
computeKineticEnergy
(
*
context
,
*
this
);
}
std
::
vector
<
Vec3
>
DrudeNoseHooverIntegrator
::
getVelocitiesForTemperature
(
const
System
&
system
,
double
temperature
,
...
...
plugins/drude/serialization/src/DrudeNoseHooverIntegratorProxy.cpp
View file @
0b5d58d7
...
...
@@ -49,7 +49,7 @@ void DrudeNoseHooverIntegratorProxy::serialize(const void* object, Serialization
node
.
setDoubleProperty
(
"stepSize"
,
integrator
.
getStepSize
());
node
.
setDoubleProperty
(
"constraintTolerance"
,
integrator
.
getConstraintTolerance
());
node
.
setDoubleProperty
(
"maximumPairDistance"
,
integrator
.
getMaximumPairDistance
());
assert
(
not
integrator
.
hasSubsystemThermostats
());
assert
(
!
integrator
.
hasSubsystemThermostats
());
node
.
setDoubleProperty
(
"temperature"
,
integrator
.
getTemperature
());
node
.
setDoubleProperty
(
"relativeTemperature"
,
integrator
.
getRelativeTemperature
());
node
.
setDoubleProperty
(
"collisionFrequency"
,
integrator
.
getCollisionFrequency
());
...
...
plugins/drude/tests/TestDrudeNoseHoover.h
View file @
0b5d58d7
...
...
@@ -141,6 +141,15 @@ void testWaterBox() {
// Equilibrate
integ
.
step
(
1500
);
double
TOL
=
1.5
;
try
{
if
(
platform
.
getPropertyValue
(
context
,
"Precision"
)
!=
"double"
)
{
TOL
=
2.0
;
}
}
catch
(
OpenMMException
)
{
// The defaults above are for double precision, which is assumed in this case
}
// Compute the internal and center of mass temperatures.
double
totalKE
=
0
;
const
int
numSteps
=
500
;
...
...
@@ -162,7 +171,7 @@ void testWaterBox() {
double
conserved
=
PE
+
fullKE
+
heatBathEnergy
;
meanConserved
=
(
i
*
meanConserved
+
conserved
)
/
(
i
+
1
);
totalKE
+=
KE
;
ASSERT
(
fabs
(
meanConserved
-
conserved
)
<
0.3
);
ASSERT
(
fabs
(
meanConserved
-
conserved
)
<
TOL
);
}
totalKE
/=
numSteps
;
ASSERT_USUALLY_EQUAL_TOL
(
temperature
,
meanTemp
,
0.03
);
...
...
tests/TestCompoundIntegrator.h
View file @
0b5d58d7
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2015 Stanford University and the Authors.
*
* Portions copyright (c) 2015
-2020
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -33,6 +33,7 @@
#include "openmm/BrownianIntegrator.h"
#include "openmm/CompoundIntegrator.h"
#include "openmm/Context.h"
#include "openmm/CustomIntegrator.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/System.h"
...
...
@@ -208,6 +209,36 @@ void testDifferentStepSizes() {
}
}
void
testCheckpoint
()
{
// Test that member integrators get loaded correctly from checkpoints.
System
system
;
system
.
addParticle
(
1.0
);
CustomIntegrator
*
custom
=
new
CustomIntegrator
(
0.001
);
custom
->
addGlobalVariable
(
"a"
,
1.0
);
custom
->
addPerDofVariable
(
"b"
,
2.0
);
CompoundIntegrator
integrator
;
integrator
.
addIntegrator
(
custom
);
integrator
.
addIntegrator
(
new
VerletIntegrator
(
0.005
));
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
1
,
Vec3
());
context
.
setPositions
(
positions
);
custom
->
setGlobalVariable
(
0
,
5.0
);
vector
<
Vec3
>
b1
(
1
,
Vec3
(
1
,
2
,
3
));
custom
->
setPerDofVariable
(
0
,
b1
);
stringstream
checkpoint
;
context
.
createCheckpoint
(
checkpoint
);
custom
->
setGlobalVariable
(
0
,
10.0
);
vector
<
Vec3
>
b2
(
1
,
Vec3
(
4
,
5
,
6
));
custom
->
setPerDofVariable
(
0
,
b2
);
integrator
.
setCurrentIntegrator
(
1
);
context
.
loadCheckpoint
(
checkpoint
);
ASSERT_EQUAL
(
0
,
integrator
.
getCurrentIntegrator
());
ASSERT_EQUAL
(
5.0
,
custom
->
getGlobalVariable
(
0
));
vector
<
Vec3
>
b3
;
custom
->
getPerDofVariable
(
0
,
b3
);
ASSERT_EQUAL_VEC
(
b1
[
0
],
b3
[
0
],
1e-6
);
}
void
runPlatformTests
();
int
main
(
int
argc
,
char
*
argv
[])
{
...
...
@@ -216,6 +247,7 @@ int main(int argc, char* argv[]) {
testChangingIntegrator
();
testChangingParameters
();
testDifferentStepSizes
();
testCheckpoint
();
runPlatformTests
();
}
catch
(
const
exception
&
e
)
{
...
...
tests/TestCustomIntegrator.h
View file @
0b5d58d7
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-20
19
Stanford University and the Authors. *
* Portions copyright (c) 2008-20
20
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -48,6 +48,7 @@
#include <algorithm>
#include <cmath>
#include <iostream>
#include <sstream>
#include <vector>
using
namespace
OpenMM
;
...
...
@@ -1156,6 +1157,31 @@ void testInitialTemperature() {
ASSERT_USUALLY_EQUAL_TOL
(
targetTemperature
,
temperature
,
0.01
);
}
void
testCheckpoint
()
{
// Test that integrator variables get loaded correctly from checkpoints.
System
system
;
system
.
addParticle
(
1.0
);
CustomIntegrator
integrator
(
0.001
);
integrator
.
addGlobalVariable
(
"a"
,
1.0
);
integrator
.
addPerDofVariable
(
"b"
,
2.0
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
1
,
Vec3
());
context
.
setPositions
(
positions
);
integrator
.
setGlobalVariable
(
0
,
5.0
);
vector
<
Vec3
>
b1
(
1
,
Vec3
(
1
,
2
,
3
));
integrator
.
setPerDofVariable
(
0
,
b1
);
stringstream
checkpoint
;
context
.
createCheckpoint
(
checkpoint
);
integrator
.
setGlobalVariable
(
0
,
10.0
);
vector
<
Vec3
>
b2
(
1
,
Vec3
(
4
,
5
,
6
));
integrator
.
setPerDofVariable
(
0
,
b2
);
context
.
loadCheckpoint
(
checkpoint
);
ASSERT_EQUAL
(
5.0
,
integrator
.
getGlobalVariable
(
0
));
vector
<
Vec3
>
b3
;
integrator
.
getPerDofVariable
(
0
,
b3
);
ASSERT_EQUAL_VEC
(
b1
[
0
],
b3
[
0
],
1e-6
);
}
void
runPlatformTests
();
int
main
(
int
argc
,
char
*
argv
[])
{
...
...
@@ -1184,6 +1210,7 @@ int main(int argc, char* argv[]) {
testVectorFunctions
();
testRecordEnergy
();
testInitialTemperature
();
testCheckpoint
();
runPlatformTests
();
}
catch
(
const
exception
&
e
)
{
...
...
Prev
1
2
3
4
5
6
Next
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