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
c0ccf9e3
"plugins/amoeba/openmmapi/vscode:/vscode.git/clone" did not exist on "0eb5bc0e1c9e4e9067d6dc1acdd157de8cfd75c1"
Commit
c0ccf9e3
authored
May 30, 2013
by
peastman
Browse files
Created API and reference implementation for ring polymer contraction
parent
178aa003
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
255 additions
and
24 deletions
+255
-24
plugins/rpmd/openmmapi/include/openmm/RPMDIntegrator.h
plugins/rpmd/openmmapi/include/openmm/RPMDIntegrator.h
+33
-1
plugins/rpmd/openmmapi/src/RPMDIntegrator.cpp
plugins/rpmd/openmmapi/src/RPMDIntegrator.cpp
+11
-3
plugins/rpmd/platforms/reference/src/ReferenceRpmdKernels.cpp
...ins/rpmd/platforms/reference/src/ReferenceRpmdKernels.cpp
+127
-19
plugins/rpmd/platforms/reference/src/ReferenceRpmdKernels.h
plugins/rpmd/platforms/reference/src/ReferenceRpmdKernels.h
+7
-1
plugins/rpmd/platforms/reference/tests/TestReferenceRpmd.cpp
plugins/rpmd/platforms/reference/tests/TestReferenceRpmd.cpp
+77
-0
No files found.
plugins/rpmd/openmmapi/include/openmm/RPMDIntegrator.h
View file @
c0ccf9e3
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-201
2
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -37,6 +37,7 @@
#include "openmm/State.h"
#include "openmm/Vec3.h"
#include "openmm/internal/windowsExportRpmd.h"
#include <map>
namespace
OpenMM
{
...
...
@@ -52,6 +53,14 @@ namespace OpenMM {
* to set them for specific copies of the System. Similarly, you should retrieve state information
* for particular copies by calling getState() on the Integrator. Do not query the Context for
* state information.
*
* You can optionally specify a set of "ring polymer contractions", by which different force
* groups are evaluated on different numbers of copies, instead of computing every force on
* every copy. This can be much more efficient, since different forces may vary widely in
* how many times they must be evaluated to produce sufficient accuracy. For example, you
* might simulate a 32 copy ring polymer and evaluate bonded forces on every copy, but contract
* it down to only 6 copies for computing nonbonded interactions, and down to only a single
* copy (the centroid) for computing the reciprocal space part of PME.
*/
class
OPENMM_EXPORT_RPMD
RPMDIntegrator
:
public
Integrator
{
...
...
@@ -65,6 +74,19 @@ public:
* @param stepSize the step size with which to integrator the system (in picoseconds)
*/
RPMDIntegrator
(
int
numCopies
,
double
temperature
,
double
frictionCoeff
,
double
stepSize
);
/**
* Create a RPMDIntegrator.
*
* @param numCopies the number of copies of the system that should be simulated
* @param temperature the temperature of the heat bath (in Kelvin)
* @param frictionCoeff the friction coefficient which couples the system to the heat bath (in inverse picoseconds)
* @param stepSize the step size with which to integrator the system (in picoseconds)
* @param contractions the ring polymer contractions to use for evaluating different force groups. Each key in the
* map is the index of a force group, and the corresponding value is the number of copies to evaluate
* that force group on. If no entry is provided for a force group (the default), it is evaluated
* independently on every copy.
*/
RPMDIntegrator
(
int
numCopies
,
double
temperature
,
double
frictionCoeff
,
double
stepSize
,
const
std
::
map
<
int
,
int
>&
contractions
);
/**
* Get the number of copies of the system being simulated.
*/
...
...
@@ -122,6 +144,15 @@ public:
void
setRandomNumberSeed
(
int
seed
)
{
randomNumberSeed
=
seed
;
}
/**
* Get the ring polymer contractions to use for evaluating different force groups. Each key in the
* map is the index of a force group, and the corresponding value is the number of copies to evaluate
* that force group on. If no entry is provided for a force group, it is evaluated independently on
* every copy.
*/
const
std
::
map
<
int
,
int
>&
getContractions
()
const
{
return
contractions
;
}
/**
* Set the positions of all particles in one copy of the system.
*
...
...
@@ -182,6 +213,7 @@ protected:
private:
double
temperature
,
friction
;
int
numCopies
,
randomNumberSeed
;
std
::
map
<
int
,
int
>
contractions
;
bool
forcesAreValid
,
hasSetPosition
,
hasSetVelocity
,
isFirstStep
;
Kernel
kernel
;
};
...
...
plugins/rpmd/openmmapi/src/RPMDIntegrator.cpp
View file @
c0ccf9e3
...
...
@@ -39,15 +39,23 @@
#include <string>
using
namespace
OpenMM
;
using
std
::
string
;
using
std
::
vector
;
using
namespace
std
;
RPMDIntegrator
::
RPMDIntegrator
(
int
numCopies
,
double
temperature
,
double
frictionCoeff
,
double
stepSize
,
const
map
<
int
,
int
>&
contractions
)
:
numCopies
(
numCopies
),
contractions
(
contractions
),
forcesAreValid
(
false
),
hasSetPosition
(
false
),
hasSetVelocity
(
false
),
isFirstStep
(
true
)
{
setTemperature
(
temperature
);
setFriction
(
frictionCoeff
);
setStepSize
(
stepSize
);
setConstraintTolerance
(
1e-5
);
setRandomNumberSeed
((
int
)
time
(
NULL
));
}
RPMDIntegrator
::
RPMDIntegrator
(
int
numCopies
,
double
temperature
,
double
frictionCoeff
,
double
stepSize
)
:
numCopies
(
numCopies
),
forcesAreValid
(
false
),
hasSetPosition
(
false
),
hasSetVelocity
(
false
),
isFirstStep
(
true
)
{
setTemperature
(
temperature
);
setFriction
(
frictionCoeff
);
setStepSize
(
stepSize
);
setConstraintTolerance
(
1e-
4
);
setConstraintTolerance
(
1e-
5
);
setRandomNumberSeed
((
int
)
time
(
NULL
));
}
...
...
plugins/rpmd/platforms/reference/src/ReferenceRpmdKernels.cpp
View file @
c0ccf9e3
...
...
@@ -30,6 +30,7 @@
* -------------------------------------------------------------------------- */
#include "ReferenceRpmdKernels.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "SimTKUtilities/SimTKOpenMMUtilities.h"
...
...
@@ -54,7 +55,11 @@ static vector<RealVec>& extractForces(ContextImpl& context) {
ReferenceIntegrateRPMDStepKernel
::~
ReferenceIntegrateRPMDStepKernel
()
{
if
(
fft
!=
NULL
)
fftpack_destroy
(
fft
);
for
(
map
<
int
,
fftpack
*>::
const_iterator
iter
=
contractionFFT
.
begin
();
iter
!=
contractionFFT
.
end
();
++
iter
)
if
(
iter
->
second
!=
NULL
)
fftpack_destroy
(
iter
->
second
);
}
void
ReferenceIntegrateRPMDStepKernel
::
initialize
(
const
System
&
system
,
const
RPMDIntegrator
&
integrator
)
{
int
numCopies
=
integrator
.
getNumCopies
();
int
numParticles
=
system
.
getNumParticles
();
...
...
@@ -68,6 +73,41 @@ void ReferenceIntegrateRPMDStepKernel::initialize(const System& system, const RP
}
fftpack_init_1d
(
&
fft
,
numCopies
);
SimTKOpenMMUtilities
::
setRandomNumberSeed
((
unsigned
int
)
integrator
.
getRandomNumberSeed
());
// Build a list of contractions.
groupsNotContracted
=
-
1
;
const
map
<
int
,
int
>&
contractions
=
integrator
.
getContractions
();
int
maxContractedCopies
=
0
;
for
(
map
<
int
,
int
>::
const_iterator
iter
=
contractions
.
begin
();
iter
!=
contractions
.
end
();
++
iter
)
{
int
group
=
iter
->
first
;
int
copies
=
iter
->
second
;
if
(
group
<
0
||
group
>
31
)
throw
OpenMMException
(
"RPMDIntegrator: Force group must be between 0 and 31"
);
if
(
copies
<
0
||
copies
>
numCopies
)
throw
OpenMMException
(
"RPMDIntegrator: Number of copies for contraction cannot be greater than the total number of copies being simulated"
);
if
(
copies
!=
numCopies
)
{
if
(
groupsByCopies
.
find
(
copies
)
==
groupsByCopies
.
end
())
{
groupsByCopies
[
copies
]
=
1
<<
group
;
groupsNotContracted
-=
1
<<
group
;
contractionFFT
[
copies
]
=
NULL
;
fftpack_init_1d
(
&
contractionFFT
[
copies
],
copies
);
if
(
copies
>
maxContractedCopies
)
maxContractedCopies
=
copies
;
}
else
groupsByCopies
[
copies
]
|=
1
<<
group
;
}
}
// Create workspace for doing contractions.
contractedPositions
.
resize
(
maxContractedCopies
);
contractedForces
.
resize
(
maxContractedCopies
);
for
(
int
i
=
0
;
i
<
maxContractedCopies
;
i
++
)
{
contractedPositions
[
i
].
resize
(
numParticles
);
contractedForces
[
i
].
resize
(
numParticles
);
}
}
void
ReferenceIntegrateRPMDStepKernel
::
execute
(
ContextImpl
&
context
,
const
RPMDIntegrator
&
integrator
,
bool
forcesAreValid
)
{
...
...
@@ -82,15 +122,8 @@ void ReferenceIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDI
// Loop over copies and compute the force on each one.
if
(
!
forcesAreValid
)
{
for
(
int
i
=
0
;
i
<
numCopies
;
i
++
)
{
pos
=
positions
[
i
];
vel
=
velocities
[
i
];
context
.
computeVirtualSites
();
context
.
calcForcesAndEnergy
(
true
,
false
);
forces
[
i
]
=
f
;
}
}
if
(
!
forcesAreValid
)
computeForces
(
context
,
integrator
);
// Apply the PILE-L thermostat.
...
...
@@ -176,16 +209,7 @@ void ReferenceIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDI
// Calculate forces based on the updated positions.
for
(
int
i
=
0
;
i
<
numCopies
;
i
++
)
{
pos
=
positions
[
i
];
vel
=
velocities
[
i
];
context
.
computeVirtualSites
();
context
.
updateContextState
();
positions
[
i
]
=
pos
;
velocities
[
i
]
=
vel
;
context
.
calcForcesAndEnergy
(
true
,
false
);
forces
[
i
]
=
f
;
}
computeForces
(
context
,
integrator
);
// Update velocities.
...
...
@@ -234,6 +258,90 @@ void ReferenceIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDI
context
.
setTime
(
context
.
getTime
()
+
dt
);
}
void
ReferenceIntegrateRPMDStepKernel
::
computeForces
(
ContextImpl
&
context
,
const
RPMDIntegrator
&
integrator
)
{
const
int
totalCopies
=
positions
.
size
();
const
int
numParticles
=
positions
[
0
].
size
();
vector
<
RealVec
>&
pos
=
extractPositions
(
context
);
vector
<
RealVec
>&
vel
=
extractVelocities
(
context
);
vector
<
RealVec
>&
f
=
extractForces
(
context
);
// Compute forces from all groups that didn't have a specified contraction.
for
(
int
i
=
0
;
i
<
totalCopies
;
i
++
)
{
pos
=
positions
[
i
];
vel
=
velocities
[
i
];
context
.
computeVirtualSites
();
context
.
updateContextState
();
positions
[
i
]
=
pos
;
velocities
[
i
]
=
vel
;
context
.
calcForcesAndEnergy
(
true
,
false
,
groupsNotContracted
);
forces
[
i
]
=
f
;
}
// Now loop over contractions and compute forces from them.
for
(
map
<
int
,
int
>::
const_iterator
iter
=
groupsByCopies
.
begin
();
iter
!=
groupsByCopies
.
end
();
++
iter
)
{
int
copies
=
iter
->
first
;
int
groupFlags
=
iter
->
second
;
fftpack
*
shortFFT
=
contractionFFT
[
copies
];
// Find the contracted positions.
vector
<
t_complex
>
q
(
totalCopies
);
const
RealOpenMM
scale1
=
1.0
/
totalCopies
;
for
(
int
particle
=
0
;
particle
<
numParticles
;
particle
++
)
{
for
(
int
component
=
0
;
component
<
3
;
component
++
)
{
// Transform to the frequency domain, set high frequency components to zero, and transform back.
for
(
int
k
=
0
;
k
<
totalCopies
;
k
++
)
q
[
k
]
=
t_complex
(
positions
[
k
][
particle
][
component
],
0.0
);
fftpack_exec_1d
(
fft
,
FFTPACK_FORWARD
,
&
q
[
0
],
&
q
[
0
]);
if
(
copies
>
1
)
{
int
start
=
(
copies
+
1
)
/
2
;
int
end
=
totalCopies
-
copies
+
start
;
for
(
int
k
=
end
;
k
<
totalCopies
;
k
++
)
q
[
k
-
(
totalCopies
-
copies
)]
=
q
[
k
];
fftpack_exec_1d
(
shortFFT
,
FFTPACK_BACKWARD
,
&
q
[
0
],
&
q
[
0
]);
}
for
(
int
k
=
0
;
k
<
copies
;
k
++
)
contractedPositions
[
k
][
particle
][
component
]
=
scale1
*
q
[
k
].
re
;
}
}
// Compute forces.
for
(
int
i
=
0
;
i
<
copies
;
i
++
)
{
pos
=
contractedPositions
[
i
];
context
.
computeVirtualSites
();
context
.
calcForcesAndEnergy
(
true
,
false
,
groupFlags
);
contractedForces
[
i
]
=
f
;
}
// Apply the forces to the original copies.
const
RealOpenMM
scale2
=
1.0
/
copies
;
for
(
int
particle
=
0
;
particle
<
numParticles
;
particle
++
)
{
for
(
int
component
=
0
;
component
<
3
;
component
++
)
{
// Transform to the frequency domain, pad with zeros, and transform back.
for
(
int
k
=
0
;
k
<
copies
;
k
++
)
q
[
k
]
=
t_complex
(
contractedForces
[
k
][
particle
][
component
],
0.0
);
if
(
copies
>
1
)
fftpack_exec_1d
(
shortFFT
,
FFTPACK_FORWARD
,
&
q
[
0
],
&
q
[
0
]);
int
start
=
(
copies
+
1
)
/
2
;
int
end
=
totalCopies
-
copies
+
start
;
for
(
int
k
=
end
;
k
<
totalCopies
;
k
++
)
q
[
k
]
=
q
[
k
-
(
totalCopies
-
copies
)];
for
(
int
k
=
start
;
k
<
end
;
k
++
)
q
[
k
]
=
t_complex
(
0
,
0
);
fftpack_exec_1d
(
fft
,
FFTPACK_BACKWARD
,
&
q
[
0
],
&
q
[
0
]);
for
(
int
k
=
0
;
k
<
totalCopies
;
k
++
)
forces
[
k
][
particle
][
component
]
=
scale2
*
q
[
k
].
re
;
}
}
}
}
double
ReferenceIntegrateRPMDStepKernel
::
computeKineticEnergy
(
ContextImpl
&
context
,
const
RPMDIntegrator
&
integrator
)
{
const
System
&
system
=
context
.
getSystem
();
int
numParticles
=
system
.
getNumParticles
();
...
...
plugins/rpmd/platforms/reference/src/ReferenceRpmdKernels.h
View file @
c0ccf9e3
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2011 Stanford University and the Authors.
*
* Portions copyright (c) 2011
-2013
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -85,10 +85,16 @@ public:
*/
void
copyToContext
(
int
copy
,
ContextImpl
&
context
);
private:
void
computeForces
(
ContextImpl
&
context
,
const
RPMDIntegrator
&
integrator
);
std
::
vector
<
std
::
vector
<
RealVec
>
>
positions
;
std
::
vector
<
std
::
vector
<
RealVec
>
>
velocities
;
std
::
vector
<
std
::
vector
<
RealVec
>
>
forces
;
std
::
vector
<
std
::
vector
<
RealVec
>
>
contractedPositions
;
std
::
vector
<
std
::
vector
<
RealVec
>
>
contractedForces
;
std
::
map
<
int
,
int
>
groupsByCopies
;
int
groupsNotContracted
;
fftpack
*
fft
;
std
::
map
<
int
,
fftpack
*>
contractionFFT
;
};
}
// namespace OpenMM
...
...
plugins/rpmd/platforms/reference/tests/TestReferenceRpmd.cpp
View file @
c0ccf9e3
...
...
@@ -237,11 +237,88 @@ void testVirtualSites() {
ASSERT_USUALLY_EQUAL_TOL
(
expectedKE
,
meanKE
,
1e-2
);
}
void
testContractions
()
{
const
int
gridSize
=
3
;
const
int
numMolecules
=
gridSize
*
gridSize
*
gridSize
;
const
int
numParticles
=
numMolecules
*
2
;
const
int
numCopies
=
10
;
const
double
spacing
=
2.0
;
const
double
cutoff
=
3.0
;
const
double
boxSize
=
spacing
*
(
gridSize
+
1
);
const
double
temperature
=
300.0
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
HarmonicBondForce
*
bonds
=
new
HarmonicBondForce
();
system
.
addForce
(
bonds
);
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
nonbonded
->
setCutoffDistance
(
cutoff
);
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
nonbonded
->
setForceGroup
(
1
);
nonbonded
->
setReciprocalSpaceForceGroup
(
2
);
system
.
addForce
(
nonbonded
);
// Create a cloud of molecules.
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
positions
(
numParticles
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
-
0.2
,
0.2
,
0.2
);
nonbonded
->
addParticle
(
0.2
,
0.2
,
0.2
);
nonbonded
->
addException
(
2
*
i
,
2
*
i
+
1
,
0
,
1
,
0
);
bonds
->
addBond
(
2
*
i
,
2
*
i
+
1
,
1.0
,
10000.0
);
}
map
<
int
,
int
>
contractions
;
contractions
[
1
]
=
3
;
contractions
[
2
]
=
1
;
RPMDIntegrator
integ
(
numCopies
,
temperature
,
10.0
,
0.001
,
contractions
);
Platform
&
platform
=
Platform
::
getPlatformByName
(
"Reference"
);
Context
context
(
system
,
integ
,
platform
);
for
(
int
copy
=
0
;
copy
<
numCopies
;
copy
++
)
{
for
(
int
i
=
0
;
i
<
gridSize
;
i
++
)
for
(
int
j
=
0
;
j
<
gridSize
;
j
++
)
for
(
int
k
=
0
;
k
<
gridSize
;
k
++
)
{
Vec3
pos
=
Vec3
(
spacing
*
(
i
+
0.02
*
genrand_real2
(
sfmt
)),
spacing
*
(
j
+
0.02
*
genrand_real2
(
sfmt
)),
spacing
*
(
k
+
0.02
*
genrand_real2
(
sfmt
)));
int
index
=
k
+
gridSize
*
(
j
+
gridSize
*
i
);
positions
[
2
*
index
]
=
pos
;
positions
[
2
*
index
+
1
]
=
Vec3
(
pos
[
0
]
+
1.0
,
pos
[
1
],
pos
[
2
]);
}
integ
.
setPositions
(
copy
,
positions
);
}
// Check the temperature.
const
int
numSteps
=
1000
;
integ
.
step
(
1000
);
vector
<
double
>
ke
(
numCopies
,
0.0
);
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integ
.
step
(
1
);
vector
<
State
>
state
(
numCopies
);
for
(
int
j
=
0
;
j
<
numCopies
;
j
++
)
state
[
j
]
=
integ
.
getState
(
j
,
State
::
Velocities
,
true
);
for
(
int
j
=
0
;
j
<
numParticles
;
j
++
)
{
for
(
int
k
=
0
;
k
<
numCopies
;
k
++
)
{
Vec3
v
=
state
[
k
].
getVelocities
()[
j
];
ke
[
k
]
+=
0.5
*
system
.
getParticleMass
(
j
)
*
v
.
dot
(
v
);
}
}
}
double
meanKE
=
0.0
;
for
(
int
i
=
0
;
i
<
numCopies
;
i
++
)
meanKE
+=
ke
[
i
];
meanKE
/=
numSteps
*
numCopies
;
double
expectedKE
=
0.5
*
numCopies
*
numParticles
*
3
*
BOLTZ
*
temperature
;
ASSERT_USUALLY_EQUAL_TOL
(
expectedKE
,
meanKE
,
1e-2
);
}
int
main
()
{
try
{
testFreeParticles
();
testCMMotionRemoval
();
testVirtualSites
();
testContractions
();
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"exception: "
<<
e
.
what
()
<<
std
::
endl
;
...
...
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