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
0e6cbcea
Commit
0e6cbcea
authored
May 09, 2012
by
Peter Eastman
Browse files
Created OpenCL implementation of CustomCompoundBondForce
parent
35aef079
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
656 additions
and
5 deletions
+656
-5
platforms/opencl/src/OpenCLBondedUtilities.cpp
platforms/opencl/src/OpenCLBondedUtilities.cpp
+6
-0
platforms/opencl/src/OpenCLBondedUtilities.h
platforms/opencl/src/OpenCLBondedUtilities.h
+8
-0
platforms/opencl/src/OpenCLKernelFactory.cpp
platforms/opencl/src/OpenCLKernelFactory.cpp
+4
-0
platforms/opencl/src/OpenCLKernels.cpp
platforms/opencl/src/OpenCLKernels.cpp
+293
-0
platforms/opencl/src/OpenCLKernels.h
platforms/opencl/src/OpenCLKernels.h
+37
-0
platforms/opencl/src/OpenCLParallelKernels.cpp
platforms/opencl/src/OpenCLParallelKernels.cpp
+36
-0
platforms/opencl/src/OpenCLParallelKernels.h
platforms/opencl/src/OpenCLParallelKernels.h
+31
-0
platforms/opencl/src/OpenCLPlatform.cpp
platforms/opencl/src/OpenCLPlatform.cpp
+1
-0
platforms/opencl/src/kernels/customCompoundBond.cl
platforms/opencl/src/kernels/customCompoundBond.cl
+38
-0
platforms/opencl/tests/TestOpenCLCustomCompoundBondForce.cpp
platforms/opencl/tests/TestOpenCLCustomCompoundBondForce.cpp
+198
-0
platforms/reference/tests/TestReferenceCustomCompoundBondForce.cpp
.../reference/tests/TestReferenceCustomCompoundBondForce.cpp
+4
-5
No files found.
platforms/opencl/src/OpenCLBondedUtilities.cpp
View file @
0e6cbcea
...
@@ -61,6 +61,10 @@ std::string OpenCLBondedUtilities::addArgument(cl::Memory& data, const string& t
...
@@ -61,6 +61,10 @@ std::string OpenCLBondedUtilities::addArgument(cl::Memory& data, const string& t
return
"customArg"
+
OpenCLExpressionUtilities
::
intToString
(
arguments
.
size
());
return
"customArg"
+
OpenCLExpressionUtilities
::
intToString
(
arguments
.
size
());
}
}
void
OpenCLBondedUtilities
::
addPrefixCode
(
const
string
&
source
)
{
prefixCode
.
push_back
(
source
);
}
void
OpenCLBondedUtilities
::
initialize
(
const
System
&
system
)
{
void
OpenCLBondedUtilities
::
initialize
(
const
System
&
system
)
{
int
numForces
=
forceAtoms
.
size
();
int
numForces
=
forceAtoms
.
size
();
if
(
numForces
==
0
)
if
(
numForces
==
0
)
...
@@ -155,6 +159,8 @@ void OpenCLBondedUtilities::initialize(const System& system) {
...
@@ -155,6 +159,8 @@ void OpenCLBondedUtilities::initialize(const System& system) {
const
vector
<
int
>&
set
=
*
iter
;
const
vector
<
int
>&
set
=
*
iter
;
int
setSize
=
set
.
size
();
int
setSize
=
set
.
size
();
stringstream
s
;
stringstream
s
;
for
(
int
i
=
0
;
i
<
(
int
)
prefixCode
.
size
();
i
++
)
s
<<
prefixCode
[
i
];
s
<<
"__kernel void computeBondedForces(__global float4* restrict forceBuffers, __global float* restrict energyBuffer, __global const float4* restrict posq, int groups"
;
s
<<
"__kernel void computeBondedForces(__global float4* restrict forceBuffers, __global float* restrict energyBuffer, __global const float4* restrict posq, int groups"
;
for
(
int
i
=
0
;
i
<
setSize
;
i
++
)
{
for
(
int
i
=
0
;
i
<
setSize
;
i
++
)
{
int
force
=
set
[
i
];
int
force
=
set
[
i
];
...
...
platforms/opencl/src/OpenCLBondedUtilities.h
View file @
0e6cbcea
...
@@ -100,6 +100,13 @@ public:
...
@@ -100,6 +100,13 @@ public:
* refer to it by this name.
* refer to it by this name.
*/
*/
std
::
string
addArgument
(
cl
::
Memory
&
data
,
const
std
::
string
&
type
);
std
::
string
addArgument
(
cl
::
Memory
&
data
,
const
std
::
string
&
type
);
/**
* Add some OpenCL code that should be included in the program, before the start of the kernel.
* This can be used, for example, to define functions that will be called by the kernel.
*
* @param source the code to include
*/
void
addPrefixCode
(
const
std
::
string
&
source
);
/**
/**
* Initialize this object in preparation for a simulation.
* Initialize this object in preparation for a simulation.
*/
*/
...
@@ -129,6 +136,7 @@ private:
...
@@ -129,6 +136,7 @@ private:
std
::
vector
<
std
::
string
>
argTypes
;
std
::
vector
<
std
::
string
>
argTypes
;
std
::
vector
<
OpenCLArray
<
cl_uint
>*>
atomIndices
;
std
::
vector
<
OpenCLArray
<
cl_uint
>*>
atomIndices
;
std
::
vector
<
OpenCLArray
<
cl_uint
>*>
bufferIndices
;
std
::
vector
<
OpenCLArray
<
cl_uint
>*>
bufferIndices
;
std
::
vector
<
std
::
string
>
prefixCode
;
int
numForceBuffers
,
maxBonds
;
int
numForceBuffers
,
maxBonds
;
bool
hasInitializedKernels
;
bool
hasInitializedKernels
;
};
};
...
...
platforms/opencl/src/OpenCLKernelFactory.cpp
View file @
0e6cbcea
...
@@ -62,6 +62,8 @@ KernelImpl* OpenCLKernelFactory::createKernelImpl(std::string name, const Platfo
...
@@ -62,6 +62,8 @@ KernelImpl* OpenCLKernelFactory::createKernelImpl(std::string name, const Platfo
return
new
OpenCLParallelCalcCustomExternalForceKernel
(
name
,
platform
,
data
,
context
.
getSystem
());
return
new
OpenCLParallelCalcCustomExternalForceKernel
(
name
,
platform
,
data
,
context
.
getSystem
());
if
(
name
==
CalcCustomHbondForceKernel
::
Name
())
if
(
name
==
CalcCustomHbondForceKernel
::
Name
())
return
new
OpenCLParallelCalcCustomHbondForceKernel
(
name
,
platform
,
data
,
context
.
getSystem
());
return
new
OpenCLParallelCalcCustomHbondForceKernel
(
name
,
platform
,
data
,
context
.
getSystem
());
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
return
new
OpenCLParallelCalcCustomCompoundBondForceKernel
(
name
,
platform
,
data
,
context
.
getSystem
());
}
}
OpenCLContext
&
cl
=
*
data
.
contexts
[
0
];
OpenCLContext
&
cl
=
*
data
.
contexts
[
0
];
if
(
name
==
CalcForcesAndEnergyKernel
::
Name
())
if
(
name
==
CalcForcesAndEnergyKernel
::
Name
())
...
@@ -100,6 +102,8 @@ KernelImpl* OpenCLKernelFactory::createKernelImpl(std::string name, const Platfo
...
@@ -100,6 +102,8 @@ KernelImpl* OpenCLKernelFactory::createKernelImpl(std::string name, const Platfo
return
new
OpenCLCalcCustomExternalForceKernel
(
name
,
platform
,
cl
,
context
.
getSystem
());
return
new
OpenCLCalcCustomExternalForceKernel
(
name
,
platform
,
cl
,
context
.
getSystem
());
if
(
name
==
CalcCustomHbondForceKernel
::
Name
())
if
(
name
==
CalcCustomHbondForceKernel
::
Name
())
return
new
OpenCLCalcCustomHbondForceKernel
(
name
,
platform
,
cl
,
context
.
getSystem
());
return
new
OpenCLCalcCustomHbondForceKernel
(
name
,
platform
,
cl
,
context
.
getSystem
());
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
return
new
OpenCLCalcCustomCompoundBondForceKernel
(
name
,
platform
,
cl
,
context
.
getSystem
());
if
(
name
==
IntegrateVerletStepKernel
::
Name
())
if
(
name
==
IntegrateVerletStepKernel
::
Name
())
return
new
OpenCLIntegrateVerletStepKernel
(
name
,
platform
,
cl
);
return
new
OpenCLIntegrateVerletStepKernel
(
name
,
platform
,
cl
);
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
...
...
platforms/opencl/src/OpenCLKernels.cpp
View file @
0e6cbcea
...
@@ -31,6 +31,7 @@
...
@@ -31,6 +31,7 @@
#include "openmm/internal/AndersenThermostatImpl.h"
#include "openmm/internal/AndersenThermostatImpl.h"
#include "openmm/internal/CMAPTorsionForceImpl.h"
#include "openmm/internal/CMAPTorsionForceImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "OpenCLBondedUtilities.h"
#include "OpenCLBondedUtilities.h"
...
@@ -3196,6 +3197,298 @@ double OpenCLCalcCustomHbondForceKernel::execute(ContextImpl& context, bool incl
...
@@ -3196,6 +3197,298 @@ double OpenCLCalcCustomHbondForceKernel::execute(ContextImpl& context, bool incl
return
0.0
;
return
0.0
;
}
}
class
OpenCLCustomCompoundBondForceInfo
:
public
OpenCLForceInfo
{
public:
OpenCLCustomCompoundBondForceInfo
(
const
CustomCompoundBondForce
&
force
)
:
OpenCLForceInfo
(
1
),
force
(
force
)
{
}
int
getNumParticleGroups
()
{
return
force
.
getNumBonds
();
}
void
getParticlesInGroup
(
int
index
,
vector
<
int
>&
particles
)
{
vector
<
double
>
parameters
;
force
.
getBondParameters
(
index
,
particles
,
parameters
);
}
bool
areGroupsIdentical
(
int
group1
,
int
group2
)
{
vector
<
int
>
particles
;
vector
<
double
>
parameters1
,
parameters2
;
force
.
getBondParameters
(
group1
,
particles
,
parameters1
);
force
.
getBondParameters
(
group2
,
particles
,
parameters2
);
for
(
int
i
=
0
;
i
<
(
int
)
parameters1
.
size
();
i
++
)
if
(
parameters1
[
i
]
!=
parameters2
[
i
])
return
false
;
return
true
;
}
private:
const
CustomCompoundBondForce
&
force
;
};
OpenCLCalcCustomCompoundBondForceKernel
::~
OpenCLCalcCustomCompoundBondForceKernel
()
{
if
(
params
!=
NULL
)
delete
params
;
if
(
globals
!=
NULL
)
delete
globals
;
if
(
tabulatedFunctionParams
!=
NULL
)
delete
tabulatedFunctionParams
;
for
(
int
i
=
0
;
i
<
(
int
)
tabulatedFunctions
.
size
();
i
++
)
delete
tabulatedFunctions
[
i
];
}
void
OpenCLCalcCustomCompoundBondForceKernel
::
initialize
(
const
System
&
system
,
const
CustomCompoundBondForce
&
force
)
{
int
numContexts
=
cl
.
getPlatformData
().
contexts
.
size
();
int
startIndex
=
cl
.
getContextIndex
()
*
force
.
getNumBonds
()
/
numContexts
;
int
endIndex
=
(
cl
.
getContextIndex
()
+
1
)
*
force
.
getNumBonds
()
/
numContexts
;
numBonds
=
endIndex
-
startIndex
;
if
(
numBonds
==
0
)
return
;
int
particlesPerBond
=
force
.
getNumParticlesPerBond
();
vector
<
vector
<
int
>
>
atoms
(
numBonds
,
vector
<
int
>
(
particlesPerBond
));
params
=
new
OpenCLParameterSet
(
cl
,
force
.
getNumPerBondParameters
(),
numBonds
,
"customCompoundBondParams"
);
vector
<
vector
<
cl_float
>
>
paramVector
(
numBonds
);
for
(
int
i
=
0
;
i
<
numBonds
;
i
++
)
{
vector
<
double
>
parameters
;
force
.
getBondParameters
(
startIndex
+
i
,
atoms
[
i
],
parameters
);
paramVector
[
i
].
resize
(
parameters
.
size
());
for
(
int
j
=
0
;
j
<
(
int
)
parameters
.
size
();
j
++
)
paramVector
[
i
][
j
]
=
(
cl_float
)
parameters
[
j
];
}
params
->
setParameterValues
(
paramVector
);
cl
.
addForce
(
new
OpenCLCustomCompoundBondForceInfo
(
force
));
// Record the tabulated functions.
OpenCLExpressionUtilities
::
FunctionPlaceholder
fp
;
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
vector
<
pair
<
string
,
string
>
>
functionDefinitions
;
vector
<
mm_float4
>
tabulatedFunctionParamsVec
(
force
.
getNumFunctions
());
stringstream
tableArgs
;
for
(
int
i
=
0
;
i
<
force
.
getNumFunctions
();
i
++
)
{
string
name
;
vector
<
double
>
values
;
double
min
,
max
;
force
.
getFunctionParameters
(
i
,
name
,
values
,
min
,
max
);
functions
[
name
]
=
&
fp
;
tabulatedFunctionParamsVec
[
i
]
=
mm_float4
((
float
)
min
,
(
float
)
max
,
(
float
)
((
values
.
size
()
-
1
)
/
(
max
-
min
)),
(
float
)
values
.
size
()
-
2
);
vector
<
mm_float4
>
f
=
OpenCLExpressionUtilities
::
computeFunctionCoefficients
(
values
,
min
,
max
);
OpenCLArray
<
mm_float4
>*
array
=
new
OpenCLArray
<
mm_float4
>
(
cl
,
values
.
size
()
-
1
,
"TabulatedFunction"
);
tabulatedFunctions
.
push_back
(
array
);
array
->
upload
(
f
);
string
arrayName
=
cl
.
getBondedUtilities
().
addArgument
(
array
->
getDeviceBuffer
(),
"float4"
);
functionDefinitions
.
push_back
(
make_pair
(
name
,
arrayName
));
}
string
functionParamsName
;
if
(
force
.
getNumFunctions
()
>
0
)
{
tabulatedFunctionParams
=
new
OpenCLArray
<
mm_float4
>
(
cl
,
tabulatedFunctionParamsVec
.
size
(),
"tabulatedFunctionParameters"
,
false
,
CL_MEM_READ_ONLY
);
tabulatedFunctionParams
->
upload
(
tabulatedFunctionParamsVec
);
functionParamsName
=
cl
.
getBondedUtilities
().
addArgument
(
tabulatedFunctionParams
->
getDeviceBuffer
(),
"float4"
);
}
// Record information about parameters.
globalParamNames
.
resize
(
force
.
getNumGlobalParameters
());
globalParamValues
.
resize
(
force
.
getNumGlobalParameters
());
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
{
globalParamNames
[
i
]
=
force
.
getGlobalParameterName
(
i
);
globalParamValues
[
i
]
=
(
cl_float
)
force
.
getGlobalParameterDefaultValue
(
i
);
}
map
<
string
,
string
>
variables
;
for
(
int
i
=
0
;
i
<
particlesPerBond
;
i
++
)
{
string
index
=
intToString
(
i
+
1
);
variables
[
"x"
+
index
]
=
"pos"
+
index
+
".x"
;
variables
[
"y"
+
index
]
=
"pos"
+
index
+
".y"
;
variables
[
"z"
+
index
]
=
"pos"
+
index
+
".z"
;
}
for
(
int
i
=
0
;
i
<
force
.
getNumPerBondParameters
();
i
++
)
{
const
string
&
name
=
force
.
getPerBondParameterName
(
i
);
variables
[
name
]
=
"bondParams"
+
params
->
getParameterSuffix
(
i
);
}
if
(
force
.
getNumGlobalParameters
()
>
0
)
{
globals
=
new
OpenCLArray
<
cl_float
>
(
cl
,
force
.
getNumGlobalParameters
(),
"customCompoundBondGlobals"
,
false
,
CL_MEM_READ_ONLY
);
globals
->
upload
(
globalParamValues
);
string
argName
=
cl
.
getBondedUtilities
().
addArgument
(
globals
->
getDeviceBuffer
(),
"float"
);
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
{
const
string
&
name
=
force
.
getGlobalParameterName
(
i
);
string
value
=
argName
+
"["
+
intToString
(
i
)
+
"]"
;
variables
[
name
]
=
value
;
}
}
// Now to generate the kernel. First, it needs to calculate all distances, angles,
// and dihedrals the expression depends on.
map
<
string
,
vector
<
int
>
>
distances
;
map
<
string
,
vector
<
int
>
>
angles
;
map
<
string
,
vector
<
int
>
>
dihedrals
;
Lepton
::
ParsedExpression
energyExpression
=
CustomCompoundBondForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
map
<
string
,
Lepton
::
ParsedExpression
>
forceExpressions
;
set
<
string
>
computedDeltas
;
vector
<
string
>
atomNames
,
posNames
;
for
(
int
i
=
0
;
i
<
particlesPerBond
;
i
++
)
{
string
index
=
intToString
(
i
+
1
);
atomNames
.
push_back
(
"P"
+
index
);
posNames
.
push_back
(
"pos"
+
index
);
}
stringstream
compute
;
int
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
atoms
=
iter
->
second
;
string
deltaName
=
atomNames
[
atoms
[
0
]]
+
atomNames
[
atoms
[
1
]];
if
(
computedDeltas
.
count
(
deltaName
)
==
0
)
{
compute
<<
"float4 delta"
<<
deltaName
<<
" = ccb_delta("
<<
posNames
[
atoms
[
0
]]
<<
", "
<<
posNames
[
atoms
[
1
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName
);
}
compute
<<
"float r_"
<<
deltaName
<<
" = sqrt(delta"
<<
deltaName
<<
".w);
\n
"
;
variables
[
iter
->
first
]
=
"r_"
+
deltaName
;
forceExpressions
[
"float dEdDistance"
+
intToString
(
index
)
+
" = "
]
=
energyExpression
.
differentiate
(
iter
->
first
).
optimize
();
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
atoms
=
iter
->
second
;
string
deltaName1
=
atomNames
[
atoms
[
1
]]
+
atomNames
[
atoms
[
0
]];
string
deltaName2
=
atomNames
[
atoms
[
1
]]
+
atomNames
[
atoms
[
2
]];
string
angleName
=
"angle_"
+
atomNames
[
atoms
[
0
]]
+
atomNames
[
atoms
[
1
]]
+
atomNames
[
atoms
[
2
]];
if
(
computedDeltas
.
count
(
deltaName1
)
==
0
)
{
compute
<<
"float4 delta"
<<
deltaName1
<<
" = ccb_delta("
<<
posNames
[
atoms
[
1
]]
<<
", "
<<
posNames
[
atoms
[
0
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName1
);
}
if
(
computedDeltas
.
count
(
deltaName2
)
==
0
)
{
compute
<<
"float4 delta"
<<
deltaName2
<<
" = ccb_delta("
<<
posNames
[
atoms
[
1
]]
<<
", "
<<
posNames
[
atoms
[
2
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName2
);
}
compute
<<
"float "
<<
angleName
<<
" = ccb_computeAngle(delta"
<<
deltaName1
<<
", delta"
<<
deltaName2
<<
");
\n
"
;
variables
[
iter
->
first
]
=
angleName
;
forceExpressions
[
"float dEdAngle"
+
intToString
(
index
)
+
" = "
]
=
energyExpression
.
differentiate
(
iter
->
first
).
optimize
();
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
atoms
=
iter
->
second
;
string
deltaName1
=
atomNames
[
atoms
[
0
]]
+
atomNames
[
atoms
[
1
]];
string
deltaName2
=
atomNames
[
atoms
[
2
]]
+
atomNames
[
atoms
[
1
]];
string
deltaName3
=
atomNames
[
atoms
[
2
]]
+
atomNames
[
atoms
[
3
]];
string
crossName1
=
"cross_"
+
deltaName1
+
"_"
+
deltaName2
;
string
crossName2
=
"cross_"
+
deltaName2
+
"_"
+
deltaName3
;
string
dihedralName
=
"dihedral_"
+
atomNames
[
atoms
[
0
]]
+
atomNames
[
atoms
[
1
]]
+
atomNames
[
atoms
[
2
]]
+
atomNames
[
atoms
[
3
]];
if
(
computedDeltas
.
count
(
deltaName1
)
==
0
)
{
compute
<<
"float4 delta"
<<
deltaName1
<<
" = ccb_delta("
<<
posNames
[
atoms
[
0
]]
<<
", "
<<
posNames
[
atoms
[
1
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName1
);
}
if
(
computedDeltas
.
count
(
deltaName2
)
==
0
)
{
compute
<<
"float4 delta"
<<
deltaName2
<<
" = ccb_delta("
<<
posNames
[
atoms
[
2
]]
<<
", "
<<
posNames
[
atoms
[
1
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName2
);
}
if
(
computedDeltas
.
count
(
deltaName3
)
==
0
)
{
compute
<<
"float4 delta"
<<
deltaName3
<<
" = ccb_delta("
<<
posNames
[
atoms
[
2
]]
<<
", "
<<
posNames
[
atoms
[
3
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName3
);
}
compute
<<
"float4 "
<<
crossName1
<<
" = ccb_computeCross(delta"
<<
deltaName1
<<
", delta"
<<
deltaName2
<<
");
\n
"
;
compute
<<
"float4 "
<<
crossName2
<<
" = ccb_computeCross(delta"
<<
deltaName2
<<
", delta"
<<
deltaName3
<<
");
\n
"
;
compute
<<
"float "
<<
dihedralName
<<
" = ccb_computeAngle("
<<
crossName1
<<
", "
<<
crossName2
<<
");
\n
"
;
compute
<<
dihedralName
<<
" *= (delta"
<<
deltaName1
<<
".x*"
<<
crossName2
<<
".x + delta"
<<
deltaName1
<<
".y*"
<<
crossName2
<<
".y + delta"
<<
deltaName1
<<
".z*"
<<
crossName2
<<
".z < 0 ? -1 : 1);
\n
"
;
variables
[
iter
->
first
]
=
dihedralName
;
forceExpressions
[
"float dEdDihedral"
+
intToString
(
index
)
+
" = "
]
=
energyExpression
.
differentiate
(
iter
->
first
).
optimize
();
}
// Now evaluate the expressions.
for
(
int
i
=
0
;
i
<
(
int
)
params
->
getBuffers
().
size
();
i
++
)
{
const
OpenCLNonbondedUtilities
::
ParameterInfo
&
buffer
=
params
->
getBuffers
()[
i
];
string
argName
=
cl
.
getBondedUtilities
().
addArgument
(
buffer
.
getMemory
(),
buffer
.
getType
());
compute
<<
buffer
.
getType
()
<<
" bondParams"
<<
(
i
+
1
)
<<
" = "
<<
argName
<<
"[index];
\n
"
;
}
forceExpressions
[
"energy += "
]
=
energyExpression
;
compute
<<
OpenCLExpressionUtilities
::
createExpressions
(
forceExpressions
,
variables
,
functionDefinitions
,
"temp"
,
functionParamsName
);
// Finally, apply forces to atoms.
vector
<
string
>
forceNames
;
for
(
int
i
=
0
;
i
<
particlesPerBond
;
i
++
)
{
string
istr
=
intToString
(
i
+
1
);
string
forceName
=
"force"
+
istr
;
forceNames
.
push_back
(
forceName
);
compute
<<
"float4 "
<<
forceName
<<
" = (float4) (0.0f, 0.0f, 0.0f, 0.0f);
\n
"
;
compute
<<
"{
\n
"
;
Lepton
::
ParsedExpression
forceExpressionX
=
energyExpression
.
differentiate
(
"x"
+
istr
).
optimize
();
Lepton
::
ParsedExpression
forceExpressionY
=
energyExpression
.
differentiate
(
"y"
+
istr
).
optimize
();
Lepton
::
ParsedExpression
forceExpressionZ
=
energyExpression
.
differentiate
(
"z"
+
istr
).
optimize
();
map
<
string
,
Lepton
::
ParsedExpression
>
expressions
;
if
(
!
isZeroExpression
(
forceExpressionX
))
expressions
[
forceName
+
".x -= "
]
=
forceExpressionX
;
if
(
!
isZeroExpression
(
forceExpressionY
))
expressions
[
forceName
+
".y -= "
]
=
forceExpressionY
;
if
(
!
isZeroExpression
(
forceExpressionZ
))
expressions
[
forceName
+
".z -= "
]
=
forceExpressionZ
;
if
(
expressions
.
size
()
>
0
)
compute
<<
OpenCLExpressionUtilities
::
createExpressions
(
expressions
,
variables
,
functionDefinitions
,
"coordtemp"
,
functionParamsName
);
compute
<<
"}
\n
"
;
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
atoms
=
iter
->
second
;
string
deltaName
=
atomNames
[
atoms
[
0
]]
+
atomNames
[
atoms
[
1
]];
string
value
=
"(dEdDistance"
+
intToString
(
index
)
+
"/r_"
+
deltaName
+
")*delta"
+
deltaName
+
".xyz"
;
compute
<<
forceNames
[
atoms
[
0
]]
<<
".xyz += "
<<
"-"
<<
value
<<
";
\n
"
;
compute
<<
forceNames
[
atoms
[
1
]]
<<
".xyz += "
<<
value
<<
";
\n
"
;
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
atoms
=
iter
->
second
;
string
deltaName1
=
atomNames
[
atoms
[
1
]]
+
atomNames
[
atoms
[
0
]];
string
deltaName2
=
atomNames
[
atoms
[
1
]]
+
atomNames
[
atoms
[
2
]];
compute
<<
"{
\n
"
;
compute
<<
"float4 crossProd = cross(delta"
<<
deltaName2
<<
", delta"
<<
deltaName1
<<
");
\n
"
;
compute
<<
"float lengthCross = max(length(crossProd), 1e-6f);
\n
"
;
compute
<<
"float4 deltaCross0 = -cross(delta"
<<
deltaName1
<<
", crossProd)*dEdAngle"
<<
intToString
(
index
)
<<
"/(delta"
<<
deltaName1
<<
".w*lengthCross);
\n
"
;
compute
<<
"float4 deltaCross2 = cross(delta"
<<
deltaName2
<<
", crossProd)*dEdAngle"
<<
intToString
(
index
)
<<
"/(delta"
<<
deltaName2
<<
".w*lengthCross);
\n
"
;
compute
<<
"float4 deltaCross1 = -(deltaCross0+deltaCross2);
\n
"
;
compute
<<
forceNames
[
atoms
[
0
]]
<<
".xyz += deltaCross0.xyz;
\n
"
;
compute
<<
forceNames
[
atoms
[
1
]]
<<
".xyz += deltaCross1.xyz;
\n
"
;
compute
<<
forceNames
[
atoms
[
2
]]
<<
".xyz += deltaCross2.xyz;
\n
"
;
compute
<<
"}
\n
"
;
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
atoms
=
iter
->
second
;
string
deltaName1
=
atomNames
[
atoms
[
0
]]
+
atomNames
[
atoms
[
1
]];
string
deltaName2
=
atomNames
[
atoms
[
2
]]
+
atomNames
[
atoms
[
1
]];
string
deltaName3
=
atomNames
[
atoms
[
2
]]
+
atomNames
[
atoms
[
3
]];
string
crossName1
=
"cross_"
+
deltaName1
+
"_"
+
deltaName2
;
string
crossName2
=
"cross_"
+
deltaName2
+
"_"
+
deltaName3
;
compute
<<
"{
\n
"
;
compute
<<
"float r = sqrt(delta"
<<
deltaName2
<<
".w);
\n
"
;
compute
<<
"float4 ff;
\n
"
;
compute
<<
"ff.x = (-dEdDihedral"
<<
intToString
(
index
)
<<
"*r)/"
<<
crossName1
<<
".w;
\n
"
;
compute
<<
"ff.y = (delta"
<<
deltaName1
<<
".x*delta"
<<
deltaName2
<<
".x + delta"
<<
deltaName1
<<
".y*delta"
<<
deltaName2
<<
".y + delta"
<<
deltaName1
<<
".z*delta"
<<
deltaName2
<<
".z)/delta"
<<
deltaName2
<<
".w;
\n
"
;
compute
<<
"ff.z = (delta"
<<
deltaName3
<<
".x*delta"
<<
deltaName2
<<
".x + delta"
<<
deltaName3
<<
".y*delta"
<<
deltaName2
<<
".y + delta"
<<
deltaName3
<<
".z*delta"
<<
deltaName2
<<
".z)/delta"
<<
deltaName2
<<
".w;
\n
"
;
compute
<<
"ff.w = (dEdDihedral"
<<
intToString
(
index
)
<<
"*r)/"
<<
crossName2
<<
".w;
\n
"
;
compute
<<
"float4 internalF0 = ff.x*"
<<
crossName1
<<
";
\n
"
;
compute
<<
"float4 internalF3 = ff.w*"
<<
crossName2
<<
";
\n
"
;
compute
<<
"float4 s = ff.y*internalF0 - ff.z*internalF3;
\n
"
;
compute
<<
forceNames
[
atoms
[
0
]]
<<
".xyz += internalF0.xyz;
\n
"
;
compute
<<
forceNames
[
atoms
[
1
]]
<<
".xyz += s.xyz-internalF0.xyz;
\n
"
;
compute
<<
forceNames
[
atoms
[
2
]]
<<
".xyz += -s.xyz-internalF3.xyz;
\n
"
;
compute
<<
forceNames
[
atoms
[
3
]]
<<
".xyz += internalF3.xyz;
\n
"
;
compute
<<
"}
\n
"
;
}
cl
.
getBondedUtilities
().
addInteraction
(
atoms
,
compute
.
str
(),
force
.
getForceGroup
());
map
<
string
,
string
>
replacements
;
replacements
[
"M_PI"
]
=
doubleToString
(
M_PI
);
cl
.
getBondedUtilities
().
addPrefixCode
(
cl
.
replaceStrings
(
OpenCLKernelSources
::
customCompoundBond
,
replacements
));;
}
double
OpenCLCalcCustomCompoundBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
if
(
globals
!=
NULL
)
{
bool
changed
=
false
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParamNames
.
size
();
i
++
)
{
cl_float
value
=
(
cl_float
)
context
.
getParameter
(
globalParamNames
[
i
]);
if
(
value
!=
globalParamValues
[
i
])
changed
=
true
;
globalParamValues
[
i
]
=
value
;
}
if
(
changed
)
globals
->
upload
(
globalParamValues
);
}
return
0.0
;
}
OpenCLIntegrateVerletStepKernel
::~
OpenCLIntegrateVerletStepKernel
()
{
OpenCLIntegrateVerletStepKernel
::~
OpenCLIntegrateVerletStepKernel
()
{
}
}
...
...
platforms/opencl/src/OpenCLKernels.h
View file @
0e6cbcea
...
@@ -762,6 +762,43 @@ private:
...
@@ -762,6 +762,43 @@ private:
cl
::
Kernel
donorKernel
,
acceptorKernel
;
cl
::
Kernel
donorKernel
,
acceptorKernel
;
};
};
/**
* This kernel is invoked by CustomCompoundBondForce to calculate the forces acting on the system.
*/
class
OpenCLCalcCustomCompoundBondForceKernel
:
public
CalcCustomCompoundBondForceKernel
{
public:
OpenCLCalcCustomCompoundBondForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
OpenCLContext
&
cl
,
System
&
system
)
:
CalcCustomCompoundBondForceKernel
(
name
,
platform
),
cl
(
cl
),
params
(
NULL
),
globals
(
NULL
),
tabulatedFunctionParams
(
NULL
),
system
(
system
)
{
}
~
OpenCLCalcCustomCompoundBondForceKernel
();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the CustomCompoundBondForce this kernel will be used for
*/
void
initialize
(
const
System
&
system
,
const
CustomCompoundBondForce
&
force
);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @return the potential energy due to the force
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
private:
int
numBonds
;
OpenCLContext
&
cl
;
OpenCLParameterSet
*
params
;
OpenCLArray
<
cl_float
>*
globals
;
OpenCLArray
<
mm_float4
>*
tabulatedFunctionParams
;
std
::
vector
<
std
::
string
>
globalParamNames
;
std
::
vector
<
cl_float
>
globalParamValues
;
std
::
vector
<
OpenCLArray
<
mm_float4
>*>
tabulatedFunctions
;
System
&
system
;
};
/**
/**
* This kernel is invoked by VerletIntegrator to take one time step.
* This kernel is invoked by VerletIntegrator to take one time step.
*/
*/
...
...
platforms/opencl/src/OpenCLParallelKernels.cpp
View file @
0e6cbcea
...
@@ -629,3 +629,39 @@ double OpenCLParallelCalcCustomHbondForceKernel::execute(ContextImpl& context, b
...
@@ -629,3 +629,39 @@ double OpenCLParallelCalcCustomHbondForceKernel::execute(ContextImpl& context, b
}
}
return
0.0
;
return
0.0
;
}
}
class
OpenCLParallelCalcCustomCompoundBondForceKernel
::
Task
:
public
OpenCLContext
::
WorkTask
{
public:
Task
(
ContextImpl
&
context
,
OpenCLCalcCustomCompoundBondForceKernel
&
kernel
,
bool
includeForce
,
bool
includeEnergy
,
double
&
energy
)
:
context
(
context
),
kernel
(
kernel
),
includeForce
(
includeForce
),
includeEnergy
(
includeEnergy
),
energy
(
energy
)
{
}
void
execute
()
{
energy
+=
kernel
.
execute
(
context
,
includeForce
,
includeEnergy
);
}
private:
ContextImpl
&
context
;
OpenCLCalcCustomCompoundBondForceKernel
&
kernel
;
bool
includeForce
,
includeEnergy
;
double
&
energy
;
};
OpenCLParallelCalcCustomCompoundBondForceKernel
::
OpenCLParallelCalcCustomCompoundBondForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
OpenCLPlatform
::
PlatformData
&
data
,
System
&
system
)
:
CalcCustomCompoundBondForceKernel
(
name
,
platform
),
data
(
data
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
contexts
.
size
();
i
++
)
kernels
.
push_back
(
Kernel
(
new
OpenCLCalcCustomCompoundBondForceKernel
(
name
,
platform
,
*
data
.
contexts
[
i
],
system
)));
}
void
OpenCLParallelCalcCustomCompoundBondForceKernel
::
initialize
(
const
System
&
system
,
const
CustomCompoundBondForce
&
force
)
{
for
(
int
i
=
0
;
i
<
(
int
)
kernels
.
size
();
i
++
)
getKernel
(
i
).
initialize
(
system
,
force
);
}
double
OpenCLParallelCalcCustomCompoundBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
contexts
.
size
();
i
++
)
{
OpenCLContext
&
cl
=
*
data
.
contexts
[
i
];
OpenCLContext
::
WorkThread
&
thread
=
cl
.
getWorkThread
();
thread
.
addTask
(
new
Task
(
context
,
getKernel
(
i
),
includeForces
,
includeEnergy
,
data
.
contextEnergy
[
i
]));
}
return
0.0
;
}
platforms/opencl/src/OpenCLParallelKernels.h
View file @
0e6cbcea
...
@@ -462,6 +462,37 @@ private:
...
@@ -462,6 +462,37 @@ private:
std
::
vector
<
Kernel
>
kernels
;
std
::
vector
<
Kernel
>
kernels
;
};
};
/**
* This kernel is invoked by CustomCompoundBondForce to calculate the forces acting on the system.
*/
class
OpenCLParallelCalcCustomCompoundBondForceKernel
:
public
CalcCustomCompoundBondForceKernel
{
public:
OpenCLParallelCalcCustomCompoundBondForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
OpenCLPlatform
::
PlatformData
&
data
,
System
&
system
);
OpenCLCalcCustomCompoundBondForceKernel
&
getKernel
(
int
index
)
{
return
dynamic_cast
<
OpenCLCalcCustomCompoundBondForceKernel
&>
(
kernels
[
index
].
getImpl
());
}
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the CustomCompoundBondForce this kernel will be used for
*/
void
initialize
(
const
System
&
system
,
const
CustomCompoundBondForce
&
force
);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @return the potential energy due to the force
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
private:
class
Task
;
OpenCLPlatform
::
PlatformData
&
data
;
std
::
vector
<
Kernel
>
kernels
;
};
}
// namespace OpenMM
}
// namespace OpenMM
#endif
/*OPENMM_OPENCLPARALLELKERNELS_H_*/
#endif
/*OPENMM_OPENCLPARALLELKERNELS_H_*/
platforms/opencl/src/OpenCLPlatform.cpp
View file @
0e6cbcea
...
@@ -63,6 +63,7 @@ OpenCLPlatform::OpenCLPlatform() {
...
@@ -63,6 +63,7 @@ OpenCLPlatform::OpenCLPlatform() {
registerKernelFactory
(
CalcCustomGBForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomGBForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomExternalForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomExternalForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomHbondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomHbondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCompoundBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateBrownianStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateBrownianStepKernel
::
Name
(),
factory
);
...
...
platforms/opencl/src/kernels/customCompoundBond.cl
0 → 100644
View file @
0e6cbcea
/**
*
Compute
the
difference
between
two
vectors,
setting
the
fourth
component
to
the
squared
magnitude.
*/
float4
ccb_delta
(
float4
vec1,
float4
vec2
)
{
float4
result
=
(
float4
)
(
vec1.x-vec2.x,
vec1.y-vec2.y,
vec1.z-vec2.z,
0.0f
)
;
result.w
=
result.x*result.x
+
result.y*result.y
+
result.z*result.z
;
return
result
;
}
/**
*
Compute
the
angle
between
two
vectors.
The
w
component
of
each
vector
should
contain
the
squared
magnitude.
*/
float
ccb_computeAngle
(
float4
vec1,
float4
vec2
)
{
float
dotProduct
=
vec1.x*vec2.x
+
vec1.y*vec2.y
+
vec1.z*vec2.z
;
float
cosine
=
dotProduct*RSQRT
(
vec1.w*vec2.w
)
;
float
angle
;
if
(
cosine
>
0.99f
||
cosine
<
-0.99f
)
{
//
We
're
close
to
the
singularity
in
acos
()
,
so
take
the
cross
product
and
use
asin
()
instead.
float4
crossProduct
=
cross
(
vec1,
vec2
)
;
float
scale
=
vec1.w*vec2.w
;
angle
=
asin
(
SQRT
(
dot
(
crossProduct,
crossProduct
)
/scale
))
;
if
(
cosine
<
0.0f
)
angle
=
M_PI-angle
;
}
else
angle
=
acos
(
cosine
)
;
return
angle
;
}
/**
*
Compute
the
cross
product
of
two
vectors,
setting
the
fourth
component
to
the
squared
magnitude.
*/
float4
ccb_computeCross
(
float4
vec1,
float4
vec2
)
{
float4
result
=
cross
(
vec1,
vec2
)
;
result.w
=
result.x*result.x
+
result.y*result.y
+
result.z*result.z
;
return
result
;
}
platforms/opencl/tests/TestOpenCLCustomCompoundBondForce.cpp
0 → 100644
View file @
0e6cbcea
/* -------------------------------------------------------------------------- *
* 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) 2012 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. *
* -------------------------------------------------------------------------- */
/**
* This tests the OpenCL implementation of CustomCompoundBondForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "OpenCLPlatform.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
const
double
TOL
=
1e-5
;
void
testBond
()
{
OpenCLPlatform
platform
;
// Create a system using a CustomCompoundBondForce.
System
customSystem
;
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
CustomCompoundBondForce
*
custom
=
new
CustomCompoundBondForce
(
4
,
"0.5*kb*((distance(p1,p2)-b0)^2+(distance(p2,p3)-b0)^2)+0.5*ka*(angle(p2,p3,p4)-a0)^2+kt*(1+cos(dihedral(p1,p2,p3,p4)-t0))"
);
custom
->
addPerBondParameter
(
"kb"
);
custom
->
addPerBondParameter
(
"ka"
);
custom
->
addPerBondParameter
(
"kt"
);
custom
->
addPerBondParameter
(
"b0"
);
custom
->
addPerBondParameter
(
"a0"
);
custom
->
addPerBondParameter
(
"t0"
);
vector
<
int
>
particles
(
4
);
particles
[
0
]
=
0
;
particles
[
1
]
=
1
;
particles
[
2
]
=
3
;
particles
[
3
]
=
2
;
vector
<
double
>
parameters
(
6
);
parameters
[
0
]
=
1.5
;
parameters
[
1
]
=
0.8
;
parameters
[
2
]
=
0.6
;
parameters
[
3
]
=
1.1
;
parameters
[
4
]
=
2.9
;
parameters
[
5
]
=
1.3
;
custom
->
addBond
(
particles
,
parameters
);
customSystem
.
addForce
(
custom
);
// Create an identical system using standard forces.
System
standardSystem
;
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
HarmonicBondForce
*
bonds
=
new
HarmonicBondForce
();
bonds
->
addBond
(
0
,
1
,
1.1
,
1.5
);
bonds
->
addBond
(
1
,
3
,
1.1
,
1.5
);
standardSystem
.
addForce
(
bonds
);
HarmonicAngleForce
*
angles
=
new
HarmonicAngleForce
();
angles
->
addAngle
(
1
,
3
,
2
,
2.9
,
0.8
);
standardSystem
.
addForce
(
angles
);
PeriodicTorsionForce
*
torsions
=
new
PeriodicTorsionForce
();
torsions
->
addTorsion
(
0
,
1
,
3
,
2
,
1
,
1.3
,
0.6
);
standardSystem
.
addForce
(
torsions
);
// Set the atoms in various positions, and verify that both systems give identical forces and energy.
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
c1
(
customSystem
,
integrator1
,
platform
);
Context
c2
(
standardSystem
,
integrator2
,
platform
);
vector
<
Vec3
>
positions
(
4
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
c1
.
setPositions
(
positions
);
c2
.
setPositions
(
positions
);
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
for
(
int
i
=
0
;
i
<
customSystem
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s1
.
getForces
()[
i
],
s2
.
getForces
()[
i
],
TOL
);
ASSERT_EQUAL_TOL
(
s1
.
getPotentialEnergy
(),
s2
.
getPotentialEnergy
(),
TOL
);
}
}
void
testPositionDependence
()
{
OpenCLPlatform
platform
;
System
customSystem
;
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
CustomCompoundBondForce
*
custom
=
new
CustomCompoundBondForce
(
2
,
"scale1*distance(p1,p2)+scale2*x1+2*y2"
);
custom
->
addGlobalParameter
(
"scale1"
,
0.3
);
custom
->
addGlobalParameter
(
"scale2"
,
0.2
);
vector
<
int
>
particles
(
2
);
particles
[
0
]
=
0
;
particles
[
1
]
=
1
;
vector
<
double
>
parameters
;
custom
->
addBond
(
particles
,
parameters
);
customSystem
.
addForce
(
custom
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0.5
,
1
,
0
);
positions
[
1
]
=
Vec3
(
1.5
,
1
,
0
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
customSystem
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.3
*
1.0
+
0.2
*
0.5
+
2
*
1
,
state
.
getPotentialEnergy
(),
1e-5
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.3
-
0.2
,
0
,
0
),
state
.
getForces
()[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.3
,
-
2
,
0
),
state
.
getForces
()[
1
],
1e-5
);
}
void
testParallelComputation
()
{
OpenCLPlatform
platform
;
System
system
;
const
int
numParticles
=
200
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system
.
addParticle
(
1.0
);
CustomCompoundBondForce
*
force
=
new
CustomCompoundBondForce
(
2
,
(
"(distance(p1,p2)-1.1)^2"
));
vector
<
int
>
particles
(
2
);
vector
<
double
>
params
;
for
(
int
i
=
1
;
i
<
numParticles
;
i
++
)
{
particles
[
0
]
=
i
-
1
;
particles
[
1
]
=
i
;
force
->
addBond
(
particles
,
params
);
}
system
.
addForce
(
force
);
vector
<
Vec3
>
positions
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
positions
[
i
]
=
Vec3
(
i
,
0
,
0
);
VerletIntegrator
integrator1
(
0.01
);
Context
context1
(
system
,
integrator1
,
platform
);
context1
.
setPositions
(
positions
);
State
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
VerletIntegrator
integrator2
(
0.01
);
string
deviceIndex
=
platform
.
getPropertyValue
(
context1
,
OpenCLPlatform
::
OpenCLDeviceIndex
());
map
<
string
,
string
>
props
;
props
[
OpenCLPlatform
::
OpenCLDeviceIndex
()]
=
deviceIndex
+
","
+
deviceIndex
;
Context
context2
(
system
,
integrator2
,
platform
,
props
);
context2
.
setPositions
(
positions
);
State
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
1e-5
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
1e-5
);
}
int
main
()
{
try
{
testBond
();
testPositionDependence
();
testParallelComputation
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/tests/TestReferenceCustomCompoundBondForce.cpp
View file @
0e6cbcea
...
@@ -105,13 +105,12 @@ void testBond() {
...
@@ -105,13 +105,12 @@ void testBond() {
OpenMM_SFMT
::
SFMT
sfmt
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
init_gen_rand
(
0
,
sfmt
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
c1
(
customSystem
,
integrator1
,
platform
);
Context
c2
(
standardSystem
,
integrator2
,
platform
);
vector
<
Vec3
>
positions
(
4
);
vector
<
Vec3
>
positions
(
4
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
c1
(
customSystem
,
integrator1
,
platform
);
Context
c2
(
standardSystem
,
integrator2
,
platform
);
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
c1
.
setPositions
(
positions
);
c1
.
setPositions
(
positions
);
...
...
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