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
4d823b0a
"platforms/opencl/tests/TestOpenCLNonbondedForce.cpp" did not exist on "ad75a3907915beba16c0f81c0b129a4b98f2f106"
Commit
4d823b0a
authored
Sep 02, 2015
by
peastman
Browse files
Began CUDA version of CustomCentroidBondForce
parent
56d95193
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
858 additions
and
4 deletions
+858
-4
platforms/cuda/include/CudaKernels.h
platforms/cuda/include/CudaKernels.h
+52
-0
platforms/cuda/src/CudaKernelFactory.cpp
platforms/cuda/src/CudaKernelFactory.cpp
+2
-0
platforms/cuda/src/CudaKernels.cpp
platforms/cuda/src/CudaKernels.cpp
+416
-4
platforms/cuda/src/CudaPlatform.cpp
platforms/cuda/src/CudaPlatform.cpp
+1
-0
platforms/cuda/src/kernels/customCentroidBond.cu
platforms/cuda/src/kernels/customCentroidBond.cu
+137
-0
platforms/cuda/tests/TestCudaCustomCentroidBondForce.cpp
platforms/cuda/tests/TestCudaCustomCentroidBondForce.cpp
+250
-0
No files found.
platforms/cuda/include/CudaKernels.h
View file @
4d823b0a
...
@@ -922,6 +922,58 @@ private:
...
@@ -922,6 +922,58 @@ private:
CUfunction
donorKernel
,
acceptorKernel
;
CUfunction
donorKernel
,
acceptorKernel
;
};
};
/**
* This kernel is invoked by CustomCentroidBondForce to calculate the forces acting on the system.
*/
class
CudaCalcCustomCentroidBondForceKernel
:
public
CalcCustomCentroidBondForceKernel
{
public:
CudaCalcCustomCentroidBondForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
CudaContext
&
cu
,
const
System
&
system
)
:
CalcCustomCentroidBondForceKernel
(
name
,
platform
),
cu
(
cu
),
params
(
NULL
),
globals
(
NULL
),
groupParticles
(
NULL
),
groupWeights
(
NULL
),
groupOffsets
(
NULL
),
groupForces
(
NULL
),
bondGroups
(
NULL
),
centerPositions
(
NULL
),
system
(
system
)
{
}
~
CudaCalcCustomCentroidBondForceKernel
();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the CustomCentroidBondForce this kernel will be used for
*/
void
initialize
(
const
System
&
system
,
const
CustomCentroidBondForce
&
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
);
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the CustomCentroidBondForce to copy the parameters from
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomCentroidBondForce
&
force
);
private:
int
numGroups
,
numBonds
;
CudaContext
&
cu
;
CudaParameterSet
*
params
;
CudaArray
*
globals
;
CudaArray
*
groupParticles
;
CudaArray
*
groupWeights
;
CudaArray
*
groupOffsets
;
CudaArray
*
groupForces
;
CudaArray
*
bondGroups
;
CudaArray
*
centerPositions
;
std
::
vector
<
std
::
string
>
globalParamNames
;
std
::
vector
<
float
>
globalParamValues
;
std
::
vector
<
CudaArray
*>
tabulatedFunctions
;
std
::
vector
<
void
*>
groupForcesArgs
;
CUfunction
computeCentersKernel
,
groupForcesKernel
,
applyForcesKernel
;
const
System
&
system
;
};
/**
/**
* This kernel is invoked by CustomCompoundBondForce to calculate the forces acting on the system.
* This kernel is invoked by CustomCompoundBondForce to calculate the forces acting on the system.
*/
*/
...
...
platforms/cuda/src/CudaKernelFactory.cpp
View file @
4d823b0a
...
@@ -104,6 +104,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
...
@@ -104,6 +104,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
return
new
CudaCalcCustomExternalForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
return
new
CudaCalcCustomExternalForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
if
(
name
==
CalcCustomHbondForceKernel
::
Name
())
if
(
name
==
CalcCustomHbondForceKernel
::
Name
())
return
new
CudaCalcCustomHbondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
return
new
CudaCalcCustomHbondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
if
(
name
==
CalcCustomCentroidBondForceKernel
::
Name
())
return
new
CudaCalcCustomCentroidBondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
return
new
CudaCalcCustomCompoundBondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
return
new
CudaCalcCustomCompoundBondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
if
(
name
==
CalcCustomManyParticleForceKernel
::
Name
())
if
(
name
==
CalcCustomManyParticleForceKernel
::
Name
())
...
...
platforms/cuda/src/CudaKernels.cpp
View file @
4d823b0a
...
@@ -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/CustomCentroidBondForceImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
...
@@ -2570,8 +2571,8 @@ void CudaCalcGBSAOBCForceKernel::initialize(const System& system, const GBSAOBCF
...
@@ -2570,8 +2571,8 @@ void CudaCalcGBSAOBCForceKernel::initialize(const System& system, const GBSAOBCF
cutoff
=
force
.
getCutoffDistance
();
cutoff
=
force
.
getCutoffDistance
();
string
source
=
CudaKernelSources
::
gbsaObc2
;
string
source
=
CudaKernelSources
::
gbsaObc2
;
nb
.
addInteraction
(
useCutoff
,
usePeriodic
,
false
,
cutoff
,
vector
<
vector
<
int
>
>
(),
source
,
force
.
getForceGroup
());
nb
.
addInteraction
(
useCutoff
,
usePeriodic
,
false
,
cutoff
,
vector
<
vector
<
int
>
>
(),
source
,
force
.
getForceGroup
());
nb
.
addParameter
(
CudaNonbondedUtilities
::
ParameterInfo
(
"obcParams"
,
"float"
,
2
,
sizeof
(
float2
),
params
->
getDevicePointer
()));
;
nb
.
addParameter
(
CudaNonbondedUtilities
::
ParameterInfo
(
"obcParams"
,
"float"
,
2
,
sizeof
(
float2
),
params
->
getDevicePointer
()));
nb
.
addParameter
(
CudaNonbondedUtilities
::
ParameterInfo
(
"bornForce"
,
"long long"
,
1
,
sizeof
(
long
long
),
bornForce
->
getDevicePointer
()));
;
nb
.
addParameter
(
CudaNonbondedUtilities
::
ParameterInfo
(
"bornForce"
,
"long long"
,
1
,
sizeof
(
long
long
),
bornForce
->
getDevicePointer
()));
cu
.
addForce
(
new
CudaGBSAOBCForceInfo
(
force
));
cu
.
addForce
(
new
CudaGBSAOBCForceInfo
(
force
));
}
}
...
@@ -4242,6 +4243,418 @@ void CudaCalcCustomHbondForceKernel::copyParametersToContext(ContextImpl& contex
...
@@ -4242,6 +4243,418 @@ void CudaCalcCustomHbondForceKernel::copyParametersToContext(ContextImpl& contex
cu
.
invalidateMolecules
();
cu
.
invalidateMolecules
();
}
}
class
CudaCustomCentroidBondForceInfo
:
public
CudaForceInfo
{
public:
CudaCustomCentroidBondForceInfo
(
const
CustomCentroidBondForce
&
force
)
:
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
CustomCentroidBondForce
&
force
;
};
CudaCalcCustomCentroidBondForceKernel
::~
CudaCalcCustomCentroidBondForceKernel
()
{
cu
.
setAsCurrent
();
if
(
params
!=
NULL
)
delete
params
;
if
(
globals
!=
NULL
)
delete
globals
;
if
(
groupParticles
!=
NULL
)
delete
groupParticles
;
if
(
groupWeights
!=
NULL
)
delete
groupWeights
;
if
(
groupOffsets
!=
NULL
)
delete
groupOffsets
;
if
(
groupForces
!=
NULL
)
delete
groupForces
;
if
(
bondGroups
!=
NULL
)
delete
bondGroups
;
if
(
centerPositions
!=
NULL
)
delete
centerPositions
;
for
(
int
i
=
0
;
i
<
(
int
)
tabulatedFunctions
.
size
();
i
++
)
delete
tabulatedFunctions
[
i
];
}
void
CudaCalcCustomCentroidBondForceKernel
::
initialize
(
const
System
&
system
,
const
CustomCentroidBondForce
&
force
)
{
cu
.
setAsCurrent
();
numBonds
=
force
.
getNumBonds
();
if
(
numBonds
==
0
)
return
;
cu
.
addForce
(
new
CudaCustomCentroidBondForceInfo
(
force
));
// Record the groups.
numGroups
=
force
.
getNumGroups
();
vector
<
int
>
groupParticleVec
;
vector
<
float
>
groupWeightVecFloat
;
vector
<
double
>
groupWeightVecDouble
;
vector
<
int
>
groupOffsetVec
;
groupOffsetVec
.
push_back
(
0
);
for
(
int
i
=
0
;
i
<
numGroups
;
i
++
)
{
vector
<
int
>
particles
;
vector
<
double
>
weights
;
force
.
getGroupParameters
(
i
,
particles
,
weights
);
groupParticleVec
.
insert
(
groupParticleVec
.
end
(),
particles
.
begin
(),
particles
.
end
());
groupOffsetVec
.
push_back
(
groupParticleVec
.
size
());
}
vector
<
vector
<
double
>
>
normalizedWeights
;
CustomCentroidBondForceImpl
::
computeNormalizedWeights
(
force
,
system
,
normalizedWeights
);
if
(
cu
.
getUseDoublePrecision
())
{
for
(
int
i
=
0
;
i
<
numGroups
;
i
++
)
groupWeightVecDouble
.
insert
(
groupWeightVecDouble
.
end
(),
normalizedWeights
[
i
].
begin
(),
normalizedWeights
[
i
].
end
());
}
else
{
for
(
int
i
=
0
;
i
<
numGroups
;
i
++
)
for
(
int
j
=
0
;
j
<
normalizedWeights
[
i
].
size
();
j
++
)
groupWeightVecFloat
.
push_back
((
float
)
normalizedWeights
[
i
][
j
]);
}
groupParticles
=
CudaArray
::
create
<
int
>
(
cu
,
groupParticleVec
.
size
(),
"groupParticles"
);
groupParticles
->
upload
(
groupParticleVec
);
if
(
cu
.
getUseDoublePrecision
())
{
groupWeights
=
CudaArray
::
create
<
double
>
(
cu
,
groupParticleVec
.
size
(),
"groupWeights"
);
groupWeights
->
upload
(
groupWeightVecDouble
);
centerPositions
=
CudaArray
::
create
<
double4
>
(
cu
,
numGroups
,
"centerPositions"
);
}
else
{
groupWeights
=
CudaArray
::
create
<
float
>
(
cu
,
groupParticleVec
.
size
(),
"groupWeights"
);
groupWeights
->
upload
(
groupWeightVecFloat
);
centerPositions
=
CudaArray
::
create
<
float4
>
(
cu
,
numGroups
,
"centerPositions"
);
}
groupOffsets
=
CudaArray
::
create
<
int
>
(
cu
,
groupOffsetVec
.
size
(),
"groupOffsets"
);
groupOffsets
->
upload
(
groupOffsetVec
);
groupForces
=
CudaArray
::
create
<
long
long
>
(
cu
,
numGroups
*
3
,
"groupForces"
);
cu
.
addAutoclearBuffer
(
*
groupForces
);
// Record the bonds.
int
groupsPerBond
=
force
.
getNumGroupsPerBond
();
vector
<
int
>
bondGroupVec
(
numBonds
*
groupsPerBond
);
params
=
new
CudaParameterSet
(
cu
,
force
.
getNumPerBondParameters
(),
numBonds
,
"customCentroidBondParams"
);
vector
<
vector
<
float
>
>
paramVector
(
numBonds
);
for
(
int
i
=
0
;
i
<
numBonds
;
i
++
)
{
vector
<
int
>
groups
;
vector
<
double
>
parameters
;
force
.
getBondParameters
(
i
,
groups
,
parameters
);
for
(
int
j
=
0
;
j
<
groups
.
size
();
j
++
)
bondGroupVec
[
i
+
j
*
numBonds
]
=
groups
[
j
];
paramVector
[
i
].
resize
(
parameters
.
size
());
for
(
int
j
=
0
;
j
<
(
int
)
parameters
.
size
();
j
++
)
paramVector
[
i
][
j
]
=
(
float
)
parameters
[
j
];
}
params
->
setParameterValues
(
paramVector
);
bondGroups
=
CudaArray
::
create
<
int
>
(
cu
,
bondGroupVec
.
size
(),
"bondGroups"
);
bondGroups
->
upload
(
bondGroupVec
);
// Record the arguments to the force kernel.
groupForcesArgs
.
push_back
(
&
groupForces
->
getDevicePointer
());
groupForcesArgs
.
push_back
(
NULL
);
// Energy buffer hasn't been created yet
groupForcesArgs
.
push_back
(
&
centerPositions
->
getDevicePointer
());
groupForcesArgs
.
push_back
(
&
bondGroups
->
getDevicePointer
());
// Record the tabulated functions.
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
vector
<
pair
<
string
,
string
>
>
functionDefinitions
;
vector
<
const
TabulatedFunction
*>
functionList
;
stringstream
extraArgs
;
for
(
int
i
=
0
;
i
<
force
.
getNumTabulatedFunctions
();
i
++
)
{
functionList
.
push_back
(
&
force
.
getTabulatedFunction
(
i
));
string
name
=
force
.
getTabulatedFunctionName
(
i
);
string
arrayName
=
"table"
+
cu
.
intToString
(
i
);
functionDefinitions
.
push_back
(
make_pair
(
name
,
arrayName
));
functions
[
name
]
=
cu
.
getExpressionUtilities
().
getFunctionPlaceholder
(
force
.
getTabulatedFunction
(
i
));
int
width
;
vector
<
float
>
f
=
cu
.
getExpressionUtilities
().
computeFunctionCoefficients
(
force
.
getTabulatedFunction
(
i
),
width
);
tabulatedFunctions
.
push_back
(
CudaArray
::
create
<
float
>
(
cu
,
f
.
size
(),
"TabulatedFunction"
));
tabulatedFunctions
.
back
()
->
upload
(
f
);
extraArgs
<<
", const float"
;
if
(
width
>
1
)
extraArgs
<<
width
;
extraArgs
<<
"* __restrict__ "
<<
arrayName
;
groupForcesArgs
.
push_back
(
&
tabulatedFunctions
.
back
()
->
getDevicePointer
());
}
// 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
]
=
(
float
)
force
.
getGlobalParameterDefaultValue
(
i
);
}
map
<
string
,
string
>
variables
;
for
(
int
i
=
0
;
i
<
groupsPerBond
;
i
++
)
{
string
index
=
cu
.
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
=
CudaArray
::
create
<
float
>
(
cu
,
force
.
getNumGlobalParameters
(),
"customCentroidBondGlobals"
);
globals
->
upload
(
globalParamValues
);
extraArgs
<<
", const float* __restrict__ globals"
;
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
{
const
string
&
name
=
force
.
getGlobalParameterName
(
i
);
string
value
=
"globals["
+
cu
.
intToString
(
i
)
+
"]"
;
variables
[
name
]
=
value
;
}
groupForcesArgs
.
push_back
(
&
globals
->
getDevicePointer
());
}
// 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
=
CustomCentroidBondForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
map
<
string
,
Lepton
::
ParsedExpression
>
forceExpressions
;
set
<
string
>
computedDeltas
;
vector
<
string
>
atomNames
,
posNames
;
for
(
int
i
=
0
;
i
<
groupsPerBond
;
i
++
)
{
string
index
=
cu
.
intToString
(
i
+
1
);
atomNames
.
push_back
(
"P"
+
index
);
posNames
.
push_back
(
"pos"
+
index
);
}
stringstream
compute
;
for
(
int
i
=
0
;
i
<
groupsPerBond
;
i
++
)
{
compute
<<
"int group"
<<
(
i
+
1
)
<<
" = bondGroups[index+"
<<
(
i
*
numBonds
)
<<
"];
\n
"
;
compute
<<
"real4 pos"
<<
(
i
+
1
)
<<
" = centerPositions[group"
<<
(
i
+
1
)
<<
"];
\n
"
;
}
int
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
groups
=
iter
->
second
;
string
deltaName
=
atomNames
[
groups
[
0
]]
+
atomNames
[
groups
[
1
]];
if
(
computedDeltas
.
count
(
deltaName
)
==
0
)
{
compute
<<
"real4 delta"
<<
deltaName
<<
" = delta("
<<
posNames
[
groups
[
0
]]
<<
", "
<<
posNames
[
groups
[
1
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName
);
}
compute
<<
"real r_"
<<
deltaName
<<
" = sqrt(delta"
<<
deltaName
<<
".w);
\n
"
;
variables
[
iter
->
first
]
=
"r_"
+
deltaName
;
forceExpressions
[
"real dEdDistance"
+
cu
.
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
>&
groups
=
iter
->
second
;
string
deltaName1
=
atomNames
[
groups
[
1
]]
+
atomNames
[
groups
[
0
]];
string
deltaName2
=
atomNames
[
groups
[
1
]]
+
atomNames
[
groups
[
2
]];
string
angleName
=
"angle_"
+
atomNames
[
groups
[
0
]]
+
atomNames
[
groups
[
1
]]
+
atomNames
[
groups
[
2
]];
if
(
computedDeltas
.
count
(
deltaName1
)
==
0
)
{
compute
<<
"real4 delta"
<<
deltaName1
<<
" = delta("
<<
posNames
[
groups
[
1
]]
<<
", "
<<
posNames
[
groups
[
0
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName1
);
}
if
(
computedDeltas
.
count
(
deltaName2
)
==
0
)
{
compute
<<
"real4 delta"
<<
deltaName2
<<
" = delta("
<<
posNames
[
groups
[
1
]]
<<
", "
<<
posNames
[
groups
[
2
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName2
);
}
compute
<<
"real "
<<
angleName
<<
" = computeAngle(delta"
<<
deltaName1
<<
", delta"
<<
deltaName2
<<
");
\n
"
;
variables
[
iter
->
first
]
=
angleName
;
forceExpressions
[
"real dEdAngle"
+
cu
.
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
>&
groups
=
iter
->
second
;
string
deltaName1
=
atomNames
[
groups
[
0
]]
+
atomNames
[
groups
[
1
]];
string
deltaName2
=
atomNames
[
groups
[
2
]]
+
atomNames
[
groups
[
1
]];
string
deltaName3
=
atomNames
[
groups
[
2
]]
+
atomNames
[
groups
[
3
]];
string
crossName1
=
"cross_"
+
deltaName1
+
"_"
+
deltaName2
;
string
crossName2
=
"cross_"
+
deltaName2
+
"_"
+
deltaName3
;
string
dihedralName
=
"dihedral_"
+
atomNames
[
groups
[
0
]]
+
atomNames
[
groups
[
1
]]
+
atomNames
[
groups
[
2
]]
+
atomNames
[
groups
[
3
]];
if
(
computedDeltas
.
count
(
deltaName1
)
==
0
)
{
compute
<<
"real4 delta"
<<
deltaName1
<<
" = delta("
<<
posNames
[
groups
[
0
]]
<<
", "
<<
posNames
[
groups
[
1
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName1
);
}
if
(
computedDeltas
.
count
(
deltaName2
)
==
0
)
{
compute
<<
"real4 delta"
<<
deltaName2
<<
" = delta("
<<
posNames
[
groups
[
2
]]
<<
", "
<<
posNames
[
groups
[
1
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName2
);
}
if
(
computedDeltas
.
count
(
deltaName3
)
==
0
)
{
compute
<<
"real4 delta"
<<
deltaName3
<<
" = delta("
<<
posNames
[
groups
[
2
]]
<<
", "
<<
posNames
[
groups
[
3
]]
<<
");
\n
"
;
computedDeltas
.
insert
(
deltaName3
);
}
compute
<<
"real4 "
<<
crossName1
<<
" = computeCross(delta"
<<
deltaName1
<<
", delta"
<<
deltaName2
<<
");
\n
"
;
compute
<<
"real4 "
<<
crossName2
<<
" = computeCross(delta"
<<
deltaName2
<<
", delta"
<<
deltaName3
<<
");
\n
"
;
compute
<<
"real "
<<
dihedralName
<<
" = 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
[
"real dEdDihedral"
+
cu
.
intToString
(
index
)
+
" = "
]
=
energyExpression
.
differentiate
(
iter
->
first
).
optimize
();
}
// Now evaluate the expressions.
for
(
int
i
=
0
;
i
<
(
int
)
params
->
getBuffers
().
size
();
i
++
)
{
CudaNonbondedUtilities
::
ParameterInfo
&
buffer
=
params
->
getBuffers
()[
i
];
extraArgs
<<
", const "
<<
buffer
.
getType
()
<<
"* __restrict__ globalParams"
<<
i
;
compute
<<
buffer
.
getType
()
<<
" bondParams"
<<
(
i
+
1
)
<<
" = globalParams"
<<
i
<<
"[index];
\n
"
;
groupForcesArgs
.
push_back
(
&
buffer
.
getMemory
());
}
forceExpressions
[
"energy += "
]
=
energyExpression
;
compute
<<
cu
.
getExpressionUtilities
().
createExpressions
(
forceExpressions
,
variables
,
functionList
,
functionDefinitions
,
"temp"
);
// Finally, apply forces to groups.
vector
<
string
>
forceNames
;
for
(
int
i
=
0
;
i
<
groupsPerBond
;
i
++
)
{
string
istr
=
cu
.
intToString
(
i
+
1
);
string
forceName
=
"force"
+
istr
;
forceNames
.
push_back
(
forceName
);
compute
<<
"real3 "
<<
forceName
<<
" = make_real3(0);
\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
<<
cu
.
getExpressionUtilities
().
createExpressions
(
expressions
,
variables
,
functionList
,
functionDefinitions
,
"coordtemp"
);
compute
<<
"}
\n
"
;
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
groups
=
iter
->
second
;
string
deltaName
=
atomNames
[
groups
[
0
]]
+
atomNames
[
groups
[
1
]];
string
value
=
"(dEdDistance"
+
cu
.
intToString
(
index
)
+
"/r_"
+
deltaName
+
")*trim(delta"
+
deltaName
+
")"
;
compute
<<
forceNames
[
groups
[
0
]]
<<
" += "
<<
"-"
<<
value
<<
";
\n
"
;
compute
<<
forceNames
[
groups
[
1
]]
<<
" += "
<<
value
<<
";
\n
"
;
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
groups
=
iter
->
second
;
string
deltaName1
=
atomNames
[
groups
[
1
]]
+
atomNames
[
groups
[
0
]];
string
deltaName2
=
atomNames
[
groups
[
1
]]
+
atomNames
[
groups
[
2
]];
compute
<<
"{
\n
"
;
compute
<<
"real3 crossProd = cross(delta"
<<
deltaName2
<<
", delta"
<<
deltaName1
<<
");
\n
"
;
compute
<<
"real lengthCross = max(SQRT(dot(crossProd, crossProd)), 1e-6f);
\n
"
;
compute
<<
"real3 deltaCross0 = -cross(trim(delta"
<<
deltaName1
<<
"), crossProd)*dEdAngle"
<<
cu
.
intToString
(
index
)
<<
"/(delta"
<<
deltaName1
<<
".w*lengthCross);
\n
"
;
compute
<<
"real3 deltaCross2 = cross(trim(delta"
<<
deltaName2
<<
"), crossProd)*dEdAngle"
<<
cu
.
intToString
(
index
)
<<
"/(delta"
<<
deltaName2
<<
".w*lengthCross);
\n
"
;
compute
<<
"real3 deltaCross1 = -(deltaCross0+deltaCross2);
\n
"
;
compute
<<
forceNames
[
groups
[
0
]]
<<
" += deltaCross0;
\n
"
;
compute
<<
forceNames
[
groups
[
1
]]
<<
" += deltaCross1;
\n
"
;
compute
<<
forceNames
[
groups
[
2
]]
<<
" += deltaCross2;
\n
"
;
compute
<<
"}
\n
"
;
}
index
=
0
;
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
,
++
index
)
{
const
vector
<
int
>&
groups
=
iter
->
second
;
string
deltaName1
=
atomNames
[
groups
[
0
]]
+
atomNames
[
groups
[
1
]];
string
deltaName2
=
atomNames
[
groups
[
2
]]
+
atomNames
[
groups
[
1
]];
string
deltaName3
=
atomNames
[
groups
[
2
]]
+
atomNames
[
groups
[
3
]];
string
crossName1
=
"cross_"
+
deltaName1
+
"_"
+
deltaName2
;
string
crossName2
=
"cross_"
+
deltaName2
+
"_"
+
deltaName3
;
compute
<<
"{
\n
"
;
compute
<<
"real r = sqrt(delta"
<<
deltaName2
<<
".w);
\n
"
;
compute
<<
"real4 ff;
\n
"
;
compute
<<
"ff.x = (-dEdDihedral"
<<
cu
.
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"
<<
cu
.
intToString
(
index
)
<<
"*r)/"
<<
crossName2
<<
".w;
\n
"
;
compute
<<
"real3 internalF0 = ff.x*trim("
<<
crossName1
<<
");
\n
"
;
compute
<<
"real3 internalF3 = ff.w*trim("
<<
crossName2
<<
");
\n
"
;
compute
<<
"real3 s = ff.y*internalF0 - ff.z*internalF3;
\n
"
;
compute
<<
forceNames
[
groups
[
0
]]
<<
" += internalF0;
\n
"
;
compute
<<
forceNames
[
groups
[
1
]]
<<
" += s-internalF0;
\n
"
;
compute
<<
forceNames
[
groups
[
2
]]
<<
" += -s-internalF3;
\n
"
;
compute
<<
forceNames
[
groups
[
3
]]
<<
" += internalF3;
\n
"
;
compute
<<
"}
\n
"
;
}
// Save the forces to global memory.
for
(
int
i
=
0
;
i
<
groupsPerBond
;
i
++
)
{
compute
<<
"atomicAdd(&groupForce[group"
<<
(
i
+
1
)
<<
"], static_cast<unsigned long long>((long long) (force"
<<
(
i
+
1
)
<<
".x*0x100000000)));
\n
"
;
compute
<<
"atomicAdd(&groupForce[group"
<<
(
i
+
1
)
<<
"+NUM_GROUPS], static_cast<unsigned long long>((long long) (force"
<<
(
i
+
1
)
<<
".y*0x100000000)));
\n
"
;
compute
<<
"atomicAdd(&groupForce[group"
<<
(
i
+
1
)
<<
"+NUM_GROUPS*2], static_cast<unsigned long long>((long long) (force"
<<
(
i
+
1
)
<<
".z*0x100000000)));
\n
"
;
compute
<<
"__threadfence_block();
\n
"
;
}
map
<
string
,
string
>
replacements
;
replacements
[
"M_PI"
]
=
cu
.
doubleToString
(
M_PI
);
replacements
[
"NUM_GROUPS"
]
=
cu
.
intToString
(
numGroups
);
replacements
[
"NUM_BONDS"
]
=
cu
.
intToString
(
numBonds
);
replacements
[
"PADDED_NUM_ATOMS"
]
=
cu
.
intToString
(
cu
.
getPaddedNumAtoms
());
replacements
[
"EXTRA_ARGS"
]
=
extraArgs
.
str
();
replacements
[
"COMPUTE_FORCE"
]
=
compute
.
str
();
CUmodule
module
=
cu
.
createModule
(
CudaKernelSources
::
vectorOps
+
cu
.
replaceStrings
(
CudaKernelSources
::
customCentroidBond
,
replacements
));
computeCentersKernel
=
cu
.
getKernel
(
module
,
"computeGroupCenters"
);
groupForcesKernel
=
cu
.
getKernel
(
module
,
"computeGroupForces"
);
applyForcesKernel
=
cu
.
getKernel
(
module
,
"applyForcesToAtoms"
);
}
double
CudaCalcCustomCentroidBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
if
(
globals
!=
NULL
)
{
bool
changed
=
false
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParamNames
.
size
();
i
++
)
{
float
value
=
(
float
)
context
.
getParameter
(
globalParamNames
[
i
]);
if
(
value
!=
globalParamValues
[
i
])
changed
=
true
;
globalParamValues
[
i
]
=
value
;
}
if
(
changed
)
globals
->
upload
(
globalParamValues
);
}
void
*
computeCentersArgs
[]
=
{
&
cu
.
getPosq
().
getDevicePointer
(),
&
groupParticles
->
getDevicePointer
(),
&
groupWeights
->
getDevicePointer
(),
&
groupOffsets
->
getDevicePointer
(),
&
centerPositions
->
getDevicePointer
()};
cu
.
executeKernel
(
computeCentersKernel
,
computeCentersArgs
,
CudaContext
::
TileSize
*
numGroups
);
groupForcesArgs
[
1
]
=
&
cu
.
getEnergyBuffer
().
getDevicePointer
();
cu
.
executeKernel
(
groupForcesKernel
,
&
groupForcesArgs
[
0
],
numBonds
);
void
*
applyForcesArgs
[]
=
{
&
groupParticles
->
getDevicePointer
(),
&
groupWeights
->
getDevicePointer
(),
&
groupOffsets
->
getDevicePointer
(),
&
groupForces
->
getDevicePointer
(),
&
cu
.
getForce
().
getDevicePointer
()};
cu
.
executeKernel
(
applyForcesKernel
,
applyForcesArgs
,
CudaContext
::
TileSize
*
numGroups
);
return
0.0
;
}
void
CudaCalcCustomCentroidBondForceKernel
::
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomCentroidBondForce
&
force
)
{
cu
.
setAsCurrent
();
int
numContexts
=
cu
.
getPlatformData
().
contexts
.
size
();
int
startIndex
=
cu
.
getContextIndex
()
*
force
.
getNumBonds
()
/
numContexts
;
int
endIndex
=
(
cu
.
getContextIndex
()
+
1
)
*
force
.
getNumBonds
()
/
numContexts
;
if
(
numBonds
!=
endIndex
-
startIndex
)
throw
OpenMMException
(
"updateParametersInContext: The number of bonds has changed"
);
if
(
numBonds
==
0
)
return
;
// Record the per-bond parameters.
vector
<
vector
<
float
>
>
paramVector
(
numBonds
);
vector
<
int
>
particles
;
vector
<
double
>
parameters
;
for
(
int
i
=
0
;
i
<
numBonds
;
i
++
)
{
force
.
getBondParameters
(
startIndex
+
i
,
particles
,
parameters
);
paramVector
[
i
].
resize
(
parameters
.
size
());
for
(
int
j
=
0
;
j
<
(
int
)
parameters
.
size
();
j
++
)
paramVector
[
i
][
j
]
=
(
float
)
parameters
[
j
];
}
params
->
setParameterValues
(
paramVector
);
// Mark that the current reordering may be invalid.
cu
.
invalidateMolecules
();
}
class
CudaCustomCompoundBondForceInfo
:
public
CudaForceInfo
{
class
CudaCustomCompoundBondForceInfo
:
public
CudaForceInfo
{
public:
public:
CudaCustomCompoundBondForceInfo
(
const
CustomCompoundBondForce
&
force
)
:
force
(
force
)
{
CudaCustomCompoundBondForceInfo
(
const
CustomCompoundBondForce
&
force
)
:
force
(
force
)
{
...
@@ -4304,7 +4717,6 @@ void CudaCalcCustomCompoundBondForceKernel::initialize(const System& system, con
...
@@ -4304,7 +4717,6 @@ void CudaCalcCustomCompoundBondForceKernel::initialize(const System& system, con
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
vector
<
pair
<
string
,
string
>
>
functionDefinitions
;
vector
<
pair
<
string
,
string
>
>
functionDefinitions
;
vector
<
const
TabulatedFunction
*>
functionList
;
vector
<
const
TabulatedFunction
*>
functionList
;
stringstream
tableArgs
;
for
(
int
i
=
0
;
i
<
force
.
getNumTabulatedFunctions
();
i
++
)
{
for
(
int
i
=
0
;
i
<
force
.
getNumTabulatedFunctions
();
i
++
)
{
functionList
.
push_back
(
&
force
.
getTabulatedFunction
(
i
));
functionList
.
push_back
(
&
force
.
getTabulatedFunction
(
i
));
string
name
=
force
.
getTabulatedFunctionName
(
i
);
string
name
=
force
.
getTabulatedFunctionName
(
i
);
...
@@ -4507,7 +4919,7 @@ void CudaCalcCustomCompoundBondForceKernel::initialize(const System& system, con
...
@@ -4507,7 +4919,7 @@ void CudaCalcCustomCompoundBondForceKernel::initialize(const System& system, con
cu
.
getBondedUtilities
().
addInteraction
(
atoms
,
compute
.
str
(),
force
.
getForceGroup
());
cu
.
getBondedUtilities
().
addInteraction
(
atoms
,
compute
.
str
(),
force
.
getForceGroup
());
map
<
string
,
string
>
replacements
;
map
<
string
,
string
>
replacements
;
replacements
[
"M_PI"
]
=
cu
.
doubleToString
(
M_PI
);
replacements
[
"M_PI"
]
=
cu
.
doubleToString
(
M_PI
);
cu
.
getBondedUtilities
().
addPrefixCode
(
cu
.
replaceStrings
(
CudaKernelSources
::
customCompoundBond
,
replacements
));
;
cu
.
getBondedUtilities
().
addPrefixCode
(
cu
.
replaceStrings
(
CudaKernelSources
::
customCompoundBond
,
replacements
));
}
}
double
CudaCalcCustomCompoundBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
CudaCalcCustomCompoundBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
...
...
platforms/cuda/src/CudaPlatform.cpp
View file @
4d823b0a
...
@@ -80,6 +80,7 @@ CudaPlatform::CudaPlatform() {
...
@@ -80,6 +80,7 @@ CudaPlatform::CudaPlatform() {
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
(
CalcCustomCentroidBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCompoundBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCompoundBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
...
...
platforms/cuda/src/kernels/customCentroidBond.cu
0 → 100644
View file @
4d823b0a
/**
* Compute the center of each group.
*/
extern
"C"
__global__
void
computeGroupCenters
(
const
real4
*
__restrict__
posq
,
const
int
*
__restrict__
groupParticles
,
const
real
*
__restrict__
groupWeights
,
const
int
*
__restrict__
groupOffsets
,
real4
*
__restrict__
centerPositions
)
{
__shared__
volatile
real3
temp
[
64
];
for
(
int
group
=
blockIdx
.
x
;
group
<
NUM_GROUPS
;
group
+=
gridDim
.
x
)
{
// The threads in this block work together to compute the center one group.
int
firstIndex
=
groupOffsets
[
group
];
int
lastIndex
=
groupOffsets
[
group
+
1
];
real3
center
=
make_real3
(
0
,
0
,
0
);
for
(
int
index
=
threadIdx
.
x
;
index
<
lastIndex
-
firstIndex
;
index
+=
blockDim
.
x
)
{
int
atom
=
groupParticles
[
firstIndex
+
index
];
real
weight
=
groupWeights
[
firstIndex
+
index
];
real4
pos
=
posq
[
atom
];
center
.
x
+=
weight
*
pos
.
x
;
center
.
y
+=
weight
*
pos
.
y
;
center
.
z
+=
weight
*
pos
.
z
;
}
// Sum the values.
int
thread
=
threadIdx
.
x
;
temp
[
thread
].
x
=
center
.
x
;
temp
[
thread
].
y
=
center
.
y
;
temp
[
thread
].
z
=
center
.
z
;
__syncthreads
();
if
(
thread
<
32
)
{
temp
[
thread
].
x
+=
temp
[
thread
+
32
].
x
;
temp
[
thread
].
y
+=
temp
[
thread
+
32
].
y
;
temp
[
thread
].
z
+=
temp
[
thread
+
32
].
z
;
if
(
thread
<
16
)
{
temp
[
thread
].
x
+=
temp
[
thread
+
16
].
x
;
temp
[
thread
].
y
+=
temp
[
thread
+
16
].
y
;
temp
[
thread
].
z
+=
temp
[
thread
+
16
].
z
;
}
if
(
thread
<
8
)
{
temp
[
thread
].
x
+=
temp
[
thread
+
8
].
x
;
temp
[
thread
].
y
+=
temp
[
thread
+
8
].
y
;
temp
[
thread
].
z
+=
temp
[
thread
+
8
].
z
;
}
if
(
thread
<
4
)
{
temp
[
thread
].
x
+=
temp
[
thread
+
4
].
x
;
temp
[
thread
].
y
+=
temp
[
thread
+
4
].
y
;
temp
[
thread
].
z
+=
temp
[
thread
+
4
].
z
;
}
if
(
thread
<
2
)
{
temp
[
thread
].
x
+=
temp
[
thread
+
2
].
x
;
temp
[
thread
].
y
+=
temp
[
thread
+
2
].
y
;
temp
[
thread
].
z
+=
temp
[
thread
+
2
].
z
;
}
}
if
(
thread
==
0
)
centerPositions
[
group
]
=
make_real4
(
temp
[
0
].
x
+
temp
[
1
].
x
,
temp
[
0
].
y
+
temp
[
1
].
y
,
temp
[
0
].
z
+
temp
[
1
].
z
,
0
);
}
}
/**
* Convert a real4 to a real3 by removing its last element.
*/
inline
__device__
real3
trim
(
real4
v
)
{
return
make_real3
(
v
.
x
,
v
.
y
,
v
.
z
);
}
/**
* Compute the difference between two vectors, setting the fourth component to the squared magnitude.
*/
inline
__device__
real4
delta
(
real4
vec1
,
real4
vec2
)
{
real4
result
=
make_real4
(
vec1
.
x
-
vec2
.
x
,
vec1
.
y
-
vec2
.
y
,
vec1
.
z
-
vec2
.
z
,
0
);
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.
*/
__device__
real
computeAngle
(
real4
vec1
,
real4
vec2
)
{
real
dotProduct
=
vec1
.
x
*
vec2
.
x
+
vec1
.
y
*
vec2
.
y
+
vec1
.
z
*
vec2
.
z
;
real
cosine
=
dotProduct
*
RSQRT
(
vec1
.
w
*
vec2
.
w
);
real
angle
;
if
(
cosine
>
0.99
f
||
cosine
<
-
0.99
f
)
{
// We're close to the singularity in acos(), so take the cross product and use asin() instead.
real3
crossProduct
=
cross
(
vec1
,
vec2
);
real
scale
=
vec1
.
w
*
vec2
.
w
;
angle
=
ASIN
(
SQRT
(
dot
(
crossProduct
,
crossProduct
)
/
scale
));
if
(
cosine
<
0.0
f
)
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.
*/
inline
__device__
real4
computeCross
(
real4
vec1
,
real4
vec2
)
{
real3
cp
=
cross
(
vec1
,
vec2
);
return
make_real4
(
cp
.
x
,
cp
.
y
,
cp
.
z
,
cp
.
x
*
cp
.
x
+
cp
.
y
*
cp
.
y
+
cp
.
z
*
cp
.
z
);
}
/**
* Compute the forces on groups based on the bonds.
*/
extern
"C"
__global__
void
computeGroupForces
(
unsigned
long
long
*
__restrict__
groupForce
,
real
*
__restrict__
energyBuffer
,
const
real4
*
__restrict__
centerPositions
,
const
int
*
__restrict__
bondGroups
EXTRA_ARGS
)
{
extern
__shared__
real4
posBuffer
[];
real
energy
=
0
;
for
(
int
index
=
blockIdx
.
x
*
blockDim
.
x
+
threadIdx
.
x
;
index
<
NUM_BONDS
;
index
+=
blockDim
.
x
*
gridDim
.
x
)
{
COMPUTE_FORCE
}
energyBuffer
[
blockIdx
.
x
*
blockDim
.
x
+
threadIdx
.
x
]
+=
energy
;
}
/**
* Apply the forces from the group centers to the individual atoms.
*/
extern
"C"
__global__
void
applyForcesToAtoms
(
const
int
*
__restrict__
groupParticles
,
const
real
*
__restrict__
groupWeights
,
const
int
*
__restrict__
groupOffsets
,
const
long
long
*
__restrict__
groupForce
,
unsigned
long
long
*
__restrict__
atomForce
)
{
for
(
int
group
=
blockIdx
.
x
;
group
<
NUM_GROUPS
;
group
+=
gridDim
.
x
)
{
long
long
fx
=
groupForce
[
group
];
long
long
fy
=
groupForce
[
group
+
NUM_GROUPS
];
long
long
fz
=
groupForce
[
group
+
NUM_GROUPS
*
2
];
int
firstIndex
=
groupOffsets
[
group
];
int
lastIndex
=
groupOffsets
[
group
+
1
];
for
(
int
index
=
threadIdx
.
x
;
index
<
lastIndex
-
firstIndex
;
index
+=
blockDim
.
x
)
{
int
atom
=
groupParticles
[
firstIndex
+
index
];
real
weight
=
groupWeights
[
firstIndex
+
index
];
atomicAdd
(
&
atomForce
[
atom
],
static_cast
<
unsigned
long
long
>
((
long
long
)
(
fx
*
weight
)));
atomicAdd
(
&
atomForce
[
atom
+
PADDED_NUM_ATOMS
],
static_cast
<
unsigned
long
long
>
((
long
long
)
(
fy
*
weight
)));
atomicAdd
(
&
atomForce
[
atom
+
2
*
PADDED_NUM_ATOMS
],
static_cast
<
unsigned
long
long
>
((
long
long
)
(
fz
*
weight
)));
}
}
}
platforms/cuda/tests/TestCudaCustomCentroidBondForce.cpp
0 → 100644
View file @
4d823b0a
/* -------------------------------------------------------------------------- *
* 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) 2015 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 reference implementation of CustomCompoundBondForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "CudaPlatform.h"
#include "openmm/CustomCentroidBondForce.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
CudaPlatform
platform
;
const
double
TOL
=
1e-5
;
void
testHarmonicBond
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
2.0
);
system
.
addParticle
(
3.0
);
system
.
addParticle
(
4.0
);
system
.
addParticle
(
5.0
);
CustomCentroidBondForce
*
force
=
new
CustomCentroidBondForce
(
2
,
"k*distance(g1,g2)^2"
);
force
->
addPerBondParameter
(
"k"
);
vector
<
int
>
particles1
;
particles1
.
push_back
(
0
);
particles1
.
push_back
(
1
);
vector
<
int
>
particles2
;
particles2
.
push_back
(
2
);
particles2
.
push_back
(
3
);
particles2
.
push_back
(
4
);
force
->
addGroup
(
particles1
);
force
->
addGroup
(
particles2
);
vector
<
int
>
groups
;
groups
.
push_back
(
0
);
groups
.
push_back
(
1
);
vector
<
double
>
parameters
;
parameters
.
push_back
(
1.0
);
force
->
addBond
(
groups
,
parameters
);
system
.
addForce
(
force
);
ASSERT
(
!
system
.
usesPeriodicBoundaryConditions
());
// The center of mass of group 0 is (1.5, 0, 0).
vector
<
Vec3
>
positions
(
5
);
positions
[
0
]
=
Vec3
(
2.5
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
// The center of mass of group 1 is (-1, 0, 0).
positions
[
2
]
=
Vec3
(
-
6
,
0
,
0
);
positions
[
3
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
4
]
=
Vec3
(
2
,
0
,
0
);
// Check the forces and energy.
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
2.5
*
2.5
,
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
2
*
2.5
*
(
1.0
/
3.0
),
0
,
0
),
state
.
getForces
()[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
2
*
2.5
*
(
2.0
/
3.0
),
0
,
0
),
state
.
getForces
()[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
2
*
2.5
*
(
3.0
/
12.0
),
0
,
0
),
state
.
getForces
()[
2
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
2
*
2.5
*
(
4.0
/
12.0
),
0
,
0
),
state
.
getForces
()[
3
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
2
*
2.5
*
(
5.0
/
12.0
),
0
,
0
),
state
.
getForces
()[
4
],
TOL
);
// Update the per-bond parameter and see if the results change.
parameters
[
0
]
=
2.0
;
force
->
setBondParameters
(
0
,
groups
,
parameters
);
force
->
updateParametersInContext
(
context
);
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
2
*
2.5
*
2.5
,
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
4
*
2.5
*
(
1.0
/
3.0
),
0
,
0
),
state
.
getForces
()[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
4
*
2.5
*
(
2.0
/
3.0
),
0
,
0
),
state
.
getForces
()[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
4
*
2.5
*
(
3.0
/
12.0
),
0
,
0
),
state
.
getForces
()[
2
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
4
*
2.5
*
(
4.0
/
12.0
),
0
,
0
),
state
.
getForces
()[
3
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
4
*
2.5
*
(
5.0
/
12.0
),
0
,
0
),
state
.
getForces
()[
4
],
TOL
);
}
void
testComplexFunction
()
{
int
numParticles
=
4
;
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system
.
addParticle
(
2.0
);
// When every group contains only one particle, a CustomCentroidBondForce is identical to a
// CustomCompoundBondForce. Use that to test a complicated energy function with lots of terms.
CustomCompoundBondForce
*
compound
=
new
CustomCompoundBondForce
(
4
,
"x1+y2+z4+distance(p1,p2)*angle(p3,p2,p4)+0.5*dihedral(p2,p1,p4,p3)"
);
CustomCentroidBondForce
*
centroid
=
new
CustomCentroidBondForce
(
4
,
"x1+y2+z4+distance(g1,g2)*angle(g3,g2,g4)+0.5*dihedral(g2,g1,g4,g3)"
);
// Add a single bond to the CustomCompoundBondForce.
vector
<
int
>
particles
(
4
);
vector
<
double
>
parameters
;
particles
[
0
]
=
0
;
particles
[
1
]
=
1
;
particles
[
2
]
=
2
;
particles
[
3
]
=
3
;
compound
->
addBond
(
particles
,
parameters
);
// Add an identical bond to the CustomCentroidBondForce. As a stronger test, make sure that
// group number is different from particle number.
vector
<
int
>
groupMembers
(
1
);
groupMembers
[
0
]
=
3
;
centroid
->
addGroup
(
groupMembers
);
groupMembers
[
0
]
=
0
;
centroid
->
addGroup
(
groupMembers
);
groupMembers
[
0
]
=
1
;
centroid
->
addGroup
(
groupMembers
);
groupMembers
[
0
]
=
2
;
centroid
->
addGroup
(
groupMembers
);
vector
<
int
>
groups
(
4
);
groups
[
0
]
=
1
;
groups
[
1
]
=
2
;
groups
[
2
]
=
3
;
groups
[
3
]
=
0
;
centroid
->
addBond
(
groups
,
parameters
);
// Add both forces as different force groups, and create a context.
centroid
->
setForceGroup
(
1
);
system
.
addForce
(
compound
);
system
.
addForce
(
centroid
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
// Evaluate the force and energy for various positions and see if they match.
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
positions
(
numParticles
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
j
=
0
;
j
<
numParticles
;
j
++
)
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
context
.
setPositions
(
positions
);
State
state1
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
,
false
,
1
<<
0
);
State
state2
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
,
false
,
1
<<
1
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
TOL
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
TOL
);
}
}
void
testCustomWeights
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
2.0
);
system
.
addParticle
(
3.0
);
system
.
addParticle
(
4.0
);
CustomCentroidBondForce
*
force
=
new
CustomCentroidBondForce
(
2
,
"distance(g1,g2)^2"
);
vector
<
int
>
particles
(
2
);
vector
<
double
>
weights
(
2
);
particles
[
0
]
=
0
;
particles
[
1
]
=
1
;
weights
[
0
]
=
0.5
;
weights
[
1
]
=
1.5
;
force
->
addGroup
(
particles
,
weights
);
particles
[
0
]
=
2
;
particles
[
1
]
=
3
;
weights
[
0
]
=
2.0
;
weights
[
1
]
=
1.0
;
force
->
addGroup
(
particles
,
weights
);
vector
<
int
>
groups
;
groups
.
push_back
(
0
);
groups
.
push_back
(
1
);
vector
<
double
>
parameters
;
force
->
addBond
(
groups
,
parameters
);
system
.
addForce
(
force
);
// The center of mass of group 0 is (0, 1, 0).
vector
<
Vec3
>
positions
(
4
);
positions
[
0
]
=
Vec3
(
0
,
4
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
// The center of mass of group 1 is (0, 10, 0).
positions
[
2
]
=
Vec3
(
0
,
9
,
0
);
positions
[
3
]
=
Vec3
(
0
,
12
,
0
);
// Check the forces and energy.
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
9
*
9
,
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
2
*
9
*
(
0.5
/
2.0
),
0
),
state
.
getForces
()[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
2
*
9
*
(
1.5
/
2.0
),
0
),
state
.
getForces
()[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
-
2
*
9
*
(
2.0
/
3.0
),
0
),
state
.
getForces
()[
2
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
-
2
*
9
*
(
1.0
/
3.0
),
0
),
state
.
getForces
()[
3
],
TOL
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
if
(
argc
>
1
)
platform
.
setPropertyDefaultValue
(
"CudaPrecision"
,
string
(
argv
[
1
]));
testHarmonicBond
();
testComplexFunction
();
testCustomWeights
();
}
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