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
4be5daf1
Commit
4be5daf1
authored
Apr 23, 2014
by
peastman
Browse files
Created LocalCoordinatesSite, including reference implementation
parent
ede48b85
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
284 additions
and
4 deletions
+284
-4
openmmapi/include/openmm/VirtualSite.h
openmmapi/include/openmm/VirtualSite.h
+61
-1
openmmapi/src/VirtualSite.cpp
openmmapi/src/VirtualSite.cpp
+33
-1
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
No files found.
openmmapi/include/openmm/VirtualSite.h
View file @
4be5daf1
...
...
@@ -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 normalize, 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 @
4be5daf1
...
...
@@ -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/reference/src/SimTKReference/ReferenceVirtualSites.cpp
View file @
4be5daf1
...
...
@@ -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 @
4be5daf1
...
...
@@ -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
)
{
...
...
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