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
ed03c83f
Commit
ed03c83f
authored
Apr 24, 2014
by
peastman
Browse files
Merge pull request #423 from peastman/vsite
Created a new type of virtual site
parents
dab7a82c
f1d8c869
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
873 additions
and
22 deletions
+873
-22
docs/usersguide/theory.rst
docs/usersguide/theory.rst
+30
-0
openmmapi/include/openmm/VirtualSite.h
openmmapi/include/openmm/VirtualSite.h
+61
-1
openmmapi/src/VirtualSite.cpp
openmmapi/src/VirtualSite.cpp
+33
-1
platforms/cuda/include/CudaIntegrationUtilities.h
platforms/cuda/include/CudaIntegrationUtilities.h
+3
-1
platforms/cuda/src/CudaIntegrationUtilities.cpp
platforms/cuda/src/CudaIntegrationUtilities.cpp
+50
-5
platforms/cuda/src/kernels/integrationUtilities.cu
platforms/cuda/src/kernels/integrationUtilities.cu
+119
-2
platforms/cuda/tests/TestCudaVirtualSites.cpp
platforms/cuda/tests/TestCudaVirtualSites.cpp
+101
-2
platforms/opencl/include/OpenCLIntegrationUtilities.h
platforms/opencl/include/OpenCLIntegrationUtilities.h
+3
-1
platforms/opencl/src/OpenCLIntegrationUtilities.cpp
platforms/opencl/src/OpenCLIntegrationUtilities.cpp
+51
-3
platforms/opencl/src/kernels/virtualSites.cl
platforms/opencl/src/kernels/virtualSites.cl
+119
-2
platforms/opencl/tests/TestOpenCLVirtualSites.cpp
platforms/opencl/tests/TestOpenCLVirtualSites.cpp
+101
-2
platforms/reference/src/SimTKReference/ReferenceVirtualSites.cpp
...ms/reference/src/SimTKReference/ReferenceVirtualSites.cpp
+89
-1
platforms/reference/tests/TestReferenceVirtualSites.cpp
platforms/reference/tests/TestReferenceVirtualSites.cpp
+101
-1
wrappers/python/src/swig_doxygen/swigInputConfig.py
wrappers/python/src/swig_doxygen/swigInputConfig.py
+4
-0
wrappers/python/src/swig_doxygen/swig_lib/python/typemaps.i
wrappers/python/src/swig_doxygen/swig_lib/python/typemaps.i
+8
-0
No files found.
docs/usersguide/theory.rst
View file @
ed03c83f
...
...
@@ -1334,3 +1334,33 @@ specific types of rules. They are:
:math:`\mathbf{r}_{13} = \mathbf{r}_{3}-\mathbf{r}_{1}`\ . This allows
the virtual site to be located outside the plane of the three particles.
* LocalCoordinatesSite: The locations of three other particles are used to compute a local
coordinate system, and the virtual site is placed at a fixed location in that coordinate
system. The origin of the coordinate system and the directions of its x and y axes
are each specified as a weighted sum of the locations of the three particles:
.. math::
\mathbf{o}={w}^{o}_{1}\mathbf{r}_{1} + {w}^{o}_{2}\mathbf{r}_{2} + {w}^{o}_{3}\mathbf{r}_{3}
\mathbf{dx}={w}^{x}_{1}\mathbf{r}_{1} + {w}^{x}_{2}\mathbf{r}_{2} + {w}^{x}_{3}\mathbf{r}_{3}
\mathbf{dy}={w}^{y}_{1}\mathbf{r}_{1} + {w}^{y}_{2}\mathbf{r}_{2} + {w}^{y}_{3}\mathbf{r}_{3}
\mathbf{dz}=\mathbf{dx}\times \mathbf{dy}
..
These vectors are then used to construct a set of orthonormal coordinate axes as follows:
.. math::
\mathbf{\hat{x}}=\mathbf{dx}/|\mathbf{dx}|
\mathbf{\hat{z}}=\mathbf{dz}/|\mathbf{dz}|
\mathbf{\hat{y}}=\mathbf{\hat{z}}\times \mathbf{\hat{x}}
..
Finally, the position of the virtual site is set to
.. math::
\mathbf{r}=\mathbf{o}+p_1\mathbf{\hat{x}}+p_2\mathbf{\hat{y}}+p_3\mathbf{\hat{z}}
..
openmmapi/include/openmm/VirtualSite.h
View file @
ed03c83f
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2012 Stanford University and the Authors.
*
* Portions copyright (c) 2012
-2014
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -32,6 +32,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include <openmm/Vec3.h>
#include "internal/windowsExport.h"
#include <vector>
...
...
@@ -166,6 +167,65 @@ private:
double
weight12
,
weight13
,
weightCross
;
};
/**
* This is a VirtualSite that uses the locations of three other particles to compute a local
* coordinate system, then places the virtual site at a fixed location in that coordinate
* system. The origin of the coordinate system and the directions of its x and y axes
* are each specified as a weighted sum of the locations of the three particles:
*
* origin = w<sup>o</sup><sub>1</sub>r<sub>1</sub> + w<sup>o</sup><sub>2</sub>r<sub>2</sub> + w<sup>o</sup><sub>3</sub>r<sub>3</sub>
*
* xdir = w<sup>x</sup><sub>1</sub>r<sub>1</sub> + w<sup>x</sup><sub>2</sub>r<sub>2</sub> + w<sup>x</sup><sub>3</sub>r<sub>3</sub>
*
* ydir = w<sup>y</sup><sub>1</sub>r<sub>1</sub> + w<sup>y</sup><sub>2</sub>r<sub>2</sub> + w<sup>y</sup><sub>3</sub>r<sub>3</sub>
*
* For the origin, the three weights must add to one. For example if
* (w<sup>o</sup><sub>1</sub>, w<sup>o</sup><sub>2</sub>, w<sup>o</sup><sub>3</sub>) = (1.0, 0.0, 0.0),
* the origin of the local coordinate system is at the location of particle 1. For xdir and ydir,
* the weights must add to zero. For excample, if
* (w<sup>x</sup><sub>1</sub>, w<sup>x</sup><sub>2</sub>, w<sup>x</sup><sub>3</sub>) = (-1.0, 0.5, 0.5),
* the x axis points from particle 1 toward the midpoint between particles 2 and 3.
*
* The z direction is computed as zdir = xdir x ydir. To ensure the axes are all orthogonal,
* ydir is then recomputed as ydir = zdir x xdir. All three axis vectors are then normalized, and
* the virtual site location is set to
*
* origin + x*xdir + y*ydir + z*zdir
*/
class
OPENMM_EXPORT
LocalCoordinatesSite
:
public
VirtualSite
{
public:
/**
* Create a new LocalCoordinatesSite virtual site.
*
* @param particle1 the index of the first particle
* @param particle2 the index of the second particle
* @param particle3 the index of the third particle
* @param originWeights the weight factors for the three particles when computing the origin location
* @param xWeights the weight factors for the three particles when computing xdir
* @param yWeights the weight factors for the three particles when computing ydir
* @param localPosition the position of the virtual site in the local coordinate system
*/
LocalCoordinatesSite
(
int
particle1
,
int
particle2
,
int
particle3
,
const
Vec3
&
originWeights
,
const
Vec3
&
xWeights
,
const
Vec3
&
yWeights
,
const
Vec3
&
localPosition
);
/**
* Get the weight factors for the three particles when computing the origin location.
*/
const
Vec3
&
getOriginWeights
()
const
;
/**
* Get the weight factors for the three particles when computing xdir.
*/
const
Vec3
&
getXWeights
()
const
;
/**
* Get the weight factors for the three particles when computing ydir.
*/
const
Vec3
&
getYWeights
()
const
;
/**
* Get the position of the virtual site in the local coordinate system.
*/
const
Vec3
&
getLocalPosition
()
const
;
private:
Vec3
originWeights
,
xWeights
,
yWeights
,
localPosition
;
};
}
// namespace OpenMM
#endif
/*OPENMM_VIRTUALSITE_H_*/
openmmapi/src/VirtualSite.cpp
View file @
ed03c83f
...
...
@@ -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) 2012 Stanford University and the Authors.
*
* Portions copyright (c) 2012
-2014
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -31,6 +31,7 @@
#include "openmm/VirtualSite.h"
#include "openmm/OpenMMException.h"
#include <cmath>
#include <vector>
using
namespace
OpenMM
;
...
...
@@ -103,3 +104,34 @@ double OutOfPlaneSite::getWeight13() const {
double
OutOfPlaneSite
::
getWeightCross
()
const
{
return
weightCross
;
}
LocalCoordinatesSite
::
LocalCoordinatesSite
(
int
particle1
,
int
particle2
,
int
particle3
,
const
Vec3
&
originWeights
,
const
Vec3
&
xWeights
,
const
Vec3
&
yWeights
,
const
Vec3
&
localPosition
)
:
originWeights
(
originWeights
),
xWeights
(
xWeights
),
yWeights
(
yWeights
),
localPosition
(
localPosition
)
{
if
(
fabs
(
originWeights
[
0
]
+
originWeights
[
1
]
+
originWeights
[
2
]
-
1.0
)
>
1e-6
)
throw
OpenMMException
(
"LocalCoordinatesSite: Weights for computing origin must add to 1"
);
if
(
fabs
(
xWeights
[
0
]
+
xWeights
[
1
]
+
xWeights
[
2
])
>
1e-6
)
throw
OpenMMException
(
"LocalCoordinatesSite: Weights for computing x axis must add to 0"
);
if
(
fabs
(
yWeights
[
0
]
+
yWeights
[
1
]
+
yWeights
[
2
])
>
1e-6
)
throw
OpenMMException
(
"LocalCoordinatesSite: Weights for computing y axis must add to 0"
);
vector
<
int
>
particles
(
3
);
particles
[
0
]
=
particle1
;
particles
[
1
]
=
particle2
;
particles
[
2
]
=
particle3
;
setParticles
(
particles
);
}
const
Vec3
&
LocalCoordinatesSite
::
getOriginWeights
()
const
{
return
originWeights
;
}
const
Vec3
&
LocalCoordinatesSite
::
getXWeights
()
const
{
return
xWeights
;
}
const
Vec3
&
LocalCoordinatesSite
::
getYWeights
()
const
{
return
yWeights
;
}
const
Vec3
&
LocalCoordinatesSite
::
getLocalPosition
()
const
{
return
localPosition
;
}
platforms/cuda/include/CudaIntegrationUtilities.h
View file @
ed03c83f
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2009-201
4
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -150,6 +150,8 @@ private:
CudaArray
*
vsite3AvgWeights
;
CudaArray
*
vsiteOutOfPlaneAtoms
;
CudaArray
*
vsiteOutOfPlaneWeights
;
CudaArray
*
vsiteLocalCoordsAtoms
;
CudaArray
*
vsiteLocalCoordsParams
;
int
randomPos
;
int
lastSeed
,
numVsites
;
struct
ShakeCluster
;
...
...
platforms/cuda/src/CudaIntegrationUtilities.cpp
View file @
ed03c83f
...
...
@@ -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) 2009-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2009-201
4
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -101,7 +101,7 @@ CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const S
ccmaReducedMass
(
NULL
),
ccmaAtomConstraints
(
NULL
),
ccmaNumAtomConstraints
(
NULL
),
ccmaConstraintMatrixColumn
(
NULL
),
ccmaConstraintMatrixValue
(
NULL
),
ccmaDelta1
(
NULL
),
ccmaDelta2
(
NULL
),
ccmaConverged
(
NULL
),
ccmaConvergedMemory
(
NULL
),
vsite2AvgAtoms
(
NULL
),
vsite2AvgWeights
(
NULL
),
vsite3AvgAtoms
(
NULL
),
vsite3AvgWeights
(
NULL
),
vsiteOutOfPlaneAtoms
(
NULL
),
vsiteOutOfPlaneWeights
(
NULL
)
{
vsiteOutOfPlaneAtoms
(
NULL
),
vsiteOutOfPlaneWeights
(
NULL
)
,
vsiteLocalCoordsAtoms
(
NULL
),
vsiteLocalCoordsParams
(
NULL
)
{
// Create workspace arrays.
if
(
context
.
getUseDoublePrecision
()
||
context
.
getUseMixedPrecision
())
{
...
...
@@ -553,6 +553,8 @@ CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const S
vector
<
double4
>
vsite3AvgWeightVec
;
vector
<
int4
>
vsiteOutOfPlaneAtomVec
;
vector
<
double4
>
vsiteOutOfPlaneWeightVec
;
vector
<
int4
>
vsiteLocalCoordsAtomVec
;
vector
<
double
>
vsiteLocalCoordsParamVec
;
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
if
(
system
.
isVirtualSite
(
i
))
{
if
(
dynamic_cast
<
const
TwoParticleAverageSite
*>
(
&
system
.
getVirtualSite
(
i
))
!=
NULL
)
{
...
...
@@ -576,35 +578,65 @@ CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const S
vsiteOutOfPlaneAtomVec
.
push_back
(
make_int4
(
i
,
site
.
getParticle
(
0
),
site
.
getParticle
(
1
),
site
.
getParticle
(
2
)));
vsiteOutOfPlaneWeightVec
.
push_back
(
make_double4
(
site
.
getWeight12
(),
site
.
getWeight13
(),
site
.
getWeightCross
(),
0.0
));
}
else
if
(
dynamic_cast
<
const
LocalCoordinatesSite
*>
(
&
system
.
getVirtualSite
(
i
))
!=
NULL
)
{
// An out of plane site.
const
LocalCoordinatesSite
&
site
=
dynamic_cast
<
const
LocalCoordinatesSite
&>
(
system
.
getVirtualSite
(
i
));
vsiteLocalCoordsAtomVec
.
push_back
(
make_int4
(
i
,
site
.
getParticle
(
0
),
site
.
getParticle
(
1
),
site
.
getParticle
(
2
)));
Vec3
origin
=
site
.
getOriginWeights
();
Vec3
x
=
site
.
getXWeights
();
Vec3
y
=
site
.
getYWeights
();
Vec3
pos
=
site
.
getLocalPosition
();
vsiteLocalCoordsParamVec
.
push_back
(
origin
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
origin
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
origin
[
2
]);
vsiteLocalCoordsParamVec
.
push_back
(
x
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
x
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
x
[
2
]);
vsiteLocalCoordsParamVec
.
push_back
(
y
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
y
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
y
[
2
]);
vsiteLocalCoordsParamVec
.
push_back
(
pos
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
pos
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
pos
[
2
]);
}
}
}
int
num2Avg
=
vsite2AvgAtomVec
.
size
();
int
num3Avg
=
vsite3AvgAtomVec
.
size
();
int
numOutOfPlane
=
vsiteOutOfPlaneAtomVec
.
size
();
int
numLocalCoords
=
vsiteLocalCoordsAtomVec
.
size
();
vsite2AvgAtoms
=
CudaArray
::
create
<
int4
>
(
context
,
max
(
1
,
num2Avg
),
"vsite2AvgAtoms"
);
vsite3AvgAtoms
=
CudaArray
::
create
<
int4
>
(
context
,
max
(
1
,
num3Avg
),
"vsite3AvgAtoms"
);
vsiteOutOfPlaneAtoms
=
CudaArray
::
create
<
int4
>
(
context
,
max
(
1
,
numOutOfPlane
),
"vsiteOutOfPlaneAtoms"
);
vsiteLocalCoordsAtoms
=
CudaArray
::
create
<
int4
>
(
context
,
max
(
1
,
numLocalCoords
),
"vsiteLocalCoordinatesAtoms"
);
if
(
num2Avg
>
0
)
vsite2AvgAtoms
->
upload
(
vsite2AvgAtomVec
);
if
(
num3Avg
>
0
)
vsite3AvgAtoms
->
upload
(
vsite3AvgAtomVec
);
if
(
numOutOfPlane
>
0
)
vsiteOutOfPlaneAtoms
->
upload
(
vsiteOutOfPlaneAtomVec
);
if
(
numLocalCoords
>
0
)
vsiteLocalCoordsAtoms
->
upload
(
vsiteLocalCoordsAtomVec
);
if
(
context
.
getUseDoublePrecision
())
{
vsite2AvgWeights
=
CudaArray
::
create
<
double2
>
(
context
,
max
(
1
,
num2Avg
),
"vsite2AvgWeights"
);
vsite3AvgWeights
=
CudaArray
::
create
<
double4
>
(
context
,
max
(
1
,
num3Avg
),
"vsite3AvgWeights"
);
vsiteOutOfPlaneWeights
=
CudaArray
::
create
<
double4
>
(
context
,
max
(
1
,
numOutOfPlane
),
"vsiteOutOfPlaneWeights"
);
vsiteLocalCoordsParams
=
CudaArray
::
create
<
double
>
(
context
,
max
(
1
,
12
*
numLocalCoords
),
"vsiteLocalCoordinatesParams"
);
if
(
num2Avg
>
0
)
vsite2AvgWeights
->
upload
(
vsite2AvgWeightVec
);
if
(
num3Avg
>
0
)
vsite3AvgWeights
->
upload
(
vsite3AvgWeightVec
);
if
(
numOutOfPlane
>
0
)
vsiteOutOfPlaneWeights
->
upload
(
vsiteOutOfPlaneWeightVec
);
if
(
numLocalCoords
>
0
)
vsiteLocalCoordsParams
->
upload
(
vsiteLocalCoordsParamVec
);
}
else
{
vsite2AvgWeights
=
CudaArray
::
create
<
float2
>
(
context
,
max
(
1
,
num2Avg
),
"vsite2AvgWeights"
);
vsite3AvgWeights
=
CudaArray
::
create
<
float4
>
(
context
,
max
(
1
,
num3Avg
),
"vsite3AvgWeights"
);
vsiteOutOfPlaneWeights
=
CudaArray
::
create
<
float4
>
(
context
,
max
(
1
,
numOutOfPlane
),
"vsiteOutOfPlaneWeights"
);
vsiteLocalCoordsParams
=
CudaArray
::
create
<
float
>
(
context
,
max
(
1
,
12
*
numLocalCoords
),
"vsiteLocalCoordinatesParams"
);
if
(
num2Avg
>
0
)
{
vector
<
float2
>
floatWeights
(
num2Avg
);
for
(
int
i
=
0
;
i
<
num2Avg
;
i
++
)
...
...
@@ -623,6 +655,12 @@ CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const S
floatWeights
[
i
]
=
make_float4
((
float
)
vsiteOutOfPlaneWeightVec
[
i
].
x
,
(
float
)
vsiteOutOfPlaneWeightVec
[
i
].
y
,
(
float
)
vsiteOutOfPlaneWeightVec
[
i
].
z
,
0.0
f
);
vsiteOutOfPlaneWeights
->
upload
(
floatWeights
);
}
if
(
numLocalCoords
>
0
)
{
vector
<
float
>
floatParams
(
vsiteLocalCoordsParamVec
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
vsiteLocalCoordsParamVec
.
size
();
i
++
)
floatParams
[
i
]
=
(
float
)
vsiteLocalCoordsParamVec
[
i
];
vsiteLocalCoordsParams
->
upload
(
floatParams
);
}
}
// Create the kernels used by this class.
...
...
@@ -633,6 +671,7 @@ CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const S
defines
[
"NUM_2_AVERAGE"
]
=
context
.
intToString
(
num2Avg
);
defines
[
"NUM_3_AVERAGE"
]
=
context
.
intToString
(
num3Avg
);
defines
[
"NUM_OUT_OF_PLANE"
]
=
context
.
intToString
(
numOutOfPlane
);
defines
[
"NUM_LOCAL_COORDS"
]
=
context
.
intToString
(
numLocalCoords
);
defines
[
"PADDED_NUM_ATOMS"
]
=
context
.
intToString
(
context
.
getPaddedNumAtoms
());
CUmodule
module
=
context
.
createModule
(
CudaKernelSources
::
vectorOps
+
CudaKernelSources
::
integrationUtilities
,
defines
);
settlePosKernel
=
context
.
getKernel
(
module
,
"applySettleToPositions"
);
...
...
@@ -647,7 +686,7 @@ CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const S
CHECK_RESULT2
(
cuEventCreate
(
&
ccmaEvent
,
CU_EVENT_DISABLE_TIMING
),
"Error creating event for CCMA"
);
vsitePositionKernel
=
context
.
getKernel
(
module
,
"computeVirtualSites"
);
vsiteForceKernel
=
context
.
getKernel
(
module
,
"distributeVirtualSiteForces"
);
numVsites
=
num2Avg
+
num3Avg
+
numOutOfPlane
;
numVsites
=
num2Avg
+
num3Avg
+
numOutOfPlane
+
numLocalCoords
;
randomKernel
=
context
.
getKernel
(
module
,
"generateRandomNumbers"
);
timeShiftKernel
=
context
.
getKernel
(
module
,
"timeShiftVelocities"
);
}
...
...
@@ -704,6 +743,10 @@ CudaIntegrationUtilities::~CudaIntegrationUtilities() {
delete
vsiteOutOfPlaneAtoms
;
if
(
vsiteOutOfPlaneWeights
!=
NULL
)
delete
vsiteOutOfPlaneWeights
;
if
(
vsiteLocalCoordsAtoms
!=
NULL
)
delete
vsiteLocalCoordsAtoms
;
if
(
vsiteLocalCoordsParams
!=
NULL
)
delete
vsiteLocalCoordsParams
;
}
void
CudaIntegrationUtilities
::
applyConstraints
(
double
tol
)
{
...
...
@@ -779,7 +822,8 @@ void CudaIntegrationUtilities::computeVirtualSites() {
CUdeviceptr
posCorrection
=
(
context
.
getUseMixedPrecision
()
?
context
.
getPosqCorrection
().
getDevicePointer
()
:
0
);
void
*
args
[]
=
{
&
context
.
getPosq
().
getDevicePointer
(),
&
posCorrection
,
&
vsite2AvgAtoms
->
getDevicePointer
(),
&
vsite2AvgWeights
->
getDevicePointer
(),
&
vsite3AvgAtoms
->
getDevicePointer
(),
&
vsite3AvgWeights
->
getDevicePointer
(),
&
vsiteOutOfPlaneAtoms
->
getDevicePointer
(),
&
vsiteOutOfPlaneWeights
->
getDevicePointer
()};
&
vsiteOutOfPlaneAtoms
->
getDevicePointer
(),
&
vsiteOutOfPlaneWeights
->
getDevicePointer
(),
&
vsiteLocalCoordsAtoms
->
getDevicePointer
(),
&
vsiteLocalCoordsParams
->
getDevicePointer
()};
context
.
executeKernel
(
vsitePositionKernel
,
args
,
numVsites
);
}
}
...
...
@@ -790,7 +834,8 @@ void CudaIntegrationUtilities::distributeForcesFromVirtualSites() {
void
*
args
[]
=
{
&
context
.
getPosq
().
getDevicePointer
(),
&
posCorrection
,
&
context
.
getForce
().
getDevicePointer
(),
&
vsite2AvgAtoms
->
getDevicePointer
(),
&
vsite2AvgWeights
->
getDevicePointer
(),
&
vsite3AvgAtoms
->
getDevicePointer
(),
&
vsite3AvgWeights
->
getDevicePointer
(),
&
vsiteOutOfPlaneAtoms
->
getDevicePointer
(),
&
vsiteOutOfPlaneWeights
->
getDevicePointer
()};
&
vsiteOutOfPlaneAtoms
->
getDevicePointer
(),
&
vsiteOutOfPlaneWeights
->
getDevicePointer
(),
&
vsiteLocalCoordsAtoms
->
getDevicePointer
(),
&
vsiteLocalCoordsParams
->
getDevicePointer
()};
context
.
executeKernel
(
vsiteForceKernel
,
args
,
numVsites
);
}
}
...
...
platforms/cuda/src/kernels/integrationUtilities.cu
View file @
ed03c83f
...
...
@@ -685,7 +685,8 @@ extern "C" __global__ void updateCCMAAtomPositions(const int* __restrict__ numAt
*/
extern
"C"
__global__
void
computeVirtualSites
(
real4
*
__restrict__
posq
,
real4
*
__restrict__
posqCorrection
,
const
int4
*
__restrict__
avg2Atoms
,
const
real2
*
__restrict__
avg2Weights
,
const
int4
*
__restrict__
avg3Atoms
,
const
real4
*
__restrict__
avg3Weights
,
const
int4
*
__restrict__
outOfPlaneAtoms
,
const
real4
*
__restrict__
outOfPlaneWeights
)
{
const
int4
*
__restrict__
outOfPlaneAtoms
,
const
real4
*
__restrict__
outOfPlaneWeights
,
const
int4
*
__restrict__
localCoordsAtoms
,
const
real
*
__restrict__
localCoordsParams
)
{
// Two particle average sites.
...
...
@@ -733,6 +734,35 @@ extern "C" __global__ void computeVirtualSites(real4* __restrict__ posq, real4*
pos
.
z
=
pos1
.
z
+
v12
.
z
*
weights
.
x
+
v13
.
z
*
weights
.
y
+
cr
.
z
*
weights
.
z
;
storePos
(
posq
,
posqCorrection
,
atoms
.
x
,
pos
);
}
// Local coordinates sites.
for
(
int
index
=
blockIdx
.
x
*
blockDim
.
x
+
threadIdx
.
x
;
index
<
NUM_LOCAL_COORDS
;
index
+=
blockDim
.
x
*
gridDim
.
x
)
{
int4
atoms
=
localCoordsAtoms
[
index
];
const
real
*
params
=
&
localCoordsParams
[
12
*
index
];
mixed4
pos
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
x
);
mixed4
pos1_4
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
y
);
mixed4
pos2_4
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
z
);
mixed4
pos3_4
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
w
);
mixed3
pos1
=
make_mixed3
(
pos1_4
.
x
,
pos1_4
.
y
,
pos1_4
.
z
);
mixed3
pos2
=
make_mixed3
(
pos2_4
.
x
,
pos2_4
.
y
,
pos2_4
.
z
);
mixed3
pos3
=
make_mixed3
(
pos3_4
.
x
,
pos3_4
.
y
,
pos3_4
.
z
);
mixed3
originWeights
=
make_mixed3
(
params
[
0
],
params
[
1
],
params
[
2
]);
mixed3
xWeights
=
make_mixed3
(
params
[
3
],
params
[
4
],
params
[
5
]);
mixed3
yWeights
=
make_mixed3
(
params
[
6
],
params
[
7
],
params
[
8
]);
mixed3
localPosition
=
make_mixed3
(
params
[
9
],
params
[
10
],
params
[
11
]);
mixed3
origin
=
pos1
*
originWeights
.
x
+
pos2
*
originWeights
.
y
+
pos3
*
originWeights
.
z
;
mixed3
xdir
=
pos1
*
xWeights
.
x
+
pos2
*
xWeights
.
y
+
pos3
*
xWeights
.
z
;
mixed3
ydir
=
pos1
*
yWeights
.
x
+
pos2
*
yWeights
.
y
+
pos3
*
yWeights
.
z
;
mixed3
zdir
=
cross
(
xdir
,
ydir
);
xdir
*=
rsqrt
(
xdir
.
x
*
xdir
.
x
+
xdir
.
y
*
xdir
.
y
+
xdir
.
z
*
xdir
.
z
);
zdir
*=
rsqrt
(
zdir
.
x
*
zdir
.
x
+
zdir
.
y
*
zdir
.
y
+
zdir
.
z
*
zdir
.
z
);
ydir
=
cross
(
zdir
,
xdir
);
pos
.
x
=
origin
.
x
+
xdir
.
x
*
localPosition
.
x
+
ydir
.
x
*
localPosition
.
y
+
zdir
.
x
*
localPosition
.
z
;
pos
.
y
=
origin
.
y
+
xdir
.
y
*
localPosition
.
x
+
ydir
.
y
*
localPosition
.
y
+
zdir
.
y
*
localPosition
.
z
;
pos
.
z
=
origin
.
z
+
xdir
.
z
*
localPosition
.
x
+
ydir
.
z
*
localPosition
.
y
+
zdir
.
z
*
localPosition
.
z
;
storePos
(
posq
,
posqCorrection
,
atoms
.
x
,
pos
);
}
}
inline
__device__
real3
loadForce
(
int
index
,
long
long
*
__restrict__
force
)
{
...
...
@@ -753,7 +783,8 @@ inline __device__ void addForce(int index, long long* __restrict__ force, real3
extern
"C"
__global__
void
distributeVirtualSiteForces
(
const
real4
*
__restrict__
posq
,
const
real4
*
__restrict__
posqCorrection
,
long
long
*
__restrict__
force
,
const
int4
*
__restrict__
avg2Atoms
,
const
real2
*
__restrict__
avg2Weights
,
const
int4
*
__restrict__
avg3Atoms
,
const
real4
*
__restrict__
avg3Weights
,
const
int4
*
__restrict__
outOfPlaneAtoms
,
const
real4
*
__restrict__
outOfPlaneWeights
)
{
const
int4
*
__restrict__
outOfPlaneAtoms
,
const
real4
*
__restrict__
outOfPlaneWeights
,
const
int4
*
__restrict__
localCoordsAtoms
,
const
real
*
__restrict__
localCoordsParams
)
{
// Two particle average sites.
...
...
@@ -797,6 +828,92 @@ extern "C" __global__ void distributeVirtualSiteForces(const real4* __restrict__
addForce
(
atoms
.
z
,
force
,
fp2
);
addForce
(
atoms
.
w
,
force
,
fp3
);
}
// Local coordinates sites.
for
(
int
index
=
blockIdx
.
x
*
blockDim
.
x
+
threadIdx
.
x
;
index
<
NUM_LOCAL_COORDS
;
index
+=
blockDim
.
x
*
gridDim
.
x
)
{
int4
atoms
=
localCoordsAtoms
[
index
];
const
real
*
params
=
&
localCoordsParams
[
12
*
index
];
mixed4
pos
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
x
);
mixed4
pos1_4
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
y
);
mixed4
pos2_4
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
z
);
mixed4
pos3_4
=
loadPos
(
posq
,
posqCorrection
,
atoms
.
w
);
mixed3
pos1
=
make_mixed3
(
pos1_4
.
x
,
pos1_4
.
y
,
pos1_4
.
z
);
mixed3
pos2
=
make_mixed3
(
pos2_4
.
x
,
pos2_4
.
y
,
pos2_4
.
z
);
mixed3
pos3
=
make_mixed3
(
pos3_4
.
x
,
pos3_4
.
y
,
pos3_4
.
z
);
mixed3
originWeights
=
make_mixed3
(
params
[
0
],
params
[
1
],
params
[
2
]);
mixed3
wx
=
make_mixed3
(
params
[
3
],
params
[
4
],
params
[
5
]);
mixed3
wy
=
make_mixed3
(
params
[
6
],
params
[
7
],
params
[
8
]);
mixed3
localPosition
=
make_mixed3
(
params
[
9
],
params
[
10
],
params
[
11
]);
mixed3
origin
=
pos1
*
originWeights
.
x
+
pos2
*
originWeights
.
y
+
pos3
*
originWeights
.
z
;
mixed3
xdir
=
pos1
*
wx
.
x
+
pos2
*
wx
.
y
+
pos3
*
wx
.
z
;
mixed3
ydir
=
pos1
*
wy
.
x
+
pos2
*
wy
.
y
+
pos3
*
wy
.
z
;
mixed3
zdir
=
cross
(
xdir
,
ydir
);
mixed
invNormXdir
=
rsqrt
(
xdir
.
x
*
xdir
.
x
+
xdir
.
y
*
xdir
.
y
+
xdir
.
z
*
xdir
.
z
);
mixed
invNormZdir
=
rsqrt
(
zdir
.
x
*
zdir
.
x
+
zdir
.
y
*
zdir
.
y
+
zdir
.
z
*
zdir
.
z
);
mixed3
dx
=
xdir
*
invNormXdir
;
mixed3
dz
=
zdir
*
invNormZdir
;
mixed3
dy
=
cross
(
dz
,
dx
);
// The derivatives for this case are very complicated. They were computed with SymPy then simplified by hand.
mixed
t11
=
(
wx
.
x
*
ydir
.
x
-
wy
.
x
*
xdir
.
x
)
*
invNormZdir
;
mixed
t12
=
(
wx
.
x
*
ydir
.
y
-
wy
.
x
*
xdir
.
y
)
*
invNormZdir
;
mixed
t13
=
(
wx
.
x
*
ydir
.
z
-
wy
.
x
*
xdir
.
z
)
*
invNormZdir
;
mixed
t21
=
(
wx
.
y
*
ydir
.
x
-
wy
.
y
*
xdir
.
x
)
*
invNormZdir
;
mixed
t22
=
(
wx
.
y
*
ydir
.
y
-
wy
.
y
*
xdir
.
y
)
*
invNormZdir
;
mixed
t23
=
(
wx
.
y
*
ydir
.
z
-
wy
.
y
*
xdir
.
z
)
*
invNormZdir
;
mixed
t31
=
(
wx
.
z
*
ydir
.
x
-
wy
.
z
*
xdir
.
x
)
*
invNormZdir
;
mixed
t32
=
(
wx
.
z
*
ydir
.
y
-
wy
.
z
*
xdir
.
y
)
*
invNormZdir
;
mixed
t33
=
(
wx
.
z
*
ydir
.
z
-
wy
.
z
*
xdir
.
z
)
*
invNormZdir
;
mixed
sx1
=
t13
*
dz
.
y
-
t12
*
dz
.
z
;
mixed
sy1
=
t11
*
dz
.
z
-
t13
*
dz
.
x
;
mixed
sz1
=
t12
*
dz
.
x
-
t11
*
dz
.
y
;
mixed
sx2
=
t23
*
dz
.
y
-
t22
*
dz
.
z
;
mixed
sy2
=
t21
*
dz
.
z
-
t23
*
dz
.
x
;
mixed
sz2
=
t22
*
dz
.
x
-
t21
*
dz
.
y
;
mixed
sx3
=
t33
*
dz
.
y
-
t32
*
dz
.
z
;
mixed
sy3
=
t31
*
dz
.
z
-
t33
*
dz
.
x
;
mixed
sz3
=
t32
*
dz
.
x
-
t31
*
dz
.
y
;
mixed3
wxScaled
=
wx
*
invNormXdir
;
real3
f
=
loadForce
(
atoms
.
x
,
force
);
mixed3
fp1
=
localPosition
*
f
.
x
;
mixed3
fp2
=
localPosition
*
f
.
y
;
mixed3
fp3
=
localPosition
*
f
.
z
;
real3
f1
=
make_real3
(
0
);
real3
f2
=
make_real3
(
0
);
real3
f3
=
make_real3
(
0
);
f1
.
x
+=
fp1
.
x
*
wxScaled
.
x
*
(
1
-
dx
.
x
*
dx
.
x
)
+
fp1
.
z
*
(
dz
.
x
*
sx1
)
+
fp1
.
y
*
((
-
dx
.
x
*
dy
.
x
)
*
wxScaled
.
x
+
dy
.
x
*
sx1
-
dx
.
y
*
t12
-
dx
.
z
*
t13
)
+
f
.
x
*
originWeights
.
x
;
f1
.
y
+=
fp1
.
x
*
wxScaled
.
x
*
(
-
dx
.
x
*
dx
.
y
)
+
fp1
.
z
*
(
dz
.
x
*
sy1
+
t13
)
+
fp1
.
y
*
((
-
dx
.
y
*
dy
.
x
-
dz
.
z
)
*
wxScaled
.
x
+
dy
.
x
*
sy1
+
dx
.
y
*
t11
);
f1
.
z
+=
fp1
.
x
*
wxScaled
.
x
*
(
-
dx
.
x
*
dx
.
z
)
+
fp1
.
z
*
(
dz
.
x
*
sz1
-
t12
)
+
fp1
.
y
*
((
-
dx
.
z
*
dy
.
x
+
dz
.
y
)
*
wxScaled
.
x
+
dy
.
x
*
sz1
+
dx
.
z
*
t11
);
f2
.
x
+=
fp1
.
x
*
wxScaled
.
y
*
(
1
-
dx
.
x
*
dx
.
x
)
+
fp1
.
z
*
(
dz
.
x
*
sx2
)
+
fp1
.
y
*
((
-
dx
.
x
*
dy
.
x
)
*
wxScaled
.
y
+
dy
.
x
*
sx2
-
dx
.
y
*
t22
-
dx
.
z
*
t23
)
+
f
.
x
*
originWeights
.
y
;
f2
.
y
+=
fp1
.
x
*
wxScaled
.
y
*
(
-
dx
.
x
*
dx
.
y
)
+
fp1
.
z
*
(
dz
.
x
*
sy2
+
t23
)
+
fp1
.
y
*
((
-
dx
.
y
*
dy
.
x
-
dz
.
z
)
*
wxScaled
.
y
+
dy
.
x
*
sy2
+
dx
.
y
*
t21
);
f2
.
z
+=
fp1
.
x
*
wxScaled
.
y
*
(
-
dx
.
x
*
dx
.
z
)
+
fp1
.
z
*
(
dz
.
x
*
sz2
-
t22
)
+
fp1
.
y
*
((
-
dx
.
z
*
dy
.
x
+
dz
.
y
)
*
wxScaled
.
y
+
dy
.
x
*
sz2
+
dx
.
z
*
t21
);
f3
.
x
+=
fp1
.
x
*
wxScaled
.
z
*
(
1
-
dx
.
x
*
dx
.
x
)
+
fp1
.
z
*
(
dz
.
x
*
sx3
)
+
fp1
.
y
*
((
-
dx
.
x
*
dy
.
x
)
*
wxScaled
.
z
+
dy
.
x
*
sx3
-
dx
.
y
*
t32
-
dx
.
z
*
t33
)
+
f
.
x
*
originWeights
.
z
;
f3
.
y
+=
fp1
.
x
*
wxScaled
.
z
*
(
-
dx
.
x
*
dx
.
y
)
+
fp1
.
z
*
(
dz
.
x
*
sy3
+
t33
)
+
fp1
.
y
*
((
-
dx
.
y
*
dy
.
x
-
dz
.
z
)
*
wxScaled
.
z
+
dy
.
x
*
sy3
+
dx
.
y
*
t31
);
f3
.
z
+=
fp1
.
x
*
wxScaled
.
z
*
(
-
dx
.
x
*
dx
.
z
)
+
fp1
.
z
*
(
dz
.
x
*
sz3
-
t32
)
+
fp1
.
y
*
((
-
dx
.
z
*
dy
.
x
+
dz
.
y
)
*
wxScaled
.
z
+
dy
.
x
*
sz3
+
dx
.
z
*
t31
);
f1
.
x
+=
fp2
.
x
*
wxScaled
.
x
*
(
-
dx
.
y
*
dx
.
x
)
+
fp2
.
z
*
(
dz
.
y
*
sx1
-
t13
)
-
fp2
.
y
*
((
dx
.
x
*
dy
.
y
-
dz
.
z
)
*
wxScaled
.
x
-
dy
.
y
*
sx1
-
dx
.
x
*
t12
);
f1
.
y
+=
fp2
.
x
*
wxScaled
.
x
*
(
1
-
dx
.
y
*
dx
.
y
)
+
fp2
.
z
*
(
dz
.
y
*
sy1
)
-
fp2
.
y
*
((
dx
.
y
*
dy
.
y
)
*
wxScaled
.
x
-
dy
.
y
*
sy1
+
dx
.
x
*
t11
+
dx
.
z
*
t13
)
+
f
.
y
*
originWeights
.
x
;
f1
.
z
+=
fp2
.
x
*
wxScaled
.
x
*
(
-
dx
.
y
*
dx
.
z
)
+
fp2
.
z
*
(
dz
.
y
*
sz1
+
t11
)
-
fp2
.
y
*
((
dx
.
z
*
dy
.
y
+
dz
.
x
)
*
wxScaled
.
x
-
dy
.
y
*
sz1
-
dx
.
z
*
t12
);
f2
.
x
+=
fp2
.
x
*
wxScaled
.
y
*
(
-
dx
.
y
*
dx
.
x
)
+
fp2
.
z
*
(
dz
.
y
*
sx2
-
t23
)
-
fp2
.
y
*
((
dx
.
x
*
dy
.
y
-
dz
.
z
)
*
wxScaled
.
y
-
dy
.
y
*
sx2
-
dx
.
x
*
t22
);
f2
.
y
+=
fp2
.
x
*
wxScaled
.
y
*
(
1
-
dx
.
y
*
dx
.
y
)
+
fp2
.
z
*
(
dz
.
y
*
sy2
)
-
fp2
.
y
*
((
dx
.
y
*
dy
.
y
)
*
wxScaled
.
y
-
dy
.
y
*
sy2
+
dx
.
x
*
t21
+
dx
.
z
*
t23
)
+
f
.
y
*
originWeights
.
y
;
f2
.
z
+=
fp2
.
x
*
wxScaled
.
y
*
(
-
dx
.
y
*
dx
.
z
)
+
fp2
.
z
*
(
dz
.
y
*
sz2
+
t21
)
-
fp2
.
y
*
((
dx
.
z
*
dy
.
y
+
dz
.
x
)
*
wxScaled
.
y
-
dy
.
y
*
sz2
-
dx
.
z
*
t22
);
f3
.
x
+=
fp2
.
x
*
wxScaled
.
z
*
(
-
dx
.
y
*
dx
.
x
)
+
fp2
.
z
*
(
dz
.
y
*
sx3
-
t33
)
-
fp2
.
y
*
((
dx
.
x
*
dy
.
y
-
dz
.
z
)
*
wxScaled
.
z
-
dy
.
y
*
sx3
-
dx
.
x
*
t32
);
f3
.
y
+=
fp2
.
x
*
wxScaled
.
z
*
(
1
-
dx
.
y
*
dx
.
y
)
+
fp2
.
z
*
(
dz
.
y
*
sy3
)
-
fp2
.
y
*
((
dx
.
y
*
dy
.
y
)
*
wxScaled
.
z
-
dy
.
y
*
sy3
+
dx
.
x
*
t31
+
dx
.
z
*
t33
)
+
f
.
y
*
originWeights
.
z
;
f3
.
z
+=
fp2
.
x
*
wxScaled
.
z
*
(
-
dx
.
y
*
dx
.
z
)
+
fp2
.
z
*
(
dz
.
y
*
sz3
+
t31
)
-
fp2
.
y
*
((
dx
.
z
*
dy
.
y
+
dz
.
x
)
*
wxScaled
.
z
-
dy
.
y
*
sz3
-
dx
.
z
*
t32
);
f1
.
x
+=
fp3
.
x
*
wxScaled
.
x
*
(
-
dx
.
z
*
dx
.
x
)
+
fp3
.
z
*
(
dz
.
z
*
sx1
+
t12
)
+
fp3
.
y
*
((
-
dx
.
x
*
dy
.
z
-
dz
.
y
)
*
wxScaled
.
x
+
dy
.
z
*
sx1
+
dx
.
x
*
t13
);
f1
.
y
+=
fp3
.
x
*
wxScaled
.
x
*
(
-
dx
.
z
*
dx
.
y
)
+
fp3
.
z
*
(
dz
.
z
*
sy1
-
t11
)
+
fp3
.
y
*
((
-
dx
.
y
*
dy
.
z
+
dz
.
x
)
*
wxScaled
.
x
+
dy
.
z
*
sy1
+
dx
.
y
*
t13
);
f1
.
z
+=
fp3
.
x
*
wxScaled
.
x
*
(
1
-
dx
.
z
*
dx
.
z
)
+
fp3
.
z
*
(
dz
.
z
*
sz1
)
+
fp3
.
y
*
((
-
dx
.
z
*
dy
.
z
)
*
wxScaled
.
x
+
dy
.
z
*
sz1
-
dx
.
x
*
t11
-
dx
.
y
*
t12
)
+
f
.
z
*
originWeights
.
x
;
f2
.
x
+=
fp3
.
x
*
wxScaled
.
y
*
(
-
dx
.
z
*
dx
.
x
)
+
fp3
.
z
*
(
dz
.
z
*
sx2
+
t22
)
+
fp3
.
y
*
((
-
dx
.
x
*
dy
.
z
-
dz
.
y
)
*
wxScaled
.
y
+
dy
.
z
*
sx2
+
dx
.
x
*
t23
);
f2
.
y
+=
fp3
.
x
*
wxScaled
.
y
*
(
-
dx
.
z
*
dx
.
y
)
+
fp3
.
z
*
(
dz
.
z
*
sy2
-
t21
)
+
fp3
.
y
*
((
-
dx
.
y
*
dy
.
z
+
dz
.
x
)
*
wxScaled
.
y
+
dy
.
z
*
sy2
+
dx
.
y
*
t23
);
f2
.
z
+=
fp3
.
x
*
wxScaled
.
y
*
(
1
-
dx
.
z
*
dx
.
z
)
+
fp3
.
z
*
(
dz
.
z
*
sz2
)
+
fp3
.
y
*
((
-
dx
.
z
*
dy
.
z
)
*
wxScaled
.
y
+
dy
.
z
*
sz2
-
dx
.
x
*
t21
-
dx
.
y
*
t22
)
+
f
.
z
*
originWeights
.
y
;
f3
.
x
+=
fp3
.
x
*
wxScaled
.
z
*
(
-
dx
.
z
*
dx
.
x
)
+
fp3
.
z
*
(
dz
.
z
*
sx3
+
t32
)
+
fp3
.
y
*
((
-
dx
.
x
*
dy
.
z
-
dz
.
y
)
*
wxScaled
.
z
+
dy
.
z
*
sx3
+
dx
.
x
*
t33
);
f3
.
y
+=
fp3
.
x
*
wxScaled
.
z
*
(
-
dx
.
z
*
dx
.
y
)
+
fp3
.
z
*
(
dz
.
z
*
sy3
-
t31
)
+
fp3
.
y
*
((
-
dx
.
y
*
dy
.
z
+
dz
.
x
)
*
wxScaled
.
z
+
dy
.
z
*
sy3
+
dx
.
y
*
t33
);
f3
.
z
+=
fp3
.
x
*
wxScaled
.
z
*
(
1
-
dx
.
z
*
dx
.
z
)
+
fp3
.
z
*
(
dz
.
z
*
sz3
)
+
fp3
.
y
*
((
-
dx
.
z
*
dy
.
z
)
*
wxScaled
.
z
+
dy
.
z
*
sz3
-
dx
.
x
*
t31
-
dx
.
y
*
t32
)
+
f
.
z
*
originWeights
.
z
;
addForce
(
atoms
.
y
,
force
,
f1
);
addForce
(
atoms
.
z
,
force
,
f2
);
addForce
(
atoms
.
w
,
force
,
f3
);
}
}
/**
...
...
platforms/cuda/tests/TestCudaVirtualSites.cpp
View file @
ed03c83f
...
...
@@ -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) 2012 Stanford University and the Authors.
*
* Portions copyright (c) 2012
-2014
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -213,6 +213,84 @@ void testOutOfPlane() {
}
}
/**
* Test a LocalCoordinatesSite virtual site.
*/
void
testLocalCoordinates
()
{
const
Vec3
originWeights
(
0.2
,
0.3
,
0.5
);
const
Vec3
xWeights
(
-
1.0
,
0.5
,
0.5
);
const
Vec3
yWeights
(
0.0
,
-
1.0
,
1.0
);
const
Vec3
localPosition
(
0.4
,
0.3
,
0.2
);
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
0.0
);
system
.
setVirtualSite
(
3
,
new
LocalCoordinatesSite
(
0
,
1
,
2
,
originWeights
,
xWeights
,
yWeights
,
localPosition
));
CustomExternalForce
*
forceField
=
new
CustomExternalForce
(
"2*x^2+3*y^2+4*z^2"
);
system
.
addForce
(
forceField
);
vector
<
double
>
params
;
forceField
->
addParticle
(
0
,
params
);
forceField
->
addParticle
(
1
,
params
);
forceField
->
addParticle
(
2
,
params
);
forceField
->
addParticle
(
3
,
params
);
LangevinIntegrator
integrator
(
300.0
,
0.1
,
0.002
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
4
),
positions2
(
4
),
positions3
(
4
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
// Set the particles at random positions.
Vec3
xdir
,
ydir
,
zdir
;
do
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
positions
[
j
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
xdir
=
positions
[
0
]
*
xWeights
[
0
]
+
positions
[
1
]
*
xWeights
[
1
]
+
positions
[
2
]
*
xWeights
[
2
];
ydir
=
positions
[
0
]
*
yWeights
[
0
]
+
positions
[
1
]
*
yWeights
[
1
]
+
positions
[
2
]
*
yWeights
[
2
];
zdir
=
xdir
.
cross
(
ydir
);
if
(
sqrt
(
xdir
.
dot
(
xdir
))
>
0.1
&&
sqrt
(
ydir
.
dot
(
ydir
))
>
0.1
&&
sqrt
(
zdir
.
dot
(
zdir
))
>
0.1
)
break
;
// These positions give a reasonable coordinate system.
}
while
(
true
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
0.0001
);
// See if the virtual site is positioned correctly.
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Forces
);
const
vector
<
Vec3
>&
pos
=
state
.
getPositions
();
Vec3
origin
=
pos
[
0
]
*
originWeights
[
0
]
+
pos
[
1
]
*
originWeights
[
1
]
+
pos
[
2
]
*
originWeights
[
2
];
xdir
/=
sqrt
(
xdir
.
dot
(
xdir
));
zdir
/=
sqrt
(
zdir
.
dot
(
zdir
));
ydir
=
zdir
.
cross
(
xdir
);
ASSERT_EQUAL_VEC
(
origin
+
xdir
*
localPosition
[
0
]
+
ydir
*
localPosition
[
1
]
+
zdir
*
localPosition
[
2
],
pos
[
3
],
1e-5
);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
Vec3
f
=
state
.
getForces
()[
i
];
norm
+=
f
[
0
]
*
f
[
0
]
+
f
[
1
]
*
f
[
1
]
+
f
[
2
]
*
f
[
2
];
}
norm
=
std
::
sqrt
(
norm
);
const
double
delta
=
1e-2
;
double
step
=
0.5
*
delta
/
norm
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
state
.
getForces
()[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
context
.
applyConstraints
(
0.0001
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
context
.
applyConstraints
(
0.0001
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
delta
,
1e-3
)
}
}
/**
* Make sure that energy, linear momentum, and angular momentum are all conserved
* when using virtual sites.
...
...
@@ -278,6 +356,26 @@ void testConservationLaws() {
positions
.
push_back
(
Vec3
(
2
,
0
,
-
1
));
positions
.
push_back
(
Vec3
(
1
,
1
,
-
1
));
positions
.
push_back
(
Vec3
());
// Create a molecule with a LocalCoordinatesSite virtual site.
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
0.0
);
system
.
setVirtualSite
(
14
,
new
LocalCoordinatesSite
(
11
,
12
,
13
,
Vec3
(
0.3
,
0.3
,
0.4
),
Vec3
(
1.0
,
-
0.5
,
-
0.5
),
Vec3
(
0
,
-
1.0
,
1.0
),
Vec3
(
0.2
,
0.2
,
1.0
)));
system
.
addConstraint
(
11
,
12
,
1.0
);
system
.
addConstraint
(
11
,
13
,
1.0
);
system
.
addConstraint
(
12
,
13
,
sqrt
(
2.0
));
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
forceField
->
addParticle
(
0
,
1
,
10
);
for
(
int
j
=
0
;
j
<
i
;
j
++
)
forceField
->
addException
(
i
+
11
,
j
+
11
,
0
,
1
,
0
);
}
positions
.
push_back
(
Vec3
(
1
,
2
,
0
));
positions
.
push_back
(
Vec3
(
2
,
2
,
0
));
positions
.
push_back
(
Vec3
(
1
,
3
,
0
));
positions
.
push_back
(
Vec3
());
// Simulate it and check conservation laws.
...
...
@@ -315,7 +413,7 @@ void testConservationLaws() {
if
(
i
==
0
)
initialAngularMomentum
=
angularMomentum
;
else
ASSERT_EQUAL_VEC
(
initialAngularMomentum
,
angularMomentum
,
0.0
2
);
ASSERT_EQUAL_VEC
(
initialAngularMomentum
,
angularMomentum
,
0.0
3
);
integrator
.
step
(
1
);
}
}
...
...
@@ -434,6 +532,7 @@ int main(int argc, char* argv[]) {
testTwoParticleAverage
();
testThreeParticleAverage
();
testOutOfPlane
();
testLocalCoordinates
();
testConservationLaws
();
testReordering
();
}
...
...
platforms/opencl/include/OpenCLIntegrationUtilities.h
View file @
ed03c83f
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2009-201
4
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -148,6 +148,8 @@ private:
OpenCLArray
*
vsite3AvgWeights
;
OpenCLArray
*
vsiteOutOfPlaneAtoms
;
OpenCLArray
*
vsiteOutOfPlaneWeights
;
OpenCLArray
*
vsiteLocalCoordsAtoms
;
OpenCLArray
*
vsiteLocalCoordsParams
;
int
randomPos
;
int
lastSeed
,
numVsites
;
bool
hasInitializedPosConstraintKernels
,
hasInitializedVelConstraintKernels
,
ccmaUseDirectBuffer
;
...
...
platforms/opencl/src/OpenCLIntegrationUtilities.cpp
View file @
ed03c83f
...
...
@@ -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) 2009-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2009-201
4
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -100,7 +100,8 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
ccmaReducedMass
(
NULL
),
ccmaAtomConstraints
(
NULL
),
ccmaNumAtomConstraints
(
NULL
),
ccmaConstraintMatrixColumn
(
NULL
),
ccmaConstraintMatrixValue
(
NULL
),
ccmaDelta1
(
NULL
),
ccmaDelta2
(
NULL
),
ccmaConverged
(
NULL
),
ccmaConvergedHostBuffer
(
NULL
),
vsite2AvgAtoms
(
NULL
),
vsite2AvgWeights
(
NULL
),
vsite3AvgAtoms
(
NULL
),
vsite3AvgWeights
(
NULL
),
vsiteOutOfPlaneAtoms
(
NULL
),
vsiteOutOfPlaneWeights
(
NULL
),
hasInitializedPosConstraintKernels
(
false
),
hasInitializedVelConstraintKernels
(
false
)
{
vsiteOutOfPlaneAtoms
(
NULL
),
vsiteOutOfPlaneWeights
(
NULL
),
vsiteLocalCoordsAtoms
(
NULL
),
vsiteLocalCoordsParams
(
NULL
),
hasInitializedPosConstraintKernels
(
false
),
hasInitializedVelConstraintKernels
(
false
)
{
// Create workspace arrays.
if
(
context
.
getUseDoublePrecision
()
||
context
.
getUseMixedPrecision
())
{
...
...
@@ -595,6 +596,8 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
vector
<
mm_double4
>
vsite3AvgWeightVec
;
vector
<
mm_int4
>
vsiteOutOfPlaneAtomVec
;
vector
<
mm_double4
>
vsiteOutOfPlaneWeightVec
;
vector
<
mm_int4
>
vsiteLocalCoordsAtomVec
;
vector
<
cl_double
>
vsiteLocalCoordsParamVec
;
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
if
(
system
.
isVirtualSite
(
i
))
{
if
(
dynamic_cast
<
const
TwoParticleAverageSite
*>
(
&
system
.
getVirtualSite
(
i
))
!=
NULL
)
{
...
...
@@ -618,35 +621,65 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
vsiteOutOfPlaneAtomVec
.
push_back
(
mm_int4
(
i
,
site
.
getParticle
(
0
),
site
.
getParticle
(
1
),
site
.
getParticle
(
2
)));
vsiteOutOfPlaneWeightVec
.
push_back
(
mm_double4
(
site
.
getWeight12
(),
site
.
getWeight13
(),
site
.
getWeightCross
(),
0.0
));
}
else
if
(
dynamic_cast
<
const
LocalCoordinatesSite
*>
(
&
system
.
getVirtualSite
(
i
))
!=
NULL
)
{
// An out of plane site.
const
LocalCoordinatesSite
&
site
=
dynamic_cast
<
const
LocalCoordinatesSite
&>
(
system
.
getVirtualSite
(
i
));
vsiteLocalCoordsAtomVec
.
push_back
(
mm_int4
(
i
,
site
.
getParticle
(
0
),
site
.
getParticle
(
1
),
site
.
getParticle
(
2
)));
Vec3
origin
=
site
.
getOriginWeights
();
Vec3
x
=
site
.
getXWeights
();
Vec3
y
=
site
.
getYWeights
();
Vec3
pos
=
site
.
getLocalPosition
();
vsiteLocalCoordsParamVec
.
push_back
(
origin
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
origin
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
origin
[
2
]);
vsiteLocalCoordsParamVec
.
push_back
(
x
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
x
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
x
[
2
]);
vsiteLocalCoordsParamVec
.
push_back
(
y
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
y
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
y
[
2
]);
vsiteLocalCoordsParamVec
.
push_back
(
pos
[
0
]);
vsiteLocalCoordsParamVec
.
push_back
(
pos
[
1
]);
vsiteLocalCoordsParamVec
.
push_back
(
pos
[
2
]);
}
}
}
int
num2Avg
=
vsite2AvgAtomVec
.
size
();
int
num3Avg
=
vsite3AvgAtomVec
.
size
();
int
numOutOfPlane
=
vsiteOutOfPlaneAtomVec
.
size
();
int
numLocalCoords
=
vsiteLocalCoordsAtomVec
.
size
();
vsite2AvgAtoms
=
OpenCLArray
::
create
<
mm_int4
>
(
context
,
max
(
1
,
num2Avg
),
"vsite2AvgAtoms"
);
vsite3AvgAtoms
=
OpenCLArray
::
create
<
mm_int4
>
(
context
,
max
(
1
,
num3Avg
),
"vsite3AvgAtoms"
);
vsiteOutOfPlaneAtoms
=
OpenCLArray
::
create
<
mm_int4
>
(
context
,
max
(
1
,
numOutOfPlane
),
"vsiteOutOfPlaneAtoms"
);
vsiteLocalCoordsAtoms
=
OpenCLArray
::
create
<
mm_int4
>
(
context
,
max
(
1
,
numLocalCoords
),
"vsiteLocalCoordinatesAtoms"
);
if
(
num2Avg
>
0
)
vsite2AvgAtoms
->
upload
(
vsite2AvgAtomVec
);
if
(
num3Avg
>
0
)
vsite3AvgAtoms
->
upload
(
vsite3AvgAtomVec
);
if
(
numOutOfPlane
>
0
)
vsiteOutOfPlaneAtoms
->
upload
(
vsiteOutOfPlaneAtomVec
);
if
(
numLocalCoords
>
0
)
vsiteLocalCoordsAtoms
->
upload
(
vsiteLocalCoordsAtomVec
);
if
(
context
.
getUseDoublePrecision
())
{
vsite2AvgWeights
=
OpenCLArray
::
create
<
mm_double2
>
(
context
,
max
(
1
,
num2Avg
),
"vsite2AvgWeights"
);
vsite3AvgWeights
=
OpenCLArray
::
create
<
mm_double4
>
(
context
,
max
(
1
,
num3Avg
),
"vsite3AvgWeights"
);
vsiteOutOfPlaneWeights
=
OpenCLArray
::
create
<
mm_double4
>
(
context
,
max
(
1
,
numOutOfPlane
),
"vsiteOutOfPlaneWeights"
);
vsiteLocalCoordsParams
=
OpenCLArray
::
create
<
cl_double
>
(
context
,
max
(
1
,
12
*
numLocalCoords
),
"vsiteLocalCoordinatesParams"
);
if
(
num2Avg
>
0
)
vsite2AvgWeights
->
upload
(
vsite2AvgWeightVec
);
if
(
num3Avg
>
0
)
vsite3AvgWeights
->
upload
(
vsite3AvgWeightVec
);
if
(
numOutOfPlane
>
0
)
vsiteOutOfPlaneWeights
->
upload
(
vsiteOutOfPlaneWeightVec
);
if
(
numLocalCoords
>
0
)
vsiteLocalCoordsParams
->
upload
(
vsiteLocalCoordsParamVec
);
}
else
{
vsite2AvgWeights
=
OpenCLArray
::
create
<
mm_float2
>
(
context
,
max
(
1
,
num2Avg
),
"vsite2AvgWeights"
);
vsite3AvgWeights
=
OpenCLArray
::
create
<
mm_float4
>
(
context
,
max
(
1
,
num3Avg
),
"vsite3AvgWeights"
);
vsiteOutOfPlaneWeights
=
OpenCLArray
::
create
<
mm_float4
>
(
context
,
max
(
1
,
numOutOfPlane
),
"vsiteOutOfPlaneWeights"
);
vsiteLocalCoordsParams
=
OpenCLArray
::
create
<
float
>
(
context
,
max
(
1
,
12
*
numLocalCoords
),
"vsiteLocalCoordinatesParams"
);
if
(
num2Avg
>
0
)
{
vector
<
mm_float2
>
floatWeights
(
num2Avg
);
for
(
int
i
=
0
;
i
<
num2Avg
;
i
++
)
...
...
@@ -665,6 +698,12 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
floatWeights
[
i
]
=
mm_float4
((
float
)
vsiteOutOfPlaneWeightVec
[
i
].
x
,
(
float
)
vsiteOutOfPlaneWeightVec
[
i
].
y
,
(
float
)
vsiteOutOfPlaneWeightVec
[
i
].
z
,
0.0
f
);
vsiteOutOfPlaneWeights
->
upload
(
floatWeights
);
}
if
(
numLocalCoords
>
0
)
{
vector
<
cl_float
>
floatParams
(
vsiteLocalCoordsParamVec
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
vsiteLocalCoordsParamVec
.
size
();
i
++
)
floatParams
[
i
]
=
(
cl_float
)
vsiteLocalCoordsParamVec
[
i
];
vsiteLocalCoordsParams
->
upload
(
floatParams
);
}
}
// Create the kernels for virtual sites.
...
...
@@ -673,6 +712,7 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
defines
[
"NUM_2_AVERAGE"
]
=
context
.
intToString
(
num2Avg
);
defines
[
"NUM_3_AVERAGE"
]
=
context
.
intToString
(
num3Avg
);
defines
[
"NUM_OUT_OF_PLANE"
]
=
context
.
intToString
(
numOutOfPlane
);
defines
[
"NUM_LOCAL_COORDS"
]
=
context
.
intToString
(
numLocalCoords
);
cl
::
Program
vsiteProgram
=
context
.
createProgram
(
OpenCLKernelSources
::
virtualSites
,
defines
);
vsitePositionKernel
=
cl
::
Kernel
(
vsiteProgram
,
"computeVirtualSites"
);
int
index
=
0
;
...
...
@@ -685,6 +725,8 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
vsitePositionKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsite3AvgWeights
->
getDeviceBuffer
());
vsitePositionKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteOutOfPlaneAtoms
->
getDeviceBuffer
());
vsitePositionKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteOutOfPlaneWeights
->
getDeviceBuffer
());
vsitePositionKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteLocalCoordsAtoms
->
getDeviceBuffer
());
vsitePositionKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteLocalCoordsParams
->
getDeviceBuffer
());
vsiteForceKernel
=
cl
::
Kernel
(
vsiteProgram
,
"distributeForces"
);
index
=
0
;
vsiteForceKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
context
.
getPosq
().
getDeviceBuffer
());
...
...
@@ -697,7 +739,9 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
vsiteForceKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsite3AvgWeights
->
getDeviceBuffer
());
vsiteForceKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteOutOfPlaneAtoms
->
getDeviceBuffer
());
vsiteForceKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteOutOfPlaneWeights
->
getDeviceBuffer
());
numVsites
=
num2Avg
+
num3Avg
+
numOutOfPlane
;
vsiteForceKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteLocalCoordsAtoms
->
getDeviceBuffer
());
vsiteForceKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
vsiteLocalCoordsParams
->
getDeviceBuffer
());
numVsites
=
num2Avg
+
num3Avg
+
numOutOfPlane
+
numLocalCoords
;
}
OpenCLIntegrationUtilities
::~
OpenCLIntegrationUtilities
()
{
...
...
@@ -751,6 +795,10 @@ OpenCLIntegrationUtilities::~OpenCLIntegrationUtilities() {
delete
vsiteOutOfPlaneAtoms
;
if
(
vsiteOutOfPlaneWeights
!=
NULL
)
delete
vsiteOutOfPlaneWeights
;
if
(
vsiteLocalCoordsAtoms
!=
NULL
)
delete
vsiteLocalCoordsAtoms
;
if
(
vsiteLocalCoordsParams
!=
NULL
)
delete
vsiteLocalCoordsParams
;
}
void
OpenCLIntegrationUtilities
::
applyConstraints
(
double
tol
)
{
...
...
platforms/opencl/src/kernels/virtualSites.cl
View file @
ed03c83f
...
...
@@ -32,7 +32,8 @@ __kernel void computeVirtualSites(__global real4* restrict posq,
#
endif
__global
const
int4*
restrict
avg2Atoms,
__global
const
real2*
restrict
avg2Weights,
__global
const
int4*
restrict
avg3Atoms,
__global
const
real4*
restrict
avg3Weights,
__global
const
int4*
restrict
outOfPlaneAtoms,
__global
const
real4*
restrict
outOfPlaneWeights
)
{
__global
const
int4*
restrict
outOfPlaneAtoms,
__global
const
real4*
restrict
outOfPlaneWeights,
__global
const
int4*
restrict
localCoordsAtoms,
__global
const
real*
restrict
localCoordsParams
)
{
#
ifndef
USE_MIXED_PRECISION
__global
real4*
posqCorrection
=
0
;
#
endif
...
...
@@ -76,6 +77,35 @@ __kernel void computeVirtualSites(__global real4* restrict posq,
pos.xyz
=
pos1.xyz
+
v12.xyz*weights.x
+
v13.xyz*weights.y
+
cross
(
v12,
v13
)
.
xyz*weights.z
;
storePos
(
posq,
posqCorrection,
atoms.x,
pos
)
;
}
//
Local
coordinates
sites.
for
(
int
index
=
get_global_id
(
0
)
; index < NUM_LOCAL_COORDS; index += get_global_size(0)) {
int4
atoms
=
localCoordsAtoms[index]
;
__global
const
real*
params
=
&localCoordsParams[12*index]
;
mixed4
pos
=
loadPos
(
posq,
posqCorrection,
atoms.x
)
;
mixed4
pos1_4
=
loadPos
(
posq,
posqCorrection,
atoms.y
)
;
mixed4
pos2_4
=
loadPos
(
posq,
posqCorrection,
atoms.z
)
;
mixed4
pos3_4
=
loadPos
(
posq,
posqCorrection,
atoms.w
)
;
mixed4
pos1
=
(
mixed4
)
(
pos1_4.x,
pos1_4.y,
pos1_4.z,
0
)
;
mixed4
pos2
=
(
mixed4
)
(
pos2_4.x,
pos2_4.y,
pos2_4.z,
0
)
;
mixed4
pos3
=
(
mixed4
)
(
pos3_4.x,
pos3_4.y,
pos3_4.z,
0
)
;
mixed4
originWeights
=
(
mixed4
)
(
params[0],
params[1],
params[2],
0
)
;
mixed4
xWeights
=
(
mixed4
)
(
params[3],
params[4],
params[5],
0
)
;
mixed4
yWeights
=
(
mixed4
)
(
params[6],
params[7],
params[8],
0
)
;
mixed4
localPosition
=
(
mixed4
)
(
params[9],
params[10],
params[11],
0
)
;
mixed4
origin
=
pos1*originWeights.x
+
pos2*originWeights.y
+
pos3*originWeights.z
;
mixed4
xdir
=
pos1*xWeights.x
+
pos2*xWeights.y
+
pos3*xWeights.z
;
mixed4
ydir
=
pos1*yWeights.x
+
pos2*yWeights.y
+
pos3*yWeights.z
;
mixed4
zdir
=
cross
(
xdir,
ydir
)
;
xdir
*=
rsqrt
(
xdir.x*xdir.x+xdir.y*xdir.y+xdir.z*xdir.z
)
;
zdir
*=
rsqrt
(
zdir.x*zdir.x+zdir.y*zdir.y+zdir.z*zdir.z
)
;
ydir
=
cross
(
zdir,
xdir
)
;
pos.x
=
origin.x
+
xdir.x*localPosition.x
+
ydir.x*localPosition.y
+
zdir.x*localPosition.z
;
pos.y
=
origin.y
+
xdir.y*localPosition.x
+
ydir.y*localPosition.y
+
zdir.y*localPosition.z
;
pos.z
=
origin.z
+
xdir.z*localPosition.x
+
ydir.z*localPosition.y
+
zdir.z*localPosition.z
;
storePos
(
posq,
posqCorrection,
atoms.x,
pos
)
;
}
}
/**
...
...
@@ -87,7 +117,8 @@ __kernel void distributeForces(__global const real4* restrict posq, __global rea
#
endif
__global
const
int4*
restrict
avg2Atoms,
__global
const
real2*
restrict
avg2Weights,
__global
const
int4*
restrict
avg3Atoms,
__global
const
real4*
restrict
avg3Weights,
__global
const
int4*
restrict
outOfPlaneAtoms,
__global
const
real4*
restrict
outOfPlaneWeights
)
{
__global
const
int4*
restrict
outOfPlaneAtoms,
__global
const
real4*
restrict
outOfPlaneWeights,
__global
const
int4*
restrict
localCoordsAtoms,
__global
const
real*
restrict
localCoordsParams
)
{
#
ifndef
USE_MIXED_PRECISION
__global
real4*
posqCorrection
=
0
;
#
endif
...
...
@@ -150,4 +181,90 @@ __kernel void distributeForces(__global const real4* restrict posq, __global rea
force[atoms.z]
=
f2
;
force[atoms.w]
=
f3
;
}
//
Local
coordinates
sites.
for
(
int
index
=
get_global_id
(
0
)
; index < NUM_LOCAL_COORDS; index += get_global_size(0)) {
int4
atoms
=
localCoordsAtoms[index]
;
__global
const
real*
params
=
&localCoordsParams[12*index]
;
mixed4
pos
=
loadPos
(
posq,
posqCorrection,
atoms.x
)
;
mixed4
pos1_4
=
loadPos
(
posq,
posqCorrection,
atoms.y
)
;
mixed4
pos2_4
=
loadPos
(
posq,
posqCorrection,
atoms.z
)
;
mixed4
pos3_4
=
loadPos
(
posq,
posqCorrection,
atoms.w
)
;
mixed4
pos1
=
(
mixed4
)
(
pos1_4.x,
pos1_4.y,
pos1_4.z,
0
)
;
mixed4
pos2
=
(
mixed4
)
(
pos2_4.x,
pos2_4.y,
pos2_4.z,
0
)
;
mixed4
pos3
=
(
mixed4
)
(
pos3_4.x,
pos3_4.y,
pos3_4.z,
0
)
;
mixed4
originWeights
=
(
mixed4
)
(
params[0],
params[1],
params[2],
0
)
;
mixed4
wx
=
(
mixed4
)
(
params[3],
params[4],
params[5],
0
)
;
mixed4
wy
=
(
mixed4
)
(
params[6],
params[7],
params[8],
0
)
;
mixed4
localPosition
=
(
mixed4
)
(
params[9],
params[10],
params[11],
0
)
;
mixed4
origin
=
pos1*originWeights.x
+
pos2*originWeights.y
+
pos3*originWeights.z
;
mixed4
xdir
=
pos1*wx.x
+
pos2*wx.y
+
pos3*wx.z
;
mixed4
ydir
=
pos1*wy.x
+
pos2*wy.y
+
pos3*wy.z
;
mixed4
zdir
=
cross
(
xdir,
ydir
)
;
mixed
invNormXdir
=
rsqrt
(
xdir.x*xdir.x+xdir.y*xdir.y+xdir.z*xdir.z
)
;
mixed
invNormZdir
=
rsqrt
(
zdir.x*zdir.x+zdir.y*zdir.y+zdir.z*zdir.z
)
;
mixed4
dx
=
xdir*invNormXdir
;
mixed4
dz
=
zdir*invNormZdir
;
mixed4
dy
=
cross
(
dz,
dx
)
;
//
The
derivatives
for
this
case
are
very
complicated.
They
were
computed
with
SymPy
then
simplified
by
hand.
mixed
t11
=
(
wx.x*ydir.x-wy.x*xdir.x
)
*invNormZdir
;
mixed
t12
=
(
wx.x*ydir.y-wy.x*xdir.y
)
*invNormZdir
;
mixed
t13
=
(
wx.x*ydir.z-wy.x*xdir.z
)
*invNormZdir
;
mixed
t21
=
(
wx.y*ydir.x-wy.y*xdir.x
)
*invNormZdir
;
mixed
t22
=
(
wx.y*ydir.y-wy.y*xdir.y
)
*invNormZdir
;
mixed
t23
=
(
wx.y*ydir.z-wy.y*xdir.z
)
*invNormZdir
;
mixed
t31
=
(
wx.z*ydir.x-wy.z*xdir.x
)
*invNormZdir
;
mixed
t32
=
(
wx.z*ydir.y-wy.z*xdir.y
)
*invNormZdir
;
mixed
t33
=
(
wx.z*ydir.z-wy.z*xdir.z
)
*invNormZdir
;
mixed
sx1
=
t13*dz.y-t12*dz.z
;
mixed
sy1
=
t11*dz.z-t13*dz.x
;
mixed
sz1
=
t12*dz.x-t11*dz.y
;
mixed
sx2
=
t23*dz.y-t22*dz.z
;
mixed
sy2
=
t21*dz.z-t23*dz.x
;
mixed
sz2
=
t22*dz.x-t21*dz.y
;
mixed
sx3
=
t33*dz.y-t32*dz.z
;
mixed
sy3
=
t31*dz.z-t33*dz.x
;
mixed
sz3
=
t32*dz.x-t31*dz.y
;
mixed4
wxScaled
=
wx*invNormXdir
;
real4
f
=
force[atoms.x]
;
real4
f1
=
force[atoms.y]
;
real4
f2
=
force[atoms.z]
;
real4
f3
=
force[atoms.w]
;
mixed4
fp1
=
localPosition*f.x
;
mixed4
fp2
=
localPosition*f.y
;
mixed4
fp3
=
localPosition*f.z
;
f1.x
+=
fp1.x*wxScaled.x*
(
1-dx.x*dx.x
)
+
fp1.z*
(
dz.x*sx1
)
+
fp1.y*
((
-dx.x*dy.x
)
*wxScaled.x
+
dy.x*sx1
-
dx.y*t12
-
dx.z*t13
)
+
f.x*originWeights.x
;
f1.y
+=
fp1.x*wxScaled.x*
(
-dx.x*dx.y
)
+
fp1.z*
(
dz.x*sy1+t13
)
+
fp1.y*
((
-dx.y*dy.x-dz.z
)
*wxScaled.x
+
dy.x*sy1
+
dx.y*t11
)
;
f1.z
+=
fp1.x*wxScaled.x*
(
-dx.x*dx.z
)
+
fp1.z*
(
dz.x*sz1-t12
)
+
fp1.y*
((
-dx.z*dy.x+dz.y
)
*wxScaled.x
+
dy.x*sz1
+
dx.z*t11
)
;
f2.x
+=
fp1.x*wxScaled.y*
(
1-dx.x*dx.x
)
+
fp1.z*
(
dz.x*sx2
)
+
fp1.y*
((
-dx.x*dy.x
)
*wxScaled.y
+
dy.x*sx2
-
dx.y*t22
-
dx.z*t23
)
+
f.x*originWeights.y
;
f2.y
+=
fp1.x*wxScaled.y*
(
-dx.x*dx.y
)
+
fp1.z*
(
dz.x*sy2+t23
)
+
fp1.y*
((
-dx.y*dy.x-dz.z
)
*wxScaled.y
+
dy.x*sy2
+
dx.y*t21
)
;
f2.z
+=
fp1.x*wxScaled.y*
(
-dx.x*dx.z
)
+
fp1.z*
(
dz.x*sz2-t22
)
+
fp1.y*
((
-dx.z*dy.x+dz.y
)
*wxScaled.y
+
dy.x*sz2
+
dx.z*t21
)
;
f3.x
+=
fp1.x*wxScaled.z*
(
1-dx.x*dx.x
)
+
fp1.z*
(
dz.x*sx3
)
+
fp1.y*
((
-dx.x*dy.x
)
*wxScaled.z
+
dy.x*sx3
-
dx.y*t32
-
dx.z*t33
)
+
f.x*originWeights.z
;
f3.y
+=
fp1.x*wxScaled.z*
(
-dx.x*dx.y
)
+
fp1.z*
(
dz.x*sy3+t33
)
+
fp1.y*
((
-dx.y*dy.x-dz.z
)
*wxScaled.z
+
dy.x*sy3
+
dx.y*t31
)
;
f3.z
+=
fp1.x*wxScaled.z*
(
-dx.x*dx.z
)
+
fp1.z*
(
dz.x*sz3-t32
)
+
fp1.y*
((
-dx.z*dy.x+dz.y
)
*wxScaled.z
+
dy.x*sz3
+
dx.z*t31
)
;
f1.x
+=
fp2.x*wxScaled.x*
(
-dx.y*dx.x
)
+
fp2.z*
(
dz.y*sx1-t13
)
-
fp2.y*
((
dx.x*dy.y-dz.z
)
*wxScaled.x
-
dy.y*sx1
-
dx.x*t12
)
;
f1.y
+=
fp2.x*wxScaled.x*
(
1-dx.y*dx.y
)
+
fp2.z*
(
dz.y*sy1
)
-
fp2.y*
((
dx.y*dy.y
)
*wxScaled.x
-
dy.y*sy1
+
dx.x*t11
+
dx.z*t13
)
+
f.y*originWeights.x
;
f1.z
+=
fp2.x*wxScaled.x*
(
-dx.y*dx.z
)
+
fp2.z*
(
dz.y*sz1+t11
)
-
fp2.y*
((
dx.z*dy.y+dz.x
)
*wxScaled.x
-
dy.y*sz1
-
dx.z*t12
)
;
f2.x
+=
fp2.x*wxScaled.y*
(
-dx.y*dx.x
)
+
fp2.z*
(
dz.y*sx2-t23
)
-
fp2.y*
((
dx.x*dy.y-dz.z
)
*wxScaled.y
-
dy.y*sx2
-
dx.x*t22
)
;
f2.y
+=
fp2.x*wxScaled.y*
(
1-dx.y*dx.y
)
+
fp2.z*
(
dz.y*sy2
)
-
fp2.y*
((
dx.y*dy.y
)
*wxScaled.y
-
dy.y*sy2
+
dx.x*t21
+
dx.z*t23
)
+
f.y*originWeights.y
;
f2.z
+=
fp2.x*wxScaled.y*
(
-dx.y*dx.z
)
+
fp2.z*
(
dz.y*sz2+t21
)
-
fp2.y*
((
dx.z*dy.y+dz.x
)
*wxScaled.y
-
dy.y*sz2
-
dx.z*t22
)
;
f3.x
+=
fp2.x*wxScaled.z*
(
-dx.y*dx.x
)
+
fp2.z*
(
dz.y*sx3-t33
)
-
fp2.y*
((
dx.x*dy.y-dz.z
)
*wxScaled.z
-
dy.y*sx3
-
dx.x*t32
)
;
f3.y
+=
fp2.x*wxScaled.z*
(
1-dx.y*dx.y
)
+
fp2.z*
(
dz.y*sy3
)
-
fp2.y*
((
dx.y*dy.y
)
*wxScaled.z
-
dy.y*sy3
+
dx.x*t31
+
dx.z*t33
)
+
f.y*originWeights.z
;
f3.z
+=
fp2.x*wxScaled.z*
(
-dx.y*dx.z
)
+
fp2.z*
(
dz.y*sz3+t31
)
-
fp2.y*
((
dx.z*dy.y+dz.x
)
*wxScaled.z
-
dy.y*sz3
-
dx.z*t32
)
;
f1.x
+=
fp3.x*wxScaled.x*
(
-dx.z*dx.x
)
+
fp3.z*
(
dz.z*sx1+t12
)
+
fp3.y*
((
-dx.x*dy.z-dz.y
)
*wxScaled.x
+
dy.z*sx1
+
dx.x*t13
)
;
f1.y
+=
fp3.x*wxScaled.x*
(
-dx.z*dx.y
)
+
fp3.z*
(
dz.z*sy1-t11
)
+
fp3.y*
((
-dx.y*dy.z+dz.x
)
*wxScaled.x
+
dy.z*sy1
+
dx.y*t13
)
;
f1.z
+=
fp3.x*wxScaled.x*
(
1-dx.z*dx.z
)
+
fp3.z*
(
dz.z*sz1
)
+
fp3.y*
((
-dx.z*dy.z
)
*wxScaled.x
+
dy.z*sz1
-
dx.x*t11
-
dx.y*t12
)
+
f.z*originWeights.x
;
f2.x
+=
fp3.x*wxScaled.y*
(
-dx.z*dx.x
)
+
fp3.z*
(
dz.z*sx2+t22
)
+
fp3.y*
((
-dx.x*dy.z-dz.y
)
*wxScaled.y
+
dy.z*sx2
+
dx.x*t23
)
;
f2.y
+=
fp3.x*wxScaled.y*
(
-dx.z*dx.y
)
+
fp3.z*
(
dz.z*sy2-t21
)
+
fp3.y*
((
-dx.y*dy.z+dz.x
)
*wxScaled.y
+
dy.z*sy2
+
dx.y*t23
)
;
f2.z
+=
fp3.x*wxScaled.y*
(
1-dx.z*dx.z
)
+
fp3.z*
(
dz.z*sz2
)
+
fp3.y*
((
-dx.z*dy.z
)
*wxScaled.y
+
dy.z*sz2
-
dx.x*t21
-
dx.y*t22
)
+
f.z*originWeights.y
;
f3.x
+=
fp3.x*wxScaled.z*
(
-dx.z*dx.x
)
+
fp3.z*
(
dz.z*sx3+t32
)
+
fp3.y*
((
-dx.x*dy.z-dz.y
)
*wxScaled.z
+
dy.z*sx3
+
dx.x*t33
)
;
f3.y
+=
fp3.x*wxScaled.z*
(
-dx.z*dx.y
)
+
fp3.z*
(
dz.z*sy3-t31
)
+
fp3.y*
((
-dx.y*dy.z+dz.x
)
*wxScaled.z
+
dy.z*sy3
+
dx.y*t33
)
;
f3.z
+=
fp3.x*wxScaled.z*
(
1-dx.z*dx.z
)
+
fp3.z*
(
dz.z*sz3
)
+
fp3.y*
((
-dx.z*dy.z
)
*wxScaled.z
+
dy.z*sz3
-
dx.x*t31
-
dx.y*t32
)
+
f.z*originWeights.z
;
force[atoms.y]
=
f1
;
force[atoms.z]
=
f2
;
force[atoms.w]
=
f3
;
}
}
platforms/opencl/tests/TestOpenCLVirtualSites.cpp
View file @
ed03c83f
...
...
@@ -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) 2012 Stanford University and the Authors.
*
* Portions copyright (c) 2012
-2014
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -213,6 +213,84 @@ void testOutOfPlane() {
}
}
/**
* Test a LocalCoordinatesSite virtual site.
*/
void
testLocalCoordinates
()
{
const
Vec3
originWeights
(
0.2
,
0.3
,
0.5
);
const
Vec3
xWeights
(
-
1.0
,
0.5
,
0.5
);
const
Vec3
yWeights
(
0.0
,
-
1.0
,
1.0
);
const
Vec3
localPosition
(
0.4
,
0.3
,
0.2
);
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
0.0
);
system
.
setVirtualSite
(
3
,
new
LocalCoordinatesSite
(
0
,
1
,
2
,
originWeights
,
xWeights
,
yWeights
,
localPosition
));
CustomExternalForce
*
forceField
=
new
CustomExternalForce
(
"2*x^2+3*y^2+4*z^2"
);
system
.
addForce
(
forceField
);
vector
<
double
>
params
;
forceField
->
addParticle
(
0
,
params
);
forceField
->
addParticle
(
1
,
params
);
forceField
->
addParticle
(
2
,
params
);
forceField
->
addParticle
(
3
,
params
);
LangevinIntegrator
integrator
(
300.0
,
0.1
,
0.002
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
4
),
positions2
(
4
),
positions3
(
4
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
// Set the particles at random positions.
Vec3
xdir
,
ydir
,
zdir
;
do
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
positions
[
j
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
xdir
=
positions
[
0
]
*
xWeights
[
0
]
+
positions
[
1
]
*
xWeights
[
1
]
+
positions
[
2
]
*
xWeights
[
2
];
ydir
=
positions
[
0
]
*
yWeights
[
0
]
+
positions
[
1
]
*
yWeights
[
1
]
+
positions
[
2
]
*
yWeights
[
2
];
zdir
=
xdir
.
cross
(
ydir
);
if
(
sqrt
(
xdir
.
dot
(
xdir
))
>
0.1
&&
sqrt
(
ydir
.
dot
(
ydir
))
>
0.1
&&
sqrt
(
zdir
.
dot
(
zdir
))
>
0.1
)
break
;
// These positions give a reasonable coordinate system.
}
while
(
true
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
0.0001
);
// See if the virtual site is positioned correctly.
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Forces
);
const
vector
<
Vec3
>&
pos
=
state
.
getPositions
();
Vec3
origin
=
pos
[
0
]
*
originWeights
[
0
]
+
pos
[
1
]
*
originWeights
[
1
]
+
pos
[
2
]
*
originWeights
[
2
];
xdir
/=
sqrt
(
xdir
.
dot
(
xdir
));
zdir
/=
sqrt
(
zdir
.
dot
(
zdir
));
ydir
=
zdir
.
cross
(
xdir
);
ASSERT_EQUAL_VEC
(
origin
+
xdir
*
localPosition
[
0
]
+
ydir
*
localPosition
[
1
]
+
zdir
*
localPosition
[
2
],
pos
[
3
],
1e-5
);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
Vec3
f
=
state
.
getForces
()[
i
];
norm
+=
f
[
0
]
*
f
[
0
]
+
f
[
1
]
*
f
[
1
]
+
f
[
2
]
*
f
[
2
];
}
norm
=
std
::
sqrt
(
norm
);
const
double
delta
=
1e-2
;
double
step
=
0.5
*
delta
/
norm
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
state
.
getForces
()[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
context
.
applyConstraints
(
0.0001
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
context
.
applyConstraints
(
0.0001
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
delta
,
1e-3
)
}
}
/**
* Make sure that energy, linear momentum, and angular momentum are all conserved
* when using virtual sites.
...
...
@@ -278,6 +356,26 @@ void testConservationLaws() {
positions
.
push_back
(
Vec3
(
2
,
0
,
-
1
));
positions
.
push_back
(
Vec3
(
1
,
1
,
-
1
));
positions
.
push_back
(
Vec3
());
// Create a molecule with a LocalCoordinatesSite virtual site.
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
0.0
);
system
.
setVirtualSite
(
14
,
new
LocalCoordinatesSite
(
11
,
12
,
13
,
Vec3
(
0.3
,
0.3
,
0.4
),
Vec3
(
1.0
,
-
0.5
,
-
0.5
),
Vec3
(
0
,
-
1.0
,
1.0
),
Vec3
(
0.2
,
0.2
,
1.0
)));
system
.
addConstraint
(
11
,
12
,
1.0
);
system
.
addConstraint
(
11
,
13
,
1.0
);
system
.
addConstraint
(
12
,
13
,
sqrt
(
2.0
));
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
forceField
->
addParticle
(
0
,
1
,
10
);
for
(
int
j
=
0
;
j
<
i
;
j
++
)
forceField
->
addException
(
i
+
11
,
j
+
11
,
0
,
1
,
0
);
}
positions
.
push_back
(
Vec3
(
1
,
2
,
0
));
positions
.
push_back
(
Vec3
(
2
,
2
,
0
));
positions
.
push_back
(
Vec3
(
1
,
3
,
0
));
positions
.
push_back
(
Vec3
());
// Simulate it and check conservation laws.
...
...
@@ -315,7 +413,7 @@ void testConservationLaws() {
if
(
i
==
0
)
initialAngularMomentum
=
angularMomentum
;
else
ASSERT_EQUAL_VEC
(
initialAngularMomentum
,
angularMomentum
,
0.0
2
);
ASSERT_EQUAL_VEC
(
initialAngularMomentum
,
angularMomentum
,
0.0
3
);
integrator
.
step
(
1
);
}
}
...
...
@@ -434,6 +532,7 @@ int main(int argc, char* argv[]) {
testTwoParticleAverage
();
testThreeParticleAverage
();
testOutOfPlane
();
testLocalCoordinates
();
testConservationLaws
();
testReordering
();
}
...
...
platforms/reference/src/SimTKReference/ReferenceVirtualSites.cpp
View file @
ed03c83f
...
...
@@ -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) 2012 Stanford University and the Authors.
*
* Portions copyright (c) 2012
-2014
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -65,6 +65,24 @@ void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vecto
RealVec
cross
=
v12
.
cross
(
v13
);
atomCoordinates
[
i
]
=
atomCoordinates
[
p1
]
+
v12
*
w12
+
v13
*
w13
+
cross
*
wcross
;
}
else
if
(
dynamic_cast
<
const
LocalCoordinatesSite
*>
(
&
system
.
getVirtualSite
(
i
))
!=
NULL
)
{
// A local coordinates site.
const
LocalCoordinatesSite
&
site
=
dynamic_cast
<
const
LocalCoordinatesSite
&>
(
system
.
getVirtualSite
(
i
));
int
p1
=
site
.
getParticle
(
0
),
p2
=
site
.
getParticle
(
1
),
p3
=
site
.
getParticle
(
2
);
RealVec
originWeights
=
site
.
getOriginWeights
();
RealVec
xWeights
=
site
.
getXWeights
();
RealVec
yWeights
=
site
.
getYWeights
();
RealVec
localPosition
=
site
.
getLocalPosition
();
RealVec
origin
=
atomCoordinates
[
p1
]
*
originWeights
[
0
]
+
atomCoordinates
[
p2
]
*
originWeights
[
1
]
+
atomCoordinates
[
p3
]
*
originWeights
[
2
];
RealVec
xdir
=
atomCoordinates
[
p1
]
*
xWeights
[
0
]
+
atomCoordinates
[
p2
]
*
xWeights
[
1
]
+
atomCoordinates
[
p3
]
*
xWeights
[
2
];
RealVec
ydir
=
atomCoordinates
[
p1
]
*
yWeights
[
0
]
+
atomCoordinates
[
p2
]
*
yWeights
[
1
]
+
atomCoordinates
[
p3
]
*
yWeights
[
2
];
RealVec
zdir
=
xdir
.
cross
(
ydir
);
xdir
/=
sqrt
(
xdir
.
dot
(
xdir
));
zdir
/=
sqrt
(
zdir
.
dot
(
zdir
));
ydir
=
zdir
.
cross
(
xdir
);
atomCoordinates
[
i
]
=
origin
+
xdir
*
localPosition
[
0
]
+
ydir
*
localPosition
[
1
]
+
zdir
*
localPosition
[
2
];
}
}
}
...
...
@@ -110,5 +128,75 @@ void ReferenceVirtualSites::distributeForces(const OpenMM::System& system, const
forces
[
p2
]
+=
f2
;
forces
[
p3
]
+=
f3
;
}
else
if
(
dynamic_cast
<
const
LocalCoordinatesSite
*>
(
&
system
.
getVirtualSite
(
i
))
!=
NULL
)
{
// A local coordinates site.
const
LocalCoordinatesSite
&
site
=
dynamic_cast
<
const
LocalCoordinatesSite
&>
(
system
.
getVirtualSite
(
i
));
int
p1
=
site
.
getParticle
(
0
),
p2
=
site
.
getParticle
(
1
),
p3
=
site
.
getParticle
(
2
);
RealVec
originWeights
=
site
.
getOriginWeights
();
RealVec
wx
=
site
.
getXWeights
();
RealVec
wy
=
site
.
getYWeights
();
RealVec
localPosition
=
site
.
getLocalPosition
();
RealVec
xdir
=
atomCoordinates
[
p1
]
*
wx
[
0
]
+
atomCoordinates
[
p2
]
*
wx
[
1
]
+
atomCoordinates
[
p3
]
*
wx
[
2
];
RealVec
ydir
=
atomCoordinates
[
p1
]
*
wy
[
0
]
+
atomCoordinates
[
p2
]
*
wy
[
1
]
+
atomCoordinates
[
p3
]
*
wy
[
2
];
RealVec
zdir
=
xdir
.
cross
(
ydir
);
RealOpenMM
invNormXdir
=
1.0
/
SQRT
(
xdir
.
dot
(
xdir
));
RealOpenMM
invNormZdir
=
1.0
/
SQRT
(
zdir
.
dot
(
zdir
));
RealVec
dx
=
xdir
*
invNormXdir
;
RealVec
dz
=
zdir
*
invNormZdir
;
RealVec
dy
=
dz
.
cross
(
dx
);
// The derivatives for this case are very complicated. They were computed with SymPy then simplified by hand.
RealOpenMM
t11
=
(
wx
[
0
]
*
ydir
[
0
]
-
wy
[
0
]
*
xdir
[
0
])
*
invNormZdir
;
RealOpenMM
t12
=
(
wx
[
0
]
*
ydir
[
1
]
-
wy
[
0
]
*
xdir
[
1
])
*
invNormZdir
;
RealOpenMM
t13
=
(
wx
[
0
]
*
ydir
[
2
]
-
wy
[
0
]
*
xdir
[
2
])
*
invNormZdir
;
RealOpenMM
t21
=
(
wx
[
1
]
*
ydir
[
0
]
-
wy
[
1
]
*
xdir
[
0
])
*
invNormZdir
;
RealOpenMM
t22
=
(
wx
[
1
]
*
ydir
[
1
]
-
wy
[
1
]
*
xdir
[
1
])
*
invNormZdir
;
RealOpenMM
t23
=
(
wx
[
1
]
*
ydir
[
2
]
-
wy
[
1
]
*
xdir
[
2
])
*
invNormZdir
;
RealOpenMM
t31
=
(
wx
[
2
]
*
ydir
[
0
]
-
wy
[
2
]
*
xdir
[
0
])
*
invNormZdir
;
RealOpenMM
t32
=
(
wx
[
2
]
*
ydir
[
1
]
-
wy
[
2
]
*
xdir
[
1
])
*
invNormZdir
;
RealOpenMM
t33
=
(
wx
[
2
]
*
ydir
[
2
]
-
wy
[
2
]
*
xdir
[
2
])
*
invNormZdir
;
RealOpenMM
sx1
=
t13
*
dz
[
1
]
-
t12
*
dz
[
2
];
RealOpenMM
sy1
=
t11
*
dz
[
2
]
-
t13
*
dz
[
0
];
RealOpenMM
sz1
=
t12
*
dz
[
0
]
-
t11
*
dz
[
1
];
RealOpenMM
sx2
=
t23
*
dz
[
1
]
-
t22
*
dz
[
2
];
RealOpenMM
sy2
=
t21
*
dz
[
2
]
-
t23
*
dz
[
0
];
RealOpenMM
sz2
=
t22
*
dz
[
0
]
-
t21
*
dz
[
1
];
RealOpenMM
sx3
=
t33
*
dz
[
1
]
-
t32
*
dz
[
2
];
RealOpenMM
sy3
=
t31
*
dz
[
2
]
-
t33
*
dz
[
0
];
RealOpenMM
sz3
=
t32
*
dz
[
0
]
-
t31
*
dz
[
1
];
RealVec
wxScaled
=
wx
*
invNormXdir
;
RealVec
fp1
=
localPosition
*
f
[
0
];
RealVec
fp2
=
localPosition
*
f
[
1
];
RealVec
fp3
=
localPosition
*
f
[
2
];
forces
[
p1
][
0
]
+=
fp1
[
0
]
*
wxScaled
[
0
]
*
(
1
-
dx
[
0
]
*
dx
[
0
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sx1
)
+
fp1
[
1
]
*
((
-
dx
[
0
]
*
dy
[
0
]
)
*
wxScaled
[
0
]
+
dy
[
0
]
*
sx1
-
dx
[
1
]
*
t12
-
dx
[
2
]
*
t13
)
+
f
[
0
]
*
originWeights
[
0
];
forces
[
p1
][
1
]
+=
fp1
[
0
]
*
wxScaled
[
0
]
*
(
-
dx
[
0
]
*
dx
[
1
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sy1
+
t13
)
+
fp1
[
1
]
*
((
-
dx
[
1
]
*
dy
[
0
]
-
dz
[
2
])
*
wxScaled
[
0
]
+
dy
[
0
]
*
sy1
+
dx
[
1
]
*
t11
);
forces
[
p1
][
2
]
+=
fp1
[
0
]
*
wxScaled
[
0
]
*
(
-
dx
[
0
]
*
dx
[
2
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sz1
-
t12
)
+
fp1
[
1
]
*
((
-
dx
[
2
]
*
dy
[
0
]
+
dz
[
1
])
*
wxScaled
[
0
]
+
dy
[
0
]
*
sz1
+
dx
[
2
]
*
t11
);
forces
[
p2
][
0
]
+=
fp1
[
0
]
*
wxScaled
[
1
]
*
(
1
-
dx
[
0
]
*
dx
[
0
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sx2
)
+
fp1
[
1
]
*
((
-
dx
[
0
]
*
dy
[
0
]
)
*
wxScaled
[
1
]
+
dy
[
0
]
*
sx2
-
dx
[
1
]
*
t22
-
dx
[
2
]
*
t23
)
+
f
[
0
]
*
originWeights
[
1
];
forces
[
p2
][
1
]
+=
fp1
[
0
]
*
wxScaled
[
1
]
*
(
-
dx
[
0
]
*
dx
[
1
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sy2
+
t23
)
+
fp1
[
1
]
*
((
-
dx
[
1
]
*
dy
[
0
]
-
dz
[
2
])
*
wxScaled
[
1
]
+
dy
[
0
]
*
sy2
+
dx
[
1
]
*
t21
);
forces
[
p2
][
2
]
+=
fp1
[
0
]
*
wxScaled
[
1
]
*
(
-
dx
[
0
]
*
dx
[
2
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sz2
-
t22
)
+
fp1
[
1
]
*
((
-
dx
[
2
]
*
dy
[
0
]
+
dz
[
1
])
*
wxScaled
[
1
]
+
dy
[
0
]
*
sz2
+
dx
[
2
]
*
t21
);
forces
[
p3
][
0
]
+=
fp1
[
0
]
*
wxScaled
[
2
]
*
(
1
-
dx
[
0
]
*
dx
[
0
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sx3
)
+
fp1
[
1
]
*
((
-
dx
[
0
]
*
dy
[
0
]
)
*
wxScaled
[
2
]
+
dy
[
0
]
*
sx3
-
dx
[
1
]
*
t32
-
dx
[
2
]
*
t33
)
+
f
[
0
]
*
originWeights
[
2
];
forces
[
p3
][
1
]
+=
fp1
[
0
]
*
wxScaled
[
2
]
*
(
-
dx
[
0
]
*
dx
[
1
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sy3
+
t33
)
+
fp1
[
1
]
*
((
-
dx
[
1
]
*
dy
[
0
]
-
dz
[
2
])
*
wxScaled
[
2
]
+
dy
[
0
]
*
sy3
+
dx
[
1
]
*
t31
);
forces
[
p3
][
2
]
+=
fp1
[
0
]
*
wxScaled
[
2
]
*
(
-
dx
[
0
]
*
dx
[
2
])
+
fp1
[
2
]
*
(
dz
[
0
]
*
sz3
-
t32
)
+
fp1
[
1
]
*
((
-
dx
[
2
]
*
dy
[
0
]
+
dz
[
1
])
*
wxScaled
[
2
]
+
dy
[
0
]
*
sz3
+
dx
[
2
]
*
t31
);
forces
[
p1
][
0
]
+=
fp2
[
0
]
*
wxScaled
[
0
]
*
(
-
dx
[
1
]
*
dx
[
0
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sx1
-
t13
)
-
fp2
[
1
]
*
((
dx
[
0
]
*
dy
[
1
]
-
dz
[
2
])
*
wxScaled
[
0
]
-
dy
[
1
]
*
sx1
-
dx
[
0
]
*
t12
);
forces
[
p1
][
1
]
+=
fp2
[
0
]
*
wxScaled
[
0
]
*
(
1
-
dx
[
1
]
*
dx
[
1
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sy1
)
-
fp2
[
1
]
*
((
dx
[
1
]
*
dy
[
1
]
)
*
wxScaled
[
0
]
-
dy
[
1
]
*
sy1
+
dx
[
0
]
*
t11
+
dx
[
2
]
*
t13
)
+
f
[
1
]
*
originWeights
[
0
];
forces
[
p1
][
2
]
+=
fp2
[
0
]
*
wxScaled
[
0
]
*
(
-
dx
[
1
]
*
dx
[
2
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sz1
+
t11
)
-
fp2
[
1
]
*
((
dx
[
2
]
*
dy
[
1
]
+
dz
[
0
])
*
wxScaled
[
0
]
-
dy
[
1
]
*
sz1
-
dx
[
2
]
*
t12
);
forces
[
p2
][
0
]
+=
fp2
[
0
]
*
wxScaled
[
1
]
*
(
-
dx
[
1
]
*
dx
[
0
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sx2
-
t23
)
-
fp2
[
1
]
*
((
dx
[
0
]
*
dy
[
1
]
-
dz
[
2
])
*
wxScaled
[
1
]
-
dy
[
1
]
*
sx2
-
dx
[
0
]
*
t22
);
forces
[
p2
][
1
]
+=
fp2
[
0
]
*
wxScaled
[
1
]
*
(
1
-
dx
[
1
]
*
dx
[
1
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sy2
)
-
fp2
[
1
]
*
((
dx
[
1
]
*
dy
[
1
]
)
*
wxScaled
[
1
]
-
dy
[
1
]
*
sy2
+
dx
[
0
]
*
t21
+
dx
[
2
]
*
t23
)
+
f
[
1
]
*
originWeights
[
1
];
forces
[
p2
][
2
]
+=
fp2
[
0
]
*
wxScaled
[
1
]
*
(
-
dx
[
1
]
*
dx
[
2
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sz2
+
t21
)
-
fp2
[
1
]
*
((
dx
[
2
]
*
dy
[
1
]
+
dz
[
0
])
*
wxScaled
[
1
]
-
dy
[
1
]
*
sz2
-
dx
[
2
]
*
t22
);
forces
[
p3
][
0
]
+=
fp2
[
0
]
*
wxScaled
[
2
]
*
(
-
dx
[
1
]
*
dx
[
0
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sx3
-
t33
)
-
fp2
[
1
]
*
((
dx
[
0
]
*
dy
[
1
]
-
dz
[
2
])
*
wxScaled
[
2
]
-
dy
[
1
]
*
sx3
-
dx
[
0
]
*
t32
);
forces
[
p3
][
1
]
+=
fp2
[
0
]
*
wxScaled
[
2
]
*
(
1
-
dx
[
1
]
*
dx
[
1
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sy3
)
-
fp2
[
1
]
*
((
dx
[
1
]
*
dy
[
1
]
)
*
wxScaled
[
2
]
-
dy
[
1
]
*
sy3
+
dx
[
0
]
*
t31
+
dx
[
2
]
*
t33
)
+
f
[
1
]
*
originWeights
[
2
];
forces
[
p3
][
2
]
+=
fp2
[
0
]
*
wxScaled
[
2
]
*
(
-
dx
[
1
]
*
dx
[
2
])
+
fp2
[
2
]
*
(
dz
[
1
]
*
sz3
+
t31
)
-
fp2
[
1
]
*
((
dx
[
2
]
*
dy
[
1
]
+
dz
[
0
])
*
wxScaled
[
2
]
-
dy
[
1
]
*
sz3
-
dx
[
2
]
*
t32
);
forces
[
p1
][
0
]
+=
fp3
[
0
]
*
wxScaled
[
0
]
*
(
-
dx
[
2
]
*
dx
[
0
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sx1
+
t12
)
+
fp3
[
1
]
*
((
-
dx
[
0
]
*
dy
[
2
]
-
dz
[
1
])
*
wxScaled
[
0
]
+
dy
[
2
]
*
sx1
+
dx
[
0
]
*
t13
);
forces
[
p1
][
1
]
+=
fp3
[
0
]
*
wxScaled
[
0
]
*
(
-
dx
[
2
]
*
dx
[
1
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sy1
-
t11
)
+
fp3
[
1
]
*
((
-
dx
[
1
]
*
dy
[
2
]
+
dz
[
0
])
*
wxScaled
[
0
]
+
dy
[
2
]
*
sy1
+
dx
[
1
]
*
t13
);
forces
[
p1
][
2
]
+=
fp3
[
0
]
*
wxScaled
[
0
]
*
(
1
-
dx
[
2
]
*
dx
[
2
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sz1
)
+
fp3
[
1
]
*
((
-
dx
[
2
]
*
dy
[
2
]
)
*
wxScaled
[
0
]
+
dy
[
2
]
*
sz1
-
dx
[
0
]
*
t11
-
dx
[
1
]
*
t12
)
+
f
[
2
]
*
originWeights
[
0
];
forces
[
p2
][
0
]
+=
fp3
[
0
]
*
wxScaled
[
1
]
*
(
-
dx
[
2
]
*
dx
[
0
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sx2
+
t22
)
+
fp3
[
1
]
*
((
-
dx
[
0
]
*
dy
[
2
]
-
dz
[
1
])
*
wxScaled
[
1
]
+
dy
[
2
]
*
sx2
+
dx
[
0
]
*
t23
);
forces
[
p2
][
1
]
+=
fp3
[
0
]
*
wxScaled
[
1
]
*
(
-
dx
[
2
]
*
dx
[
1
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sy2
-
t21
)
+
fp3
[
1
]
*
((
-
dx
[
1
]
*
dy
[
2
]
+
dz
[
0
])
*
wxScaled
[
1
]
+
dy
[
2
]
*
sy2
+
dx
[
1
]
*
t23
);
forces
[
p2
][
2
]
+=
fp3
[
0
]
*
wxScaled
[
1
]
*
(
1
-
dx
[
2
]
*
dx
[
2
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sz2
)
+
fp3
[
1
]
*
((
-
dx
[
2
]
*
dy
[
2
]
)
*
wxScaled
[
1
]
+
dy
[
2
]
*
sz2
-
dx
[
0
]
*
t21
-
dx
[
1
]
*
t22
)
+
f
[
2
]
*
originWeights
[
1
];
forces
[
p3
][
0
]
+=
fp3
[
0
]
*
wxScaled
[
2
]
*
(
-
dx
[
2
]
*
dx
[
0
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sx3
+
t32
)
+
fp3
[
1
]
*
((
-
dx
[
0
]
*
dy
[
2
]
-
dz
[
1
])
*
wxScaled
[
2
]
+
dy
[
2
]
*
sx3
+
dx
[
0
]
*
t33
);
forces
[
p3
][
1
]
+=
fp3
[
0
]
*
wxScaled
[
2
]
*
(
-
dx
[
2
]
*
dx
[
1
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sy3
-
t31
)
+
fp3
[
1
]
*
((
-
dx
[
1
]
*
dy
[
2
]
+
dz
[
0
])
*
wxScaled
[
2
]
+
dy
[
2
]
*
sy3
+
dx
[
1
]
*
t33
);
forces
[
p3
][
2
]
+=
fp3
[
0
]
*
wxScaled
[
2
]
*
(
1
-
dx
[
2
]
*
dx
[
2
])
+
fp3
[
2
]
*
(
dz
[
2
]
*
sz3
)
+
fp3
[
1
]
*
((
-
dx
[
2
]
*
dy
[
2
]
)
*
wxScaled
[
2
]
+
dy
[
2
]
*
sz3
-
dx
[
0
]
*
t31
-
dx
[
1
]
*
t32
)
+
f
[
2
]
*
originWeights
[
2
];
}
}
}
platforms/reference/tests/TestReferenceVirtualSites.cpp
View file @
ed03c83f
...
...
@@ -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) 2012 Stanford University and the Authors.
*
* Portions copyright (c) 2012
-2014
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -215,6 +215,85 @@ void testOutOfPlane() {
}
}
/**
* Test a LocalCoordinatesSite virtual site.
*/
void
testLocalCoordinates
()
{
const
Vec3
originWeights
(
0.2
,
0.3
,
0.5
);
const
Vec3
xWeights
(
-
1.0
,
0.5
,
0.5
);
const
Vec3
yWeights
(
0.0
,
-
1.0
,
1.0
);
const
Vec3
localPosition
(
0.4
,
0.3
,
0.2
);
ReferencePlatform
platform
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
0.0
);
system
.
setVirtualSite
(
3
,
new
LocalCoordinatesSite
(
0
,
1
,
2
,
originWeights
,
xWeights
,
yWeights
,
localPosition
));
CustomExternalForce
*
forceField
=
new
CustomExternalForce
(
"2*x^2+3*y^2+4*z^2"
);
system
.
addForce
(
forceField
);
vector
<
double
>
params
;
forceField
->
addParticle
(
0
,
params
);
forceField
->
addParticle
(
1
,
params
);
forceField
->
addParticle
(
2
,
params
);
forceField
->
addParticle
(
3
,
params
);
LangevinIntegrator
integrator
(
300.0
,
0.1
,
0.002
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
4
),
positions2
(
4
),
positions3
(
4
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
// Set the particles at random positions.
Vec3
xdir
,
ydir
,
zdir
;
do
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
positions
[
j
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
xdir
=
positions
[
0
]
*
xWeights
[
0
]
+
positions
[
1
]
*
xWeights
[
1
]
+
positions
[
2
]
*
xWeights
[
2
];
ydir
=
positions
[
0
]
*
yWeights
[
0
]
+
positions
[
1
]
*
yWeights
[
1
]
+
positions
[
2
]
*
yWeights
[
2
];
zdir
=
xdir
.
cross
(
ydir
);
if
(
sqrt
(
xdir
.
dot
(
xdir
))
>
0.1
&&
sqrt
(
ydir
.
dot
(
ydir
))
>
0.1
&&
sqrt
(
zdir
.
dot
(
zdir
))
>
0.1
)
break
;
// These positions give a reasonable coordinate system.
}
while
(
true
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
0.0001
);
// See if the virtual site is positioned correctly.
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Forces
);
const
vector
<
Vec3
>&
pos
=
state
.
getPositions
();
Vec3
origin
=
pos
[
0
]
*
originWeights
[
0
]
+
pos
[
1
]
*
originWeights
[
1
]
+
pos
[
2
]
*
originWeights
[
2
];
xdir
/=
sqrt
(
xdir
.
dot
(
xdir
));
zdir
/=
sqrt
(
zdir
.
dot
(
zdir
));
ydir
=
zdir
.
cross
(
xdir
);
ASSERT_EQUAL_VEC
(
origin
+
xdir
*
localPosition
[
0
]
+
ydir
*
localPosition
[
1
]
+
zdir
*
localPosition
[
2
],
pos
[
3
],
1e-10
);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
Vec3
f
=
state
.
getForces
()[
i
];
norm
+=
f
[
0
]
*
f
[
0
]
+
f
[
1
]
*
f
[
1
]
+
f
[
2
]
*
f
[
2
];
}
norm
=
std
::
sqrt
(
norm
);
const
double
delta
=
1e-2
;
double
step
=
0.5
*
delta
/
norm
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
state
.
getForces
()[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
context
.
applyConstraints
(
0.0001
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
context
.
applyConstraints
(
0.0001
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
delta
,
1e-3
)
}
}
/**
* Make sure that energy, linear momentum, and angular momentum are all conserved
* when using virtual sites.
...
...
@@ -281,6 +360,26 @@ void testConservationLaws() {
positions
.
push_back
(
Vec3
(
2
,
0
,
-
1
));
positions
.
push_back
(
Vec3
(
1
,
1
,
-
1
));
positions
.
push_back
(
Vec3
());
// Create a molecule with a LocalCoordinatesSite virtual site.
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
0.0
);
system
.
setVirtualSite
(
14
,
new
LocalCoordinatesSite
(
11
,
12
,
13
,
Vec3
(
0.3
,
0.3
,
0.4
),
Vec3
(
1.0
,
-
0.5
,
-
0.5
),
Vec3
(
0
,
-
1.0
,
1.0
),
Vec3
(
0.2
,
0.2
,
1.0
)));
system
.
addConstraint
(
11
,
12
,
1.0
);
system
.
addConstraint
(
11
,
13
,
1.0
);
system
.
addConstraint
(
12
,
13
,
sqrt
(
2.0
));
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
forceField
->
addParticle
(
0
,
1
,
10
);
for
(
int
j
=
0
;
j
<
i
;
j
++
)
forceField
->
addException
(
i
+
11
,
j
+
11
,
0
,
1
,
0
);
}
positions
.
push_back
(
Vec3
(
1
,
2
,
0
));
positions
.
push_back
(
Vec3
(
2
,
2
,
0
));
positions
.
push_back
(
Vec3
(
1
,
3
,
0
));
positions
.
push_back
(
Vec3
());
// Simulate it and check conservation laws.
...
...
@@ -329,6 +428,7 @@ int main() {
testTwoParticleAverage
();
testThreeParticleAverage
();
testOutOfPlane
();
testLocalCoordinates
();
testConservationLaws
();
}
catch
(
const
exception
&
e
)
{
...
...
wrappers/python/src/swig_doxygen/swigInputConfig.py
View file @
ed03c83f
...
...
@@ -191,6 +191,10 @@ UNITS = {
(
"*"
,
"getWeight12"
)
:
(
None
,
()),
(
"*"
,
"getWeight13"
)
:
(
None
,
()),
(
"*"
,
"getWeightCross"
)
:
(
None
,
()),
(
"LocalCoordinatesSite"
,
"getOriginWeights"
)
:
(
None
,
()),
(
"LocalCoordinatesSite"
,
"getXWeights"
)
:
(
None
,
()),
(
"LocalCoordinatesSite"
,
"getYWeights"
)
:
(
None
,
()),
(
"LocalCoordinatesSite"
,
"getLocalPosition"
)
:
(
"unit.nanometer"
,
()),
(
"SerializationNode"
,
"getChildren"
)
:
(
None
,
()),
(
"SerializationNode"
,
"getChildNode"
)
:
(
None
,
()),
(
"SerializationNode"
,
"getProperties"
)
:
(
None
,
()),
...
...
wrappers/python/src/swig_doxygen/swig_lib/python/typemaps.i
View file @
ed03c83f
...
...
@@ -117,6 +117,14 @@
Py_DECREF
(
args
)
;
}
%
typemap
(
out
)
const
Vec3&
{
PyObject
*
mm
=
PyImport_AddModule
(
"simtk.openmm"
)
;
PyObject
*
vec3
=
PyObject_GetAttrString
(
mm
,
"Vec3"
)
;
PyObject
*
args
=
Py_BuildValue
(
"(d,d,d)"
,
(
*
$
1
)[
0
],
(
*
$
1
)[
1
],
(
*
$
1
)[
2
])
;
$
result
=
PyObject_CallObject
(
vec3
,
args
)
;
Py_DECREF
(
args
)
;
}
/* Convert C++ (Vec3&, Vec3&, Vec3&) object to python tuple or tuples */
%
typemap
(
argout
)
(
Vec3&
a
,
Vec3&
b
,
Vec3&
c
)
{
// %typemap(argout) (Vec3& a, Vec3& b, Vec3& c)
...
...
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