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
83ed602e
Commit
83ed602e
authored
Feb 05, 2015
by
peastman
Browse files
Merge pull request #797 from peastman/triclinic
C++ libraries support triclinic boxes
parents
b51e05a8
050e1262
Changes
119
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
448 additions
and
118 deletions
+448
-118
platforms/opencl/src/kernels/monteCarloBarostat.cl
platforms/opencl/src/kernels/monteCarloBarostat.cl
+8
-9
platforms/opencl/src/kernels/nonbonded.cl
platforms/opencl/src/kernels/nonbonded.cl
+7
-8
platforms/opencl/src/kernels/pme.cl
platforms/opencl/src/kernels/pme.cl
+48
-39
platforms/opencl/tests/TestOpenCLCustomManyParticleForce.cpp
platforms/opencl/tests/TestOpenCLCustomManyParticleForce.cpp
+59
-17
platforms/opencl/tests/TestOpenCLCustomNonbondedForce.cpp
platforms/opencl/tests/TestOpenCLCustomNonbondedForce.cpp
+61
-1
platforms/opencl/tests/TestOpenCLEwald.cpp
platforms/opencl/tests/TestOpenCLEwald.cpp
+52
-0
platforms/opencl/tests/TestOpenCLMonteCarloAnisotropicBarostat.cpp
.../opencl/tests/TestOpenCLMonteCarloAnisotropicBarostat.cpp
+78
-1
platforms/opencl/tests/TestOpenCLNonbondedForce.cpp
platforms/opencl/tests/TestOpenCLNonbondedForce.cpp
+91
-1
platforms/reference/include/GBVIParameters.h
platforms/reference/include/GBVIParameters.h
+4
-4
platforms/reference/include/ObcParameters.h
platforms/reference/include/ObcParameters.h
+5
-5
platforms/reference/include/ReferenceCustomGBIxn.h
platforms/reference/include/ReferenceCustomGBIxn.h
+3
-3
platforms/reference/include/ReferenceCustomHbondIxn.h
platforms/reference/include/ReferenceCustomHbondIxn.h
+3
-3
platforms/reference/include/ReferenceCustomManyParticleIxn.h
platforms/reference/include/ReferenceCustomManyParticleIxn.h
+3
-3
platforms/reference/include/ReferenceCustomNonbondedIxn.h
platforms/reference/include/ReferenceCustomNonbondedIxn.h
+3
-3
platforms/reference/include/ReferenceForce.h
platforms/reference/include/ReferenceForce.h
+12
-9
platforms/reference/include/ReferenceLJCoulombIxn.h
platforms/reference/include/ReferenceLJCoulombIxn.h
+3
-3
platforms/reference/include/ReferenceMonteCarloBarostat.h
platforms/reference/include/ReferenceMonteCarloBarostat.h
+2
-2
platforms/reference/include/ReferenceNeighborList.h
platforms/reference/include/ReferenceNeighborList.h
+3
-3
platforms/reference/include/ReferencePME.h
platforms/reference/include/ReferencePME.h
+2
-4
platforms/reference/include/ReferencePlatform.h
platforms/reference/include/ReferencePlatform.h
+1
-0
No files found.
platforms/opencl/src/kernels/monteCarloBarostat.cl
View file @
83ed602e
...
@@ -2,7 +2,8 @@
...
@@ -2,7 +2,8 @@
*
Scale
the
particle
positions
with
each
axis
independent.
*
Scale
the
particle
positions
with
each
axis
independent.
*/
*/
__kernel
void
scalePositions
(
float
scaleX,
float
scaleY,
float
scaleZ,
int
numMolecules,
real4
periodicBoxSize,
real4
invPeriodicBoxSize,
__global
real4*
restrict
posq,
__kernel
void
scalePositions
(
float
scaleX,
float
scaleY,
float
scaleZ,
int
numMolecules,
real4
periodicBoxSize,
real4
invPeriodicBoxSize,
real4
periodicBoxVecX,
real4
periodicBoxVecY,
real4
periodicBoxVecZ,
__global
real4*
restrict
posq,
__global
const
int*
restrict
moleculeAtoms,
__global
const
int*
restrict
moleculeStartIndex
)
{
__global
const
int*
restrict
moleculeAtoms,
__global
const
int*
restrict
moleculeStartIndex
)
{
for
(
int
index
=
get_global_id
(
0
)
; index < numMolecules; index += get_global_size(0)) {
for
(
int
index
=
get_global_id
(
0
)
; index < numMolecules; index += get_global_size(0)) {
int
first
=
moleculeStartIndex[index]
;
int
first
=
moleculeStartIndex[index]
;
...
@@ -11,19 +12,17 @@ __kernel void scalePositions(float scaleX, float scaleY, float scaleZ, int numMo
...
@@ -11,19 +12,17 @@ __kernel void scalePositions(float scaleX, float scaleY, float scaleZ, int numMo
//
Find
the
center
of
each
molecule.
//
Find
the
center
of
each
molecule.
real
4
center
=
(
real
4
)
0
;
real
3
center
=
(
real
3
)
0
;
for
(
int
atom
=
first
; atom < last; atom++)
for
(
int
atom
=
first
; atom < last; atom++)
center
+=
posq[moleculeAtoms[atom]]
;
center
+=
posq[moleculeAtoms[atom]]
.xyz
;
center
/=
(
real
)
numAtoms
;
center
/=
(
real
)
numAtoms
;
//
Move
it
into
the
first
periodic
box.
//
Move
it
into
the
first
periodic
box.
int
xcell
=
(
int
)
floor
(
center.x*invPeriodicBoxSize.x
)
;
real3
oldCenter
=
center
;
int
ycell
=
(
int
)
floor
(
center.y*invPeriodicBoxSize.y
)
;
APPLY_PERIODIC_TO_POS
(
center
)
int
zcell
=
(
int
)
floor
(
center.z*invPeriodicBoxSize.z
)
;
real3
delta
=
oldCenter-center
;;
real4
delta
=
(
real4
)
(
xcell*periodicBoxSize.x,
ycell*periodicBoxSize.y,
zcell*periodicBoxSize.z,
0
)
;
real3
scaleXYZ
=
(
real3
)
(
scaleX,
scaleY,
scaleZ
)
;
real4
scaleXYZ
=
(
real4
)
(
scaleX,
scaleY,
scaleZ,
1
)
;
center
-=
delta
;
//
Now
scale
the
position
of
the
molecule
center.
//
Now
scale
the
position
of
the
molecule
center.
...
...
platforms/opencl/src/kernels/nonbonded.cl
View file @
83ed602e
...
@@ -26,7 +26,8 @@ __kernel void computeNonbonded(
...
@@ -26,7 +26,8 @@ __kernel void computeNonbonded(
__global
const
ushort2*
restrict
exclusionTiles,
unsigned
int
startTileIndex,
unsigned
int
numTileIndices
__global
const
ushort2*
restrict
exclusionTiles,
unsigned
int
startTileIndex,
unsigned
int
numTileIndices
#
ifdef
USE_CUTOFF
#
ifdef
USE_CUTOFF
,
__global
const
int*
restrict
tiles,
__global
const
unsigned
int*
restrict
interactionCount,
real4
periodicBoxSize,
real4
invPeriodicBoxSize,
,
__global
const
int*
restrict
tiles,
__global
const
unsigned
int*
restrict
interactionCount,
real4
periodicBoxSize,
real4
invPeriodicBoxSize,
unsigned
int
maxTiles,
__global
const
real4*
restrict
blockCenter,
__global
const
real4*
restrict
blockSize,
__global
const
int*
restrict
interactingAtoms
real4
periodicBoxVecX,
real4
periodicBoxVecY,
real4
periodicBoxVecZ,
unsigned
int
maxTiles,
__global
const
real4*
restrict
blockCenter,
__global
const
real4*
restrict
blockSize,
__global
const
int*
restrict
interactingAtoms
#
endif
#
endif
PARAMETER_ARGUMENTS
)
{
PARAMETER_ARGUMENTS
)
{
const
unsigned
int
totalWarps
=
get_global_size
(
0
)
/TILE_SIZE
;
const
unsigned
int
totalWarps
=
get_global_size
(
0
)
/TILE_SIZE
;
...
@@ -67,7 +68,7 @@ __kernel void computeNonbonded(
...
@@ -67,7 +68,7 @@ __kernel void computeNonbonded(
real4
posq2
=
(
real4
)
(
localData[atom2].x,
localData[atom2].y,
localData[atom2].z,
localData[atom2].q
)
;
real4
posq2
=
(
real4
)
(
localData[atom2].x,
localData[atom2].y,
localData[atom2].z,
localData[atom2].q
)
;
real4
delta
=
(
real4
)
(
posq2.xyz
-
posq1.xyz,
0
)
;
real4
delta
=
(
real4
)
(
posq2.xyz
-
posq1.xyz,
0
)
;
#
ifdef
USE_PERIODIC
#
ifdef
USE_PERIODIC
delta.xyz
-=
floor
(
delta.xyz*invPeriodicBoxSize.xyz+0.5f
)
*periodicBoxSize.xyz
;
APPLY_PERIODIC_TO_DELTA
(
delta
)
#
endif
#
endif
real
r2
=
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
;
real
r2
=
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
;
real
invR
=
RSQRT
(
r2
)
;
real
invR
=
RSQRT
(
r2
)
;
...
@@ -121,7 +122,7 @@ __kernel void computeNonbonded(
...
@@ -121,7 +122,7 @@ __kernel void computeNonbonded(
real4
posq2
=
(
real4
)
(
localData[atom2].x,
localData[atom2].y,
localData[atom2].z,
localData[atom2].q
)
;
real4
posq2
=
(
real4
)
(
localData[atom2].x,
localData[atom2].y,
localData[atom2].z,
localData[atom2].q
)
;
real4
delta
=
(
real4
)
(
posq2.xyz
-
posq1.xyz,
0
)
;
real4
delta
=
(
real4
)
(
posq2.xyz
-
posq1.xyz,
0
)
;
#
ifdef
USE_PERIODIC
#
ifdef
USE_PERIODIC
delta.xyz
-=
floor
(
delta.xyz*invPeriodicBoxSize.xyz+0.5f
)
*periodicBoxSize.xyz
;
APPLY_PERIODIC_TO_DELTA
(
delta
)
#
endif
#
endif
real
r2
=
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
;
real
r2
=
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
;
#
ifdef
PRUNE_BY_CUTOFF
#
ifdef
PRUNE_BY_CUTOFF
...
@@ -289,10 +290,8 @@ __kernel void computeNonbonded(
...
@@ -289,10 +290,8 @@ __kernel void computeNonbonded(
// box, then skip having to apply periodic boundary conditions later.
// box, then skip having to apply periodic boundary conditions later.
real4 blockCenterX = blockCenter[x];
real4 blockCenterX = blockCenter[x];
posq1.xyz -= floor((posq1.xyz-blockCenterX.xyz)*invPeriodicBoxSize.xyz+0.5f)*periodicBoxSize.xyz;
APPLY_PERIODIC_TO_POS_WITH_CENTER(posq1, blockCenterX)
localData[localAtomIndex].x -= floor((localData[localAtomIndex].x-blockCenterX.x)*invPeriodicBoxSize.x+0.5f)*periodicBoxSize.x;
APPLY_PERIODIC_TO_POS_WITH_CENTER(localData[localAtomIndex], blockCenterX)
localData[localAtomIndex].y -= floor((localData[localAtomIndex].y-blockCenterX.y)*invPeriodicBoxSize.y+0.5f)*periodicBoxSize.y;
localData[localAtomIndex].z -= floor((localData[localAtomIndex].z-blockCenterX.z)*invPeriodicBoxSize.z+0.5f)*periodicBoxSize.z;
SYNC_WARPS;
SYNC_WARPS;
unsigned int tj = tgx;
unsigned int tj = tgx;
for (j = 0; j < TILE_SIZE; j++) {
for (j = 0; j < TILE_SIZE; j++) {
...
@@ -349,7 +348,7 @@ __kernel void computeNonbonded(
...
@@ -349,7 +348,7 @@ __kernel void computeNonbonded(
real4 posq2 = (real4) (localData[atom2].x, localData[atom2].y, localData[atom2].z, localData[atom2].q);
real4 posq2 = (real4) (localData[atom2].x, localData[atom2].y, localData[atom2].z, localData[atom2].q);
real4 delta = (real4) (posq2.xyz - posq1.xyz, 0);
real4 delta = (real4) (posq2.xyz - posq1.xyz, 0);
#ifdef USE_PERIODIC
#ifdef USE_PERIODIC
delta.xyz -= floor(delta.xyz*invPeriodicBoxSize.xyz+0.5f)*periodicBoxSize.xyz;
APPLY_PERIODIC_TO_DELTA(delta)
#endif
#endif
real r2 = delta.x*delta.x + delta.y*delta.y + delta.z*delta.z;
real r2 = delta.x*delta.x + delta.y*delta.y + delta.z*delta.z;
#ifdef PRUNE_BY_CUTOFF
#ifdef PRUNE_BY_CUTOFF
...
...
platforms/opencl/src/kernels/pme.cl
View file @
83ed602e
__kernel
void
updateBsplines
(
__global
const
real4*
restrict
posq,
__global
real4*
restrict
pmeBsplineTheta,
__local
real4*
restrict
bsplinesCache,
__kernel
void
updateBsplines
(
__global
const
real4*
restrict
posq,
__global
real4*
restrict
pmeBsplineTheta,
__local
real4*
restrict
bsplinesCache,
__global
int2*
restrict
pmeAtomGridIndex,
real4
periodicBoxSize,
real4
invPeriodicBoxSize
)
{
__global
int2*
restrict
pmeAtomGridIndex,
real4
periodicBoxSize,
real4
recipBoxVecX,
real4
recipBoxVecY,
real4
recipBoxVecZ
)
{
const
real4
scale
=
1/
(
real
)
(
PME_ORDER-1
)
;
const
real4
scale
=
1/
(
real
)
(
PME_ORDER-1
)
;
for
(
int
i
=
get_global_id
(
0
)
; i < NUM_ATOMS; i += get_global_size(0)) {
for
(
int
i
=
get_global_id
(
0
)
; i < NUM_ATOMS; i += get_global_size(0)) {
__local
real4*
data
=
&bsplinesCache[get_local_id
(
0
)
*PME_ORDER]
;
__local
real4*
data
=
&bsplinesCache[get_local_id
(
0
)
*PME_ORDER]
;
real4
pos
=
posq[i]
;
real4
pos
=
posq[i]
;
pos.x
-=
floor
(
pos.x*invPeriodicBoxSize.x
)
*periodicBoxSize
.x
;
real3
t
=
(
real3
)
(
pos.x*recipBoxVecX.x+pos.y*recipBoxVecY.x+pos.z*recipBoxVecZ
.x
,
pos.y
-=
floor
(
pos.y*invPeriodicBoxSize.y
)
*periodicBoxSize
.y
;
pos.y*recipBoxVecY.y+pos.z*recipBoxVecZ
.y
,
pos.z
-=
floor
(
pos.z*invPeriodicBoxSize.z
)
*periodicBoxSize
.z
;
pos.z*recipBoxVecZ
.z
)
;
real4
t
=
(
real4
)
((
pos.x*invPeriodicBoxSize
.x
)
*GRID_SIZE_X
,
t.x
=
(
t.x-floor
(
t
.x
)
)
*GRID_SIZE_X
;
(
pos.y*invPeriodicBoxSize
.y
)
*GRID_SIZE_Y
,
t.y
=
(
t.y-floor
(
t
.y
)
)
*GRID_SIZE_Y
;
(
pos.z*invPeriodicBoxSize
.z
)
*GRID_SIZE_Z
,
0.0f
)
;
t.z
=
(
t.z-floor
(
t
.z
)
)
*GRID_SIZE_Z
;
real4
dr
=
(
real4
)
(
t.x-
(
int
)
t.x,
t.y-
(
int
)
t.y,
t.z-
(
int
)
t.z,
0.0f
)
;
real4
dr
=
(
real4
)
(
t.x-
(
int
)
t.x,
t.y-
(
int
)
t.y,
t.z-
(
int
)
t.z,
0.0f
)
;
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
((
int
)
t.y
)
%
GRID_SIZE_Y,
((
int
)
t.y
)
%
GRID_SIZE_Y,
...
@@ -41,7 +41,7 @@ __kernel void updateBsplines(__global const real4* restrict posq, __global real4
...
@@ -41,7 +41,7 @@ __kernel void updateBsplines(__global const real4* restrict posq, __global real4
/**
/**
*
For
each
grid
point,
find
the
range
of
sorted
atoms
associated
with
that
point.
*
For
each
grid
point,
find
the
range
of
sorted
atoms
associated
with
that
point.
*/
*/
__kernel
void
findAtomRangeForGrid
(
__global
int2*
restrict
pmeAtomGridIndex,
__global
int*
restrict
pmeAtomRange,
__global
const
real4*
restrict
posq
,
real4
periodicBoxSize,
real4
invPeriodicBoxSize
)
{
__kernel
void
findAtomRangeForGrid
(
__global
int2*
restrict
pmeAtomGridIndex,
__global
int*
restrict
pmeAtomRange,
__global
const
real4*
restrict
posq
)
{
int
start
=
(
NUM_ATOMS*get_global_id
(
0
))
/get_global_size
(
0
)
;
int
start
=
(
NUM_ATOMS*get_global_id
(
0
))
/get_global_size
(
0
)
;
int
end
=
(
NUM_ATOMS*
(
get_global_id
(
0
)
+1
))
/get_global_size
(
0
)
;
int
end
=
(
NUM_ATOMS*
(
get_global_id
(
0
)
+1
))
/get_global_size
(
0
)
;
int
last
=
(
start
==
0
?
-1
:
pmeAtomGridIndex[start-1].y
)
;
int
last
=
(
start
==
0
?
-1
:
pmeAtomGridIndex[start-1].y
)
;
...
@@ -68,13 +68,13 @@ __kernel void findAtomRangeForGrid(__global int2* restrict pmeAtomGridIndex, __g
...
@@ -68,13 +68,13 @@ __kernel void findAtomRangeForGrid(__global int2* restrict pmeAtomGridIndex, __g
*
The
grid
index
won
't
be
needed
again.
Reuse
that
component
to
hold
the
z
index,
thus
saving
*
The
grid
index
won
't
be
needed
again.
Reuse
that
component
to
hold
the
z
index,
thus
saving
*
some
work
in
the
charge
spreading
kernel.
*
some
work
in
the
charge
spreading
kernel.
*/
*/
__kernel
void
recordZIndex
(
__global
int2*
restrict
pmeAtomGridIndex,
__global
const
real4*
restrict
posq,
real4
periodicBoxSize,
real4
invPeriodicBoxSize
)
{
__kernel
void
recordZIndex
(
__global
int2*
restrict
pmeAtomGridIndex,
__global
const
real4*
restrict
posq,
real4
periodicBoxSize,
real4
recipBoxVecZ
)
{
int
start
=
(
NUM_ATOMS*get_global_id
(
0
))
/get_global_size
(
0
)
;
int
start
=
(
NUM_ATOMS*get_global_id
(
0
))
/get_global_size
(
0
)
;
int
end
=
(
NUM_ATOMS*
(
get_global_id
(
0
)
+1
))
/get_global_size
(
0
)
;
int
end
=
(
NUM_ATOMS*
(
get_global_id
(
0
)
+1
))
/get_global_size
(
0
)
;
for
(
int
i
=
start
; i < end; ++i) {
for
(
int
i
=
start
; i < end; ++i) {
real
posz
=
posq[pmeAtomGridIndex[i].x].z
;
real
posz
=
posq[pmeAtomGridIndex[i].x].z
;
posz
-=
floor
(
posz*
invPeriodicBoxSize
.z
)
*periodicBoxSize.z
;
posz
-=
floor
(
posz*
recipBoxVecZ
.z
)
*periodicBoxSize.z
;
int
z
=
((
int
)
((
posz*
invPeriodicBoxSize
.z
)
*GRID_SIZE_Z
))
%
GRID_SIZE_Z
;
int
z
=
((
int
)
((
posz*
recipBoxVecZ
.z
)
*GRID_SIZE_Z
))
%
GRID_SIZE_Z
;
pmeAtomGridIndex[i].y
=
z
;
pmeAtomGridIndex[i].y
=
z
;
}
}
}
}
...
@@ -83,7 +83,7 @@ __kernel void recordZIndex(__global int2* restrict pmeAtomGridIndex, __global co
...
@@ -83,7 +83,7 @@ __kernel void recordZIndex(__global int2* restrict pmeAtomGridIndex, __global co
#
pragma
OPENCL
EXTENSION
cl_khr_int64_base_atomics
:
enable
#
pragma
OPENCL
EXTENSION
cl_khr_int64_base_atomics
:
enable
__kernel
void
gridSpreadCharge
(
__global
const
real4*
restrict
posq,
__global
const
int2*
restrict
pmeAtomGridIndex,
__global
const
int*
restrict
pmeAtomRange,
__kernel
void
gridSpreadCharge
(
__global
const
real4*
restrict
posq,
__global
const
int2*
restrict
pmeAtomGridIndex,
__global
const
int*
restrict
pmeAtomRange,
__global
long*
restrict
pmeGrid,
__global
const
real4*
restrict
pmeBsplineTheta,
real4
periodicBoxSize,
real4
invPeriodicBoxSize
)
{
__global
long*
restrict
pmeGrid,
__global
const
real4*
restrict
pmeBsplineTheta,
real4
periodicBoxSize,
real4
recipBoxVecX,
real4
recipBoxVecY,
real4
recipBoxVecZ
)
{
const
real4
scale
=
1/
(
real
)
(
PME_ORDER-1
)
;
const
real4
scale
=
1/
(
real
)
(
PME_ORDER-1
)
;
real4
data[PME_ORDER]
;
real4
data[PME_ORDER]
;
...
@@ -93,12 +93,15 @@ __kernel void gridSpreadCharge(__global const real4* restrict posq, __global con
...
@@ -93,12 +93,15 @@ __kernel void gridSpreadCharge(__global const real4* restrict posq, __global con
for
(
int
i
=
get_global_id
(
0
)
; i < NUM_ATOMS; i += get_global_size(0)) {
for
(
int
i
=
get_global_id
(
0
)
; i < NUM_ATOMS; i += get_global_size(0)) {
int
atom
=
pmeAtomGridIndex[i].x
;
int
atom
=
pmeAtomGridIndex[i].x
;
real4
pos
=
posq[atom]
;
real4
pos
=
posq[atom]
;
pos.x
-=
floor
(
pos.x*invPeriodicBoxSize.x
)
*periodicBoxSize.x
;
pos.x
-=
floor
(
pos.x*recipBoxVecX.x
)
*periodicBoxSize.x
;
pos.y
-=
floor
(
pos.y*invPeriodicBoxSize.y
)
*periodicBoxSize.y
;
pos.y
-=
floor
(
pos.y*recipBoxVecY.y
)
*periodicBoxSize.y
;
pos.z
-=
floor
(
pos.z*invPeriodicBoxSize.z
)
*periodicBoxSize.z
;
pos.z
-=
floor
(
pos.z*recipBoxVecZ.z
)
*periodicBoxSize.z
;
real4
t
=
(
real4
)
((
pos.x*invPeriodicBoxSize.x
)
*GRID_SIZE_X,
real3
t
=
(
real3
)
(
pos.x*recipBoxVecX.x+pos.y*recipBoxVecY.x+pos.z*recipBoxVecZ.x,
(
pos.y*invPeriodicBoxSize.y
)
*GRID_SIZE_Y,
pos.y*recipBoxVecY.y+pos.z*recipBoxVecZ.y,
(
pos.z*invPeriodicBoxSize.z
)
*GRID_SIZE_Z,
0.0f
)
;
pos.z*recipBoxVecZ.z
)
;
t.x
=
(
t.x-floor
(
t.x
))
*GRID_SIZE_X
;
t.y
=
(
t.y-floor
(
t.y
))
*GRID_SIZE_Y
;
t.z
=
(
t.z-floor
(
t.z
))
*GRID_SIZE_Z
;
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
((
int
)
t.y
)
%
GRID_SIZE_Y,
((
int
)
t.y
)
%
GRID_SIZE_Y,
((
int
)
t.z
)
%
GRID_SIZE_Z,
0
)
;
((
int
)
t.z
)
%
GRID_SIZE_Z,
0
)
;
...
@@ -163,7 +166,7 @@ __kernel void finishSpreadCharge(__global long* restrict pmeGrid) {
...
@@ -163,7 +166,7 @@ __kernel void finishSpreadCharge(__global long* restrict pmeGrid) {
}
}
#
elif
defined
(
DEVICE_IS_CPU
)
#
elif
defined
(
DEVICE_IS_CPU
)
__kernel
void
gridSpreadCharge
(
__global
const
real4*
restrict
posq,
__global
const
int2*
restrict
pmeAtomGridIndex,
__global
const
int*
restrict
pmeAtomRange,
__kernel
void
gridSpreadCharge
(
__global
const
real4*
restrict
posq,
__global
const
int2*
restrict
pmeAtomGridIndex,
__global
const
int*
restrict
pmeAtomRange,
__global
real2*
restrict
pmeGrid,
__global
const
real4*
restrict
pmeBsplineTheta,
real4
periodicBoxSize,
real4
invPeriodicBoxSize
)
{
__global
real2*
restrict
pmeGrid,
__global
const
real4*
restrict
pmeBsplineTheta,
real4
periodicBoxSize,
real4
recipBoxVecX,
real4
recipBoxVecY,
real4
recipBoxVecZ
)
{
const
int
firstx
=
get_global_id
(
0
)
*GRID_SIZE_X/get_global_size
(
0
)
;
const
int
firstx
=
get_global_id
(
0
)
*GRID_SIZE_X/get_global_size
(
0
)
;
const
int
lastx
=
(
get_global_id
(
0
)
+1
)
*GRID_SIZE_X/get_global_size
(
0
)
;
const
int
lastx
=
(
get_global_id
(
0
)
+1
)
*GRID_SIZE_X/get_global_size
(
0
)
;
if
(
firstx
==
lastx
)
if
(
firstx
==
lastx
)
...
@@ -177,12 +180,15 @@ __kernel void gridSpreadCharge(__global const real4* restrict posq, __global con
...
@@ -177,12 +180,15 @@ __kernel void gridSpreadCharge(__global const real4* restrict posq, __global con
for
(
int
i
=
0
; i < NUM_ATOMS; i++) {
for
(
int
i
=
0
; i < NUM_ATOMS; i++) {
int
atom
=
i
;//pmeAtomGridIndex[i].x;
int
atom
=
i
;//pmeAtomGridIndex[i].x;
real4
pos
=
posq[atom]
;
real4
pos
=
posq[atom]
;
pos.x
-=
floor
(
pos.x*invPeriodicBoxSize.x
)
*periodicBoxSize.x
;
pos.x
-=
floor
(
pos.x*recipBoxVecX.x
)
*periodicBoxSize.x
;
pos.y
-=
floor
(
pos.y*invPeriodicBoxSize.y
)
*periodicBoxSize.y
;
pos.y
-=
floor
(
pos.y*recipBoxVecY.y
)
*periodicBoxSize.y
;
pos.z
-=
floor
(
pos.z*invPeriodicBoxSize.z
)
*periodicBoxSize.z
;
pos.z
-=
floor
(
pos.z*recipBoxVecZ.z
)
*periodicBoxSize.z
;
real4
t
=
(
real4
)
((
pos.x*invPeriodicBoxSize.x
)
*GRID_SIZE_X,
real3
t
=
(
real3
)
(
pos.x*recipBoxVecX.x+pos.y*recipBoxVecY.x+pos.z*recipBoxVecZ.x,
(
pos.y*invPeriodicBoxSize.y
)
*GRID_SIZE_Y,
pos.y*recipBoxVecY.y+pos.z*recipBoxVecZ.y,
(
pos.z*invPeriodicBoxSize.z
)
*GRID_SIZE_Z,
0.0f
)
;
pos.z*recipBoxVecZ.z
)
;
t.x
=
(
t.x-floor
(
t.x
))
*GRID_SIZE_X
;
t.y
=
(
t.y-floor
(
t.y
))
*GRID_SIZE_Y
;
t.z
=
(
t.z-floor
(
t.z
))
*GRID_SIZE_Z
;
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
((
int
)
t.y
)
%
GRID_SIZE_Y,
((
int
)
t.y
)
%
GRID_SIZE_Y,
((
int
)
t.z
)
%
GRID_SIZE_Z,
0
)
;
((
int
)
t.z
)
%
GRID_SIZE_Z,
0
)
;
...
@@ -290,7 +296,7 @@ __kernel void gridSpreadCharge(__global const real4* restrict posq, __global con
...
@@ -290,7 +296,7 @@ __kernel void gridSpreadCharge(__global const real4* restrict posq, __global con
#
endif
#
endif
__kernel
void
reciprocalConvolution
(
__global
real2*
restrict
pmeGrid,
__global
real*
restrict
energyBuffer,
__global
const
real*
restrict
pmeBsplineModuliX,
__kernel
void
reciprocalConvolution
(
__global
real2*
restrict
pmeGrid,
__global
real*
restrict
energyBuffer,
__global
const
real*
restrict
pmeBsplineModuliX,
__global
const
real*
restrict
pmeBsplineModuliY,
__global
const
real*
restrict
pmeBsplineModuliZ,
real4
invPeriodicBoxSize
,
real
recipScaleFactor
)
{
__global
const
real*
restrict
pmeBsplineModuliY,
__global
const
real*
restrict
pmeBsplineModuliZ,
real4
recipBoxVecX,
real4
recipBoxVecY,
real4
recipBoxVecZ
,
real
recipScaleFactor
)
{
const
unsigned
int
gridSize
=
GRID_SIZE_X*GRID_SIZE_Y*GRID_SIZE_Z
;
const
unsigned
int
gridSize
=
GRID_SIZE_X*GRID_SIZE_Y*GRID_SIZE_Z
;
real
energy
=
0.0f
;
real
energy
=
0.0f
;
for
(
int
index
=
get_global_id
(
0
)
; index < gridSize; index += get_global_size(0)) {
for
(
int
index
=
get_global_id
(
0
)
; index < gridSize; index += get_global_size(0)) {
...
@@ -303,9 +309,9 @@ __kernel void reciprocalConvolution(__global real2* restrict pmeGrid, __global r
...
@@ -303,9 +309,9 @@ __kernel void reciprocalConvolution(__global real2* restrict pmeGrid, __global r
int
mx
=
(
kx
<
(
GRID_SIZE_X+1
)
/2
)
?
kx
:
(
kx-GRID_SIZE_X
)
;
int
mx
=
(
kx
<
(
GRID_SIZE_X+1
)
/2
)
?
kx
:
(
kx-GRID_SIZE_X
)
;
int
my
=
(
ky
<
(
GRID_SIZE_Y+1
)
/2
)
?
ky
:
(
ky-GRID_SIZE_Y
)
;
int
my
=
(
ky
<
(
GRID_SIZE_Y+1
)
/2
)
?
ky
:
(
ky-GRID_SIZE_Y
)
;
int
mz
=
(
kz
<
(
GRID_SIZE_Z+1
)
/2
)
?
kz
:
(
kz-GRID_SIZE_Z
)
;
int
mz
=
(
kz
<
(
GRID_SIZE_Z+1
)
/2
)
?
kz
:
(
kz-GRID_SIZE_Z
)
;
real
mhx
=
mx*
invPeriodicBoxSize
.x
;
real
mhx
=
mx*
recipBoxVecX
.x
;
real
mhy
=
m
y*invPeriodicBoxSize
.y
;
real
mhy
=
m
x*recipBoxVecY.x+my*recipBoxVecY
.y
;
real
mhz
=
m
z*invPeriodicBoxSize
.z
;
real
mhz
=
m
x*recipBoxVecZ.x+my*recipBoxVecZ.y+mz*recipBoxVecZ
.z
;
real
bx
=
pmeBsplineModuliX[kx]
;
real
bx
=
pmeBsplineModuliX[kx]
;
real
by
=
pmeBsplineModuliY[ky]
;
real
by
=
pmeBsplineModuliY[ky]
;
real
bz
=
pmeBsplineModuliZ[kz]
;
real
bz
=
pmeBsplineModuliZ[kz]
;
...
@@ -320,7 +326,7 @@ __kernel void reciprocalConvolution(__global real2* restrict pmeGrid, __global r
...
@@ -320,7 +326,7 @@ __kernel void reciprocalConvolution(__global real2* restrict pmeGrid, __global r
}
}
__kernel
void
gridInterpolateForce
(
__global
const
real4*
restrict
posq,
__global
real4*
restrict
forceBuffers,
__global
const
real2*
restrict
pmeGrid,
__kernel
void
gridInterpolateForce
(
__global
const
real4*
restrict
posq,
__global
real4*
restrict
forceBuffers,
__global
const
real2*
restrict
pmeGrid,
real4
periodicBoxSize,
real4
invPeriodicBoxSize
,
__global
int2*
restrict
pmeAtomGridIndex
)
{
real4
periodicBoxSize,
real4
recipBoxVecX,
real4
recipBoxVecY,
real4
recipBoxVecZ
,
__global
int2*
restrict
pmeAtomGridIndex
)
{
const
real4
scale
=
1/
(
real
)
(
PME_ORDER-1
)
;
const
real4
scale
=
1/
(
real
)
(
PME_ORDER-1
)
;
real4
data[PME_ORDER]
;
real4
data[PME_ORDER]
;
real4
ddata[PME_ORDER]
;
real4
ddata[PME_ORDER]
;
...
@@ -332,12 +338,15 @@ __kernel void gridInterpolateForce(__global const real4* restrict posq, __global
...
@@ -332,12 +338,15 @@ __kernel void gridInterpolateForce(__global const real4* restrict posq, __global
int
atom
=
pmeAtomGridIndex[i].x
;
int
atom
=
pmeAtomGridIndex[i].x
;
real4
force
=
0.0f
;
real4
force
=
0.0f
;
real4
pos
=
posq[atom]
;
real4
pos
=
posq[atom]
;
pos.x
-=
floor
(
pos.x*invPeriodicBoxSize.x
)
*periodicBoxSize.x
;
pos.x
-=
floor
(
pos.x*recipBoxVecX.x
)
*periodicBoxSize.x
;
pos.y
-=
floor
(
pos.y*invPeriodicBoxSize.y
)
*periodicBoxSize.y
;
pos.y
-=
floor
(
pos.y*recipBoxVecY.y
)
*periodicBoxSize.y
;
pos.z
-=
floor
(
pos.z*invPeriodicBoxSize.z
)
*periodicBoxSize.z
;
pos.z
-=
floor
(
pos.z*recipBoxVecZ.z
)
*periodicBoxSize.z
;
real4
t
=
(
real4
)
((
pos.x*invPeriodicBoxSize.x
)
*GRID_SIZE_X,
real3
t
=
(
real3
)
(
pos.x*recipBoxVecX.x+pos.y*recipBoxVecY.x+pos.z*recipBoxVecZ.x,
(
pos.y*invPeriodicBoxSize.y
)
*GRID_SIZE_Y,
pos.y*recipBoxVecY.y+pos.z*recipBoxVecZ.y,
(
pos.z*invPeriodicBoxSize.z
)
*GRID_SIZE_Z,
0.0f
)
;
pos.z*recipBoxVecZ.z
)
;
t.x
=
(
t.x-floor
(
t.x
))
*GRID_SIZE_X
;
t.y
=
(
t.y-floor
(
t.y
))
*GRID_SIZE_Y
;
t.z
=
(
t.z-floor
(
t.z
))
*GRID_SIZE_Z
;
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
int4
gridIndex
=
(
int4
)
(((
int
)
t.x
)
%
GRID_SIZE_X,
((
int
)
t.y
)
%
GRID_SIZE_Y,
((
int
)
t.y
)
%
GRID_SIZE_Y,
((
int
)
t.z
)
%
GRID_SIZE_Z,
0
)
;
((
int
)
t.z
)
%
GRID_SIZE_Z,
0
)
;
...
@@ -385,9 +394,9 @@ __kernel void gridInterpolateForce(__global const real4* restrict posq, __global
...
@@ -385,9 +394,9 @@ __kernel void gridInterpolateForce(__global const real4* restrict posq, __global
}
}
real4
totalForce
=
forceBuffers[atom]
;
real4
totalForce
=
forceBuffers[atom]
;
real
q
=
pos.w*EPSILON_FACTOR
;
real
q
=
pos.w*EPSILON_FACTOR
;
totalForce.x
-=
q*force.x*GRID_SIZE_X*
invPeriodicBoxSize
.x
;
totalForce.x
-=
q*
(
force.x*GRID_SIZE_X*
recipBoxVecX
.x
)
;
totalForce.y
-=
q*force.y*GRID_SIZE_Y*
invPeriodicBoxSize
.y
;
totalForce.y
-=
q*
(
force.x*GRID_SIZE_X*recipBoxVecY.x+
force.y*GRID_SIZE_Y*
recipBoxVecY
.y
)
;
totalForce.z
-=
q*force.
z
*GRID_SIZE_
Z*invPeriodicBoxSize
.z
;
totalForce.z
-=
q*
(
force.
x
*GRID_SIZE_
X*recipBoxVecZ.x+force.y*GRID_SIZE_Y*recipBoxVecZ.y+force.z*GRID_SIZE_Z*recipBoxVecZ
.z
)
;
forceBuffers[atom]
=
totalForce
;
forceBuffers[atom]
=
totalForce
;
}
}
}
}
...
...
platforms/opencl/tests/TestOpenCLCustomManyParticleForce.cpp
View file @
83ed602e
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2014 Stanford University and the Authors.
*
* Portions copyright (c) 2014
-2015
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -55,7 +55,17 @@ const double TOL = 1e-5;
...
@@ -55,7 +55,17 @@ const double TOL = 1e-5;
OpenCLPlatform
platform
;
OpenCLPlatform
platform
;
void
validateAxilrodTeller
(
CustomManyParticleForce
*
force
,
const
vector
<
Vec3
>&
positions
,
const
vector
<
const
int
*>&
expectedSets
,
double
boxSize
)
{
Vec3
computeDelta
(
const
Vec3
&
pos1
,
const
Vec3
&
pos2
,
bool
periodic
,
const
Vec3
*
periodicBoxVectors
)
{
Vec3
diff
=
pos1
-
pos2
;
if
(
periodic
)
{
diff
-=
periodicBoxVectors
[
2
]
*
floor
(
diff
[
2
]
/
periodicBoxVectors
[
2
][
2
]
+
0.5
);
diff
-=
periodicBoxVectors
[
1
]
*
floor
(
diff
[
1
]
/
periodicBoxVectors
[
1
][
1
]
+
0.5
);
diff
-=
periodicBoxVectors
[
0
]
*
floor
(
diff
[
0
]
/
periodicBoxVectors
[
0
][
0
]
+
0.5
);
}
return
diff
;
}
void
validateAxilrodTeller
(
CustomManyParticleForce
*
force
,
const
vector
<
Vec3
>&
positions
,
const
vector
<
const
int
*>&
expectedSets
,
double
boxSize
,
bool
triclinic
)
{
// Create a System and Context.
// Create a System and Context.
int
numParticles
=
force
->
getNumParticles
();
int
numParticles
=
force
->
getNumParticles
();
...
@@ -63,7 +73,18 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
...
@@ -63,7 +73,18 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
System
system
;
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
Vec3
boxVectors
[
3
];
if
(
triclinic
)
{
boxVectors
[
0
]
=
Vec3
(
boxSize
,
0
,
0
);
boxVectors
[
1
]
=
Vec3
(
0.2
*
boxSize
,
boxSize
,
0
);
boxVectors
[
2
]
=
Vec3
(
-
0.3
*
boxSize
,
-
0.1
*
boxSize
,
boxSize
);
}
else
{
boxVectors
[
0
]
=
Vec3
(
boxSize
,
0
,
0
);
boxVectors
[
1
]
=
Vec3
(
0
,
boxSize
,
0
);
boxVectors
[
2
]
=
Vec3
(
0
,
0
,
boxSize
);
}
system
.
setDefaultPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
system
.
addForce
(
force
);
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
VerletIntegrator
integrator
(
0.001
);
Context
context
(
system
,
integrator
,
platform
);
Context
context
(
system
,
integrator
,
platform
);
...
@@ -74,20 +95,14 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
...
@@ -74,20 +95,14 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
// See if the energy matches the expected value.
// See if the energy matches the expected value.
double
expectedEnergy
=
0
;
double
expectedEnergy
=
0
;
bool
periodic
=
(
nonbondedMethod
==
CustomManyParticleForce
::
CutoffPeriodic
);
for
(
int
i
=
0
;
i
<
(
int
)
expectedSets
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
expectedSets
.
size
();
i
++
)
{
int
p1
=
expectedSets
[
i
][
0
];
int
p1
=
expectedSets
[
i
][
0
];
int
p2
=
expectedSets
[
i
][
1
];
int
p2
=
expectedSets
[
i
][
1
];
int
p3
=
expectedSets
[
i
][
2
];
int
p3
=
expectedSets
[
i
][
2
];
Vec3
d12
=
positions
[
p2
]
-
positions
[
p1
];
Vec3
d12
=
computeDelta
(
positions
[
p2
],
positions
[
p1
],
periodic
,
boxVectors
);
Vec3
d13
=
positions
[
p3
]
-
positions
[
p1
];
Vec3
d13
=
computeDelta
(
positions
[
p3
],
positions
[
p1
],
periodic
,
boxVectors
);
Vec3
d23
=
positions
[
p3
]
-
positions
[
p2
];
Vec3
d23
=
computeDelta
(
positions
[
p3
],
positions
[
p2
],
periodic
,
boxVectors
);
if
(
nonbondedMethod
==
CustomManyParticleForce
::
CutoffPeriodic
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
d12
[
j
]
-=
floor
(
d12
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
d13
[
j
]
-=
floor
(
d13
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
d23
[
j
]
-=
floor
(
d23
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
}
}
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
...
@@ -210,7 +225,7 @@ void testNoCutoff() {
...
@@ -210,7 +225,7 @@ void testNoCutoff() {
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
int
sets
[
4
][
3
]
=
{{
0
,
1
,
2
},
{
1
,
2
,
3
},
{
2
,
3
,
0
},
{
3
,
0
,
1
}};
int
sets
[
4
][
3
]
=
{{
0
,
1
,
2
},
{
1
,
2
,
3
},
{
2
,
3
,
0
},
{
3
,
0
,
1
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
}
void
testCutoff
()
{
void
testCutoff
()
{
...
@@ -235,7 +250,7 @@ void testCutoff() {
...
@@ -235,7 +250,7 @@ void testCutoff() {
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
int
sets
[
7
][
3
]
=
{{
0
,
1
,
2
},
{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
2
,
4
},
{
1
,
3
,
4
}};
int
sets
[
7
][
3
]
=
{{
0
,
1
,
2
},
{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
2
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
7
]);
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
7
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
}
void
testPeriodic
()
{
void
testPeriodic
()
{
...
@@ -261,7 +276,33 @@ void testPeriodic() {
...
@@ -261,7 +276,33 @@ void testPeriodic() {
double
boxSize
=
2.1
;
double
boxSize
=
2.1
;
int
sets
[
5
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
3
,
4
}};
int
sets
[
5
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
boxSize
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
boxSize
,
false
);
}
void
testTriclinic
()
{
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*(1+3*cos(theta1)*cos(theta2)*cos(theta3))/(r12*r13*r23)^3;"
"theta1=angle(p1,p2,p3); theta2=angle(p2,p3,p1); theta3=angle(p3,p1,p2);"
"r12=distance(p1,p2); r13=distance(p1,p3); r23=distance(p2,p3)"
);
force
->
addGlobalParameter
(
"C"
,
1.5
);
force
->
setNonbondedMethod
(
CustomManyParticleForce
::
CutoffPeriodic
);
force
->
setCutoffDistance
(
1.05
);
vector
<
double
>
params
;
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
vector
<
Vec3
>
positions
;
positions
.
push_back
(
Vec3
(
0
,
0
,
0
));
positions
.
push_back
(
Vec3
(
1
,
0
,
0
));
positions
.
push_back
(
Vec3
(
0
,
1.1
,
0.3
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
double
boxSize
=
2.1
;
int
sets
[
4
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
3
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
boxSize
,
true
);
}
}
void
testExclusions
()
{
void
testExclusions
()
{
...
@@ -286,7 +327,7 @@ void testExclusions() {
...
@@ -286,7 +327,7 @@ void testExclusions() {
force
->
addExclusion
(
0
,
3
);
force
->
addExclusion
(
0
,
3
);
int
sets
[
5
][
3
]
=
{{
0
,
1
,
4
},
{
1
,
2
,
3
},
{
1
,
2
,
4
},
{
1
,
3
,
4
},
{
2
,
3
,
4
}};
int
sets
[
5
][
3
]
=
{{
0
,
1
,
4
},
{
1
,
2
,
3
},
{
1
,
2
,
4
},
{
1
,
3
,
4
},
{
2
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
}
void
testAllTerms
()
{
void
testAllTerms
()
{
...
@@ -672,6 +713,7 @@ int main(int argc, char* argv[]) {
...
@@ -672,6 +713,7 @@ int main(int argc, char* argv[]) {
testNoCutoff
();
testNoCutoff
();
testCutoff
();
testCutoff
();
testPeriodic
();
testPeriodic
();
testTriclinic
();
testExclusions
();
testExclusions
();
testAllTerms
();
testAllTerms
();
testParameters
();
testParameters
();
...
...
platforms/opencl/tests/TestOpenCLCustomNonbondedForce.cpp
View file @
83ed602e
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
4
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -261,6 +261,65 @@ void testPeriodic() {
...
@@ -261,6 +261,65 @@ void testPeriodic() {
ASSERT_EQUAL_TOL
(
1.9
+
1
+
0.9
,
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_TOL
(
1.9
+
1
+
0.9
,
state
.
getPotentialEnergy
(),
TOL
);
}
}
void
testTriclinic
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
Vec3
a
(
3.1
,
0
,
0
);
Vec3
b
(
0.4
,
3.5
,
0
);
Vec3
c
(
-
0.1
,
-
0.5
,
4.0
);
system
.
setDefaultPeriodicBoxVectors
(
a
,
b
,
c
);
VerletIntegrator
integrator
(
0.01
);
CustomNonbondedForce
*
nonbonded
=
new
CustomNonbondedForce
(
"r"
);
nonbonded
->
addParticle
(
vector
<
double
>
());
nonbonded
->
addParticle
(
vector
<
double
>
());
nonbonded
->
setNonbondedMethod
(
CustomNonbondedForce
::
CutoffPeriodic
);
const
double
cutoff
=
1.5
;
nonbonded
->
setCutoffDistance
(
cutoff
);
system
.
addForce
(
nonbonded
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
iteration
=
0
;
iteration
<
50
;
iteration
++
)
{
// Generate random positions for the two particles.
positions
[
0
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
positions
[
1
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
context
.
setPositions
(
positions
);
// Loop over all possible periodic copies and find the nearest one.
Vec3
delta
;
double
distance2
=
100.0
;
for
(
int
i
=
-
1
;
i
<
2
;
i
++
)
for
(
int
j
=
-
1
;
j
<
2
;
j
++
)
for
(
int
k
=
-
1
;
k
<
2
;
k
++
)
{
Vec3
d
=
positions
[
1
]
-
positions
[
0
]
+
a
*
i
+
b
*
j
+
c
*
k
;
if
(
d
.
dot
(
d
)
<
distance2
)
{
delta
=
d
;
distance2
=
d
.
dot
(
d
);
}
}
double
distance
=
sqrt
(
distance2
);
// See if the force and energy are correct.
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
if
(
distance
>=
cutoff
)
{
ASSERT_EQUAL
(
0.0
,
state
.
getPotentialEnergy
());
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
0
],
0
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
1
],
0
);
}
else
{
const
Vec3
force
=
delta
/
sqrt
(
delta
.
dot
(
delta
));
ASSERT_EQUAL_TOL
(
distance
,
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_VEC
(
force
,
state
.
getForces
()[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
-
force
,
state
.
getForces
()[
1
],
TOL
);
}
}
}
void
testContinuous1DFunction
()
{
void
testContinuous1DFunction
()
{
System
system
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
...
@@ -924,6 +983,7 @@ int main(int argc, char* argv[]) {
...
@@ -924,6 +983,7 @@ int main(int argc, char* argv[]) {
testExclusions
();
testExclusions
();
testCutoff
();
testCutoff
();
testPeriodic
();
testPeriodic
();
testTriclinic
();
testContinuous1DFunction
();
testContinuous1DFunction
();
testContinuous2DFunction
();
testContinuous2DFunction
();
testContinuous3DFunction
();
testContinuous3DFunction
();
...
...
platforms/opencl/tests/TestOpenCLEwald.cpp
View file @
83ed602e
...
@@ -201,6 +201,57 @@ void testEwald2Ions() {
...
@@ -201,6 +201,57 @@ void testEwald2Ions() {
ASSERT_EQUAL_TOL
(
-
217.276
,
state
.
getPotentialEnergy
(),
0.01
/*10*TOL*/
);
ASSERT_EQUAL_TOL
(
-
217.276
,
state
.
getPotentialEnergy
(),
0.01
/*10*TOL*/
);
}
}
void
testTriclinic
()
{
// Create a triclinic box containing eight particles.
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
2.5
,
0
,
0
),
Vec3
(
0.5
,
3.0
,
0
),
Vec3
(
0.7
,
0.9
,
3.5
));
for
(
int
i
=
0
;
i
<
8
;
i
++
)
system
.
addParticle
(
1.0
);
NonbondedForce
*
force
=
new
NonbondedForce
();
system
.
addForce
(
force
);
force
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
force
->
setCutoffDistance
(
1.0
);
force
->
setPMEParameters
(
3.45891
,
32
,
40
,
48
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
force
->
addParticle
(
-
1
,
0.440104
,
0.4184
);
// Cl parameters
for
(
int
i
=
0
;
i
<
4
;
i
++
)
force
->
addParticle
(
1
,
0.332840
,
0.0115897
);
// Na parameters
vector
<
Vec3
>
positions
(
8
);
positions
[
0
]
=
Vec3
(
1.744
,
2.788
,
3.162
);
positions
[
1
]
=
Vec3
(
1.048
,
0.762
,
2.340
);
positions
[
2
]
=
Vec3
(
2.489
,
1.570
,
2.817
);
positions
[
3
]
=
Vec3
(
1.027
,
1.893
,
3.271
);
positions
[
4
]
=
Vec3
(
0.937
,
0.825
,
0.009
);
positions
[
5
]
=
Vec3
(
2.290
,
1.887
,
3.352
);
positions
[
6
]
=
Vec3
(
1.266
,
1.111
,
2.894
);
positions
[
7
]
=
Vec3
(
0.933
,
1.862
,
3.490
);
// Compute the forces and energy.
VerletIntegrator
integ
(
0.001
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
// Compare them to values computed by Gromacs.
double
expectedEnergy
=
-
963.370
;
vector
<
Vec3
>
expectedForce
(
8
);
expectedForce
[
0
]
=
Vec3
(
4.25253e+01
,
-
1.23503e+02
,
1.22139e+02
);
expectedForce
[
1
]
=
Vec3
(
9.74752e+01
,
1.68213e+02
,
1.93169e+02
);
expectedForce
[
2
]
=
Vec3
(
-
1.50348e+02
,
1.29165e+02
,
3.70435e+02
);
expectedForce
[
3
]
=
Vec3
(
9.18644e+02
,
-
3.52571e+00
,
-
1.34772e+03
);
expectedForce
[
4
]
=
Vec3
(
-
1.61193e+02
,
9.01528e+01
,
-
7.12904e+01
);
expectedForce
[
5
]
=
Vec3
(
2.82630e+02
,
2.78029e+01
,
-
3.72864e+02
);
expectedForce
[
6
]
=
Vec3
(
-
1.47454e+02
,
-
2.14448e+02
,
-
3.55789e+02
);
expectedForce
[
7
]
=
Vec3
(
-
8.82195e+02
,
-
7.39132e+01
,
1.46202e+03
);
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
ASSERT_EQUAL_VEC
(
expectedForce
[
i
],
state
.
getForces
()[
i
],
1e-4
);
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-4
);
}
void
testErrorTolerance
(
NonbondedForce
::
NonbondedMethod
method
)
{
void
testErrorTolerance
(
NonbondedForce
::
NonbondedMethod
method
)
{
// Create a cloud of random point charges.
// Create a cloud of random point charges.
...
@@ -307,6 +358,7 @@ int main(int argc, char* argv[]) {
...
@@ -307,6 +358,7 @@ int main(int argc, char* argv[]) {
testEwaldPME
(
false
);
testEwaldPME
(
false
);
testEwaldPME
(
true
);
testEwaldPME
(
true
);
// testEwald2Ions();
// testEwald2Ions();
testTriclinic
();
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
PME
);
testErrorTolerance
(
NonbondedForce
::
PME
);
testPMEParameters
();
testPMEParameters
();
...
...
platforms/opencl/tests/TestOpenCLMonteCarloAnisotropicBarostat.cpp
View file @
83ed602e
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman, Lee-Ping Wang *
* Authors: Peter Eastman, Lee-Ping Wang *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -236,6 +236,82 @@ void testRandomSeed() {
...
@@ -236,6 +236,82 @@ void testRandomSeed() {
}
}
}
}
void
testTriclinic
()
{
const
int
numParticles
=
64
;
const
int
frequency
=
10
;
const
int
steps
=
1000
;
const
double
pressure
=
1.5
;
const
double
pressureInMD
=
pressure
*
(
AVOGADRO
*
1e-25
);
// pressure in kJ/mol/nm^3
const
double
temperature
=
300.0
;
const
double
initialVolume
=
numParticles
*
BOLTZ
*
temperature
/
pressureInMD
;
const
double
initialLength
=
std
::
pow
(
initialVolume
,
1.0
/
3.0
);
// Create a gas of noninteracting particles.
System
system
;
Vec3
initialBox
[
3
];
initialBox
[
0
]
=
Vec3
(
initialLength
,
0
,
0
);
initialBox
[
1
]
=
Vec3
(
0.2
*
initialLength
,
initialLength
,
0
);
initialBox
[
2
]
=
Vec3
(
0.1
*
initialLength
,
0.3
*
initialLength
,
initialLength
);
system
.
setDefaultPeriodicBoxVectors
(
initialBox
[
0
],
initialBox
[
1
],
initialBox
[
2
]);
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
1.0
);
positions
[
i
]
=
Vec3
(
initialLength
*
genrand_real2
(
sfmt
),
initialLength
*
genrand_real2
(
sfmt
),
initialLength
*
genrand_real2
(
sfmt
));
}
MonteCarloAnisotropicBarostat
*
barostat
=
new
MonteCarloAnisotropicBarostat
(
Vec3
(
pressure
,
pressure
,
pressure
),
temperature
,
true
,
true
,
true
,
frequency
);
system
.
addForce
(
barostat
);
// Run a simulation
LangevinIntegrator
integrator
(
temperature
,
0.1
,
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
10000
);
// Now run it for a while and see if the volume is correct.
double
volume
=
0.0
;
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
}
volume
/=
steps
;
double
expected
=
(
numParticles
+
1
)
*
BOLTZ
*
temperature
/
pressureInMD
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
volume
,
3
/
std
::
sqrt
((
double
)
steps
));
// Make sure the box vectors have been scaled consistently.
State
state
=
context
.
getState
(
State
::
Positions
);
Vec3
box
[
3
];
state
.
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
double
xscale
=
box
[
2
][
0
]
/
(
0.1
*
initialLength
);
double
yscale
=
box
[
2
][
1
]
/
(
0.3
*
initialLength
);
double
zscale
=
box
[
2
][
2
]
/
(
1.0
*
initialLength
);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
ASSERT_EQUAL_VEC
(
Vec3
(
xscale
*
initialBox
[
i
][
0
],
yscale
*
initialBox
[
i
][
1
],
zscale
*
initialBox
[
i
][
2
]),
box
[
i
],
1e-5
);
}
// The barostat should have put all particles inside the first periodic box. One integration step
// has happened since then, so they may have moved slightly outside it.
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
Vec3
pos
=
state
.
getPositions
()[
i
];
ASSERT
(
pos
[
2
]
/
box
[
2
][
2
]
>
-
1
&&
pos
[
2
]
/
box
[
2
][
2
]
<
2
);
pos
-=
box
[
2
]
*
floor
(
pos
[
2
]
/
box
[
2
][
2
]);
ASSERT
(
pos
[
1
]
/
box
[
1
][
1
]
>
-
1
&&
pos
[
1
]
/
box
[
1
][
1
]
<
2
);
pos
-=
box
[
1
]
*
floor
(
pos
[
1
]
/
box
[
1
][
1
]);
ASSERT
(
pos
[
0
]
/
box
[
0
][
0
]
>
-
1
&&
pos
[
0
]
/
box
[
0
][
0
]
<
2
);
}
}
/**
/**
* Run a constant pressure simulation on an anisotropic Einstein crystal
* Run a constant pressure simulation on an anisotropic Einstein crystal
* using isotropic and anisotropic barostats. There are a total of 15 simulations:
* using isotropic and anisotropic barostats. There are a total of 15 simulations:
...
@@ -389,6 +465,7 @@ int main(int argc, char* argv[]) {
...
@@ -389,6 +465,7 @@ int main(int argc, char* argv[]) {
testIdealGasAxis
(
1
);
testIdealGasAxis
(
1
);
testIdealGasAxis
(
2
);
testIdealGasAxis
(
2
);
testRandomSeed
();
testRandomSeed
();
testTriclinic
();
//testEinsteinCrystal();
//testEinsteinCrystal();
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
...
...
platforms/opencl/tests/TestOpenCLNonbondedForce.cpp
View file @
83ed602e
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -355,6 +355,67 @@ void testPeriodic() {
...
@@ -355,6 +355,67 @@ void testPeriodic() {
ASSERT_EQUAL_TOL
(
2
*
ONE_4PI_EPS0
*
(
1.0
)
*
(
1.0
+
krf
*
1.0
-
crf
),
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_TOL
(
2
*
ONE_4PI_EPS0
*
(
1.0
)
*
(
1.0
+
krf
*
1.0
-
crf
),
state
.
getPotentialEnergy
(),
TOL
);
}
}
void
testTriclinic
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
Vec3
a
(
3.1
,
0
,
0
);
Vec3
b
(
0.4
,
3.5
,
0
);
Vec3
c
(
-
0.1
,
-
0.5
,
4.0
);
system
.
setDefaultPeriodicBoxVectors
(
a
,
b
,
c
);
VerletIntegrator
integrator
(
0.01
);
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
nonbonded
->
addParticle
(
1.0
,
1
,
0
);
nonbonded
->
addParticle
(
1.0
,
1
,
0
);
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
const
double
cutoff
=
1.5
;
nonbonded
->
setCutoffDistance
(
cutoff
);
system
.
addForce
(
nonbonded
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
const
double
eps
=
78.3
;
const
double
krf
=
(
1.0
/
(
cutoff
*
cutoff
*
cutoff
))
*
(
eps
-
1.0
)
/
(
2.0
*
eps
+
1.0
);
const
double
crf
=
(
1.0
/
cutoff
)
*
(
3.0
*
eps
)
/
(
2.0
*
eps
+
1.0
);
for
(
int
iteration
=
0
;
iteration
<
50
;
iteration
++
)
{
// Generate random positions for the two particles.
positions
[
0
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
positions
[
1
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
context
.
setPositions
(
positions
);
// Loop over all possible periodic copies and find the nearest one.
Vec3
delta
;
double
distance2
=
100.0
;
for
(
int
i
=
-
1
;
i
<
2
;
i
++
)
for
(
int
j
=
-
1
;
j
<
2
;
j
++
)
for
(
int
k
=
-
1
;
k
<
2
;
k
++
)
{
Vec3
d
=
positions
[
1
]
-
positions
[
0
]
+
a
*
i
+
b
*
j
+
c
*
k
;
if
(
d
.
dot
(
d
)
<
distance2
)
{
delta
=
d
;
distance2
=
d
.
dot
(
d
);
}
}
double
distance
=
sqrt
(
distance2
);
// See if the force and energy are correct.
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
if
(
distance
>=
cutoff
)
{
ASSERT_EQUAL
(
0.0
,
state
.
getPotentialEnergy
());
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
0
],
0
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
1
],
0
);
}
else
{
const
Vec3
force
=
delta
*
ONE_4PI_EPS0
*
(
-
1.0
/
(
distance
*
distance
*
distance
)
+
2.0
*
krf
);
ASSERT_EQUAL_TOL
(
ONE_4PI_EPS0
*
(
1.0
/
distance
+
krf
*
distance
*
distance
-
crf
),
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_VEC
(
force
,
state
.
getForces
()[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
-
force
,
state
.
getForces
()[
1
],
TOL
);
}
}
}
void
testLargeSystem
()
{
void
testLargeSystem
()
{
const
int
numMolecules
=
600
;
const
int
numMolecules
=
600
;
...
@@ -865,6 +926,33 @@ void testSwitchingFunction(NonbondedForce::NonbondedMethod method) {
...
@@ -865,6 +926,33 @@ void testSwitchingFunction(NonbondedForce::NonbondedMethod method) {
}
}
}
}
void
testReordering
()
{
// Check that reordering of atoms doesn't alter their positions.
const
int
numParticles
=
200
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
6
,
0
,
0
),
Vec3
(
2.1
,
6
,
0
),
Vec3
(
-
1.5
,
-
0.5
,
6
));
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
system
.
addForce
(
nonbonded
);
vector
<
Vec3
>
positions
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
0.0
,
0.0
,
0.0
);
positions
.
push_back
(
Vec3
(
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
)
*
20
);
}
VerletIntegrator
integrator
(
0.001
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
positions
[
i
],
state
.
getPositions
()[
i
],
1e-6
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
try
{
if
(
argc
>
1
)
if
(
argc
>
1
)
...
@@ -875,6 +963,7 @@ int main(int argc, char* argv[]) {
...
@@ -875,6 +963,7 @@ int main(int argc, char* argv[]) {
testCutoff
();
testCutoff
();
testCutoff14
();
testCutoff14
();
testPeriodic
();
testPeriodic
();
testTriclinic
();
testLargeSystem
();
testLargeSystem
();
// testBlockInteractions(false);
// testBlockInteractions(false);
// testBlockInteractions(true);
// testBlockInteractions(true);
...
@@ -885,6 +974,7 @@ int main(int argc, char* argv[]) {
...
@@ -885,6 +974,7 @@ int main(int argc, char* argv[]) {
testParallelComputation
(
NonbondedForce
::
PME
);
testParallelComputation
(
NonbondedForce
::
PME
);
testSwitchingFunction
(
NonbondedForce
::
CutoffNonPeriodic
);
testSwitchingFunction
(
NonbondedForce
::
CutoffNonPeriodic
);
testSwitchingFunction
(
NonbondedForce
::
PME
);
testSwitchingFunction
(
NonbondedForce
::
PME
);
testReordering
();
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
platforms/reference/include/GBVIParameters.h
View file @
83ed602e
...
@@ -65,7 +65,7 @@ class GBVIParameters {
...
@@ -65,7 +65,7 @@ class GBVIParameters {
bool
_cutoff
;
bool
_cutoff
;
bool
_periodic
;
bool
_periodic
;
Real
OpenMM
_periodicBox
Size
[
3
];
OpenMM
::
RealVec
_periodicBox
Vectors
[
3
];
RealOpenMM
_cutoffDistance
;
RealOpenMM
_cutoffDistance
;
int
_bornRadiusScalingMethod
;
int
_bornRadiusScalingMethod
;
...
@@ -244,11 +244,11 @@ class GBVIParameters {
...
@@ -244,11 +244,11 @@ class GBVIParameters {
already been set, and the smallest side of the periodic box is at least twice the cutoff
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
vectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
*
vectors
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -264,7 +264,7 @@ class GBVIParameters {
...
@@ -264,7 +264,7 @@ class GBVIParameters {
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
const
Real
OpenMM
*
getPeriodicBox
();
const
OpenMM
::
RealVec
*
getPeriodicBox
();
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
...
platforms/reference/include/ObcParameters.h
View file @
83ed602e
...
@@ -64,7 +64,7 @@ class ObcParameters {
...
@@ -64,7 +64,7 @@ class ObcParameters {
bool
_cutoff
;
bool
_cutoff
;
bool
_periodic
;
bool
_periodic
;
Real
OpenMM
_periodicBox
Size
[
3
];
OpenMM
::
RealVec
_periodicBox
Vectors
[
3
];
RealOpenMM
_cutoffDistance
;
RealOpenMM
_cutoffDistance
;
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -329,11 +329,11 @@ class ObcParameters {
...
@@ -329,11 +329,11 @@ class ObcParameters {
already been set, and the smallest side of the periodic box is at least twice the cutoff
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
vectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
const
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
*
vectors
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -345,11 +345,11 @@ class ObcParameters {
...
@@ -345,11 +345,11 @@ class ObcParameters {
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Get the periodic box
dimension
Get the periodic box
vectors
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
const
Real
OpenMM
*
getPeriodicBox
();
const
OpenMM
::
RealVec
*
getPeriodicBox
();
};
};
...
...
platforms/reference/include/ReferenceCustomGBIxn.h
View file @
83ed602e
...
@@ -41,7 +41,7 @@ class ReferenceCustomGBIxn {
...
@@ -41,7 +41,7 @@ class ReferenceCustomGBIxn {
bool
cutoff
;
bool
cutoff
;
bool
periodic
;
bool
periodic
;
const
OpenMM
::
NeighborList
*
neighborList
;
const
OpenMM
::
NeighborList
*
neighborList
;
Real
OpenMM
periodicBox
Size
[
3
];
OpenMM
::
RealVec
periodicBox
Vectors
[
3
];
RealOpenMM
cutoffDistance
;
RealOpenMM
cutoffDistance
;
std
::
vector
<
Lepton
::
ExpressionProgram
>
valueExpressions
;
std
::
vector
<
Lepton
::
ExpressionProgram
>
valueExpressions
;
std
::
vector
<
std
::
vector
<
Lepton
::
ExpressionProgram
>
>
valueDerivExpressions
;
std
::
vector
<
std
::
vector
<
Lepton
::
ExpressionProgram
>
>
valueDerivExpressions
;
...
@@ -263,11 +263,11 @@ class ReferenceCustomGBIxn {
...
@@ -263,11 +263,11 @@ class ReferenceCustomGBIxn {
already been set, and the smallest side of the periodic box is at least twice the cutoff
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
vectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
*
vectors
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
...
platforms/reference/include/ReferenceCustomHbondIxn.h
View file @
83ed602e
...
@@ -43,7 +43,7 @@ class ReferenceCustomHbondIxn : public ReferenceBondIxn {
...
@@ -43,7 +43,7 @@ class ReferenceCustomHbondIxn : public ReferenceBondIxn {
class
DihedralTermInfo
;
class
DihedralTermInfo
;
bool
cutoff
;
bool
cutoff
;
bool
periodic
;
bool
periodic
;
Real
OpenMM
periodicBox
Size
[
3
];
OpenMM
::
RealVec
periodicBox
Vectors
[
3
];
RealOpenMM
cutoffDistance
;
RealOpenMM
cutoffDistance
;
std
::
vector
<
std
::
vector
<
int
>
>
donorAtoms
,
acceptorAtoms
;
std
::
vector
<
std
::
vector
<
int
>
>
donorAtoms
,
acceptorAtoms
;
Lepton
::
ExpressionProgram
energyExpression
;
Lepton
::
ExpressionProgram
energyExpression
;
...
@@ -111,11 +111,11 @@ class ReferenceCustomHbondIxn : public ReferenceBondIxn {
...
@@ -111,11 +111,11 @@ class ReferenceCustomHbondIxn : public ReferenceBondIxn {
already been set, and the smallest side of the periodic box is at least twice the cutoff
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
vectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
*
vectors
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
...
platforms/reference/include/ReferenceCustomManyParticleIxn.h
View file @
83ed602e
...
@@ -46,7 +46,7 @@ class ReferenceCustomManyParticleIxn {
...
@@ -46,7 +46,7 @@ class ReferenceCustomManyParticleIxn {
int
numParticlesPerSet
,
numPerParticleParameters
,
numTypes
;
int
numParticlesPerSet
,
numPerParticleParameters
,
numTypes
;
bool
useCutoff
,
usePeriodic
,
centralParticleMode
;
bool
useCutoff
,
usePeriodic
,
centralParticleMode
;
RealOpenMM
cutoffDistance
;
RealOpenMM
cutoffDistance
;
Real
OpenMM
periodicBox
Size
[
3
];
OpenMM
::
RealVec
periodicBox
Vectors
[
3
];
Lepton
::
ExpressionProgram
energyExpression
;
Lepton
::
ExpressionProgram
energyExpression
;
std
::
vector
<
std
::
vector
<
std
::
string
>
>
particleParamNames
;
std
::
vector
<
std
::
vector
<
std
::
string
>
>
particleParamNames
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
...
@@ -118,11 +118,11 @@ class ReferenceCustomManyParticleIxn {
...
@@ -118,11 +118,11 @@ class ReferenceCustomManyParticleIxn {
already been set, and the smallest side of the periodic box is at least twice the cutoff
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
vectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
*
vectors
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
...
platforms/reference/include/ReferenceCustomNonbondedIxn.h
View file @
83ed602e
...
@@ -43,7 +43,7 @@ class ReferenceCustomNonbondedIxn {
...
@@ -43,7 +43,7 @@ class ReferenceCustomNonbondedIxn {
bool
useSwitch
;
bool
useSwitch
;
bool
periodic
;
bool
periodic
;
const
OpenMM
::
NeighborList
*
neighborList
;
const
OpenMM
::
NeighborList
*
neighborList
;
Real
OpenMM
periodicBox
Size
[
3
];
OpenMM
::
RealVec
periodicBox
Vectors
[
3
];
RealOpenMM
cutoffDistance
,
switchingDistance
;
RealOpenMM
cutoffDistance
,
switchingDistance
;
Lepton
::
CompiledExpression
energyExpression
;
Lepton
::
CompiledExpression
energyExpression
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
...
@@ -129,11 +129,11 @@ class ReferenceCustomNonbondedIxn {
...
@@ -129,11 +129,11 @@ class ReferenceCustomNonbondedIxn {
already been set, and the smallest side of the periodic box is at least twice the cutoff
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
vectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
*
vectors
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
...
platforms/reference/include/ReferenceForce.h
View file @
83ed602e
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#ifndef __ReferenceForce_H__
#ifndef __ReferenceForce_H__
#define __ReferenceForce_H__
#define __ReferenceForce_H__
#include "RealVec.h"
#include "lepton/CompiledExpression.h"
#include "lepton/CompiledExpression.h"
#include "openmm/internal/windowsExport.h"
#include "openmm/internal/windowsExport.h"
...
@@ -97,18 +98,20 @@ class OPENMM_EXPORT ReferenceForce {
...
@@ -97,18 +98,20 @@ class OPENMM_EXPORT ReferenceForce {
static
void
getDeltaRPeriodic
(
const
OpenMM
::
RealVec
&
atomCoordinatesI
,
const
OpenMM
::
RealVec
&
atomCoordinatesJ
,
static
void
getDeltaRPeriodic
(
const
OpenMM
::
RealVec
&
atomCoordinatesI
,
const
OpenMM
::
RealVec
&
atomCoordinatesJ
,
const
RealOpenMM
*
boxSize
,
RealOpenMM
*
deltaR
);
const
RealOpenMM
*
boxSize
,
RealOpenMM
*
deltaR
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Get deltaR between atomI and atomJ (static method): deltaR: j - i
Get deltaR and distance and distance**2 between atomI and atomJ, assuming periodic
boundary conditions (static method); deltaR: j - i
@param atomCoordinatesI atom i coordinates
@param atomCoordinatesI atom i coordinates
@param atomCoordinatesI atom j coordinates
@param atomCoordinatesI atom j coordinates
@param deltaR deltaX, deltaY, deltaZ upon return
@param boxVectors the vectors defining the periodic box
@param deltaR deltaX, deltaY, deltaZ, R2, R upon return
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
static
void
getDeltaR
Only
(
const
Real
OpenMM
*
atomCoordinatesI
,
const
Real
OpenMM
*
atomCoordinatesJ
,
static
void
getDeltaR
Periodic
(
const
OpenMM
::
RealVec
&
atomCoordinatesI
,
const
OpenMM
::
RealVec
&
atomCoordinatesJ
,
RealOpenMM
*
deltaR
);
const
OpenMM
::
RealVec
*
boxVectors
,
RealOpenMM
*
deltaR
);
/**
/**
* Get a pointer to the memory for setting a variable in a CompiledExpression. If the expression
* Get a pointer to the memory for setting a variable in a CompiledExpression. If the expression
...
...
platforms/reference/include/ReferenceLJCoulombIxn.h
View file @
83ed602e
...
@@ -40,7 +40,7 @@ class ReferenceLJCoulombIxn {
...
@@ -40,7 +40,7 @@ class ReferenceLJCoulombIxn {
bool
ewald
;
bool
ewald
;
bool
pme
;
bool
pme
;
const
OpenMM
::
NeighborList
*
neighborList
;
const
OpenMM
::
NeighborList
*
neighborList
;
Real
OpenMM
periodicBox
Size
[
3
];
OpenMM
::
RealVec
periodicBox
Vectors
[
3
];
RealOpenMM
cutoffDistance
,
switchingDistance
;
RealOpenMM
cutoffDistance
,
switchingDistance
;
RealOpenMM
krf
,
crf
;
RealOpenMM
krf
,
crf
;
RealOpenMM
alphaEwald
;
RealOpenMM
alphaEwald
;
...
@@ -118,11 +118,11 @@ class ReferenceLJCoulombIxn {
...
@@ -118,11 +118,11 @@ class ReferenceLJCoulombIxn {
already been set, and the smallest side of the periodic box is at least twice the cutoff
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
vectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
*
vectors
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
...
platforms/reference/include/ReferenceMonteCarloBarostat.h
View file @
83ed602e
...
@@ -61,14 +61,14 @@ class ReferenceMonteCarloBarostat {
...
@@ -61,14 +61,14 @@ class ReferenceMonteCarloBarostat {
Apply the barostat at the start of a time step, scaling x, y, and z coordinates independently.
Apply the barostat at the start of a time step, scaling x, y, and z coordinates independently.
@param atomPositions atom positions
@param atomPositions atom positions
@param box
Size
the periodic box
dimension
s
@param box
Vectors
the periodic box
vector
s
@param scaleX the factor by which to scale atomic x coordinates
@param scaleX the factor by which to scale atomic x coordinates
@param scaleY the factor by which to scale atomic y coordinates
@param scaleY the factor by which to scale atomic y coordinates
@param scaleZ the factor by which to scale atomic z coordinates
@param scaleZ the factor by which to scale atomic z coordinates
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
applyBarostat
(
std
::
vector
<
OpenMM
::
RealVec
>&
atomPositions
,
const
OpenMM
::
RealVec
&
box
Size
,
RealOpenMM
scaleX
,
RealOpenMM
scaleY
,
RealOpenMM
scaleZ
);
void
applyBarostat
(
std
::
vector
<
OpenMM
::
RealVec
>&
atomPositions
,
const
OpenMM
::
RealVec
*
box
Vectors
,
RealOpenMM
scaleX
,
RealOpenMM
scaleY
,
RealOpenMM
scaleZ
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
...
platforms/reference/include/ReferenceNeighborList.h
View file @
83ed602e
...
@@ -22,7 +22,7 @@ void OPENMM_EXPORT computeNeighborListNaive(
...
@@ -22,7 +22,7 @@ void OPENMM_EXPORT computeNeighborListNaive(
int
nAtoms
,
int
nAtoms
,
const
AtomLocationList
&
atomLocations
,
const
AtomLocationList
&
atomLocations
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
const
RealVec
&
periodicBox
Size
,
const
RealVec
*
periodicBox
Vectors
,
bool
usePeriodic
,
bool
usePeriodic
,
double
maxDistance
,
double
maxDistance
,
double
minDistance
=
0.0
,
double
minDistance
=
0.0
,
...
@@ -35,9 +35,9 @@ void OPENMM_EXPORT computeNeighborListNaive(
...
@@ -35,9 +35,9 @@ void OPENMM_EXPORT computeNeighborListNaive(
void
OPENMM_EXPORT
computeNeighborListVoxelHash
(
void
OPENMM_EXPORT
computeNeighborListVoxelHash
(
NeighborList
&
neighborList
,
NeighborList
&
neighborList
,
int
nAtoms
,
int
nAtoms
,
const
AtomLocationList
&
atomLocations
,
const
AtomLocationList
&
atomLocations
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
const
RealVec
&
periodicBox
Size
,
const
RealVec
*
periodicBox
Vectors
,
bool
usePeriodic
,
bool
usePeriodic
,
double
maxDistance
,
double
maxDistance
,
double
minDistance
=
0.0
,
double
minDistance
=
0.0
,
...
...
platforms/reference/include/ReferencePME.h
View file @
83ed602e
...
@@ -72,16 +72,14 @@ pme_init(pme_t * ppme,
...
@@ -72,16 +72,14 @@ pme_init(pme_t * ppme,
* charge Array of charges (units of e)
* charge Array of charges (units of e)
* box Simulation cell dimensions (nm)
* box Simulation cell dimensions (nm)
* energy Total energy (will be written in units of kJ/mol)
* energy Total energy (will be written in units of kJ/mol)
* pme_virial Long-range part of the virial, output.
*/
*/
int
OPENMM_EXPORT
int
OPENMM_EXPORT
pme_exec
(
pme_t
pme
,
pme_exec
(
pme_t
pme
,
const
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
const
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
RealOpenMM
periodicBoxSize
[
3
],
const
OpenMM
::
RealVec
periodicBoxVectors
[
3
],
RealOpenMM
*
energy
,
RealOpenMM
*
energy
);
RealOpenMM
pme_virial
[
3
][
3
]);
...
...
platforms/reference/include/ReferencePlatform.h
View file @
83ed602e
...
@@ -66,6 +66,7 @@ public:
...
@@ -66,6 +66,7 @@ public:
void
*
velocities
;
void
*
velocities
;
void
*
forces
;
void
*
forces
;
void
*
periodicBoxSize
;
void
*
periodicBoxSize
;
void
*
periodicBoxVectors
;
void
*
constraints
;
void
*
constraints
;
};
};
}
// namespace OpenMM
}
// namespace OpenMM
...
...
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment