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
9ed2c870
Commit
9ed2c870
authored
Dec 08, 2009
by
Peter Eastman
Browse files
Continuing OpenCL implementation of CustomGBForce
parent
a966a981
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
614 additions
and
13 deletions
+614
-13
platforms/opencl/src/OpenCLKernels.cpp
platforms/opencl/src/OpenCLKernels.cpp
+200
-11
platforms/opencl/src/OpenCLKernels.h
platforms/opencl/src/OpenCLKernels.h
+1
-1
platforms/opencl/src/kernels/customGBEnergyN2_nvidia.cl
platforms/opencl/src/kernels/customGBEnergyN2_nvidia.cl
+200
-0
platforms/opencl/src/kernels/customGBEnergyPerParticle.cl
platforms/opencl/src/kernels/customGBEnergyPerParticle.cl
+23
-0
platforms/opencl/src/kernels/customGBValuePerParticle.cl
platforms/opencl/src/kernels/customGBValuePerParticle.cl
+1
-1
platforms/opencl/tests/TestOpenCLCustomGBForce.cpp
platforms/opencl/tests/TestOpenCLCustomGBForce.cpp
+189
-0
No files found.
platforms/opencl/src/OpenCLKernels.cpp
View file @
9ed2c870
...
...
@@ -1279,6 +1279,7 @@ void OpenCLCalcCustomGBForceKernel::initialize(const System& system, const Custo
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
;
...
...
@@ -1293,11 +1294,13 @@ void OpenCLCalcCustomGBForceKernel::initialize(const System& system, const Custo
tabulatedFunctions
.
push_back
(
new
OpenCLArray
<
mm_float4
>
(
cl
,
values
.
size
()
-
1
,
"TabulatedFunction"
));
tabulatedFunctions
[
tabulatedFunctions
.
size
()
-
1
]
->
upload
(
f
);
cl
.
getNonbondedUtilities
().
addArgument
(
OpenCLNonbondedUtilities
::
ParameterInfo
(
arrayName
,
"float4"
,
sizeof
(
cl_float4
),
tabulatedFunctions
[
tabulatedFunctions
.
size
()
-
1
]
->
getDeviceBuffer
()));
tableArgs
<<
", __global float4* arrayName"
;
}
if
(
force
.
getNumFunctions
()
>
0
)
{
tabulatedFunctionParams
=
new
OpenCLArray
<
mm_float4
>
(
cl
,
tabulatedFunctionParamsVec
.
size
(),
"tabulatedFunctionParameters"
,
false
,
CL_MEM_READ_ONLY
);
tabulatedFunctionParams
->
upload
(
tabulatedFunctionParamsVec
);
cl
.
getNonbondedUtilities
().
addArgument
(
OpenCLNonbondedUtilities
::
ParameterInfo
(
prefix
+
"functionParams"
,
"float4"
,
sizeof
(
cl_float4
),
tabulatedFunctionParams
->
getDeviceBuffer
()));
tableArgs
<<
", __constant float4* "
<<
prefix
<<
"functionParams"
;
}
// Record information for the expressions.
...
...
@@ -1366,7 +1369,7 @@ void OpenCLCalcCustomGBForceKernel::initialize(const System& system, const Custo
load1
<<
buffer
.
getType
()
<<
" "
<<
paramName
<<
"1 = global_"
<<
paramName
<<
"[atom1];
\n
"
;
load2
<<
buffer
.
getType
()
<<
" "
<<
paramName
<<
"2 = local_"
<<
paramName
<<
"[atom2];
\n
"
;
}
replacements
[
"PARAMETER_ARGUMENTS"
]
=
extraArgs
.
str
();
replacements
[
"PARAMETER_ARGUMENTS"
]
=
extraArgs
.
str
()
+
tableArgs
.
str
()
;
replacements
[
"LOAD_LOCAL_PARAMETERS_FROM_1"
]
=
loadLocal1
.
str
();
replacements
[
"LOAD_LOCAL_PARAMETERS_FROM_GLOBAL"
]
=
loadLocal2
.
str
();
replacements
[
"LOAD_ATOM1_PARAMETERS"
]
=
load1
.
str
();
...
...
@@ -1426,12 +1429,138 @@ void OpenCLCalcCustomGBForceKernel::initialize(const System& system, const Custo
reductionSource
<<
"global_"
<<
valueName
<<
"[index] = local_"
<<
valueName
<<
";
\n
"
;
}
map
<
string
,
string
>
replacements
;
replacements
[
"PARAMETER_ARGUMENTS"
]
=
extraArgs
.
str
();
replacements
[
"PARAMETER_ARGUMENTS"
]
=
extraArgs
.
str
()
+
tableArgs
.
str
()
;
replacements
[
"COMPUTE_VALUES"
]
=
reductionSource
.
str
();
map
<
string
,
string
>
defines
;
defines
[
"NUM_ATOMS"
]
=
intToString
(
cl
.
getNumAtoms
());
cl
::
Program
program
=
cl
.
createProgram
(
cl
.
loadSourceFromFile
(
"customGBValueReduction.cl"
,
replacements
),
defines
);
reduceValueKernel
=
cl
::
Kernel
(
program
,
"reduceGBValue"
);
cl
::
Program
program
=
cl
.
createProgram
(
cl
.
loadSourceFromFile
(
"customGBValuePerParticle.cl"
,
replacements
),
defines
);
perParticleValueKernel
=
cl
::
Kernel
(
program
,
"computePerParticleValues"
);
}
{
// Create the N2 energy kernel.
map
<
string
,
string
>
variables
;
variables
[
"r"
]
=
"r"
;
for
(
int
i
=
0
;
i
<
force
.
getNumPerParticleParameters
();
i
++
)
{
const
string
&
name
=
force
.
getPerParticleParameterName
(
i
);
variables
[
name
+
"1"
]
=
"params"
+
params
->
getParameterSuffix
(
i
,
"1"
);
variables
[
name
+
"2"
]
=
"params"
+
params
->
getParameterSuffix
(
i
,
"2"
);
}
for
(
int
i
=
0
;
i
<
force
.
getNumComputedValues
();
i
++
)
{
variables
[
computedValueNames
[
i
]
+
"1"
]
=
"values"
+
computedValues
->
getParameterSuffix
(
i
,
"1"
);
variables
[
computedValueNames
[
i
]
+
"2"
]
=
"values"
+
computedValues
->
getParameterSuffix
(
i
,
"2"
);
}
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
variables
[
force
.
getGlobalParameterName
(
i
)]
=
"globals["
+
intToString
(
i
)
+
"]"
;
map
<
string
,
Lepton
::
ParsedExpression
>
n2EnergyExpressions
;
stringstream
n2ForceSource
;
bool
anyExclusions
=
false
;
for
(
int
i
=
0
;
i
<
force
.
getNumEnergyTerms
();
i
++
)
{
string
expression
;
CustomGBForce
::
ComputationType
type
;
force
.
getEnergyTermParameters
(
i
,
expression
,
type
);
if
(
type
==
CustomGBForce
::
SingleParticle
)
continue
;
bool
exclude
=
(
type
==
CustomGBForce
::
ParticlePair
);
anyExclusions
!=
exclude
;
string
excludePrefix
=
(
exclude
?
"if (!isExcluded) "
:
""
);
n2EnergyExpressions
[
excludePrefix
+
"tempEnergy += "
]
=
Lepton
::
Parser
::
parse
(
expression
,
functions
).
optimize
();
n2EnergyExpressions
[
excludePrefix
+
"dEdR += "
]
=
Lepton
::
Parser
::
parse
(
expression
,
functions
).
differentiate
(
"r"
).
optimize
();
n2ForceSource
<<
OpenCLExpressionUtilities
::
createExpressions
(
n2EnergyExpressions
,
variables
,
functionDefinitions
,
"temp"
,
prefix
+
"functionParams"
);
}
map
<
string
,
string
>
replacements
;
replacements
[
"COMPUTE_INTERACTION"
]
=
n2ForceSource
.
str
();
stringstream
extraArgs
,
loadLocal1
,
loadLocal2
,
load1
,
load2
;
if
(
force
.
getNumGlobalParameters
()
>
0
)
extraArgs
<<
", __constant float* globals"
;
for
(
int
i
=
0
;
i
<
(
int
)
params
->
getBuffers
().
size
();
i
++
)
{
const
OpenCLNonbondedUtilities
::
ParameterInfo
&
buffer
=
params
->
getBuffers
()[
i
];
string
paramName
=
"params"
+
intToString
(
i
+
1
);
extraArgs
<<
", __global "
<<
buffer
.
getType
()
<<
"* global_"
<<
paramName
<<
", __local "
<<
buffer
.
getType
()
<<
"* local_"
<<
paramName
;
loadLocal1
<<
"local_"
<<
paramName
<<
"[get_local_id(0)] = "
<<
paramName
<<
"1;
\n
"
;
loadLocal2
<<
"local_"
<<
paramName
<<
"[get_local_id(0)] = global_"
<<
paramName
<<
"[j];
\n
"
;
load1
<<
buffer
.
getType
()
<<
" "
<<
paramName
<<
"1 = global_"
<<
paramName
<<
"[atom1];
\n
"
;
load2
<<
buffer
.
getType
()
<<
" "
<<
paramName
<<
"2 = local_"
<<
paramName
<<
"[atom2];
\n
"
;
}
for
(
int
i
=
0
;
i
<
(
int
)
computedValues
->
getBuffers
().
size
();
i
++
)
{
const
OpenCLNonbondedUtilities
::
ParameterInfo
&
buffer
=
computedValues
->
getBuffers
()[
i
];
string
valueName
=
"values"
+
intToString
(
i
+
1
);
extraArgs
<<
", __global "
<<
buffer
.
getType
()
<<
"* global_"
<<
valueName
<<
", __local "
<<
buffer
.
getType
()
<<
"* local_"
<<
valueName
;
loadLocal1
<<
"local_"
<<
valueName
<<
"[get_local_id(0)] = "
<<
valueName
<<
"1;
\n
"
;
loadLocal2
<<
"local_"
<<
valueName
<<
"[get_local_id(0)] = global_"
<<
valueName
<<
"[j];
\n
"
;
load1
<<
buffer
.
getType
()
<<
" "
<<
valueName
<<
"1 = global_"
<<
valueName
<<
"[atom1];
\n
"
;
load2
<<
buffer
.
getType
()
<<
" "
<<
valueName
<<
"2 = local_"
<<
valueName
<<
"[atom2];
\n
"
;
}
replacements
[
"PARAMETER_ARGUMENTS"
]
=
extraArgs
.
str
()
+
tableArgs
.
str
();
replacements
[
"LOAD_LOCAL_PARAMETERS_FROM_1"
]
=
loadLocal1
.
str
();
replacements
[
"LOAD_LOCAL_PARAMETERS_FROM_GLOBAL"
]
=
loadLocal2
.
str
();
replacements
[
"LOAD_ATOM1_PARAMETERS"
]
=
load1
.
str
();
replacements
[
"LOAD_ATOM2_PARAMETERS"
]
=
load2
.
str
();
map
<
string
,
string
>
defines
;
if
(
cl
.
getNonbondedUtilities
().
getForceBufferPerAtomBlock
())
defines
[
"USE_OUTPUT_BUFFER_PER_BLOCK"
]
=
"1"
;
if
(
useCutoff
)
defines
[
"USE_CUTOFF"
]
=
"1"
;
if
(
usePeriodic
)
defines
[
"USE_PERIODIC"
]
=
"1"
;
if
(
anyExclusions
)
defines
[
"USE_EXCLUSIONS"
]
=
"1"
;
Vec3
boxVectors
[
3
];
system
.
getPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
defines
[
"PERIODIC_BOX_SIZE_X"
]
=
doubleToString
(
boxVectors
[
0
][
0
]);
defines
[
"PERIODIC_BOX_SIZE_Y"
]
=
doubleToString
(
boxVectors
[
1
][
1
]);
defines
[
"PERIODIC_BOX_SIZE_Z"
]
=
doubleToString
(
boxVectors
[
2
][
2
]);
defines
[
"CUTOFF_SQUARED"
]
=
doubleToString
(
force
.
getCutoffDistance
()
*
force
.
getCutoffDistance
());
defines
[
"NUM_ATOMS"
]
=
intToString
(
cl
.
getNumAtoms
());
defines
[
"PADDED_NUM_ATOMS"
]
=
intToString
(
cl
.
getPaddedNumAtoms
());
string
filename
=
(
cl
.
getSIMDWidth
()
==
32
?
"customGBEnergyN2_nvidia.cl"
:
"customGBEnergyN2_default.cl"
);
cl
::
Program
program
=
cl
.
createProgram
(
cl
.
loadSourceFromFile
(
filename
,
replacements
),
defines
);
pairEnergyKernel
=
cl
::
Kernel
(
program
,
"computeN2Energy"
);
}
{
// Create the kernel to reduce the derivatives and calculate per-particle energy terms.
stringstream
source
,
extraArgs
;
if
(
force
.
getNumGlobalParameters
()
>
0
)
extraArgs
<<
", __constant float* globals"
;
for
(
int
i
=
0
;
i
<
(
int
)
params
->
getBuffers
().
size
();
i
++
)
{
const
OpenCLNonbondedUtilities
::
ParameterInfo
&
buffer
=
params
->
getBuffers
()[
i
];
string
paramName
=
"params"
+
intToString
(
i
+
1
);
extraArgs
<<
", __global "
<<
buffer
.
getType
()
<<
"* "
<<
paramName
;
}
for
(
int
i
=
0
;
i
<
(
int
)
computedValues
->
getBuffers
().
size
();
i
++
)
{
const
OpenCLNonbondedUtilities
::
ParameterInfo
&
buffer
=
computedValues
->
getBuffers
()[
i
];
string
valueName
=
"values"
+
intToString
(
i
+
1
);
extraArgs
<<
", __global "
<<
buffer
.
getType
()
<<
"* "
<<
valueName
;
}
map
<
string
,
string
>
variables
;
for
(
int
i
=
0
;
i
<
force
.
getNumPerParticleParameters
();
i
++
)
variables
[
force
.
getPerParticleParameterName
(
i
)]
=
"params"
+
params
->
getParameterSuffix
(
i
,
"[index]"
);
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
variables
[
force
.
getGlobalParameterName
(
i
)]
=
"globals["
+
intToString
(
i
)
+
"]"
;
for
(
int
i
=
0
;
i
<
force
.
getNumComputedValues
();
i
++
)
variables
[
computedValueNames
[
i
]]
=
"values"
+
computedValues
->
getParameterSuffix
(
i
,
"[index]"
);
map
<
string
,
Lepton
::
ParsedExpression
>
energyExpressions
;
for
(
int
i
=
0
;
i
<
force
.
getNumEnergyTerms
();
i
++
)
{
string
expression
;
CustomGBForce
::
ComputationType
type
;
force
.
getEnergyTermParameters
(
i
,
expression
,
type
);
if
(
type
!=
CustomGBForce
::
SingleParticle
)
continue
;
energyExpressions
[
"/*"
+
intToString
(
i
+
1
)
+
"*/ energy += "
]
=
Lepton
::
Parser
::
parse
(
expression
,
functions
).
optimize
();
}
source
<<
OpenCLExpressionUtilities
::
createExpressions
(
energyExpressions
,
variables
,
functionDefinitions
,
"temp"
,
prefix
+
"functionParams"
);
// for (int i = 0; i < (int) computedValues->getBuffers().size(); i++) {
// string valueName = "values"+intToString(i+1);
// source << "global_" << valueName << "[index] = local_" << valueName << ";\n";
// }
map
<
string
,
string
>
replacements
;
replacements
[
"PARAMETER_ARGUMENTS"
]
=
extraArgs
.
str
()
+
tableArgs
.
str
();
replacements
[
"COMPUTE_ENERGY"
]
=
source
.
str
();
map
<
string
,
string
>
defines
;
defines
[
"NUM_ATOMS"
]
=
intToString
(
cl
.
getNumAtoms
());
cl
::
Program
program
=
cl
.
createProgram
(
cl
.
loadSourceFromFile
(
"customGBEnergyPerParticle.cl"
,
replacements
),
defines
);
perParticleEnergyKernel
=
cl
::
Kernel
(
program
,
"computePerParticleEnergy"
);
}
if
(
globals
!=
NULL
)
{
globals
->
upload
(
globalParamValues
);
...
...
@@ -1467,16 +1596,74 @@ void OpenCLCalcCustomGBForceKernel::executeForces(ContextImpl& context) {
pairValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
buffer
.
getBuffer
());
pairValueKernel
.
setArg
(
index
++
,
OpenCLContext
::
ThreadBlockSize
*
buffer
.
getSize
(),
NULL
);
}
if
(
tabulatedFunctionParams
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
(
int
)
tabulatedFunctions
.
size
();
i
++
)
pairValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctions
[
i
]
->
getDeviceBuffer
());
pairValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctionParams
->
getDeviceBuffer
());
}
index
=
0
;
reduc
eValueKernel
.
setArg
<
cl_int
>
(
index
++
,
cl
.
getPaddedNumAtoms
());
reduc
eValueKernel
.
setArg
<
cl_int
>
(
index
++
,
nb
.
getNumForceBuffers
());
reduc
eValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
valueBuffers
->
getDeviceBuffer
());
perParticl
eValueKernel
.
setArg
<
cl_int
>
(
index
++
,
cl
.
getPaddedNumAtoms
());
perParticl
eValueKernel
.
setArg
<
cl_int
>
(
index
++
,
nb
.
getNumForceBuffers
());
perParticl
eValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
valueBuffers
->
getDeviceBuffer
());
if
(
globals
!=
NULL
)
reduc
eValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
globals
->
getDeviceBuffer
());
perParticl
eValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
globals
->
getDeviceBuffer
());
for
(
int
i
=
0
;
i
<
(
int
)
params
->
getBuffers
().
size
();
i
++
)
reduc
eValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
params
->
getBuffers
()[
i
].
getBuffer
());
perParticl
eValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
params
->
getBuffers
()[
i
].
getBuffer
());
for
(
int
i
=
0
;
i
<
(
int
)
computedValues
->
getBuffers
().
size
();
i
++
)
reduceValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
computedValues
->
getBuffers
()[
i
].
getBuffer
());
perParticleValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
computedValues
->
getBuffers
()[
i
].
getBuffer
());
if
(
tabulatedFunctionParams
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
(
int
)
tabulatedFunctions
.
size
();
i
++
)
perParticleValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctions
[
i
]
->
getDeviceBuffer
());
perParticleValueKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctionParams
->
getDeviceBuffer
());
}
index
=
0
;
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
cl
.
getForceBuffers
().
getDeviceBuffer
());
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
cl
.
getEnergyBuffer
().
getDeviceBuffer
());
pairEnergyKernel
.
setArg
(
index
++
,
OpenCLContext
::
ThreadBlockSize
*
sizeof
(
cl_float4
),
NULL
);
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
cl
.
getPosq
().
getDeviceBuffer
());
pairEnergyKernel
.
setArg
(
index
++
,
OpenCLContext
::
ThreadBlockSize
*
sizeof
(
cl_float4
),
NULL
);
pairEnergyKernel
.
setArg
(
index
++
,
OpenCLContext
::
ThreadBlockSize
*
sizeof
(
cl_float4
),
NULL
);
if
(
nb
.
getUseCutoff
())
{
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
nb
.
getInteractingTiles
().
getDeviceBuffer
());
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
nb
.
getInteractionFlags
().
getDeviceBuffer
());
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
nb
.
getInteractionCount
().
getDeviceBuffer
());
}
else
{
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
nb
.
getTiles
().
getDeviceBuffer
());
pairEnergyKernel
.
setArg
<
cl_uint
>
(
index
++
,
nb
.
getTiles
().
getSize
());
}
if
(
globals
!=
NULL
)
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
globals
->
getDeviceBuffer
());
for
(
int
i
=
0
;
i
<
(
int
)
params
->
getBuffers
().
size
();
i
++
)
{
const
OpenCLNonbondedUtilities
::
ParameterInfo
&
buffer
=
params
->
getBuffers
()[
i
];
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
buffer
.
getBuffer
());
pairEnergyKernel
.
setArg
(
index
++
,
OpenCLContext
::
ThreadBlockSize
*
buffer
.
getSize
(),
NULL
);
}
for
(
int
i
=
0
;
i
<
(
int
)
computedValues
->
getBuffers
().
size
();
i
++
)
{
const
OpenCLNonbondedUtilities
::
ParameterInfo
&
buffer
=
computedValues
->
getBuffers
()[
i
];
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
buffer
.
getBuffer
());
pairEnergyKernel
.
setArg
(
index
++
,
OpenCLContext
::
ThreadBlockSize
*
buffer
.
getSize
(),
NULL
);
}
if
(
tabulatedFunctionParams
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
(
int
)
tabulatedFunctions
.
size
();
i
++
)
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctions
[
i
]
->
getDeviceBuffer
());
pairEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctionParams
->
getDeviceBuffer
());
}
index
=
0
;
perParticleEnergyKernel
.
setArg
<
cl_int
>
(
index
++
,
cl
.
getPaddedNumAtoms
());
perParticleEnergyKernel
.
setArg
<
cl_int
>
(
index
++
,
nb
.
getNumForceBuffers
());
perParticleEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
cl
.
getEnergyBuffer
().
getDeviceBuffer
());
if
(
globals
!=
NULL
)
perParticleEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
globals
->
getDeviceBuffer
());
for
(
int
i
=
0
;
i
<
(
int
)
params
->
getBuffers
().
size
();
i
++
)
perParticleEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
params
->
getBuffers
()[
i
].
getBuffer
());
for
(
int
i
=
0
;
i
<
(
int
)
computedValues
->
getBuffers
().
size
();
i
++
)
perParticleEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
computedValues
->
getBuffers
()[
i
].
getBuffer
());
if
(
tabulatedFunctionParams
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
(
int
)
tabulatedFunctions
.
size
();
i
++
)
perParticleEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctions
[
i
]
->
getDeviceBuffer
());
perParticleEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
tabulatedFunctionParams
->
getDeviceBuffer
());
}
}
if
(
globals
!=
NULL
)
{
bool
changed
=
false
;
...
...
@@ -1491,7 +1678,9 @@ void OpenCLCalcCustomGBForceKernel::executeForces(ContextImpl& context) {
}
cl
.
clearBuffer
(
*
valueBuffers
);
cl
.
executeKernel
(
pairValueKernel
,
nb
.
getTiles
().
getSize
()
*
OpenCLContext
::
TileSize
);
cl
.
executeKernel
(
reduceValueKernel
,
cl
.
getPaddedNumAtoms
());
cl
.
executeKernel
(
perParticleValueKernel
,
cl
.
getPaddedNumAtoms
());
cl
.
executeKernel
(
pairEnergyKernel
,
nb
.
getTiles
().
getSize
()
*
OpenCLContext
::
TileSize
);
cl
.
executeKernel
(
perParticleEnergyKernel
,
cl
.
getPaddedNumAtoms
());
// vector<vector<cl_float> > values;
// computedValues->getParameterValues(values);
// for (int i = 0; i < cl.getNumAtoms(); i++)
...
...
platforms/opencl/src/OpenCLKernels.h
View file @
9ed2c870
...
...
@@ -511,7 +511,7 @@ private:
std
::
vector
<
cl_float
>
globalParamValues
;
std
::
vector
<
OpenCLArray
<
mm_float4
>*>
tabulatedFunctions
;
System
&
system
;
cl
::
Kernel
pairValueKernel
,
reduc
eValueKernel
,
pair
Force
Kernel
,
particle
Force
Kernel
;
cl
::
Kernel
pairValueKernel
,
perParticl
eValueKernel
,
pair
Energy
Kernel
,
p
erP
article
Energy
Kernel
;
};
/**
...
...
platforms/opencl/src/kernels/customGBEnergyN2_nvidia.cl
0 → 100644
View file @
9ed2c870
#
define
TILE_SIZE
32
/**
*
Compute
a
force
based
on
pair
interactions.
*/
__kernel
void
computeN2Energy
(
__global
float4*
forceBuffers,
__global
float*
energyBuffer,
__local
float4*
local_force,
__global
float4*
posq,
__local
float4*
local_posq,
__local
float4*
tempBuffer,
__global
unsigned
int*
tiles,
#
ifdef
USE_CUTOFF
__global
unsigned
int*
interactionFlags,
__global
unsigned
int*
interactionCount
#
else
unsigned
int
numTiles
#
endif
PARAMETER_ARGUMENTS
)
{
#
ifdef
USE_CUTOFF
unsigned
int
numTiles
=
interactionCount[0]
;
#
endif
unsigned
int
totalWarps
=
get_global_size
(
0
)
/TILE_SIZE
;
unsigned
int
warp
=
get_global_id
(
0
)
/TILE_SIZE
;
unsigned
int
pos
=
warp*numTiles/totalWarps
;
unsigned
int
end
=
(
warp+1
)
*numTiles/totalWarps
;
float
energy
=
0.0f
;
unsigned
int
lasty
=
0xFFFFFFFF
;
while
(
pos
<
end
)
{
//
Extract
the
coordinates
of
this
tile
unsigned
int
x
=
tiles[pos]
;
unsigned
int
y
=
((
x
>>
2
)
&
0x7fff
)
*TILE_SIZE
;
bool
hasExclusions
=
(
x
&
0x1
)
;
x
=
(
x>>17
)
*TILE_SIZE
;
unsigned
int
tgx
=
get_local_id
(
0
)
&
(
TILE_SIZE-1
)
;
unsigned
int
tbx
=
get_local_id
(
0
)
-
tgx
;
unsigned
int
atom1
=
x
+
tgx
;
float4
force
=
0.0f
;
float4
posq1
=
posq[atom1]
;
LOAD_ATOM1_PARAMETERS
if
(
x
==
y
)
{
//
This
tile
is
on
the
diagonal.
local_posq[get_local_id
(
0
)
]
=
posq1
;
LOAD_LOCAL_PARAMETERS_FROM_1
unsigned
int
xi
=
x/TILE_SIZE
;
unsigned
int
tile
=
xi+xi*PADDED_NUM_ATOMS/TILE_SIZE-xi*
(
xi+1
)
/2
;
#
ifdef
USE_EXCLUSIONS
unsigned
int
excl
=
exclusions[exclusionIndices[tile]+tgx]
;
#
endif
for
(
unsigned
int
j
=
0
; j < TILE_SIZE; j++) {
#
ifdef
USE_EXCLUSIONS
bool
isExcluded
=
!
(
excl
&
0x1
)
;
#
endif
int
atom2
=
tbx+j
;
float4
posq2
=
local_posq[atom2]
;
float4
delta
=
(
float4
)
(
posq2.xyz
-
posq1.xyz,
0.0f
)
;
#
ifdef
USE_PERIODIC
delta.x
-=
floor
(
delta.x/PERIODIC_BOX_SIZE_X+0.5f
)
*PERIODIC_BOX_SIZE_X
;
delta.y
-=
floor
(
delta.y/PERIODIC_BOX_SIZE_Y+0.5f
)
*PERIODIC_BOX_SIZE_Y
;
delta.z
-=
floor
(
delta.z/PERIODIC_BOX_SIZE_Z+0.5f
)
*PERIODIC_BOX_SIZE_Z
;
#
endif
float
r
=
sqrt
(
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
)
;
LOAD_ATOM2_PARAMETERS
atom2
=
y+j
;
float
dEdR
=
0.0f
;
float
tempEnergy
=
0.0f
;
if
(
atom1
<
NUM_ATOMS
&&
atom2
<
NUM_ATOMS
&&
atom1
!=
atom2
)
{
COMPUTE_INTERACTION
}
energy
+=
0.5f*tempEnergy
;
delta.xyz
*=
dEdR
;
force.xyz
-=
delta.xyz
;
#
ifdef
USE_EXCLUSIONS
excl
>>=
1
;
#
endif
}
//
Write
results
#
ifdef
USE_OUTPUT_BUFFER_PER_BLOCK
unsigned
int
offset
=
x
+
tgx
+
(
x/TILE_SIZE
)
*PADDED_NUM_ATOMS
;
#
else
unsigned
int
offset
=
x
+
tgx
+
warp*PADDED_NUM_ATOMS
;
#
endif
forceBuffers[offset].xyz
+=
force.xyz
;
}
else
{
//
This
is
an
off-diagonal
tile.
if
(
lasty
!=
y
)
{
unsigned
int
j
=
y
+
tgx
;
local_posq[get_local_id
(
0
)
]
=
posq[j]
;
LOAD_LOCAL_PARAMETERS_FROM_GLOBAL
}
local_force[get_local_id
(
0
)
]
=
0.0f
;
#
ifdef
USE_CUTOFF
unsigned
int
flags
=
interactionFlags[pos]
;
if
(
!hasExclusions
&&
flags
!=
0xFFFFFFFF
)
{
if
(
flags
==
0
)
{
//
No
interactions
in
this
tile.
}
else
{
//
Compute
only
a
subset
of
the
interactions
in
this
tile.
for
(
unsigned
int
j
=
0
; j < TILE_SIZE; j++) {
if
((
flags&
(
1<<j
))
!=
0
)
{
bool
isExcluded
=
false
;
int
atom2
=
tbx+j
;
float4
posq2
=
local_posq[atom2]
;
float4
delta
=
(
float4
)
(
posq2.xyz
-
posq1.xyz,
0.0f
)
;
#
ifdef
USE_PERIODIC
delta.x
-=
floor
(
delta.x/PERIODIC_BOX_SIZE_X+0.5f
)
*PERIODIC_BOX_SIZE_X
;
delta.y
-=
floor
(
delta.y/PERIODIC_BOX_SIZE_Y+0.5f
)
*PERIODIC_BOX_SIZE_Y
;
delta.z
-=
floor
(
delta.z/PERIODIC_BOX_SIZE_Z+0.5f
)
*PERIODIC_BOX_SIZE_Z
;
#
endif
float
r
=
sqrt
(
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
)
;
LOAD_ATOM2_PARAMETERS
atom2
=
y+j
;
float
dEdR
=
0.0f
;
float
tempEnergy
=
0.0f
;
if
(
atom1
<
NUM_ATOMS
&&
atom2
<
NUM_ATOMS
)
{
COMPUTE_INTERACTION
}
energy
+=
tempEnergy
;
delta.xyz
*=
dEdR
;
force.xyz
-=
delta.xyz
;
tempBuffer[get_local_id
(
0
)
].xyz
=
delta.xyz
;
//
Sum
the
forces
on
atom2.
if
(
tgx
%
2
==
0
)
tempBuffer[get_local_id
(
0
)
]
+=
tempBuffer[get_local_id
(
0
)
+1]
;
if
(
tgx
%
4
==
0
)
tempBuffer[get_local_id
(
0
)
]
+=
tempBuffer[get_local_id
(
0
)
+2]
;
if
(
tgx
%
8
==
0
)
tempBuffer[get_local_id
(
0
)
]
+=
tempBuffer[get_local_id
(
0
)
+4]
;
if
(
tgx
%
16
==
0
)
tempBuffer[get_local_id
(
0
)
]
+=
tempBuffer[get_local_id
(
0
)
+8]
;
if
(
tgx
==
0
)
local_force[tbx+j]
+=
tempBuffer[get_local_id
(
0
)
]
+
tempBuffer[get_local_id
(
0
)
+16]
;
}
}
}
}
else
#
endif
{
//
Compute
the
full
set
of
interactions
in
this
tile.
unsigned
int
xi
=
x/TILE_SIZE
;
unsigned
int
yi
=
y/TILE_SIZE
;
unsigned
int
tile
=
xi+yi*PADDED_NUM_ATOMS/TILE_SIZE-yi*
(
yi+1
)
/2
;
#
ifdef
USE_EXCLUSIONS
unsigned
int
excl
=
(
hasExclusions
?
exclusions[exclusionIndices[tile]+tgx]
:
0xFFFFFFFF
)
;
excl
=
(
excl
>>
tgx
)
|
(
excl
<<
(
TILE_SIZE
-
tgx
))
;
#
endif
unsigned
int
tj
=
tgx
;
for
(
unsigned
int
j
=
0
; j < TILE_SIZE; j++) {
#
ifdef
USE_EXCLUSIONS
bool
isExcluded
=
!
(
excl
&
0x1
)
;
#
endif
int
atom2
=
tbx+tj
;
float4
posq2
=
local_posq[atom2]
;
float4
delta
=
(
float4
)
(
posq2.xyz
-
posq1.xyz,
0.0f
)
;
#
ifdef
USE_PERIODIC
delta.x
-=
floor
(
delta.x/PERIODIC_BOX_SIZE_X+0.5f
)
*PERIODIC_BOX_SIZE_X
;
delta.y
-=
floor
(
delta.y/PERIODIC_BOX_SIZE_Y+0.5f
)
*PERIODIC_BOX_SIZE_Y
;
delta.z
-=
floor
(
delta.z/PERIODIC_BOX_SIZE_Z+0.5f
)
*PERIODIC_BOX_SIZE_Z
;
#
endif
float
r
=
sqrt
(
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
)
;
LOAD_ATOM2_PARAMETERS
atom2
=
y+tj
;
float
dEdR
=
0.0f
;
float
tempEnergy
=
0.0f
;
if
(
atom1
<
NUM_ATOMS
&&
atom2
<
NUM_ATOMS
)
{
COMPUTE_INTERACTION
}
energy
+=
tempEnergy
;
delta.xyz
*=
dEdR
;
force.xyz
-=
delta.xyz
;
local_force[tbx+tj].xyz
+=
delta.xyz
;
#
ifdef
USE_EXCLUSIONS
excl
>>=
1
;
#
endif
tj
=
(
tj
+
1
)
&
(
TILE_SIZE
-
1
)
;
}
}
//
Write
results
#
ifdef
USE_OUTPUT_BUFFER_PER_BLOCK
unsigned
int
offset1
=
x
+
tgx
+
(
y/TILE_SIZE
)
*PADDED_NUM_ATOMS
;
unsigned
int
offset2
=
y
+
tgx
+
(
x/TILE_SIZE
)
*PADDED_NUM_ATOMS
;
#
else
unsigned
int
offset1
=
x
+
tgx
+
warp*PADDED_NUM_ATOMS
;
unsigned
int
offset2
=
y
+
tgx
+
warp*PADDED_NUM_ATOMS
;
#
endif
forceBuffers[offset1].xyz
+=
force.xyz
;
forceBuffers[offset2].xyz
+=
local_force[get_local_id
(
0
)
].xyz
;
lasty
=
y
;
}
pos++
;
}
energyBuffer[get_global_id
(
0
)
]
+=
energy
;
}
platforms/opencl/src/kernels/customGBEnergyPerParticle.cl
0 → 100644
View file @
9ed2c870
/**
*
Reduce
the
derivatives
computed
in
the
N^2
energy
kernel,
and
compute
all
per-particle
energy
terms.
*/
__kernel
void
computePerParticleEnergy
(
int
bufferSize,
int
numBuffers,
__global
float*
energyBuffer
PARAMETER_ARGUMENTS
)
{
float
energy
=
0.0f
;
unsigned
int
index
=
get_global_id
(
0
)
;
while
(
index
<
NUM_ATOMS
)
{
//
Reduce
the
derivatives
//
int
totalSize
=
bufferSize*numBuffers
;
//
float
sum
=
valueBuffers[index]
;
//
for
(
int
i
=
index+bufferSize
; i < totalSize; i += bufferSize)
//
sum
+=
valueBuffers[i]
;
//
Now
calculate
the
per-particle
energy
terms.
COMPUTE_ENERGY
index
+=
get_global_size
(
0
)
;
}
energyBuffer[get_global_id
(
0
)
]
+=
energy
;
}
platforms/opencl/src/kernels/customGBValue
Reduction
.cl
→
platforms/opencl/src/kernels/customGBValue
PerParticle
.cl
View file @
9ed2c870
...
...
@@ -2,7 +2,7 @@
*
Reduce
a
pairwise
computed
value,
and
compute
per-particle
values.
*/
__kernel
void
reduceGB
Value
(
int
bufferSize,
int
numBuffers,
__global
float*
valueBuffers
__kernel
void
computePerParticle
Value
s
(
int
bufferSize,
int
numBuffers,
__global
float*
valueBuffers
PARAMETER_ARGUMENTS
)
{
unsigned
int
index
=
get_global_id
(
0
)
;
while
(
index
<
NUM_ATOMS
)
{
...
...
platforms/opencl/tests/TestOpenCLCustomGBForce.cpp
0 → 100644
View file @
9ed2c870
/* -------------------------------------------------------------------------- *
* 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) 2008-2009 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 CustomGBForce.
*/
#include "../../../tests/AssertionUtilities.h"
#include "../src/sfmt/SFMT.h"
#include "openmm/Context.h"
#include "OpenCLPlatform.h"
#include "openmm/CustomGBForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
const
double
TOL
=
1e-5
;
void
testOBC
(
GBSAOBCForce
::
NonbondedMethod
obcMethod
,
CustomGBForce
::
NonbondedMethod
customMethod
)
{
const
int
numMolecules
=
70
;
const
int
numParticles
=
numMolecules
*
2
;
const
double
boxSize
=
10.0
;
OpenCLPlatform
platform
;
// Create two systems: one with a GBSAOBCForce, and one using a CustomGBForce to implement the same interaction.
System
standardSystem
;
System
customSystem
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
standardSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
}
standardSystem
.
setPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
customSystem
.
setPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
GBSAOBCForce
*
obc
=
new
GBSAOBCForce
();
CustomGBForce
*
custom
=
new
CustomGBForce
();
obc
->
setCutoffDistance
(
2.0
);
custom
->
setCutoffDistance
(
2.0
);
custom
->
addPerParticleParameter
(
"q"
);
custom
->
addPerParticleParameter
(
"radius"
);
custom
->
addPerParticleParameter
(
"scale"
);
custom
->
addGlobalParameter
(
"solventDielectric"
,
obc
->
getSolventDielectric
());
custom
->
addGlobalParameter
(
"soluteDielectric"
,
obc
->
getSoluteDielectric
());
custom
->
addComputedValue
(
"I"
,
"step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(r*(1/U^2-1/L^2))+0.5*log(L/U)/r+0.25*(sr2*sr2/r)*(1/L^2-1/U^2)+C);"
"U=r+sr2;"
"C=2*(1/or1-1/L)*step(sr2-r-or1);"
"L=step(or1-D)*or1+step(D-or1)*D;"
"D=step(r-sr2)*(r-sr2)+step(sr2-r)*(sr2-r);"
"sr1 = scale1*or1; sr2 = scale2*or2;"
"or1 = radius1-0.009; or2 = radius2-0.009"
,
CustomGBForce
::
ParticlePairNoExclusions
);
custom
->
addComputedValue
(
"B"
,
"1/(1/or-tanh(1*psi-0.8*psi^2+4.85*psi^3)/radius);"
"psi=I*or; or=radius-0.009"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"28.3919551*(radius+0.14)^2*(radius/B)^6-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))"
,
CustomGBForce
::
ParticlePairNoExclusions
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
init_gen_rand
(
0
);
vector
<
double
>
params
(
3
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
if
(
i
<
numMolecules
/
2
)
{
obc
->
addParticle
(
1.0
,
0.2
,
0.5
);
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.5
;
custom
->
addParticle
(
params
);
obc
->
addParticle
(
-
1.0
,
0.1
,
0.5
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
else
{
obc
->
addParticle
(
1.0
,
0.2
,
0.8
);
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.8
;
custom
->
addParticle
(
params
);
obc
->
addParticle
(
-
1.0
,
0.1
,
0.8
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
positions
[
2
*
i
]
=
Vec3
(
boxSize
*
genrand_real2
(),
boxSize
*
genrand_real2
(),
boxSize
*
genrand_real2
());
positions
[
2
*
i
+
1
]
=
Vec3
(
positions
[
2
*
i
][
0
]
+
1.0
,
positions
[
2
*
i
][
1
],
positions
[
2
*
i
][
2
]);
velocities
[
2
*
i
]
=
Vec3
(
genrand_real2
(),
genrand_real2
(),
genrand_real2
());
velocities
[
2
*
i
+
1
]
=
Vec3
(
genrand_real2
(),
genrand_real2
(),
genrand_real2
());
}
obc
->
setNonbondedMethod
(
obcMethod
);
custom
->
setNonbondedMethod
(
customMethod
);
standardSystem
.
addForce
(
obc
);
customSystem
.
addForce
(
custom
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
context1
(
standardSystem
,
integrator1
,
platform
);
context1
.
setPositions
(
positions
);
context1
.
setVelocities
(
velocities
);
State
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
Context
context2
(
customSystem
,
integrator2
,
platform
);
context2
.
setPositions
(
positions
);
context2
.
setVelocities
(
velocities
);
State
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
1e-4
);
}
}
void
testTabulatedFunction
(
bool
interpolating
)
{
OpenCLPlatform
platform
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"0"
,
CustomGBForce
::
ParticlePair
);
force
->
addEnergyTerm
(
"fn(r)+1"
,
CustomGBForce
::
ParticlePair
);
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
vector
<
double
>
table
;
for
(
int
i
=
0
;
i
<
21
;
i
++
)
table
.
push_back
(
std
::
sin
(
0.25
*
i
));
force
->
addFunction
(
"fn"
,
table
,
1.0
,
6.0
,
interpolating
);
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
for
(
int
i
=
1
;
i
<
30
;
i
++
)
{
double
x
=
(
7.0
/
30.0
)
*
i
;
positions
[
1
]
=
Vec3
(
x
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
double
force
=
(
x
<
1.0
||
x
>
6.0
?
0.0
:
-
std
::
cos
(
x
-
1.0
));
double
energy
=
(
x
<
1.0
||
x
>
6.0
?
0.0
:
std
::
sin
(
x
-
1.0
))
+
1.0
;
ASSERT_EQUAL_VEC
(
Vec3
(
-
force
,
0
,
0
),
forces
[
0
],
0.1
);
ASSERT_EQUAL_VEC
(
Vec3
(
force
,
0
,
0
),
forces
[
1
],
0.1
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
0.02
);
}
}
int
main
()
{
try
{
testOBC
(
GBSAOBCForce
::
NoCutoff
,
CustomGBForce
::
NoCutoff
);
// testOBC(GBSAOBCForce::CutoffNonPeriodic, CustomGBForce::CutoffNonPeriodic);
// testOBC(GBSAOBCForce::CutoffPeriodic, CustomGBForce::CutoffPeriodic);
// testTabulatedFunction(true);
// testTabulatedFunction(false);
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
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