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
4a0d763c
Commit
4a0d763c
authored
Jan 16, 2020
by
Andy Simmonett
Browse files
Consolidate Drude platform tests
parent
19914cd4
Changes
22
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
682 additions
and
1686 deletions
+682
-1686
plugins/drude/platforms/cuda/tests/CMakeLists.txt
plugins/drude/platforms/cuda/tests/CMakeLists.txt
+1
-0
plugins/drude/platforms/cuda/tests/CudaDrudeTests.h
plugins/drude/platforms/cuda/tests/CudaDrudeTests.h
+42
-0
plugins/drude/platforms/cuda/tests/TestCudaDrudeForce.cpp
plugins/drude/platforms/cuda/tests/TestCudaDrudeForce.cpp
+3
-181
plugins/drude/platforms/cuda/tests/TestCudaDrudeLangevinIntegrator.cpp
.../platforms/cuda/tests/TestCudaDrudeLangevinIntegrator.cpp
+4
-227
plugins/drude/platforms/cuda/tests/TestCudaDrudeNoseHoover.cpp
...ns/drude/platforms/cuda/tests/TestCudaDrudeNoseHoover.cpp
+2
-28
plugins/drude/platforms/cuda/tests/TestCudaDrudeSCFIntegrator.cpp
...drude/platforms/cuda/tests/TestCudaDrudeSCFIntegrator.cpp
+3
-112
plugins/drude/platforms/opencl/tests/CMakeLists.txt
plugins/drude/platforms/opencl/tests/CMakeLists.txt
+1
-0
plugins/drude/platforms/opencl/tests/OpenCLDrudeTests.h
plugins/drude/platforms/opencl/tests/OpenCLDrudeTests.h
+42
-0
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeForce.cpp
...ins/drude/platforms/opencl/tests/TestOpenCLDrudeForce.cpp
+3
-181
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeLangevinIntegrator.cpp
...tforms/opencl/tests/TestOpenCLDrudeLangevinIntegrator.cpp
+4
-227
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeNoseHoover.cpp
...rude/platforms/opencl/tests/TestOpenCLDrudeNoseHoover.cpp
+2
-27
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeSCFIntegrator.cpp
...e/platforms/opencl/tests/TestOpenCLDrudeSCFIntegrator.cpp
+3
-112
plugins/drude/platforms/reference/tests/CMakeLists.txt
plugins/drude/platforms/reference/tests/CMakeLists.txt
+1
-0
plugins/drude/platforms/reference/tests/ReferenceDrudeTests.h
...ins/drude/platforms/reference/tests/ReferenceDrudeTests.h
+42
-0
plugins/drude/platforms/reference/tests/TestReferenceDrudeForce.cpp
...ude/platforms/reference/tests/TestReferenceDrudeForce.cpp
+3
-181
plugins/drude/platforms/reference/tests/TestReferenceDrudeLangevinIntegrator.cpp
.../reference/tests/TestReferenceDrudeLangevinIntegrator.cpp
+4
-284
plugins/drude/platforms/reference/tests/TestReferenceDrudeNoseHoover.cpp
...latforms/reference/tests/TestReferenceDrudeNoseHoover.cpp
+2
-17
plugins/drude/platforms/reference/tests/TestReferenceDrudeSCFIntegrator.cpp
...forms/reference/tests/TestReferenceDrudeSCFIntegrator.cpp
+3
-109
plugins/drude/tests/TestDrudeForce.h
plugins/drude/tests/TestDrudeForce.h
+209
-0
plugins/drude/tests/TestDrudeLangevinIntegrator.h
plugins/drude/tests/TestDrudeLangevinIntegrator.h
+308
-0
No files found.
plugins/drude/platforms/cuda/tests/CMakeLists.txt
View file @
4a0d763c
...
...
@@ -6,6 +6,7 @@ ENABLE_TESTING()
INCLUDE_DIRECTORIES
(
${
CUDA_INCLUDE_DIR
}
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/plugins/drude/tests
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/platforms/cuda/tests
)
# Automatically create tests using files named "Test*.cpp"
FILE
(
GLOB TEST_PROGS
"*Test*.cpp"
)
...
...
plugins/drude/platforms/cuda/tests/CudaDrudeTests.h
0 → 100644
View file @
4a0d763c
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "CudaTests.h"
extern
"C"
void
registerDrudeCudaKernelFactories
();
using
namespace
OpenMM
;
void
setupKernels
(
int
argc
,
char
*
argv
[])
{
registerDrudeCudaKernelFactories
();
platform
=
dynamic_cast
<
CudaPlatform
&>
(
Platform
::
getPlatformByName
(
"CUDA"
));
initializeTests
(
argc
,
argv
);
}
plugins/drude/platforms/cuda/tests/TestCudaDrudeForce.cpp
View file @
4a0d763c
...
...
@@ -29,185 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the CUDA implementation of DrudeForce.
*/
#include "CudaDrudeTests.h"
#include "TestDrudeForce.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
void
registerDrudeCudaKernelFactories
();
void
validateForce
(
System
&
system
,
vector
<
Vec3
>&
positions
,
double
expectedEnergy
)
{
// Given a System containing a Drude force, check that its energy has the expected value.
VerletIntegrator
integ
(
1.0
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"CUDA"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
// Try moving each particle along each axis, and see if the energy changes by the correct amount.
double
offset
=
1e-2
;
for
(
int
i
=
0
;
i
<
system
.
getNumParticles
();
i
++
)
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
vector
<
Vec3
>
offsetPos
=
positions
;
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
-
offset
;
context
.
setPositions
(
offsetPos
);
double
e1
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
+
offset
;
context
.
setPositions
(
offsetPos
);
double
e2
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
ASSERT_EQUAL_TOL
(
state
.
getForces
()[
i
][
j
],
(
e1
-
e2
)
/
(
2
*
offset
),
1e-3
);
}
}
void
testSingleParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
validateForce
(
system
,
positions
,
0.5
*
k
*
3
*
3
);
}
void
testAnisotropicParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
a1
=
0.8
;
const
double
a2
=
1.1
;
const
double
k1
=
k
/
a1
;
const
double
k2
=
k
/
a2
;
const
double
k3
=
k
/
(
3
-
a1
-
a2
);
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
2
,
3
,
4
,
charge
,
alpha
,
a1
,
a2
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
5
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0.1
,
-
0.5
,
0.8
);
positions
[
2
]
=
Vec3
(
0
,
2
,
0
);
positions
[
3
]
=
Vec3
(
1
,
2
,
0
);
positions
[
4
]
=
Vec3
(
1
,
2
,
3
);
validateForce
(
system
,
positions
,
0.5
*
k1
*
0.5
*
0.5
+
0.5
*
k2
*
0.8
*
0.8
+
0.5
*
k3
*
0.1
*
0.1
);
}
double
computeScreening
(
double
r
,
double
thole
,
double
alpha1
,
double
alpha2
)
{
double
u
=
r
*
thole
/
pow
(
alpha1
*
alpha2
,
1.0
/
6.0
);
return
1.0
-
(
1.0
+
u
/
2
)
*
exp
(
-
u
);
}
void
testThole
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
thole
=
2.5
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addParticle
(
3
,
2
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addScreenedPair
(
0
,
1
,
thole
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
4
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
-
0.5
,
0
);
positions
[
2
]
=
Vec3
(
1
,
0
,
0
);
positions
[
3
]
=
Vec3
(
1
,
0
,
0.3
);
double
energySpring1
=
0.5
*
k
*
0.5
*
0.5
;
double
energySpring2
=
0.5
*
k
*
0.3
*
0.3
;
double
energyDipole
=
0.0
;
double
q
[]
=
{
-
charge
,
charge
,
-
charge
,
charge
};
for
(
int
i
=
0
;
i
<
2
;
i
++
)
for
(
int
j
=
2
;
j
<
4
;
j
++
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
j
];
double
r
=
sqrt
(
delta
.
dot
(
delta
));
energyDipole
+=
ONE_4PI_EPS0
*
q
[
i
]
*
q
[
j
]
*
computeScreening
(
r
,
thole
,
alpha
,
alpha
)
/
r
;
}
validateForce
(
system
,
positions
,
energySpring1
+
energySpring2
+
energyDipole
);
}
void
testChangingParameters
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
Platform
&
platform
=
Platform
::
getPlatformByName
(
"CUDA"
);
// Create the system.
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
// Check the energy.
VerletIntegrator
integ
(
1.0
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
// Modify the parameters.
const
double
k2
=
ONE_4PI_EPS0
*
2.2
;
const
double
charge2
=
0.3
;
const
double
alpha2
=
ONE_4PI_EPS0
*
charge2
*
charge2
/
k2
;
drude
->
setParticleParameters
(
0
,
1
,
0
,
-
1
,
-
1
,
-
1
,
charge2
,
alpha2
,
1
,
1
);
drude
->
updateParametersInContext
(
context
);
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k2
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
registerDrudeCudaKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"CUDA"
).
setPropertyDefaultValue
(
"Precision"
,
std
::
string
(
argv
[
1
]));
testSingleParticle
();
testAnisotropicParticle
();
testThole
();
testChangingParameters
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/cuda/tests/TestCudaDrudeLangevinIntegrator.cpp
View file @
4a0d763c
...
...
@@ -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) 2013
-2016
Stanford University and the Authors. *
* Portions copyright (c) 2013 Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -29,230 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the CUDA implementation of DrudeLangevinIntegrator.
*/
#include "CudaDrudeTests.h"
#include "TestDrudeLangevinIntegrator.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VirtualSite.h"
#include "openmm/DrudeForce.h"
#include "openmm/DrudeLangevinIntegrator.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeCudaKernelFactories
();
void
testSinglePair
()
{
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
mass1
=
1.0
;
const
double
mass2
=
0.1
;
const
double
totalMass
=
mass1
+
mass2
;
const
double
reducedMass
=
(
mass1
*
mass2
)
/
(
mass1
+
mass2
);
const
double
maxDistance
=
0.05
;
System
system
;
system
.
addParticle
(
mass1
);
system
.
addParticle
(
mass2
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
DrudeLangevinIntegrator
integ
(
temperature
,
20.0
,
temperatureDrude
,
20.0
,
0.003
);
integ
.
setMaxDrudeDistance
(
maxDistance
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"CUDA"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
// Equilibrate.
integ
.
step
(
1000
);
// Compute the internal and center of mass temperatures.
double
keCM
=
0
,
keInternal
=
0
;
int
numSteps
=
10000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
10
);
State
state
=
context
.
getState
(
State
::
Velocities
|
State
::
Positions
);
const
vector
<
Vec3
>&
vel
=
state
.
getVelocities
();
Vec3
velCM
=
vel
[
0
]
*
(
mass1
/
totalMass
)
+
vel
[
1
]
*
(
mass2
/
totalMass
);
keCM
+=
0.5
*
totalMass
*
velCM
.
dot
(
velCM
);
Vec3
velInternal
=
vel
[
0
]
-
vel
[
1
];
keInternal
+=
0.5
*
reducedMass
*
velInternal
.
dot
(
velInternal
);
Vec3
delta
=
state
.
getPositions
()[
0
]
-
state
.
getPositions
()[
1
];
double
distance
=
sqrt
(
delta
.
dot
(
delta
));
ASSERT
(
distance
<=
maxDistance
*
(
1
+
1e-6
));
}
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperature
,
keCM
/
numSteps
,
0.1
);
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperatureDrude
,
keInternal
/
numSteps
,
0.01
);
}
void
testWater
()
{
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const
int
gridSize
=
4
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
1.0
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
15.6
);
// O
system
.
addParticle
(
0.4
);
// D
system
.
addParticle
(
1.0
);
// H1
system
.
addParticle
(
1.0
);
// H2
system
.
addParticle
(
0.0
);
// M
nonbonded
->
addParticle
(
1.71636
,
0.318395
,
0.21094
*
4.184
);
nonbonded
->
addParticle
(
-
1.71636
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.11466
,
1
,
0
);
for
(
int
j
=
0
;
j
<
5
;
j
++
)
for
(
int
k
=
0
;
k
<
j
;
k
++
)
nonbonded
->
addException
(
startIndex
+
j
,
startIndex
+
k
,
0
,
1
,
0
);
system
.
addConstraint
(
startIndex
,
startIndex
+
2
,
0.09572
);
system
.
addConstraint
(
startIndex
,
startIndex
+
3
,
0.09572
);
system
.
addConstraint
(
startIndex
+
2
,
startIndex
+
3
,
0.15139
);
system
.
setVirtualSite
(
startIndex
+
4
,
new
ThreeParticleAverageSite
(
startIndex
,
startIndex
+
2
,
startIndex
+
3
,
0.786646558
,
0.106676721
,
0.106676721
));
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.71636
,
ONE_4PI_EPS0
*
1.71636
*
1.71636
/
(
100000
*
4.184
),
1
,
1
);
}
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
+
Vec3
(
0.09572
,
0
,
0
));
positions
.
push_back
(
pos
+
Vec3
(
-
0.023999
,
0.092663
,
0
));
positions
.
push_back
(
pos
);
}
// Simulate it and check the temperature.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.0005
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"CUDA"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
1e-5
);
// Equilibrate.
integ
.
step
(
1000
);
// Compute the internal and center of mass temperatures.
double
ke
=
0
;
int
numSteps
=
10000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
ke
+=
context
.
getState
(
State
::
Energy
).
getKineticEnergy
();
}
ke
/=
numSteps
;
int
numStandardDof
=
3
*
3
*
numMolecules
-
system
.
getNumConstraints
();
int
numDrudeDof
=
3
*
numMolecules
;
int
numDof
=
numStandardDof
+
numDrudeDof
;
double
expectedTemp
=
(
numStandardDof
*
temperature
+
numDrudeDof
*
temperatureDrude
)
/
numDof
;
ASSERT_USUALLY_EQUAL_TOL
(
expectedTemp
,
ke
/
(
0.5
*
numDof
*
BOLTZ
),
0.02
);
}
void
testForceEnergyConsistency
()
{
// Create a box of polarizable particles.
const
int
gridSize
=
3
;
const
int
numAtoms
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
vector
<
Vec3
>
positions
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
nonbonded
->
setCutoffDistance
(
1.0
);
nonbonded
->
setUseSwitchingFunction
(
true
);
nonbonded
->
setSwitchingDistance
(
0.9
);
nonbonded
->
setEwaldErrorTolerance
(
5e-5
);
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
1.0
,
0.3
,
1.0
);
nonbonded
->
addParticle
(
-
1.0
,
0.3
,
1.0
);
nonbonded
->
addException
(
startIndex
,
startIndex
+
1
,
0
,
1
,
0
);
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.0
,
0.001
,
1
,
1
);
}
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
}
// Simulate it and check that force and energy remain consistent.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.001
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"CUDA"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
prevState
;
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
|
State
::
Positions
);
if
(
i
>
0
)
{
double
expectedEnergyChange
=
0
;
for
(
int
j
=
0
;
j
<
system
.
getNumParticles
();
j
++
)
{
Vec3
delta
=
state
.
getPositions
()[
j
]
-
prevState
.
getPositions
()[
j
];
expectedEnergyChange
-=
0.5
*
(
state
.
getForces
()[
j
]
+
prevState
.
getForces
()[
j
]).
dot
(
delta
);
}
ASSERT_EQUAL_TOL
(
expectedEnergyChange
,
state
.
getPotentialEnergy
()
-
prevState
.
getPotentialEnergy
(),
0.05
);
}
prevState
=
state
;
integ
.
step
(
1
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
registerDrudeCudaKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"CUDA"
).
setPropertyDefaultValue
(
"Precision"
,
string
(
argv
[
1
]));
testSinglePair
();
testWater
();
testForceEnergyConsistency
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/cuda/tests/TestCudaDrudeNoseHoover.cpp
View file @
4a0d763c
...
...
@@ -29,33 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
//#include "ReferenceTests.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "CudaPlatform.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeCudaKernelFactories
();
void
runPlatformTests
()
{
}
#include "CudaDrudeTests.h"
#include "TestDrudeNoseHoover.h"
Platform
&
initializePlatform
(
int
argc
,
char
*
argv
[])
{
registerDrudeCudaKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"CUDA"
).
setPropertyDefaultValue
(
"Precision"
,
std
::
string
(
argv
[
1
]));
return
Platform
::
getPlatformByName
(
"CUDA"
);
}
void
runPlatformTests
()
{}
plugins/drude/platforms/cuda/tests/TestCudaDrudeSCFIntegrator.cpp
View file @
4a0d763c
...
...
@@ -29,116 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the CUDA implementation of DrudeSCFIntegrator.
*/
#include "CudaDrudeTests.h"
#include "TestDrudeSCFIntegrator.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VirtualSite.h"
#include "openmm/DrudeForce.h"
#include "openmm/DrudeSCFIntegrator.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeCudaKernelFactories
();
void
testWater
()
{
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const
int
gridSize
=
4
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
1.0
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
15.6
);
// O
system
.
addParticle
(
0.4
);
// D
system
.
addParticle
(
1.0
);
// H1
system
.
addParticle
(
1.0
);
// H2
system
.
addParticle
(
0.0
);
// M
nonbonded
->
addParticle
(
1.71636
,
0.318395
,
0.21094
*
4.184
);
nonbonded
->
addParticle
(
-
1.71636
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.11466
,
1
,
0
);
for
(
int
j
=
0
;
j
<
5
;
j
++
)
for
(
int
k
=
0
;
k
<
j
;
k
++
)
nonbonded
->
addException
(
startIndex
+
j
,
startIndex
+
k
,
0
,
1
,
0
);
system
.
addConstraint
(
startIndex
,
startIndex
+
2
,
0.09572
);
system
.
addConstraint
(
startIndex
,
startIndex
+
3
,
0.09572
);
system
.
addConstraint
(
startIndex
+
2
,
startIndex
+
3
,
0.15139
);
system
.
setVirtualSite
(
startIndex
+
4
,
new
ThreeParticleAverageSite
(
startIndex
,
startIndex
+
2
,
startIndex
+
3
,
0.786646558
,
0.106676721
,
0.106676721
));
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.71636
,
ONE_4PI_EPS0
*
1.71636
*
1.71636
/
(
100000
*
4.184
),
1
,
1
);
}
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
+
Vec3
(
0.09572
,
0
,
0
));
positions
.
push_back
(
pos
+
Vec3
(
-
0.023999
,
0.092663
,
0
));
positions
.
push_back
(
pos
);
}
// Simulate it and check energy conservation and the total force on the Drude particles.
DrudeSCFIntegrator
integ
(
0.0005
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"CUDA"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
1e-5
);
context
.
setVelocitiesToTemperature
(
300.0
);
State
state
=
context
.
getState
(
State
::
Energy
);
double
initialEnergy
;
int
numSteps
=
1000
;
double
maxNorm
=
(
platform
.
getPropertyValue
(
context
,
"Precision"
)
==
"double"
?
1.0
:
5.0
);
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
if
(
i
==
0
)
initialEnergy
=
state
.
getPotentialEnergy
()
+
state
.
getKineticEnergy
();
else
ASSERT_EQUAL_TOL
(
initialEnergy
,
state
.
getPotentialEnergy
()
+
state
.
getKineticEnergy
(),
0.01
);
const
vector
<
Vec3
>&
force
=
state
.
getForces
();
double
norm
=
0.0
;
for
(
int
j
=
1
;
j
<
(
int
)
force
.
size
();
j
+=
5
)
norm
+=
sqrt
(
force
[
j
].
dot
(
force
[
j
]));
norm
=
(
norm
/
numMolecules
);
ASSERT
(
norm
<
maxNorm
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
registerDrudeCudaKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"CUDA"
).
setPropertyDefaultValue
(
"Precision"
,
string
(
argv
[
1
]));
testWater
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/opencl/tests/CMakeLists.txt
View file @
4a0d763c
...
...
@@ -6,6 +6,7 @@ ENABLE_TESTING()
INCLUDE_DIRECTORIES
(
${
OPENCL_INCLUDE_DIR
}
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/plugins/drude/tests
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/platforms/opencl/tests
)
# Automatically create tests using files named "Test*.cpp"
FILE
(
GLOB TEST_PROGS
"*Test*.cpp"
)
...
...
plugins/drude/platforms/opencl/tests/OpenCLDrudeTests.h
0 → 100644
View file @
4a0d763c
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "OpenCLTests.h"
extern
"C"
void
registerDrudeOpenCLKernelFactories
();
using
namespace
OpenMM
;
void
setupKernels
(
int
argc
,
char
*
argv
[])
{
registerDrudeOpenCLKernelFactories
();
platform
=
dynamic_cast
<
OpenCLPlatform
&>
(
Platform
::
getPlatformByName
(
"OpenCL"
));
initializeTests
(
argc
,
argv
);
}
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeForce.cpp
View file @
4a0d763c
...
...
@@ -29,185 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the OpenCL implementation of DrudeForce.
*/
#include "OpenCLDrudeTests.h"
#include "TestDrudeForce.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
void
registerDrudeOpenCLKernelFactories
();
void
validateForce
(
System
&
system
,
vector
<
Vec3
>&
positions
,
double
expectedEnergy
)
{
// Given a System containing a Drude force, check that its energy has the expected value.
VerletIntegrator
integ
(
1.0
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"OpenCL"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
// Try moving each particle along each axis, and see if the energy changes by the correct amount.
double
offset
=
1e-2
;
for
(
int
i
=
0
;
i
<
system
.
getNumParticles
();
i
++
)
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
vector
<
Vec3
>
offsetPos
=
positions
;
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
-
offset
;
context
.
setPositions
(
offsetPos
);
double
e1
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
+
offset
;
context
.
setPositions
(
offsetPos
);
double
e2
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
ASSERT_EQUAL_TOL
(
state
.
getForces
()[
i
][
j
],
(
e1
-
e2
)
/
(
2
*
offset
),
1e-3
);
}
}
void
testSingleParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
validateForce
(
system
,
positions
,
0.5
*
k
*
3
*
3
);
}
void
testAnisotropicParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
a1
=
0.8
;
const
double
a2
=
1.1
;
const
double
k1
=
k
/
a1
;
const
double
k2
=
k
/
a2
;
const
double
k3
=
k
/
(
3
-
a1
-
a2
);
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
2
,
3
,
4
,
charge
,
alpha
,
a1
,
a2
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
5
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0.1
,
-
0.5
,
0.8
);
positions
[
2
]
=
Vec3
(
0
,
2
,
0
);
positions
[
3
]
=
Vec3
(
1
,
2
,
0
);
positions
[
4
]
=
Vec3
(
1
,
2
,
3
);
validateForce
(
system
,
positions
,
0.5
*
k1
*
0.5
*
0.5
+
0.5
*
k2
*
0.8
*
0.8
+
0.5
*
k3
*
0.1
*
0.1
);
}
double
computeScreening
(
double
r
,
double
thole
,
double
alpha1
,
double
alpha2
)
{
double
u
=
r
*
thole
/
pow
(
alpha1
*
alpha2
,
1.0
/
6.0
);
return
1.0
-
(
1.0
+
u
/
2
)
*
exp
(
-
u
);
}
void
testThole
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
thole
=
2.5
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addParticle
(
3
,
2
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addScreenedPair
(
0
,
1
,
thole
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
4
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
-
0.5
,
0
);
positions
[
2
]
=
Vec3
(
1
,
0
,
0
);
positions
[
3
]
=
Vec3
(
1
,
0
,
0.3
);
double
energySpring1
=
0.5
*
k
*
0.5
*
0.5
;
double
energySpring2
=
0.5
*
k
*
0.3
*
0.3
;
double
energyDipole
=
0.0
;
double
q
[]
=
{
-
charge
,
charge
,
-
charge
,
charge
};
for
(
int
i
=
0
;
i
<
2
;
i
++
)
for
(
int
j
=
2
;
j
<
4
;
j
++
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
j
];
double
r
=
sqrt
(
delta
.
dot
(
delta
));
energyDipole
+=
ONE_4PI_EPS0
*
q
[
i
]
*
q
[
j
]
*
computeScreening
(
r
,
thole
,
alpha
,
alpha
)
/
r
;
}
validateForce
(
system
,
positions
,
energySpring1
+
energySpring2
+
energyDipole
);
}
void
testChangingParameters
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
Platform
&
platform
=
Platform
::
getPlatformByName
(
"OpenCL"
);
// Create the system.
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
// Check the energy.
VerletIntegrator
integ
(
1.0
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
// Modify the parameters.
const
double
k2
=
ONE_4PI_EPS0
*
2.2
;
const
double
charge2
=
0.3
;
const
double
alpha2
=
ONE_4PI_EPS0
*
charge2
*
charge2
/
k2
;
drude
->
setParticleParameters
(
0
,
1
,
0
,
-
1
,
-
1
,
-
1
,
charge2
,
alpha2
,
1
,
1
);
drude
->
updateParametersInContext
(
context
);
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k2
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
registerDrudeOpenCLKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"OpenCL"
).
setPropertyDefaultValue
(
"Precision"
,
std
::
string
(
argv
[
1
]));
testSingleParticle
();
testAnisotropicParticle
();
testThole
();
testChangingParameters
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeLangevinIntegrator.cpp
View file @
4a0d763c
...
...
@@ -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) 2013
-2016
Stanford University and the Authors. *
* Portions copyright (c) 2013 Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -29,230 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the OpenCL implementation of DrudeLangevinIntegrator.
*/
#include "OpenCLDrudeTests.h"
#include "TestDrudeLangevinIntegrator.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VirtualSite.h"
#include "openmm/DrudeForce.h"
#include "openmm/DrudeLangevinIntegrator.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeOpenCLKernelFactories
();
void
testSinglePair
()
{
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
mass1
=
1.0
;
const
double
mass2
=
0.1
;
const
double
totalMass
=
mass1
+
mass2
;
const
double
reducedMass
=
(
mass1
*
mass2
)
/
(
mass1
+
mass2
);
const
double
maxDistance
=
0.05
;
System
system
;
system
.
addParticle
(
mass1
);
system
.
addParticle
(
mass2
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
DrudeLangevinIntegrator
integ
(
temperature
,
20.0
,
temperatureDrude
,
20.0
,
0.003
);
integ
.
setMaxDrudeDistance
(
maxDistance
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"OpenCL"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
// Equilibrate.
integ
.
step
(
1000
);
// Compute the internal and center of mass temperatures.
double
keCM
=
0
,
keInternal
=
0
;
int
numSteps
=
10000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
10
);
State
state
=
context
.
getState
(
State
::
Velocities
|
State
::
Positions
);
const
vector
<
Vec3
>&
vel
=
state
.
getVelocities
();
Vec3
velCM
=
vel
[
0
]
*
(
mass1
/
totalMass
)
+
vel
[
1
]
*
(
mass2
/
totalMass
);
keCM
+=
0.5
*
totalMass
*
velCM
.
dot
(
velCM
);
Vec3
velInternal
=
vel
[
0
]
-
vel
[
1
];
keInternal
+=
0.5
*
reducedMass
*
velInternal
.
dot
(
velInternal
);
Vec3
delta
=
state
.
getPositions
()[
0
]
-
state
.
getPositions
()[
1
];
double
distance
=
sqrt
(
delta
.
dot
(
delta
));
ASSERT
(
distance
<=
maxDistance
*
(
1
+
1e-6
));
}
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperature
,
keCM
/
numSteps
,
0.1
);
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperatureDrude
,
keInternal
/
numSteps
,
0.01
);
}
void
testWater
()
{
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const
int
gridSize
=
4
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
1.0
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
15.6
);
// O
system
.
addParticle
(
0.4
);
// D
system
.
addParticle
(
1.0
);
// H1
system
.
addParticle
(
1.0
);
// H2
system
.
addParticle
(
0.0
);
// M
nonbonded
->
addParticle
(
1.71636
,
0.318395
,
0.21094
*
4.184
);
nonbonded
->
addParticle
(
-
1.71636
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.11466
,
1
,
0
);
for
(
int
j
=
0
;
j
<
5
;
j
++
)
for
(
int
k
=
0
;
k
<
j
;
k
++
)
nonbonded
->
addException
(
startIndex
+
j
,
startIndex
+
k
,
0
,
1
,
0
);
system
.
addConstraint
(
startIndex
,
startIndex
+
2
,
0.09572
);
system
.
addConstraint
(
startIndex
,
startIndex
+
3
,
0.09572
);
system
.
addConstraint
(
startIndex
+
2
,
startIndex
+
3
,
0.15139
);
system
.
setVirtualSite
(
startIndex
+
4
,
new
ThreeParticleAverageSite
(
startIndex
,
startIndex
+
2
,
startIndex
+
3
,
0.786646558
,
0.106676721
,
0.106676721
));
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.71636
,
ONE_4PI_EPS0
*
1.71636
*
1.71636
/
(
100000
*
4.184
),
1
,
1
);
}
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
+
Vec3
(
0.09572
,
0
,
0
));
positions
.
push_back
(
pos
+
Vec3
(
-
0.023999
,
0.092663
,
0
));
positions
.
push_back
(
pos
);
}
// Simulate it and check the temperature.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.0005
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"OpenCL"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
1e-5
);
// Equilibrate.
integ
.
step
(
1000
);
// Compute the internal and center of mass temperatures.
double
ke
=
0
;
int
numSteps
=
10000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
ke
+=
context
.
getState
(
State
::
Energy
).
getKineticEnergy
();
}
ke
/=
numSteps
;
int
numStandardDof
=
3
*
3
*
numMolecules
-
system
.
getNumConstraints
();
int
numDrudeDof
=
3
*
numMolecules
;
int
numDof
=
numStandardDof
+
numDrudeDof
;
double
expectedTemp
=
(
numStandardDof
*
temperature
+
numDrudeDof
*
temperatureDrude
)
/
numDof
;
ASSERT_USUALLY_EQUAL_TOL
(
expectedTemp
,
ke
/
(
0.5
*
numDof
*
BOLTZ
),
0.02
);
}
void
testForceEnergyConsistency
()
{
// Create a box of polarizable particles.
const
int
gridSize
=
3
;
const
int
numAtoms
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
vector
<
Vec3
>
positions
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
nonbonded
->
setCutoffDistance
(
1.0
);
nonbonded
->
setUseSwitchingFunction
(
true
);
nonbonded
->
setSwitchingDistance
(
0.9
);
nonbonded
->
setEwaldErrorTolerance
(
5e-5
);
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
1.0
,
0.3
,
1.0
);
nonbonded
->
addParticle
(
-
1.0
,
0.3
,
1.0
);
nonbonded
->
addException
(
startIndex
,
startIndex
+
1
,
0
,
1
,
0
);
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.0
,
0.001
,
1
,
1
);
}
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
}
// Simulate it and check that force and energy remain consistent.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.001
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"OpenCL"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
prevState
;
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
|
State
::
Positions
);
if
(
i
>
0
)
{
double
expectedEnergyChange
=
0
;
for
(
int
j
=
0
;
j
<
system
.
getNumParticles
();
j
++
)
{
Vec3
delta
=
state
.
getPositions
()[
j
]
-
prevState
.
getPositions
()[
j
];
expectedEnergyChange
-=
0.5
*
(
state
.
getForces
()[
j
]
+
prevState
.
getForces
()[
j
]).
dot
(
delta
);
}
ASSERT_EQUAL_TOL
(
expectedEnergyChange
,
state
.
getPotentialEnergy
()
-
prevState
.
getPotentialEnergy
(),
0.05
);
}
prevState
=
state
;
integ
.
step
(
1
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
registerDrudeOpenCLKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"OpenCL"
).
setPropertyDefaultValue
(
"Precision"
,
string
(
argv
[
1
]));
testSinglePair
();
testWater
();
testForceEnergyConsistency
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeNoseHoover.cpp
View file @
4a0d763c
...
...
@@ -29,32 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
//#include "ReferenceTests.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "OpenCLPlatform.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeOpenCLKernelFactories
();
void
runPlatformTests
()
{
}
#include "OpenCLDrudeTests.h"
#include "TestDrudeNoseHoover.h"
Platform
&
initializePlatform
(
int
argc
,
char
*
argv
[])
{
registerDrudeOpenCLKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"OpenCL"
).
setPropertyDefaultValue
(
"Precision"
,
std
::
string
(
argv
[
1
]));
return
Platform
::
getPlatformByName
(
"OpenCL"
);
}
void
runPlatformTests
()
{}
plugins/drude/platforms/opencl/tests/TestOpenCLDrudeSCFIntegrator.cpp
View file @
4a0d763c
...
...
@@ -29,116 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the OpenCL implementation of DrudeSCFIntegrator.
*/
#include "OpenCLDrudeTests.h"
#include "TestDrudeSCFIntegrator.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VirtualSite.h"
#include "openmm/DrudeForce.h"
#include "openmm/DrudeSCFIntegrator.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeOpenCLKernelFactories
();
void
testWater
()
{
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const
int
gridSize
=
4
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
1.0
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
15.6
);
// O
system
.
addParticle
(
0.4
);
// D
system
.
addParticle
(
1.0
);
// H1
system
.
addParticle
(
1.0
);
// H2
system
.
addParticle
(
0.0
);
// M
nonbonded
->
addParticle
(
1.71636
,
0.318395
,
0.21094
*
4.184
);
nonbonded
->
addParticle
(
-
1.71636
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.11466
,
1
,
0
);
for
(
int
j
=
0
;
j
<
5
;
j
++
)
for
(
int
k
=
0
;
k
<
j
;
k
++
)
nonbonded
->
addException
(
startIndex
+
j
,
startIndex
+
k
,
0
,
1
,
0
);
system
.
addConstraint
(
startIndex
,
startIndex
+
2
,
0.09572
);
system
.
addConstraint
(
startIndex
,
startIndex
+
3
,
0.09572
);
system
.
addConstraint
(
startIndex
+
2
,
startIndex
+
3
,
0.15139
);
system
.
setVirtualSite
(
startIndex
+
4
,
new
ThreeParticleAverageSite
(
startIndex
,
startIndex
+
2
,
startIndex
+
3
,
0.786646558
,
0.106676721
,
0.106676721
));
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.71636
,
ONE_4PI_EPS0
*
1.71636
*
1.71636
/
(
100000
*
4.184
),
1
,
1
);
}
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
+
Vec3
(
0.09572
,
0
,
0
));
positions
.
push_back
(
pos
+
Vec3
(
-
0.023999
,
0.092663
,
0
));
positions
.
push_back
(
pos
);
}
// Simulate it and check energy conservation and the total force on the Drude particles.
DrudeSCFIntegrator
integ
(
0.0005
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"OpenCL"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
1e-5
);
context
.
setVelocitiesToTemperature
(
300.0
);
State
state
=
context
.
getState
(
State
::
Energy
);
double
initialEnergy
;
int
numSteps
=
1000
;
double
maxNorm
=
(
platform
.
getPropertyValue
(
context
,
"Precision"
)
==
"double"
?
1.0
:
5.0
);
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
if
(
i
==
0
)
initialEnergy
=
state
.
getPotentialEnergy
()
+
state
.
getKineticEnergy
();
else
ASSERT_EQUAL_TOL
(
initialEnergy
,
state
.
getPotentialEnergy
()
+
state
.
getKineticEnergy
(),
0.01
);
const
vector
<
Vec3
>&
force
=
state
.
getForces
();
double
norm
=
0.0
;
for
(
int
j
=
1
;
j
<
(
int
)
force
.
size
();
j
+=
5
)
norm
+=
sqrt
(
force
[
j
].
dot
(
force
[
j
]));
norm
=
(
norm
/
numMolecules
);
ASSERT
(
norm
<
maxNorm
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
registerDrudeOpenCLKernelFactories
();
if
(
argc
>
1
)
Platform
::
getPlatformByName
(
"OpenCL"
).
setPropertyDefaultValue
(
"Precision"
,
string
(
argv
[
1
]));
testWater
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/reference/tests/CMakeLists.txt
View file @
4a0d763c
...
...
@@ -5,6 +5,7 @@ ENABLE_TESTING()
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/platforms/reference/include
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/openmmapi/include/openmm
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/platforms/reference/src
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/platforms/reference/tests
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/plugins/drude/tests
)
SET
(
SHARED_OPENMM_DRUDE_TARGET OpenMMDrude
)
...
...
plugins/drude/platforms/reference/tests/ReferenceDrudeTests.h
0 → 100644
View file @
4a0d763c
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "ReferenceTests.h"
extern
"C"
void
registerDrudeReferenceKernelFactories
();
using
namespace
OpenMM
;
void
setupKernels
(
int
argc
,
char
*
argv
[])
{
registerDrudeReferenceKernelFactories
();
platform
=
dynamic_cast
<
ReferencePlatform
&>
(
Platform
::
getPlatformByName
(
"Reference"
));
initializeTests
(
argc
,
argv
);
}
plugins/drude/platforms/reference/tests/TestReferenceDrudeForce.cpp
View file @
4a0d763c
...
...
@@ -29,185 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the Reference implementation of DrudeForce.
*/
#include "ReferenceDrudeTests.h"
#include "TestDrudeForce.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeReferenceKernelFactories
();
void
validateForce
(
System
&
system
,
vector
<
Vec3
>&
positions
,
double
expectedEnergy
)
{
// Given a System containing a Drude force, check that its energy has the expected value.
VerletIntegrator
integ
(
1.0
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
// Try moving each particle along each axis, and see if the energy changes by the correct amount.
double
offset
=
1e-3
;
for
(
int
i
=
0
;
i
<
system
.
getNumParticles
();
i
++
)
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
vector
<
Vec3
>
offsetPos
=
positions
;
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
-
offset
;
context
.
setPositions
(
offsetPos
);
double
e1
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
+
offset
;
context
.
setPositions
(
offsetPos
);
double
e2
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
ASSERT_EQUAL_TOL
(
state
.
getForces
()[
i
][
j
],
(
e1
-
e2
)
/
(
2
*
offset
),
1e-5
);
}
}
void
testSingleParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
ASSERT
(
!
drude
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
system
.
usesPeriodicBoundaryConditions
());
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
validateForce
(
system
,
positions
,
0.5
*
k
*
3
*
3
);
}
void
testAnisotropicParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
a1
=
0.8
;
const
double
a2
=
1.1
;
const
double
k1
=
k
/
a1
;
const
double
k2
=
k
/
a2
;
const
double
k3
=
k
/
(
3
-
a1
-
a2
);
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
2
,
3
,
4
,
charge
,
alpha
,
a1
,
a2
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
5
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0.1
,
-
0.5
,
0.8
);
positions
[
2
]
=
Vec3
(
0
,
2
,
0
);
positions
[
3
]
=
Vec3
(
1
,
2
,
0
);
positions
[
4
]
=
Vec3
(
1
,
2
,
3
);
validateForce
(
system
,
positions
,
0.5
*
k1
*
0.5
*
0.5
+
0.5
*
k2
*
0.8
*
0.8
+
0.5
*
k3
*
0.1
*
0.1
);
}
double
computeScreening
(
double
r
,
double
thole
,
double
alpha1
,
double
alpha2
)
{
double
u
=
r
*
thole
/
pow
(
alpha1
*
alpha2
,
1.0
/
6.0
);
return
1.0
-
(
1.0
+
u
/
2
)
*
exp
(
-
u
);
}
void
testThole
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
thole
=
2.5
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addParticle
(
3
,
2
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addScreenedPair
(
0
,
1
,
thole
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
4
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
-
0.5
,
0
);
positions
[
2
]
=
Vec3
(
1
,
0
,
0
);
positions
[
3
]
=
Vec3
(
1
,
0
,
0.3
);
double
energySpring1
=
0.5
*
k
*
0.5
*
0.5
;
double
energySpring2
=
0.5
*
k
*
0.3
*
0.3
;
double
energyDipole
=
0.0
;
double
q
[]
=
{
-
charge
,
charge
,
-
charge
,
charge
};
for
(
int
i
=
0
;
i
<
2
;
i
++
)
for
(
int
j
=
2
;
j
<
4
;
j
++
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
j
];
double
r
=
sqrt
(
delta
.
dot
(
delta
));
energyDipole
+=
ONE_4PI_EPS0
*
q
[
i
]
*
q
[
j
]
*
computeScreening
(
r
,
thole
,
alpha
,
alpha
)
/
r
;
}
validateForce
(
system
,
positions
,
energySpring1
+
energySpring2
+
energyDipole
);
}
void
testChangingParameters
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
// Create the system.
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
// Check the energy.
VerletIntegrator
integ
(
1.0
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
// Modify the parameters.
const
double
k2
=
ONE_4PI_EPS0
*
2.2
;
const
double
charge2
=
0.3
;
const
double
alpha2
=
ONE_4PI_EPS0
*
charge2
*
charge2
/
k2
;
drude
->
setParticleParameters
(
0
,
1
,
0
,
-
1
,
-
1
,
-
1
,
charge2
,
alpha2
,
1
,
1
);
drude
->
updateParametersInContext
(
context
);
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k2
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
}
int
main
()
{
try
{
registerDrudeReferenceKernelFactories
();
testSingleParticle
();
testAnisotropicParticle
();
testThole
();
testChangingParameters
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/reference/tests/TestReferenceDrudeLangevinIntegrator.cpp
View file @
4a0d763c
...
...
@@ -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) 2013
-2016
Stanford University and the Authors. *
* Portions copyright (c) 2013 Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -29,287 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the Reference implementation of DrudeLangevinIntegrator.
*/
#include "ReferenceDrudeTests.h"
#include "TestDrudeLangevinIntegrator.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VirtualSite.h"
#include "openmm/DrudeForce.h"
#include "openmm/DrudeLangevinIntegrator.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeReferenceKernelFactories
();
void
testSinglePair
()
{
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
mass1
=
1.0
;
const
double
mass2
=
0.1
;
const
double
totalMass
=
mass1
+
mass2
;
const
double
reducedMass
=
(
mass1
*
mass2
)
/
(
mass1
+
mass2
);
const
double
maxDistance
=
0.05
;
System
system
;
system
.
addParticle
(
mass1
);
system
.
addParticle
(
mass2
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
DrudeLangevinIntegrator
integ
(
temperature
,
20.0
,
temperatureDrude
,
20.0
,
0.003
);
integ
.
setMaxDrudeDistance
(
maxDistance
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
// Equilibrate.
integ
.
step
(
1000
);
// Compute the internal and center of mass temperatures.
double
keCM
=
0
,
keInternal
=
0
;
int
numSteps
=
10000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
10
);
State
state
=
context
.
getState
(
State
::
Velocities
|
State
::
Positions
);
const
vector
<
Vec3
>&
vel
=
state
.
getVelocities
();
Vec3
velCM
=
vel
[
0
]
*
(
mass1
/
totalMass
)
+
vel
[
1
]
*
(
mass2
/
totalMass
);
keCM
+=
0.5
*
totalMass
*
velCM
.
dot
(
velCM
);
Vec3
velInternal
=
vel
[
0
]
-
vel
[
1
];
keInternal
+=
0.5
*
reducedMass
*
velInternal
.
dot
(
velInternal
);
Vec3
delta
=
state
.
getPositions
()[
0
]
-
state
.
getPositions
()[
1
];
double
distance
=
sqrt
(
delta
.
dot
(
delta
));
ASSERT
(
distance
<=
maxDistance
*
(
1
+
1e-6
));
}
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperature
,
keCM
/
numSteps
,
0.1
);
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperatureDrude
,
keInternal
/
numSteps
,
0.01
);
}
void
testWater
()
{
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const
int
gridSize
=
3
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
1.0
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
15.6
);
// O
system
.
addParticle
(
0.4
);
// D
system
.
addParticle
(
1.0
);
// H1
system
.
addParticle
(
1.0
);
// H2
system
.
addParticle
(
0.0
);
// M
nonbonded
->
addParticle
(
1.71636
,
0.318395
,
0.21094
*
4.184
);
nonbonded
->
addParticle
(
-
1.71636
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.11466
,
1
,
0
);
for
(
int
j
=
0
;
j
<
5
;
j
++
)
for
(
int
k
=
0
;
k
<
j
;
k
++
)
nonbonded
->
addException
(
startIndex
+
j
,
startIndex
+
k
,
0
,
1
,
0
);
system
.
addConstraint
(
startIndex
,
startIndex
+
2
,
0.09572
);
system
.
addConstraint
(
startIndex
,
startIndex
+
3
,
0.09572
);
system
.
addConstraint
(
startIndex
+
2
,
startIndex
+
3
,
0.15139
);
system
.
setVirtualSite
(
startIndex
+
4
,
new
ThreeParticleAverageSite
(
startIndex
,
startIndex
+
2
,
startIndex
+
3
,
0.786646558
,
0.106676721
,
0.106676721
));
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.71636
,
ONE_4PI_EPS0
*
1.71636
*
1.71636
/
(
100000
*
4.184
),
1
,
1
);
}
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
+
Vec3
(
0.09572
,
0
,
0
));
positions
.
push_back
(
pos
+
Vec3
(
-
0.023999
,
0.092663
,
0
));
positions
.
push_back
(
pos
);
}
// Simulate it and check the temperature.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.0005
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
1e-5
);
// Equilibrate.
integ
.
step
(
500
);
// Compute the internal and center of mass temperatures.
double
ke
=
0
;
int
numSteps
=
4000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
ke
+=
context
.
getState
(
State
::
Energy
).
getKineticEnergy
();
}
ke
/=
numSteps
;
int
numStandardDof
=
3
*
3
*
numMolecules
-
system
.
getNumConstraints
();
int
numDrudeDof
=
3
*
numMolecules
;
int
numDof
=
numStandardDof
+
numDrudeDof
;
double
expectedTemp
=
(
numStandardDof
*
temperature
+
numDrudeDof
*
temperatureDrude
)
/
numDof
;
ASSERT_USUALLY_EQUAL_TOL
(
expectedTemp
,
ke
/
(
0.5
*
numDof
*
BOLTZ
),
0.03
);
}
void
testForceEnergyConsistency
()
{
// Create a box of polarizable particles.
const
int
gridSize
=
3
;
const
int
numAtoms
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
vector
<
Vec3
>
positions
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
nonbonded
->
setCutoffDistance
(
1.0
);
nonbonded
->
setUseSwitchingFunction
(
true
);
nonbonded
->
setSwitchingDistance
(
0.9
);
nonbonded
->
setEwaldErrorTolerance
(
5e-5
);
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
1.0
,
0.3
,
1.0
);
nonbonded
->
addParticle
(
-
1.0
,
0.3
,
1.0
);
nonbonded
->
addException
(
startIndex
,
startIndex
+
1
,
0
,
1
,
0
);
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.0
,
0.001
,
1
,
1
);
}
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
}
// Simulate it and check that force and energy remain consistent.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.001
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
prevState
;
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
|
State
::
Positions
);
if
(
i
>
0
)
{
double
expectedEnergyChange
=
0
;
for
(
int
j
=
0
;
j
<
system
.
getNumParticles
();
j
++
)
{
Vec3
delta
=
state
.
getPositions
()[
j
]
-
prevState
.
getPositions
()[
j
];
expectedEnergyChange
-=
0.5
*
(
state
.
getForces
()[
j
]
+
prevState
.
getForces
()[
j
]).
dot
(
delta
);
}
ASSERT_EQUAL_TOL
(
expectedEnergyChange
,
state
.
getPotentialEnergy
()
-
prevState
.
getPotentialEnergy
(),
0.05
);
}
prevState
=
state
;
integ
.
step
(
1
);
}
}
void
testInitialTemperature
()
{
// Check temperature initialization for a collection of randomly placed particles
const
int
numRealParticles
=
500000
;
const
int
numParticles
=
2
*
numRealParticles
;
const
int
nDoF
=
3
*
numRealParticles
;
const
double
targetTemperature
=
300
;
const
double
drudeTemperature
=
1
;
const
double
realMass
=
10
;
const
double
drudeMass
=
1
;
System
system
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
std
::
vector
<
Vec3
>
positions
(
numParticles
);
DrudeForce
*
drude
=
new
DrudeForce
();
for
(
int
i
=
0
;
i
<
numRealParticles
;
i
++
)
{
system
.
addParticle
(
realMass
);
system
.
addParticle
(
drudeMass
);
positions
[
2
*
i
][
0
]
=
genrand_real2
(
sfmt
);
positions
[
2
*
i
][
1
]
=
genrand_real2
(
sfmt
);
positions
[
2
*
i
][
2
]
=
genrand_real2
(
sfmt
);
positions
[
2
*
i
+
1
][
0
]
=
positions
[
2
*
i
][
0
]
+
0.01
*
genrand_real2
(
sfmt
);
positions
[
2
*
i
+
1
][
1
]
=
positions
[
2
*
i
][
1
]
+
0.01
*
genrand_real2
(
sfmt
);
positions
[
2
*
i
+
1
][
2
]
=
positions
[
2
*
i
][
2
]
+
0.01
*
genrand_real2
(
sfmt
);
drude
->
addParticle
(
2
*
i
+
1
,
2
*
i
,
-
1
,
-
1
,
-
1
,
-
1.0
,
0.001
,
1
,
1
);
}
system
.
addForce
(
drude
);
DrudeLangevinIntegrator
integrator
(
targetTemperature
,
25
,
drudeTemperature
,
25
,
0.001
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
targetTemperature
);
auto
velocities
=
context
.
getState
(
State
::
Velocities
).
getVelocities
();
double
comKineticEnergy
=
0
;
double
relKineticEnergy
=
0
;
for
(
int
i
=
0
;
i
<
numRealParticles
;
i
++
)
{
int
m1
=
realMass
;
int
m2
=
drudeMass
;
Vec3
v1
=
velocities
[
2
*
i
];
Vec3
v2
=
velocities
[
2
*
i
+
1
];
double
invMass
=
1.0
/
(
m1
+
m2
);
double
redMass
=
m1
*
m2
*
invMass
;
double
fracM1
=
m1
*
invMass
;
double
fracM2
=
m2
*
invMass
;
Vec3
comVelocity
=
fracM1
*
v1
+
fracM2
*
v2
;
Vec3
relVelocity
=
v2
-
v1
;
comKineticEnergy
+=
0.5
*
(
m1
+
m2
)
*
comVelocity
.
dot
(
comVelocity
);
relKineticEnergy
+=
0.5
*
redMass
*
relVelocity
.
dot
(
relVelocity
);
}
double
comTemperature
=
(
2
*
comKineticEnergy
/
(
nDoF
*
BOLTZ
));
double
relTemperature
=
(
2
*
relKineticEnergy
/
(
nDoF
*
BOLTZ
));
std
::
cout
<<
comTemperature
<<
std
::
endl
;
std
::
cout
<<
relTemperature
<<
std
::
endl
;
//ASSERT_USUALLY_EQUAL_TOL(targetTemperature, temperature, 0.01);
}
int
main
()
{
try
{
registerDrudeReferenceKernelFactories
();
testInitialTemperature
();
testSinglePair
();
testWater
();
testForceEnergyConsistency
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/platforms/reference/tests/TestReferenceDrudeNoseHoover.cpp
View file @
4a0d763c
...
...
@@ -29,22 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
//#include "ReferenceTests.h"
#include "openmm/Platform.h"
using
namespace
OpenMM
;
using
namespace
std
;
//extern "C" OPENMM_EXPORT void registerDrudeReferenceKernelFactories();
Platform
&
initializePlatform
(
int
argc
,
char
*
argv
[])
{
/* registerDrudeReferenceKernelFactories();
*/
return
Platform
::
getPlatformByName
(
"Reference"
);
}
#include "ReferenceDrudeTests.h"
#include "TestDrudeNoseHoover.h"
void
runPlatformTests
()
{
}
void
runPlatformTests
()
{}
plugins/drude/platforms/reference/tests/TestReferenceDrudeSCFIntegrator.cpp
View file @
4a0d763c
...
...
@@ -29,113 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests the Reference implementation of DrudeSCFIntegrator.
*/
#include "ReferenceDrudeTests.h"
#include "TestDrudeSCFIntegrator.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VirtualSite.h"
#include "openmm/DrudeForce.h"
#include "openmm/DrudeSCFIntegrator.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
extern
"C"
OPENMM_EXPORT
void
registerDrudeReferenceKernelFactories
();
void
testWater
()
{
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const
int
gridSize
=
3
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
1.0
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
15.6
);
// O
system
.
addParticle
(
0.4
);
// D
system
.
addParticle
(
1.0
);
// H1
system
.
addParticle
(
1.0
);
// H2
system
.
addParticle
(
0.0
);
// M
nonbonded
->
addParticle
(
1.71636
,
0.318395
,
0.21094
*
4.184
);
nonbonded
->
addParticle
(
-
1.71636
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.11466
,
1
,
0
);
for
(
int
j
=
0
;
j
<
5
;
j
++
)
for
(
int
k
=
0
;
k
<
j
;
k
++
)
nonbonded
->
addException
(
startIndex
+
j
,
startIndex
+
k
,
0
,
1
,
0
);
system
.
addConstraint
(
startIndex
,
startIndex
+
2
,
0.09572
);
system
.
addConstraint
(
startIndex
,
startIndex
+
3
,
0.09572
);
system
.
addConstraint
(
startIndex
+
2
,
startIndex
+
3
,
0.15139
);
system
.
setVirtualSite
(
startIndex
+
4
,
new
ThreeParticleAverageSite
(
startIndex
,
startIndex
+
2
,
startIndex
+
3
,
0.786646558
,
0.106676721
,
0.106676721
));
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.71636
,
ONE_4PI_EPS0
*
1.71636
*
1.71636
/
(
100000
*
4.184
),
1
,
1
);
}
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
+
Vec3
(
0.09572
,
0
,
0
));
positions
.
push_back
(
pos
+
Vec3
(
-
0.023999
,
0.092663
,
0
));
positions
.
push_back
(
pos
);
}
// Simulate it and check energy conservation and the total force on the Drude particles.
DrudeSCFIntegrator
integ
(
0.0005
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
1e-5
);
context
.
setVelocitiesToTemperature
(
300.0
);
State
state
=
context
.
getState
(
State
::
Energy
);
double
initialEnergy
;
int
numSteps
=
1000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
if
(
i
==
0
)
initialEnergy
=
state
.
getPotentialEnergy
()
+
state
.
getKineticEnergy
();
else
ASSERT_EQUAL_TOL
(
initialEnergy
,
state
.
getPotentialEnergy
()
+
state
.
getKineticEnergy
(),
0.01
);
const
vector
<
Vec3
>&
force
=
state
.
getForces
();
double
norm
=
0.0
;
for
(
int
j
=
1
;
j
<
(
int
)
force
.
size
();
j
+=
5
)
norm
+=
sqrt
(
force
[
j
].
dot
(
force
[
j
]));
norm
=
(
norm
/
numMolecules
);
ASSERT
(
norm
<
1.0
);
}
}
int
main
()
{
try
{
registerDrudeReferenceKernelFactories
();
testWater
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
void
runPlatformTests
()
{}
plugins/drude/tests/TestDrudeForce.h
0 → 100644
View file @
4a0d763c
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
void
validateForce
(
System
&
system
,
vector
<
Vec3
>&
positions
,
double
expectedEnergy
)
{
// Given a System containing a Drude force, check that its energy has the expected value.
VerletIntegrator
integ
(
1.0
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
// Try moving each particle along each axis, and see if the energy changes by the correct amount.
double
offset
=
1e-3
;
for
(
int
i
=
0
;
i
<
system
.
getNumParticles
();
i
++
)
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
vector
<
Vec3
>
offsetPos
=
positions
;
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
-
offset
;
context
.
setPositions
(
offsetPos
);
double
e1
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
offsetPos
[
i
][
j
]
=
positions
[
i
][
j
]
+
offset
;
context
.
setPositions
(
offsetPos
);
double
e2
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
).
getPotentialEnergy
();
ASSERT_EQUAL_TOL
(
state
.
getForces
()[
i
][
j
],
(
e1
-
e2
)
/
(
2
*
offset
),
1e-5
);
}
}
void
testSingleParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
ASSERT
(
!
drude
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
system
.
usesPeriodicBoundaryConditions
());
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
validateForce
(
system
,
positions
,
0.5
*
k
*
3
*
3
);
}
void
testAnisotropicParticle
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
a1
=
0.8
;
const
double
a2
=
1.1
;
const
double
k1
=
k
/
a1
;
const
double
k2
=
k
/
a2
;
const
double
k3
=
k
/
(
3
-
a1
-
a2
);
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
2
,
3
,
4
,
charge
,
alpha
,
a1
,
a2
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
5
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0.1
,
-
0.5
,
0.8
);
positions
[
2
]
=
Vec3
(
0
,
2
,
0
);
positions
[
3
]
=
Vec3
(
1
,
2
,
0
);
positions
[
4
]
=
Vec3
(
1
,
2
,
3
);
validateForce
(
system
,
positions
,
0.5
*
k1
*
0.5
*
0.5
+
0.5
*
k2
*
0.8
*
0.8
+
0.5
*
k3
*
0.1
*
0.1
);
}
double
computeScreening
(
double
r
,
double
thole
,
double
alpha1
,
double
alpha2
)
{
double
u
=
r
*
thole
/
pow
(
alpha1
*
alpha2
,
1.0
/
6.0
);
return
1.0
-
(
1.0
+
u
/
2
)
*
exp
(
-
u
);
}
void
testThole
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
thole
=
2.5
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addParticle
(
3
,
2
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
drude
->
addScreenedPair
(
0
,
1
,
thole
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
4
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
-
0.5
,
0
);
positions
[
2
]
=
Vec3
(
1
,
0
,
0
);
positions
[
3
]
=
Vec3
(
1
,
0
,
0.3
);
double
energySpring1
=
0.5
*
k
*
0.5
*
0.5
;
double
energySpring2
=
0.5
*
k
*
0.3
*
0.3
;
double
energyDipole
=
0.0
;
double
q
[]
=
{
-
charge
,
charge
,
-
charge
,
charge
};
for
(
int
i
=
0
;
i
<
2
;
i
++
)
for
(
int
j
=
2
;
j
<
4
;
j
++
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
j
];
double
r
=
sqrt
(
delta
.
dot
(
delta
));
energyDipole
+=
ONE_4PI_EPS0
*
q
[
i
]
*
q
[
j
]
*
computeScreening
(
r
,
thole
,
alpha
,
alpha
)
/
r
;
}
validateForce
(
system
,
positions
,
energySpring1
+
energySpring2
+
energyDipole
);
}
void
testChangingParameters
()
{
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
// Create the system.
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2
,
0
,
0
);
// Check the energy.
VerletIntegrator
integ
(
1.0
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
// Modify the parameters.
const
double
k2
=
ONE_4PI_EPS0
*
2.2
;
const
double
charge2
=
0.3
;
const
double
alpha2
=
ONE_4PI_EPS0
*
charge2
*
charge2
/
k2
;
drude
->
setParticleParameters
(
0
,
1
,
0
,
-
1
,
-
1
,
-
1
,
charge2
,
alpha2
,
1
,
1
);
drude
->
updateParametersInContext
(
context
);
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.5
*
k2
*
3
*
3
,
state
.
getPotentialEnergy
(),
1e-5
);
}
void
setupKernels
(
int
argc
,
char
*
argv
[]);
void
runPlatformTests
();
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
setupKernels
(
argc
,
argv
);
testSingleParticle
();
testAnisotropicParticle
();
testThole
();
testChangingParameters
();
runPlatformTests
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
plugins/drude/tests/TestDrudeLangevinIntegrator.h
0 → 100644
View file @
4a0d763c
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VirtualSite.h"
#include "openmm/DrudeForce.h"
#include "openmm/DrudeLangevinIntegrator.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
void
testSinglePair
()
{
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
const
double
k
=
ONE_4PI_EPS0
*
1.5
;
const
double
charge
=
0.1
;
const
double
alpha
=
ONE_4PI_EPS0
*
charge
*
charge
/
k
;
const
double
mass1
=
1.0
;
const
double
mass2
=
0.1
;
const
double
totalMass
=
mass1
+
mass2
;
const
double
reducedMass
=
(
mass1
*
mass2
)
/
(
mass1
+
mass2
);
const
double
maxDistance
=
0.05
;
System
system
;
system
.
addParticle
(
mass1
);
system
.
addParticle
(
mass2
);
DrudeForce
*
drude
=
new
DrudeForce
();
drude
->
addParticle
(
1
,
0
,
-
1
,
-
1
,
-
1
,
charge
,
alpha
,
1
,
1
);
system
.
addForce
(
drude
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
DrudeLangevinIntegrator
integ
(
temperature
,
20.0
,
temperatureDrude
,
20.0
,
0.003
);
integ
.
setMaxDrudeDistance
(
maxDistance
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
// Equilibrate.
integ
.
step
(
1000
);
// Compute the internal and center of mass temperatures.
double
keCM
=
0
,
keInternal
=
0
;
int
numSteps
=
10000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
10
);
State
state
=
context
.
getState
(
State
::
Velocities
|
State
::
Positions
);
const
vector
<
Vec3
>&
vel
=
state
.
getVelocities
();
Vec3
velCM
=
vel
[
0
]
*
(
mass1
/
totalMass
)
+
vel
[
1
]
*
(
mass2
/
totalMass
);
keCM
+=
0.5
*
totalMass
*
velCM
.
dot
(
velCM
);
Vec3
velInternal
=
vel
[
0
]
-
vel
[
1
];
keInternal
+=
0.5
*
reducedMass
*
velInternal
.
dot
(
velInternal
);
Vec3
delta
=
state
.
getPositions
()[
0
]
-
state
.
getPositions
()[
1
];
double
distance
=
sqrt
(
delta
.
dot
(
delta
));
ASSERT
(
distance
<=
maxDistance
*
(
1
+
1e-6
));
}
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperature
,
keCM
/
numSteps
,
0.1
);
ASSERT_USUALLY_EQUAL_TOL
(
3
*
0.5
*
BOLTZ
*
temperatureDrude
,
keInternal
/
numSteps
,
0.01
);
}
void
testWater
()
{
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const
int
gridSize
=
3
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
1.0
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
15.6
);
// O
system
.
addParticle
(
0.4
);
// D
system
.
addParticle
(
1.0
);
// H1
system
.
addParticle
(
1.0
);
// H2
system
.
addParticle
(
0.0
);
// M
nonbonded
->
addParticle
(
1.71636
,
0.318395
,
0.21094
*
4.184
);
nonbonded
->
addParticle
(
-
1.71636
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
0.55733
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.11466
,
1
,
0
);
for
(
int
j
=
0
;
j
<
5
;
j
++
)
for
(
int
k
=
0
;
k
<
j
;
k
++
)
nonbonded
->
addException
(
startIndex
+
j
,
startIndex
+
k
,
0
,
1
,
0
);
system
.
addConstraint
(
startIndex
,
startIndex
+
2
,
0.09572
);
system
.
addConstraint
(
startIndex
,
startIndex
+
3
,
0.09572
);
system
.
addConstraint
(
startIndex
+
2
,
startIndex
+
3
,
0.15139
);
system
.
setVirtualSite
(
startIndex
+
4
,
new
ThreeParticleAverageSite
(
startIndex
,
startIndex
+
2
,
startIndex
+
3
,
0.786646558
,
0.106676721
,
0.106676721
));
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.71636
,
ONE_4PI_EPS0
*
1.71636
*
1.71636
/
(
100000
*
4.184
),
1
,
1
);
}
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
+
Vec3
(
0.09572
,
0
,
0
));
positions
.
push_back
(
pos
+
Vec3
(
-
0.023999
,
0.092663
,
0
));
positions
.
push_back
(
pos
);
}
// Simulate it and check the temperature.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.0005
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
context
.
applyConstraints
(
1e-5
);
// Equilibrate.
integ
.
step
(
500
);
// Compute the internal and center of mass temperatures.
double
ke
=
0
;
int
numSteps
=
4000
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
ke
+=
context
.
getState
(
State
::
Energy
).
getKineticEnergy
();
}
ke
/=
numSteps
;
int
numStandardDof
=
3
*
3
*
numMolecules
-
system
.
getNumConstraints
();
int
numDrudeDof
=
3
*
numMolecules
;
int
numDof
=
numStandardDof
+
numDrudeDof
;
double
expectedTemp
=
(
numStandardDof
*
temperature
+
numDrudeDof
*
temperatureDrude
)
/
numDof
;
ASSERT_USUALLY_EQUAL_TOL
(
expectedTemp
,
ke
/
(
0.5
*
numDof
*
BOLTZ
),
0.03
);
}
void
testForceEnergyConsistency
()
{
// Create a box of polarizable particles.
const
int
gridSize
=
3
;
const
int
numAtoms
=
gridSize
*
gridSize
*
gridSize
;
const
double
spacing
=
0.6
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
const
double
temperatureDrude
=
10.0
;
System
system
;
vector
<
Vec3
>
positions
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
DrudeForce
*
drude
=
new
DrudeForce
();
system
.
addForce
(
nonbonded
);
system
.
addForce
(
drude
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
nonbonded
->
setCutoffDistance
(
1.0
);
nonbonded
->
setUseSwitchingFunction
(
true
);
nonbonded
->
setSwitchingDistance
(
0.9
);
nonbonded
->
setEwaldErrorTolerance
(
5e-5
);
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
int
startIndex
=
system
.
getNumParticles
();
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
1.0
,
0.3
,
1.0
);
nonbonded
->
addParticle
(
-
1.0
,
0.3
,
1.0
);
nonbonded
->
addException
(
startIndex
,
startIndex
+
1
,
0
,
1
,
0
);
drude
->
addParticle
(
startIndex
+
1
,
startIndex
,
-
1
,
-
1
,
-
1
,
-
1.0
,
0.001
,
1
,
1
);
}
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
(
i
*
spacing
,
j
*
spacing
,
k
*
spacing
);
positions
.
push_back
(
pos
);
positions
.
push_back
(
pos
);
}
// Simulate it and check that force and energy remain consistent.
DrudeLangevinIntegrator
integ
(
temperature
,
50.0
,
temperatureDrude
,
50.0
,
0.001
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
prevState
;
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
|
State
::
Positions
);
if
(
i
>
0
)
{
double
expectedEnergyChange
=
0
;
for
(
int
j
=
0
;
j
<
system
.
getNumParticles
();
j
++
)
{
Vec3
delta
=
state
.
getPositions
()[
j
]
-
prevState
.
getPositions
()[
j
];
expectedEnergyChange
-=
0.5
*
(
state
.
getForces
()[
j
]
+
prevState
.
getForces
()[
j
]).
dot
(
delta
);
}
ASSERT_EQUAL_TOL
(
expectedEnergyChange
,
state
.
getPotentialEnergy
()
-
prevState
.
getPotentialEnergy
(),
0.05
);
}
prevState
=
state
;
integ
.
step
(
1
);
}
}
void
testInitialTemperature
()
{
// Check temperature initialization for a collection of randomly placed particles
const
int
numRealParticles
=
500000
;
const
int
numParticles
=
2
*
numRealParticles
;
const
int
nDoF
=
3
*
numRealParticles
;
const
double
targetTemperature
=
300
;
const
double
drudeTemperature
=
1
;
const
double
realMass
=
10
;
const
double
drudeMass
=
1
;
System
system
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
std
::
vector
<
Vec3
>
positions
(
numParticles
);
DrudeForce
*
drude
=
new
DrudeForce
();
for
(
int
i
=
0
;
i
<
numRealParticles
;
i
++
)
{
system
.
addParticle
(
realMass
);
system
.
addParticle
(
drudeMass
);
positions
[
2
*
i
][
0
]
=
genrand_real2
(
sfmt
);
positions
[
2
*
i
][
1
]
=
genrand_real2
(
sfmt
);
positions
[
2
*
i
][
2
]
=
genrand_real2
(
sfmt
);
positions
[
2
*
i
+
1
][
0
]
=
positions
[
2
*
i
][
0
]
+
0.01
*
genrand_real2
(
sfmt
);
positions
[
2
*
i
+
1
][
1
]
=
positions
[
2
*
i
][
1
]
+
0.01
*
genrand_real2
(
sfmt
);
positions
[
2
*
i
+
1
][
2
]
=
positions
[
2
*
i
][
2
]
+
0.01
*
genrand_real2
(
sfmt
);
drude
->
addParticle
(
2
*
i
+
1
,
2
*
i
,
-
1
,
-
1
,
-
1
,
-
1.0
,
0.001
,
1
,
1
);
}
system
.
addForce
(
drude
);
DrudeLangevinIntegrator
integrator
(
targetTemperature
,
25
,
drudeTemperature
,
25
,
0.001
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
targetTemperature
);
auto
velocities
=
context
.
getState
(
State
::
Velocities
).
getVelocities
();
double
comKineticEnergy
=
0
;
double
relKineticEnergy
=
0
;
for
(
int
i
=
0
;
i
<
numRealParticles
;
i
++
)
{
int
m1
=
realMass
;
int
m2
=
drudeMass
;
Vec3
v1
=
velocities
[
2
*
i
];
Vec3
v2
=
velocities
[
2
*
i
+
1
];
double
invMass
=
1.0
/
(
m1
+
m2
);
double
redMass
=
m1
*
m2
*
invMass
;
double
fracM1
=
m1
*
invMass
;
double
fracM2
=
m2
*
invMass
;
Vec3
comVelocity
=
fracM1
*
v1
+
fracM2
*
v2
;
Vec3
relVelocity
=
v2
-
v1
;
comKineticEnergy
+=
0.5
*
(
m1
+
m2
)
*
comVelocity
.
dot
(
comVelocity
);
relKineticEnergy
+=
0.5
*
redMass
*
relVelocity
.
dot
(
relVelocity
);
}
double
comTemperature
=
(
2
*
comKineticEnergy
/
(
nDoF
*
BOLTZ
));
double
relTemperature
=
(
2
*
relKineticEnergy
/
(
nDoF
*
BOLTZ
));
ASSERT_USUALLY_EQUAL_TOL
(
targetTemperature
,
comTemperature
,
0.01
);
ASSERT_USUALLY_EQUAL_TOL
(
drudeTemperature
,
relTemperature
,
0.01
);
}
void
setupKernels
(
int
argc
,
char
*
argv
[]);
void
runPlatformTests
();
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
setupKernels
(
argc
,
argv
);
testInitialTemperature
();
testSinglePair
();
testWater
();
testForceEnergyConsistency
();
runPlatformTests
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"FAIL - ERROR. Test failed."
<<
std
::
endl
;
return
1
;
}
std
::
cout
<<
"Done"
<<
std
::
endl
;
return
0
;
}
Prev
1
2
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