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
0e2ffb4b
Commit
0e2ffb4b
authored
Aug 14, 2014
by
peastman
Browse files
CPU version of CustomManyParticleForce is multithreaded
parent
1bc8e327
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
906 additions
and
187 deletions
+906
-187
platforms/cpu/include/CpuCustomManyParticleForce.h
platforms/cpu/include/CpuCustomManyParticleForce.h
+53
-39
platforms/cpu/src/CpuCustomManyParticleForce.cpp
platforms/cpu/src/CpuCustomManyParticleForce.cpp
+263
-144
platforms/cpu/src/CpuKernels.cpp
platforms/cpu/src/CpuKernels.cpp
+2
-3
platforms/cpu/tests/TestCpuCustomManyParticleForce.cpp
platforms/cpu/tests/TestCpuCustomManyParticleForce.cpp
+519
-0
platforms/reference/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
...nce/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
+1
-1
platforms/reference/tests/TestReferenceCustomManyParticleForce.cpp
.../reference/tests/TestReferenceCustomManyParticleForce.cpp
+68
-0
No files found.
platforms/cpu/include/CpuCustomManyParticleForce.h
View file @
0e2ffb4b
...
@@ -36,6 +36,7 @@
...
@@ -36,6 +36,7 @@
#include "lepton/ParsedExpression.h"
#include "lepton/ParsedExpression.h"
#include <map>
#include <map>
#include <set>
#include <set>
#include <utility>
#include <vector>
#include <vector>
namespace
OpenMM
{
namespace
OpenMM
{
...
@@ -47,26 +48,36 @@ private:
...
@@ -47,26 +48,36 @@ private:
class
DistanceTermInfo
;
class
DistanceTermInfo
;
class
AngleTermInfo
;
class
AngleTermInfo
;
class
DihedralTermInfo
;
class
DihedralTermInfo
;
class
ComputeForceTask
;
class
ThreadData
;
int
numParticlesPerSet
,
numPerParticleParameters
,
numTypes
;
int
numParticlesPerSet
,
numPerParticleParameters
,
numTypes
;
bool
useCutoff
,
usePeriodic
;
bool
useCutoff
,
usePeriodic
;
RealOpenMM
cutoffDistance
;
RealOpenMM
cutoffDistance
;
RealOpenMM
periodicBoxSize
[
3
];
RealOpenMM
periodicBoxSize
[
3
];
CpuNeighborList
*
neighborList
;
CpuNeighborList
*
neighborList
;
ThreadPool
&
threads
;
ThreadPool
&
threads
;
CompiledExpressionSet
expressionSet
;
Lepton
::
CompiledExpression
energyExpression
;
std
::
vector
<
std
::
vector
<
int
>
>
particleParamIndices
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
int
>
particleTypes
;
std
::
vector
<
int
>
particleTypes
;
std
::
vector
<
int
>
orderIndex
;
std
::
vector
<
int
>
orderIndex
;
std
::
vector
<
std
::
vector
<
int
>
>
particleOrder
;
std
::
vector
<
std
::
vector
<
int
>
>
particleOrder
;
std
::
vector
<
ParticleTermInfo
>
particleTerms
;
std
::
vector
<
ThreadData
*>
threadData
;
std
::
vector
<
DistanceTermInfo
>
distanceTerms
;
// The following variables are used to make information accessible to the individual threads.
std
::
vector
<
AngleTermInfo
>
angleTerms
;
int
numParticles
;
std
::
vector
<
DihedralTermInfo
>
dihedralTerms
;
float
*
posq
;
RealVec
const
*
atomCoordinates
;
RealOpenMM
**
particleParameters
;
const
std
::
map
<
std
::
string
,
double
>*
globalParameters
;
std
::
vector
<
AlignedArray
<
float
>
>*
threadForce
;
bool
includeForces
,
includeEnergy
;
void
*
atomicCounter
;
/**
* This routine contains the code executed by each thread.
*/
void
threadComputeForce
(
ThreadPool
&
threads
,
int
threadIndex
);
void
loopOverInteractions
(
std
::
vector
<
int
>&
availableParticles
,
std
::
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
float
*
posq
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
void
loopOverInteractions
(
std
::
vector
<
int
>&
availableParticles
,
std
::
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
RealOpenMM
**
particleParameters
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -81,8 +92,8 @@ private:
...
@@ -81,8 +92,8 @@ private:
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
void
calculateOneIxn
(
std
::
vector
<
int
>&
particleSet
,
float
*
posq
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
void
calculateOneIxn
(
std
::
vector
<
int
>&
particleSet
,
RealOpenMM
**
particleParameters
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
/**
/**
* Compute the displacement and squared distance between two points, optionally using
* Compute the displacement and squared distance between two points, optionally using
...
@@ -90,9 +101,9 @@ private:
...
@@ -90,9 +101,9 @@ private:
*/
*/
void
getDeltaR
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
;
void
getDeltaR
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
;
void
computeDelta
(
int
atom1
,
int
atom2
,
RealOpenMM
*
delta
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
)
const
;
void
computeDelta
(
int
atom1
,
int
atom2
,
RealOpenMM
*
delta
,
const
OpenMM
::
RealVec
*
atomCoordinates
)
const
;
static
RealOpenMM
computeAngle
(
RealOpenMM
*
vec1
,
RealOpenMM
*
vec2
);
static
RealOpenMM
computeAngle
(
RealOpenMM
*
vec1
,
RealOpenMM
*
vec2
,
float
sign
);
public:
public:
...
@@ -150,10 +161,7 @@ public:
...
@@ -150,10 +161,7 @@ public:
void
calculateIxn
(
AlignedArray
<
float
>&
posq
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
void
calculateIxn
(
AlignedArray
<
float
>&
posq
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
const
std
::
map
<
std
::
string
,
double
>&
globalParameters
,
const
std
::
map
<
std
::
string
,
double
>&
globalParameters
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
);
std
::
vector
<
AlignedArray
<
float
>
>&
threadForce
,
bool
includeForces
,
bool
includeEnergy
,
double
&
energy
);
// ---------------------------------------------------------------------------------------
};
};
class
CpuCustomManyParticleForce
::
ParticleTermInfo
{
class
CpuCustomManyParticleForce
::
ParticleTermInfo
{
...
@@ -161,10 +169,7 @@ public:
...
@@ -161,10 +169,7 @@ public:
std
::
string
name
;
std
::
string
name
;
int
atom
,
component
,
variableIndex
;
int
atom
,
component
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
ParticleTermInfo
(
const
std
::
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
CompiledExpressionSet
&
set
)
:
ParticleTermInfo
(
const
std
::
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
name
(
name
),
atom
(
atom
),
component
(
component
),
forceExpression
(
forceExpression
)
{
variableIndex
=
set
.
getVariableIndex
(
name
);
}
};
};
class
CpuCustomManyParticleForce
::
DistanceTermInfo
{
class
CpuCustomManyParticleForce
::
DistanceTermInfo
{
...
@@ -172,11 +177,9 @@ public:
...
@@ -172,11 +177,9 @@ public:
std
::
string
name
;
std
::
string
name
;
int
p1
,
p2
,
variableIndex
;
int
p1
,
p2
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
mutable
RealOpenMM
delta
[
ReferenceForce
::
LastDeltaRIndex
];
int
delta
;
DistanceTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
CompiledExpressionSet
&
set
)
:
float
deltaSign
;
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
forceExpression
(
forceExpression
)
{
DistanceTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
variableIndex
=
set
.
getVariableIndex
(
name
);
}
};
};
class
CpuCustomManyParticleForce
::
AngleTermInfo
{
class
CpuCustomManyParticleForce
::
AngleTermInfo
{
...
@@ -184,12 +187,9 @@ public:
...
@@ -184,12 +187,9 @@ public:
std
::
string
name
;
std
::
string
name
;
int
p1
,
p2
,
p3
,
variableIndex
;
int
p1
,
p2
,
p3
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
mutable
RealOpenMM
delta1
[
ReferenceForce
::
LastDeltaRIndex
];
int
delta1
,
delta2
;
mutable
RealOpenMM
delta2
[
ReferenceForce
::
LastDeltaRIndex
];
float
delta1Sign
,
delta2Sign
;
AngleTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
CompiledExpressionSet
&
set
)
:
AngleTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
forceExpression
(
forceExpression
)
{
variableIndex
=
set
.
getVariableIndex
(
name
);
}
};
};
class
CpuCustomManyParticleForce
::
DihedralTermInfo
{
class
CpuCustomManyParticleForce
::
DihedralTermInfo
{
...
@@ -197,15 +197,29 @@ public:
...
@@ -197,15 +197,29 @@ public:
std
::
string
name
;
std
::
string
name
;
int
p1
,
p2
,
p3
,
p4
,
variableIndex
;
int
p1
,
p2
,
p3
,
p4
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
mutable
RealOpenMM
delta1
[
ReferenceForce
::
LastDeltaRIndex
];
int
delta1
,
delta2
,
delta3
;
mutable
RealOpenMM
delta2
[
ReferenceForce
::
LastDeltaRIndex
];
mutable
RealOpenMM
delta3
[
ReferenceForce
::
LastDeltaRIndex
];
mutable
RealOpenMM
cross1
[
3
];
mutable
RealOpenMM
cross1
[
3
];
mutable
RealOpenMM
cross2
[
3
];
mutable
RealOpenMM
cross2
[
3
];
DihedralTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
CompiledExpressionSet
&
set
)
:
DihedralTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
p4
(
atoms
[
3
]),
forceExpression
(
forceExpression
)
{
};
variableIndex
=
set
.
getVariableIndex
(
name
);
}
class
CpuCustomManyParticleForce
::
ThreadData
{
public:
CompiledExpressionSet
expressionSet
;
Lepton
::
CompiledExpression
energyExpression
;
std
::
vector
<
std
::
vector
<
int
>
>
particleParamIndices
;
std
::
vector
<
std
::
pair
<
int
,
int
>
>
deltaPairs
;
std
::
vector
<
ParticleTermInfo
>
particleTerms
;
std
::
vector
<
DistanceTermInfo
>
distanceTerms
;
std
::
vector
<
AngleTermInfo
>
angleTerms
;
std
::
vector
<
DihedralTermInfo
>
dihedralTerms
;
double
energy
;
ThreadData
(
const
CustomManyParticleForce
&
force
,
Lepton
::
ParsedExpression
&
energyExpr
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
/**
* Request a pair of particles whose distance or displacement vector is needed in the computation.
*/
void
requestDeltaPair
(
int
p1
,
int
p2
,
int
&
pairIndex
,
float
&
pairSign
,
bool
allowReversed
);
};
};
}
// namespace OpenMM
}
// namespace OpenMM
...
...
platforms/cpu/src/CpuCustomManyParticleForce.cpp
View file @
0e2ffb4b
...
@@ -34,10 +34,21 @@
...
@@ -34,10 +34,21 @@
#include "ReferenceTabulatedFunction.h"
#include "ReferenceTabulatedFunction.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "lepton/CustomFunction.h"
#include "lepton/CustomFunction.h"
#include "gmx_atomic.h"
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
class
CpuCustomManyParticleForce
::
ComputeForceTask
:
public
ThreadPool
::
Task
{
public:
ComputeForceTask
(
CpuCustomManyParticleForce
&
owner
)
:
owner
(
owner
)
{
}
void
execute
(
ThreadPool
&
threads
,
int
threadIndex
)
{
owner
.
threadComputeForce
(
threads
,
threadIndex
);
}
CpuCustomManyParticleForce
&
owner
;
};
CpuCustomManyParticleForce
::
CpuCustomManyParticleForce
(
const
CustomManyParticleForce
&
force
,
ThreadPool
&
threads
)
:
CpuCustomManyParticleForce
::
CpuCustomManyParticleForce
(
const
CustomManyParticleForce
&
force
,
ThreadPool
&
threads
)
:
threads
(
threads
),
useCutoff
(
false
),
usePeriodic
(
false
),
neighborList
(
NULL
)
{
threads
(
threads
),
useCutoff
(
false
),
usePeriodic
(
false
),
neighborList
(
NULL
)
{
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
...
@@ -49,15 +60,14 @@ CpuCustomManyParticleForce::CpuCustomManyParticleForce(const CustomManyParticleF
...
@@ -49,15 +60,14 @@ CpuCustomManyParticleForce::CpuCustomManyParticleForce(const CustomManyParticleF
for
(
int
i
=
0
;
i
<
(
int
)
force
.
getNumTabulatedFunctions
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
force
.
getNumTabulatedFunctions
();
i
++
)
functions
[
force
.
getTabulatedFunctionName
(
i
)]
=
createReferenceTabulatedFunction
(
force
.
getTabulatedFunction
(
i
));
functions
[
force
.
getTabulatedFunctionName
(
i
)]
=
createReferenceTabulatedFunction
(
force
.
getTabulatedFunction
(
i
));
// Parse the expression and create the object used to calculate the interaction.
// Parse the expression and create the object
s
used to calculate the interaction.
map
<
string
,
vector
<
int
>
>
distances
;
map
<
string
,
vector
<
int
>
>
distances
;
map
<
string
,
vector
<
int
>
>
angles
;
map
<
string
,
vector
<
int
>
>
angles
;
map
<
string
,
vector
<
int
>
>
dihedrals
;
map
<
string
,
vector
<
int
>
>
dihedrals
;
Lepton
::
ParsedExpression
energyExpr
=
CustomManyParticleForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
Lepton
::
ParsedExpression
energyExpr
=
CustomManyParticleForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
energyExpression
=
energyExpr
.
createCompiledExpression
();
for
(
int
i
=
0
;
i
<
threads
.
getNumThreads
();
i
++
)
expressionSet
.
registerExpression
(
energyExpression
);
threadData
.
push_back
(
new
ThreadData
(
force
,
energyExpr
,
distances
,
angles
,
dihedrals
));
vector
<
string
>
particleParameterNames
;
if
(
force
.
getNonbondedMethod
()
!=
CustomManyParticleForce
::
NoCutoff
)
if
(
force
.
getNonbondedMethod
()
!=
CustomManyParticleForce
::
NoCutoff
)
setUseCutoff
(
force
.
getCutoffDistance
());
setUseCutoff
(
force
.
getCutoffDistance
());
...
@@ -66,38 +76,6 @@ CpuCustomManyParticleForce::CpuCustomManyParticleForce(const CustomManyParticleF
...
@@ -66,38 +76,6 @@ CpuCustomManyParticleForce::CpuCustomManyParticleForce(const CustomManyParticleF
for
(
map
<
string
,
Lepton
::
CustomFunction
*>::
iterator
iter
=
functions
.
begin
();
iter
!=
functions
.
end
();
iter
++
)
for
(
map
<
string
,
Lepton
::
CustomFunction
*>::
iterator
iter
=
functions
.
begin
();
iter
!=
functions
.
end
();
iter
++
)
delete
iter
->
second
;
delete
iter
->
second
;
// Differentiate the energy to get expressions for the force.
particleParamIndices
.
resize
(
numParticlesPerSet
);
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
stringstream
xname
,
yname
,
zname
;
xname
<<
'x'
<<
(
i
+
1
);
yname
<<
'y'
<<
(
i
+
1
);
zname
<<
'z'
<<
(
i
+
1
);
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
xname
.
str
(),
i
,
0
,
energyExpr
.
differentiate
(
xname
.
str
()).
optimize
().
createCompiledExpression
(),
expressionSet
));
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
yname
.
str
(),
i
,
1
,
energyExpr
.
differentiate
(
yname
.
str
()).
optimize
().
createCompiledExpression
(),
expressionSet
));
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
zname
.
str
(),
i
,
2
,
energyExpr
.
differentiate
(
zname
.
str
()).
optimize
().
createCompiledExpression
(),
expressionSet
));
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
{
stringstream
paramname
;
paramname
<<
force
.
getPerParticleParameterName
(
j
)
<<
(
i
+
1
);
particleParamIndices
[
i
].
push_back
(
expressionSet
.
getVariableIndex
(
paramname
.
str
()));
}
}
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
)
distanceTerms
.
push_back
(
CpuCustomManyParticleForce
::
DistanceTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
expressionSet
));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
)
angleTerms
.
push_back
(
CpuCustomManyParticleForce
::
AngleTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
expressionSet
));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
)
dihedralTerms
.
push_back
(
CpuCustomManyParticleForce
::
DihedralTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
expressionSet
));
for
(
int
i
=
0
;
i
<
particleTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
particleTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
distanceTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
distanceTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
angleTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
angleTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
dihedralTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
dihedralTerms
[
i
].
forceExpression
);
// Record exclusions.
// Record exclusions.
exclusions
.
resize
(
force
.
getNumParticles
());
exclusions
.
resize
(
force
.
getNumParticles
());
...
@@ -116,23 +94,64 @@ CpuCustomManyParticleForce::CpuCustomManyParticleForce(const CustomManyParticleF
...
@@ -116,23 +94,64 @@ CpuCustomManyParticleForce::CpuCustomManyParticleForce(const CustomManyParticleF
CpuCustomManyParticleForce
::~
CpuCustomManyParticleForce
()
{
CpuCustomManyParticleForce
::~
CpuCustomManyParticleForce
()
{
if
(
neighborList
!=
NULL
)
if
(
neighborList
!=
NULL
)
delete
neighborList
;
delete
neighborList
;
for
(
int
i
=
0
;
i
<
(
int
)
threadData
.
size
();
i
++
)
delete
threadData
[
i
];
}
}
void
CpuCustomManyParticleForce
::
calculateIxn
(
AlignedArray
<
float
>&
posq
,
vector
<
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
void
CpuCustomManyParticleForce
::
calculateIxn
(
AlignedArray
<
float
>&
posq
,
vector
<
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
const
map
<
string
,
double
>&
globalParameters
,
vector
<
RealVec
>&
forces
,
const
map
<
string
,
double
>&
globalParameters
,
vector
<
AlignedArray
<
float
>
>&
threadForce
,
RealOpenMM
*
totalEnergy
)
{
bool
includeForces
,
bool
includeEnergy
,
double
&
energy
)
{
for
(
map
<
string
,
double
>::
const_iterator
iter
=
globalParameters
.
begin
();
iter
!=
globalParameters
.
end
();
++
iter
)
// Record the parameters for the threads.
expressionSet
.
setVariable
(
expressionSet
.
getVariableIndex
(
iter
->
first
),
iter
->
second
);
int
numParticles
=
atomCoordinates
.
size
();
this
->
numParticles
=
atomCoordinates
.
size
();
vector
<
int
>
particleIndices
(
numParticlesPerSet
);
this
->
posq
=
&
posq
[
0
];
fvec4
boxSize
(
periodicBoxSize
[
0
],
periodicBoxSize
[
1
],
periodicBoxSize
[
2
],
0
);
this
->
atomCoordinates
=
&
atomCoordinates
[
0
];
fvec4
invBoxSize
((
1
/
periodicBoxSize
[
0
]),
(
1
/
periodicBoxSize
[
1
]),
(
1
/
periodicBoxSize
[
2
]),
0
);
this
->
particleParameters
=
particleParameters
;
this
->
globalParameters
=
&
globalParameters
;
this
->
threadForce
=
&
threadForce
;
this
->
includeForces
=
includeForces
;
this
->
includeEnergy
=
includeEnergy
;
gmx_atomic_t
counter
;
gmx_atomic_set
(
&
counter
,
0
);
this
->
atomicCounter
=
&
counter
;
if
(
useCutoff
)
{
if
(
useCutoff
)
{
// Construct a neighbor list.
// Construct a neighbor list.
float
boxSizeFloat
[]
=
{(
float
)
periodicBoxSize
[
0
],
(
float
)
periodicBoxSize
[
1
],
(
float
)
periodicBoxSize
[
2
]};
float
boxSizeFloat
[]
=
{(
float
)
periodicBoxSize
[
0
],
(
float
)
periodicBoxSize
[
1
],
(
float
)
periodicBoxSize
[
2
]};
neighborList
->
computeNeighborList
(
numParticles
,
posq
,
exclusions
,
boxSizeFloat
,
usePeriodic
,
cutoffDistance
,
threads
);
neighborList
->
computeNeighborList
(
numParticles
,
posq
,
exclusions
,
boxSizeFloat
,
usePeriodic
,
cutoffDistance
,
threads
);
for
(
int
blockIndex
=
0
;
blockIndex
<
neighborList
->
getNumBlocks
();
blockIndex
++
)
{
}
// Signal the threads to start running and wait for them to finish.
ComputeForceTask
task
(
*
this
);
threads
.
execute
(
task
);
threads
.
waitForThreads
();
// Combine the energies from all the threads.
if
(
includeEnergy
)
{
int
numThreads
=
threads
.
getNumThreads
();
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
energy
+=
threadData
[
i
]
->
energy
;
}
}
void
CpuCustomManyParticleForce
::
threadComputeForce
(
ThreadPool
&
threads
,
int
threadIndex
)
{
vector
<
int
>
particleIndices
(
numParticlesPerSet
);
fvec4
boxSize
(
periodicBoxSize
[
0
],
periodicBoxSize
[
1
],
periodicBoxSize
[
2
],
0
);
fvec4
invBoxSize
((
1
/
periodicBoxSize
[
0
]),
(
1
/
periodicBoxSize
[
1
]),
(
1
/
periodicBoxSize
[
2
]),
0
);
float
*
forces
=
&
(
*
threadForce
)[
threadIndex
][
0
];
ThreadData
&
data
=
*
threadData
[
threadIndex
];
data
.
energy
=
0
;
for
(
map
<
string
,
double
>::
const_iterator
iter
=
globalParameters
->
begin
();
iter
!=
globalParameters
->
end
();
++
iter
)
data
.
expressionSet
.
setVariable
(
data
.
expressionSet
.
getVariableIndex
(
iter
->
first
),
iter
->
second
);
if
(
useCutoff
)
{
// Loop over interactions from the neighbor list.
while
(
true
)
{
int
blockIndex
=
gmx_atomic_fetch_add
(
reinterpret_cast
<
gmx_atomic_t
*>
(
atomicCounter
),
1
);
if
(
blockIndex
>=
neighborList
->
getNumBlocks
())
break
;
const
vector
<
int
>&
neighbors
=
neighborList
->
getBlockNeighbors
(
blockIndex
);
const
vector
<
int
>&
neighbors
=
neighborList
->
getBlockNeighbors
(
blockIndex
);
const
vector
<
char
>&
exclusions
=
neighborList
->
getBlockExclusions
(
blockIndex
);
const
vector
<
char
>&
exclusions
=
neighborList
->
getBlockExclusions
(
blockIndex
);
int
numNeighbors
=
neighbors
.
size
();
int
numNeighbors
=
neighbors
.
size
();
...
@@ -147,7 +166,7 @@ void CpuCustomManyParticleForce::calculateIxn(AlignedArray<float>& posq, vector<
...
@@ -147,7 +166,7 @@ void CpuCustomManyParticleForce::calculateIxn(AlignedArray<float>& posq, vector<
for
(
int
j
=
0
;
j
<
numNeighbors
;
j
++
)
for
(
int
j
=
0
;
j
<
numNeighbors
;
j
++
)
if
((
exclusions
[
j
]
&
(
1
<<
i
))
==
0
)
if
((
exclusions
[
j
]
&
(
1
<<
i
))
==
0
)
particles
.
push_back
(
neighbors
[
j
]);
particles
.
push_back
(
neighbors
[
j
]);
loopOverInteractions
(
particles
,
particleIndices
,
1
,
0
,
&
posq
[
0
],
atomCoordinates
,
particleParameters
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
);
loopOverInteractions
(
particles
,
particleIndices
,
1
,
0
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
}
}
}
}
}
}
...
@@ -157,9 +176,12 @@ void CpuCustomManyParticleForce::calculateIxn(AlignedArray<float>& posq, vector<
...
@@ -157,9 +176,12 @@ void CpuCustomManyParticleForce::calculateIxn(AlignedArray<float>& posq, vector<
vector
<
int
>
particles
(
numParticles
);
vector
<
int
>
particles
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
particles
[
i
]
=
i
;
particles
[
i
]
=
i
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
while
(
true
)
{
int
i
=
gmx_atomic_fetch_add
(
reinterpret_cast
<
gmx_atomic_t
*>
(
atomicCounter
),
1
);
if
(
i
>=
numParticles
)
break
;
particleIndices
[
0
]
=
i
;
particleIndices
[
0
]
=
i
;
loopOverInteractions
(
particles
,
particleIndices
,
1
,
i
+
1
,
&
posq
[
0
],
atomCoordinates
,
particleParameters
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
);
loopOverInteractions
(
particles
,
particleIndices
,
1
,
i
+
1
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
}
}
}
}
}
}
...
@@ -182,8 +204,8 @@ void CpuCustomManyParticleForce::setPeriodic(RealVec& boxSize) {
...
@@ -182,8 +204,8 @@ void CpuCustomManyParticleForce::setPeriodic(RealVec& boxSize) {
periodicBoxSize
[
2
]
=
boxSize
[
2
];
periodicBoxSize
[
2
]
=
boxSize
[
2
];
}
}
void
CpuCustomManyParticleForce
::
loopOverInteractions
(
vector
<
int
>&
availableParticles
,
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
float
*
posq
,
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
void
CpuCustomManyParticleForce
::
loopOverInteractions
(
vector
<
int
>&
availableParticles
,
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
RealOpenMM
**
particleParameters
,
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
int
numParticles
=
availableParticles
.
size
();
int
numParticles
=
availableParticles
.
size
();
// double cutoff2 = cutoffDistance*cutoffDistance;
// double cutoff2 = cutoffDistance*cutoffDistance;
for
(
int
i
=
startIndex
;
i
<
numParticles
;
i
++
)
{
for
(
int
i
=
startIndex
;
i
<
numParticles
;
i
++
)
{
...
@@ -212,14 +234,14 @@ void CpuCustomManyParticleForce::loopOverInteractions(vector<int>& availablePart
...
@@ -212,14 +234,14 @@ void CpuCustomManyParticleForce::loopOverInteractions(vector<int>& availablePart
if
(
include
)
{
if
(
include
)
{
particleSet
[
loopIndex
]
=
availableParticles
[
i
];
particleSet
[
loopIndex
]
=
availableParticles
[
i
];
if
(
loopIndex
==
numParticlesPerSet
-
1
)
if
(
loopIndex
==
numParticlesPerSet
-
1
)
calculateOneIxn
(
particleSet
,
posq
,
atomCoordinates
,
particleParameters
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
);
calculateOneIxn
(
particleSet
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
else
else
loopOverInteractions
(
availableParticles
,
particleSet
,
loopIndex
+
1
,
i
+
1
,
posq
,
atomCoordinates
,
particleParameters
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
);
loopOverInteractions
(
availableParticles
,
particleSet
,
loopIndex
+
1
,
i
+
1
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
}
}
}
}
}
}
void
CpuCustomManyParticleForce
::
calculateOneIxn
(
vector
<
int
>&
particleSet
,
float
*
posq
,
vector
<
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
vector
<
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
void
CpuCustomManyParticleForce
::
calculateOneIxn
(
vector
<
int
>&
particleSet
,
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Select the ordering to use for the particles.
// Select the ordering to use for the particles.
vector
<
int
>
permutedParticles
(
numParticlesPerSet
);
vector
<
int
>
permutedParticles
(
numParticlesPerSet
);
...
@@ -241,129 +263,141 @@ void CpuCustomManyParticleForce::calculateOneIxn(vector<int>& particleSet, float
...
@@ -241,129 +263,141 @@ void CpuCustomManyParticleForce::calculateOneIxn(vector<int>& particleSet, float
// Record per-particle parameters.
// Record per-particle parameters.
CompiledExpressionSet
&
expressionSet
=
data
.
expressionSet
;
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
expressionSet
.
setVariable
(
particleParamIndices
[
i
][
j
],
particleParameters
[
permutedParticles
[
i
]][
j
]);
expressionSet
.
setVariable
(
data
.
particleParamIndices
[
i
][
j
],
particleParameters
[
permutedParticles
[
i
]][
j
]);
// Compute inter-particle deltas.
int
numDeltas
=
data
.
deltaPairs
.
size
();
RealOpenMM
delta
[
numDeltas
][
ReferenceForce
::
LastDeltaRIndex
];
for
(
int
i
=
0
;
i
<
numDeltas
;
i
++
)
computeDelta
(
permutedParticles
[
data
.
deltaPairs
[
i
].
first
],
permutedParticles
[
data
.
deltaPairs
[
i
].
second
],
delta
[
i
],
atomCoordinates
);
// Compute all of the variables the energy can depend on.
// Compute all of the variables the energy can depend on.
for
(
int
i
=
0
;
i
<
(
int
)
particleTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
particleTerms
.
size
();
i
++
)
{
const
ParticleTermInfo
&
term
=
particleTerms
[
i
];
const
ParticleTermInfo
&
term
=
data
.
particleTerms
[
i
];
expressionSet
.
setVariable
(
term
.
variableIndex
,
atomCoordinates
[
term
.
atom
][
term
.
component
]);
expressionSet
.
setVariable
(
term
.
variableIndex
,
atomCoordinates
[
permutedParticles
[
term
.
atom
]
]
[
term
.
component
]);
}
}
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
distanceTerms
.
size
();
i
++
)
{
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
const
DistanceTermInfo
&
term
=
data
.
distanceTerms
[
i
];
computeDelta
(
permutedParticles
[
term
.
p1
],
permutedParticles
[
term
.
p2
],
term
.
delta
,
atomCoordinates
);
expressionSet
.
setVariable
(
term
.
variableIndex
,
delta
[
term
.
delta
][
ReferenceForce
::
RIndex
]);
expressionSet
.
setVariable
(
term
.
variableIndex
,
term
.
delta
[
ReferenceForce
::
RIndex
]);
}
}
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
angleTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
const
AngleTermInfo
&
term
=
data
.
angleTerms
[
i
];
computeDelta
(
permutedParticles
[
term
.
p1
],
permutedParticles
[
term
.
p2
],
term
.
delta1
,
atomCoordinates
);
expressionSet
.
setVariable
(
term
.
variableIndex
,
computeAngle
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
],
term
.
delta1Sign
*
term
.
delta2Sign
));
computeDelta
(
permutedParticles
[
term
.
p3
],
permutedParticles
[
term
.
p2
],
term
.
delta2
,
atomCoordinates
);
expressionSet
.
setVariable
(
term
.
variableIndex
,
computeAngle
(
term
.
delta1
,
term
.
delta2
));
}
}
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
dihedralTerms
.
size
();
i
++
)
{
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
const
DihedralTermInfo
&
term
=
data
.
dihedralTerms
[
i
];
computeDelta
(
permutedParticles
[
term
.
p2
],
permutedParticles
[
term
.
p1
],
term
.
delta1
,
atomCoordinates
);
computeDelta
(
permutedParticles
[
term
.
p2
],
permutedParticles
[
term
.
p3
],
term
.
delta2
,
atomCoordinates
);
computeDelta
(
permutedParticles
[
term
.
p4
],
permutedParticles
[
term
.
p3
],
term
.
delta3
,
atomCoordinates
);
RealOpenMM
dotDihedral
,
signOfDihedral
;
RealOpenMM
dotDihedral
,
signOfDihedral
;
RealOpenMM
*
crossProduct
[]
=
{
term
.
cross1
,
term
.
cross2
};
RealOpenMM
*
crossProduct
[]
=
{
term
.
cross1
,
term
.
cross2
};
expressionSet
.
setVariable
(
term
.
variableIndex
,
ReferenceBondIxn
::
getDihedralAngleBetweenThreeVectors
(
term
.
delta1
,
term
.
delta2
,
term
.
delta3
,
crossProduct
,
&
dotDihedral
,
term
.
delta1
,
&
signOfDihedral
,
1
));
expressionSet
.
setVariable
(
term
.
variableIndex
,
ReferenceBondIxn
::
getDihedralAngleBetweenThreeVectors
(
delta
[
term
.
delta1
]
,
delta
[
term
.
delta2
]
,
delta
[
term
.
delta3
]
,
crossProduct
,
&
dotDihedral
,
delta
[
term
.
delta1
]
,
&
signOfDihedral
,
1
));
}
}
// Apply forces based on individual particle coordinates.
if
(
includeForces
)
{
// Apply forces based on individual particle coordinates.
for
(
int
i
=
0
;
i
<
(
int
)
particleTerms
.
size
();
i
++
)
{
const
ParticleTermInfo
&
term
=
particleTerms
[
i
];
forces
[
permutedParticles
[
term
.
atom
]][
term
.
component
]
-=
term
.
forceExpression
.
evaluate
();
}
// Apply forces based on distances.
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
vector
<
RealVec
>
f
(
numParticlesPerSet
);
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
for
(
int
i
=
0
;
i
<
(
int
)
data
.
particleTerms
.
size
();
i
++
)
{
RealOpenMM
dEdR
=
(
RealOpenMM
)
(
term
.
forceExpression
.
evaluate
()
/
(
term
.
delta
[
ReferenceForce
::
RIndex
]));
const
ParticleTermInfo
&
term
=
data
.
particleTerms
[
i
];
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
f
[
term
.
atom
][
term
.
component
]
-=
term
.
forceExpression
.
evaluate
();
RealOpenMM
force
=
-
dEdR
*
term
.
delta
[
i
];
forces
[
permutedParticles
[
term
.
p1
]][
i
]
-=
force
;
forces
[
permutedParticles
[
term
.
p2
]][
i
]
+=
force
;
}
}
}
// Apply forces based on angles.
// Apply forces based on distances.
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
distanceTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
const
DistanceTermInfo
&
term
=
data
.
distanceTerms
[
i
];
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
();
RealOpenMM
dEdR
=
(
RealOpenMM
)
(
term
.
forceExpression
.
evaluate
()
*
term
.
deltaSign
/
(
delta
[
term
.
delta
][
ReferenceForce
::
RIndex
]));
RealOpenMM
thetaCross
[
ReferenceForce
::
LastDeltaRIndex
];
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
SimTKOpenMMUtilities
::
crossProductVector3
(
term
.
delta1
,
term
.
delta2
,
thetaCross
);
RealOpenMM
force
=
-
dEdR
*
delta
[
term
.
delta
][
i
];
RealOpenMM
lengthThetaCross
=
SQRT
(
DOT3
(
thetaCross
,
thetaCross
));
f
[
term
.
p1
][
i
]
-=
force
;
if
(
lengthThetaCross
<
1.0e-06
)
f
[
term
.
p2
][
i
]
+=
force
;
lengthThetaCross
=
(
RealOpenMM
)
1.0e-06
;
}
RealOpenMM
termA
=
dEdTheta
/
(
term
.
delta1
[
ReferenceForce
::
R2Index
]
*
lengthThetaCross
);
RealOpenMM
termC
=
-
dEdTheta
/
(
term
.
delta2
[
ReferenceForce
::
R2Index
]
*
lengthThetaCross
);
RealOpenMM
deltaCrossP
[
3
][
3
];
SimTKOpenMMUtilities
::
crossProductVector3
(
term
.
delta1
,
thetaCross
,
deltaCrossP
[
0
]);
SimTKOpenMMUtilities
::
crossProductVector3
(
term
.
delta2
,
thetaCross
,
deltaCrossP
[
2
]);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
deltaCrossP
[
0
][
i
]
*=
termA
;
deltaCrossP
[
2
][
i
]
*=
termC
;
deltaCrossP
[
1
][
i
]
=
-
(
deltaCrossP
[
0
][
i
]
+
deltaCrossP
[
2
][
i
]);
}
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
forces
[
permutedParticles
[
term
.
p1
]][
i
]
+=
deltaCrossP
[
0
][
i
];
// Apply forces based on angles.
forces
[
permutedParticles
[
term
.
p2
]][
i
]
+=
deltaCrossP
[
1
][
i
];
forces
[
permutedParticles
[
term
.
p3
]][
i
]
+=
deltaCrossP
[
2
][
i
];
for
(
int
i
=
0
;
i
<
(
int
)
data
.
angleTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
data
.
angleTerms
[
i
];
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
();
RealOpenMM
thetaCross
[
ReferenceForce
::
LastDeltaRIndex
];
SimTKOpenMMUtilities
::
crossProductVector3
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
],
thetaCross
);
RealOpenMM
lengthThetaCross
=
SQRT
(
DOT3
(
thetaCross
,
thetaCross
));
if
(
lengthThetaCross
<
1.0e-06
)
lengthThetaCross
=
(
RealOpenMM
)
1.0e-06
;
RealOpenMM
termA
=
dEdTheta
*
term
.
delta2Sign
/
(
delta
[
term
.
delta1
][
ReferenceForce
::
R2Index
]
*
lengthThetaCross
);
RealOpenMM
termC
=
-
dEdTheta
*
term
.
delta1Sign
/
(
delta
[
term
.
delta2
][
ReferenceForce
::
R2Index
]
*
lengthThetaCross
);
RealOpenMM
deltaCrossP
[
3
][
3
];
SimTKOpenMMUtilities
::
crossProductVector3
(
delta
[
term
.
delta1
],
thetaCross
,
deltaCrossP
[
0
]);
SimTKOpenMMUtilities
::
crossProductVector3
(
delta
[
term
.
delta2
],
thetaCross
,
deltaCrossP
[
2
]);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
deltaCrossP
[
0
][
i
]
*=
termA
;
deltaCrossP
[
2
][
i
]
*=
termC
;
deltaCrossP
[
1
][
i
]
=
-
(
deltaCrossP
[
0
][
i
]
+
deltaCrossP
[
2
][
i
]);
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
f
[
term
.
p1
][
i
]
+=
deltaCrossP
[
0
][
i
];
f
[
term
.
p2
][
i
]
+=
deltaCrossP
[
1
][
i
];
f
[
term
.
p3
][
i
]
+=
deltaCrossP
[
2
][
i
];
}
}
}
}
// Apply forces based on dihedrals.
// Apply forces based on dihedrals.
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
data
.
dihedralTerms
.
size
();
i
++
)
{
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
const
DihedralTermInfo
&
term
=
data
.
dihedralTerms
[
i
];
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
();
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
();
RealOpenMM
internalF
[
4
][
3
];
RealOpenMM
internalF
[
4
][
3
];
RealOpenMM
forceFactors
[
4
];
RealOpenMM
forceFactors
[
4
];
RealOpenMM
normCross1
=
DOT3
(
term
.
cross1
,
term
.
cross1
);
RealOpenMM
normCross1
=
DOT3
(
term
.
cross1
,
term
.
cross1
);
RealOpenMM
normBC
=
term
.
delta2
[
ReferenceForce
::
RIndex
];
RealOpenMM
normBC
=
delta
[
term
.
delta2
][
ReferenceForce
::
RIndex
];
forceFactors
[
0
]
=
(
-
dEdTheta
*
normBC
)
/
normCross1
;
forceFactors
[
0
]
=
(
-
dEdTheta
*
normBC
)
/
normCross1
;
RealOpenMM
normCross2
=
DOT3
(
term
.
cross2
,
term
.
cross2
);
RealOpenMM
normCross2
=
DOT3
(
term
.
cross2
,
term
.
cross2
);
forceFactors
[
3
]
=
(
dEdTheta
*
normBC
)
/
normCross2
;
forceFactors
[
3
]
=
(
dEdTheta
*
normBC
)
/
normCross2
;
forceFactors
[
1
]
=
DOT3
(
term
.
delta1
,
term
.
delta2
);
forceFactors
[
1
]
=
DOT3
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
]);
forceFactors
[
1
]
/=
term
.
delta2
[
ReferenceForce
::
R2Index
];
forceFactors
[
1
]
/=
delta
[
term
.
delta2
][
ReferenceForce
::
R2Index
];
forceFactors
[
2
]
=
DOT3
(
term
.
delta3
,
term
.
delta2
);
forceFactors
[
2
]
=
DOT3
(
delta
[
term
.
delta3
],
delta
[
term
.
delta2
]);
forceFactors
[
2
]
/=
term
.
delta2
[
ReferenceForce
::
R2Index
];
forceFactors
[
2
]
/=
delta
[
term
.
delta2
][
ReferenceForce
::
R2Index
];
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
internalF
[
0
][
i
]
=
forceFactors
[
0
]
*
term
.
cross1
[
i
];
internalF
[
0
][
i
]
=
forceFactors
[
0
]
*
term
.
cross1
[
i
];
internalF
[
3
][
i
]
=
forceFactors
[
3
]
*
term
.
cross2
[
i
];
internalF
[
3
][
i
]
=
forceFactors
[
3
]
*
term
.
cross2
[
i
];
RealOpenMM
s
=
forceFactors
[
1
]
*
internalF
[
0
][
i
]
-
forceFactors
[
2
]
*
internalF
[
3
][
i
];
RealOpenMM
s
=
forceFactors
[
1
]
*
internalF
[
0
][
i
]
-
forceFactors
[
2
]
*
internalF
[
3
][
i
];
internalF
[
1
][
i
]
=
internalF
[
0
][
i
]
-
s
;
internalF
[
1
][
i
]
=
internalF
[
0
][
i
]
-
s
;
internalF
[
2
][
i
]
=
internalF
[
3
][
i
]
+
s
;
internalF
[
2
][
i
]
=
internalF
[
3
][
i
]
+
s
;
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
f
[
term
.
p1
][
i
]
+=
internalF
[
0
][
i
];
f
[
term
.
p2
][
i
]
-=
internalF
[
1
][
i
];
f
[
term
.
p3
][
i
]
-=
internalF
[
2
][
i
];
f
[
term
.
p4
][
i
]
+=
internalF
[
3
][
i
];
}
}
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
forces
[
permutedParticles
[
term
.
p1
]][
i
]
+=
internalF
[
0
][
i
];
// Store the forces.
forces
[
permutedParticles
[
term
.
p2
]][
i
]
-=
internalF
[
1
][
i
];
forces
[
permutedParticles
[
term
.
p3
]][
i
]
-=
internalF
[
2
][
i
];
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
forces
[
permutedParticles
[
term
.
p4
]][
i
]
+=
internalF
[
3
][
i
];
int
index
=
permutedParticles
[
i
];
(
fvec4
(
forces
+
4
*
index
)
+
fvec4
((
float
)
f
[
i
][
0
],
(
float
)
f
[
i
][
1
],
(
float
)
f
[
i
][
2
],
0.0
f
)).
store
(
forces
+
4
*
index
);
}
}
}
}
// Add the energy
// Add the energy
if
(
total
Energy
)
if
(
include
Energy
)
*
totalE
nergy
+=
(
RealOpenMM
)
energyExpression
.
evaluate
();
data
.
e
nergy
+=
data
.
energyExpression
.
evaluate
();
}
}
void
CpuCustomManyParticleForce
::
computeDelta
(
int
atom1
,
int
atom2
,
RealOpenMM
*
delta
,
vector
<
RealVec
>&
atomCoordinates
)
const
{
void
CpuCustomManyParticleForce
::
computeDelta
(
int
atom1
,
int
atom2
,
RealOpenMM
*
delta
,
const
OpenMM
::
RealVec
*
atomCoordinates
)
const
{
if
(
usePeriodic
)
if
(
usePeriodic
)
ReferenceForce
::
getDeltaRPeriodic
(
atomCoordinates
[
atom1
],
atomCoordinates
[
atom2
],
periodicBoxSize
,
delta
);
ReferenceForce
::
getDeltaRPeriodic
(
atomCoordinates
[
atom1
],
atomCoordinates
[
atom2
],
periodicBoxSize
,
delta
);
else
else
ReferenceForce
::
getDeltaR
(
atomCoordinates
[
atom1
],
atomCoordinates
[
atom2
],
delta
);
ReferenceForce
::
getDeltaR
(
atomCoordinates
[
atom1
],
atomCoordinates
[
atom2
],
delta
);
}
}
RealOpenMM
CpuCustomManyParticleForce
::
computeAngle
(
RealOpenMM
*
vec1
,
RealOpenMM
*
vec2
)
{
RealOpenMM
CpuCustomManyParticleForce
::
computeAngle
(
RealOpenMM
*
vec1
,
RealOpenMM
*
vec2
,
float
sign
)
{
RealOpenMM
dot
=
DOT3
(
vec1
,
vec2
);
RealOpenMM
dot
=
DOT3
(
vec1
,
vec2
)
*
sign
;
RealOpenMM
cosine
=
dot
/
SQRT
((
vec1
[
ReferenceForce
::
R2Index
]
*
vec2
[
ReferenceForce
::
R2Index
]));
RealOpenMM
cosine
=
dot
/
SQRT
((
vec1
[
ReferenceForce
::
R2Index
]
*
vec2
[
ReferenceForce
::
R2Index
]));
RealOpenMM
angle
;
RealOpenMM
angle
;
if
(
cosine
>=
1
)
if
(
cosine
>=
1
)
...
@@ -383,3 +417,88 @@ void CpuCustomManyParticleForce::getDeltaR(const fvec4& posI, const fvec4& posJ,
...
@@ -383,3 +417,88 @@ void CpuCustomManyParticleForce::getDeltaR(const fvec4& posI, const fvec4& posJ,
}
}
r2
=
dot3
(
deltaR
,
deltaR
);
r2
=
dot3
(
deltaR
,
deltaR
);
}
}
CpuCustomManyParticleForce
::
ParticleTermInfo
::
ParticleTermInfo
(
const
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
name
(
name
),
atom
(
atom
),
component
(
component
),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
}
CpuCustomManyParticleForce
::
DistanceTermInfo
::
DistanceTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
data
.
requestDeltaPair
(
p1
,
p2
,
delta
,
deltaSign
,
true
);
}
CpuCustomManyParticleForce
::
AngleTermInfo
::
AngleTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
data
.
requestDeltaPair
(
p1
,
p2
,
delta1
,
delta1Sign
,
true
);
data
.
requestDeltaPair
(
p3
,
p2
,
delta2
,
delta2Sign
,
true
);
}
CpuCustomManyParticleForce
::
DihedralTermInfo
::
DihedralTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
p4
(
atoms
[
3
]),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
float
sign
;
data
.
requestDeltaPair
(
p2
,
p1
,
delta1
,
sign
,
false
);
data
.
requestDeltaPair
(
p2
,
p3
,
delta2
,
sign
,
false
);
data
.
requestDeltaPair
(
p4
,
p3
,
delta3
,
sign
,
false
);
}
CpuCustomManyParticleForce
::
ThreadData
::
ThreadData
(
const
CustomManyParticleForce
&
force
,
Lepton
::
ParsedExpression
&
energyExpr
,
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
int
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
int
numPerParticleParameters
=
force
.
getNumPerParticleParameters
();
particleParamIndices
.
resize
(
numParticlesPerSet
);
energyExpression
=
energyExpr
.
createCompiledExpression
();
expressionSet
.
registerExpression
(
energyExpression
);
// Differentiate the energy to get expressions for the force.
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
stringstream
xname
,
yname
,
zname
;
xname
<<
'x'
<<
(
i
+
1
);
yname
<<
'y'
<<
(
i
+
1
);
zname
<<
'z'
<<
(
i
+
1
);
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
xname
.
str
(),
i
,
0
,
energyExpr
.
differentiate
(
xname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
yname
.
str
(),
i
,
1
,
energyExpr
.
differentiate
(
yname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
zname
.
str
(),
i
,
2
,
energyExpr
.
differentiate
(
zname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
{
stringstream
paramname
;
paramname
<<
force
.
getPerParticleParameterName
(
j
)
<<
(
i
+
1
);
particleParamIndices
[
i
].
push_back
(
expressionSet
.
getVariableIndex
(
paramname
.
str
()));
}
}
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
)
dihedralTerms
.
push_back
(
CpuCustomManyParticleForce
::
DihedralTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
)
distanceTerms
.
push_back
(
CpuCustomManyParticleForce
::
DistanceTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
)
angleTerms
.
push_back
(
CpuCustomManyParticleForce
::
AngleTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
int
i
=
0
;
i
<
particleTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
particleTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
distanceTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
distanceTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
angleTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
angleTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
dihedralTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
dihedralTerms
[
i
].
forceExpression
);
}
void
CpuCustomManyParticleForce
::
ThreadData
::
requestDeltaPair
(
int
p1
,
int
p2
,
int
&
pairIndex
,
float
&
pairSign
,
bool
allowReversed
)
{
for
(
int
i
=
0
;
i
<
(
int
)
deltaPairs
.
size
();
i
++
)
{
if
(
deltaPairs
[
i
].
first
==
p1
&&
deltaPairs
[
i
].
second
==
p2
)
{
pairIndex
=
i
;
pairSign
=
1
;
return
;
}
if
(
deltaPairs
[
i
].
first
==
p2
&&
deltaPairs
[
i
].
second
==
p1
&&
allowReversed
)
{
pairIndex
=
i
;
pairSign
=
-
1
;
return
;
}
}
pairIndex
=
deltaPairs
.
size
();
pairSign
=
1
;
deltaPairs
.
push_back
(
make_pair
(
p1
,
p2
));
}
platforms/cpu/src/CpuKernels.cpp
View file @
0e2ffb4b
...
@@ -870,8 +870,6 @@ void CpuCalcCustomManyParticleForceKernel::initialize(const System& system, cons
...
@@ -870,8 +870,6 @@ void CpuCalcCustomManyParticleForceKernel::initialize(const System& system, cons
double
CpuCalcCustomManyParticleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
CpuCalcCustomManyParticleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealOpenMM
energy
=
0
;
map
<
string
,
double
>
globalParameters
;
map
<
string
,
double
>
globalParameters
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
...
@@ -882,7 +880,8 @@ double CpuCalcCustomManyParticleForceKernel::execute(ContextImpl& context, bool
...
@@ -882,7 +880,8 @@ double CpuCalcCustomManyParticleForceKernel::execute(ContextImpl& context, bool
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
ixn
->
setPeriodic
(
box
);
ixn
->
setPeriodic
(
box
);
}
}
ixn
->
calculateIxn
(
data
.
posq
,
posData
,
particleParamArray
,
globalParameters
,
forceData
,
includeEnergy
?
&
energy
:
NULL
);
double
energy
=
0
;
ixn
->
calculateIxn
(
data
.
posq
,
posData
,
particleParamArray
,
globalParameters
,
data
.
threadForce
,
includeForces
,
includeEnergy
,
energy
);
return
energy
;
return
energy
;
}
}
...
...
platforms/cpu/tests/TestCpuCustomManyParticleForce.cpp
0 → 100644
View file @
0e2ffb4b
/* -------------------------------------------------------------------------- *
* 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) 2014 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 CPU implementation of CustomManyParticleForce.
*/
#ifdef WIN32
#define _USE_MATH_DEFINES // Needed to get M_PI
#endif
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "CpuPlatform.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/System.h"
#include "openmm/TabulatedFunction.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
validateAxilrodTeller
(
CustomManyParticleForce
*
force
,
const
vector
<
Vec3
>&
positions
,
const
vector
<
const
int
*>&
expectedSets
,
double
boxSize
)
{
// Create a System and Context.
int
numParticles
=
force
->
getNumParticles
();
CustomManyParticleForce
::
NonbondedMethod
nonbondedMethod
=
force
->
getNonbondedMethod
();
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system
.
addParticle
(
1.0
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
CpuPlatform
platform
;
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state1
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
double
c
=
context
.
getParameter
(
"C"
);
// See if the energy matches the expected value.
double
expectedEnergy
=
0
;
for
(
int
i
=
0
;
i
<
(
int
)
expectedSets
.
size
();
i
++
)
{
int
p1
=
expectedSets
[
i
][
0
];
int
p2
=
expectedSets
[
i
][
1
];
int
p3
=
expectedSets
[
i
][
2
];
Vec3
d12
=
positions
[
p2
]
-
positions
[
p1
];
Vec3
d13
=
positions
[
p3
]
-
positions
[
p1
];
Vec3
d23
=
positions
[
p3
]
-
positions
[
p2
];
if
(
nonbondedMethod
==
CustomManyParticleForce
::
CutoffPeriodic
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
d12
[
j
]
-=
floor
(
d12
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
d13
[
j
]
-=
floor
(
d13
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
d23
[
j
]
-=
floor
(
d23
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
}
}
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
double
ctheta1
=
d12
.
dot
(
d13
)
/
(
r12
*
r13
);
double
ctheta2
=
-
d12
.
dot
(
d23
)
/
(
r12
*
r23
);
double
ctheta3
=
d13
.
dot
(
d23
)
/
(
r13
*
r23
);
double
rprod
=
r12
*
r13
*
r23
;
expectedEnergy
+=
c
*
(
1
+
3
*
ctheta1
*
ctheta2
*
ctheta3
)
/
(
rprod
*
rprod
*
rprod
);
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state1
.
getPotentialEnergy
(),
1e-5
);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
const
vector
<
Vec3
>&
forces
=
state1
.
getForces
();
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
(
int
)
forces
.
size
();
++
i
)
norm
+=
forces
[
i
].
dot
(
forces
[
i
]);
norm
=
std
::
sqrt
(
norm
);
const
double
stepSize
=
1e-3
;
double
step
=
0.5
*
stepSize
/
norm
;
vector
<
Vec3
>
positions2
(
numParticles
),
positions3
(
numParticles
);
for
(
int
i
=
0
;
i
<
(
int
)
positions
.
size
();
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
forces
[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
stepSize
,
1e-4
);
}
void
testNoCutoff
()
{
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*(1+3*cos(theta1)*cos(theta2)*cos(theta3))/(r12*r13*r23)^3;"
"theta1=angle(p1,p2,p3); theta2=angle(p2,p3,p1); theta3=angle(p3,p1,p2);"
"r12=distance(p1,p2); r13=distance(p1,p3); r23=distance(p2,p3)"
);
force
->
addGlobalParameter
(
"C"
,
1.5
);
vector
<
double
>
params
;
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
vector
<
Vec3
>
positions
;
positions
.
push_back
(
Vec3
(
0
,
0
,
0
));
positions
.
push_back
(
Vec3
(
1
,
0
,
0
));
positions
.
push_back
(
Vec3
(
0
,
1.1
,
0.3
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
int
sets
[
4
][
3
]
=
{{
0
,
1
,
2
},
{
1
,
2
,
3
},
{
2
,
3
,
0
},
{
3
,
0
,
1
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
}
void
testCutoff
()
{
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*(1+3*cos(theta1)*cos(theta2)*cos(theta3))/(r12*r13*r23)^3;"
"theta1=angle(p1,p2,p3); theta2=angle(p2,p3,p1); theta3=angle(p3,p1,p2);"
"r12=distance(p1,p2); r13=distance(p1,p3); r23=distance(p2,p3)"
);
force
->
addGlobalParameter
(
"C"
,
1.5
);
force
->
setNonbondedMethod
(
CustomManyParticleForce
::
CutoffNonPeriodic
);
force
->
setCutoffDistance
(
1.55
);
vector
<
double
>
params
;
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
vector
<
Vec3
>
positions
;
positions
.
push_back
(
Vec3
(
0
,
0
,
0
));
positions
.
push_back
(
Vec3
(
1
,
0
,
0
));
positions
.
push_back
(
Vec3
(
0
,
1.1
,
0.3
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
int
sets
[
7
][
3
]
=
{{
0
,
1
,
2
},
{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
2
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
7
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
}
void
testPeriodic
()
{
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*(1+3*cos(theta1)*cos(theta2)*cos(theta3))/(r12*r13*r23)^3;"
"theta1=angle(p1,p2,p3); theta2=angle(p2,p3,p1); theta3=angle(p3,p1,p2);"
"r12=distance(p1,p2); r13=distance(p1,p3); r23=distance(p2,p3)"
);
force
->
addGlobalParameter
(
"C"
,
1.5
);
force
->
setNonbondedMethod
(
CustomManyParticleForce
::
CutoffPeriodic
);
force
->
setCutoffDistance
(
1.05
);
vector
<
double
>
params
;
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
vector
<
Vec3
>
positions
;
positions
.
push_back
(
Vec3
(
0
,
0
,
0
));
positions
.
push_back
(
Vec3
(
1
,
0
,
0
));
positions
.
push_back
(
Vec3
(
0
,
1.1
,
0.3
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
double
boxSize
=
2.1
;
int
sets
[
5
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
boxSize
);
}
void
testExclusions
()
{
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*(1+3*cos(theta1)*cos(theta2)*cos(theta3))/(r12*r13*r23)^3;"
"theta1=angle(p1,p2,p3); theta2=angle(p2,p3,p1); theta3=angle(p3,p1,p2);"
"r12=distance(p1,p2); r13=distance(p1,p3); r23=distance(p2,p3)"
);
force
->
addGlobalParameter
(
"C"
,
1.5
);
vector
<
double
>
params
;
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
vector
<
Vec3
>
positions
;
positions
.
push_back
(
Vec3
(
0
,
0
,
0
));
positions
.
push_back
(
Vec3
(
1
,
0
,
0
));
positions
.
push_back
(
Vec3
(
0
,
1.1
,
0.3
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
force
->
addExclusion
(
0
,
2
);
force
->
addExclusion
(
0
,
3
);
int
sets
[
5
][
3
]
=
{{
0
,
1
,
4
},
{
1
,
2
,
3
},
{
1
,
2
,
4
},
{
1
,
3
,
4
},
{
2
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
}
void
testAllTerms
()
{
int
numParticles
=
4
;
CpuPlatform
platform
;
// Create a system with a CustomManyParticleForce.
System
system1
;
CustomManyParticleForce
*
force1
=
new
CustomManyParticleForce
(
4
,
"distance(p1,p2)+angle(p1,p4,p3)+dihedral(p1,p3,p2,p4)+x1+y4+z3"
);
system1
.
addForce
(
force1
);
vector
<
double
>
params
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system1
.
addParticle
(
1.0
);
force1
->
addParticle
(
params
,
i
);
}
set
<
int
>
filter
;
filter
.
insert
(
0
);
force1
->
setTypeFilter
(
0
,
filter
);
filter
.
clear
();
filter
.
insert
(
1
);
force1
->
setTypeFilter
(
1
,
filter
);
filter
.
clear
();
filter
.
insert
(
3
);
force1
->
setTypeFilter
(
2
,
filter
);
filter
.
clear
();
filter
.
insert
(
2
);
force1
->
setTypeFilter
(
3
,
filter
);
// Create a system that use a CustomCompoundBondForce to compute exactly the same interactions.
System
system2
;
CustomCompoundBondForce
*
force2
=
new
CustomCompoundBondForce
(
4
,
"distance(p1,p2)+angle(p1,p3,p4)+dihedral(p1,p4,p2,p3)+x1+y3+z4"
);
system2
.
addForce
(
force2
);
vector
<
int
>
particles
;
particles
.
push_back
(
0
);
particles
.
push_back
(
1
);
particles
.
push_back
(
2
);
particles
.
push_back
(
3
);
force2
->
addBond
(
particles
,
params
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system2
.
addParticle
(
1.0
);
// Create contexts for both of them.
vector
<
Vec3
>
positions
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
positions
.
push_back
(
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
)));
VerletIntegrator
integrator1
(
0.001
);
VerletIntegrator
integrator2
(
0.001
);
Context
context1
(
system1
,
integrator1
,
platform
);
Context
context2
(
system2
,
integrator2
,
platform
);
context1
.
setPositions
(
positions
);
context2
.
setPositions
(
positions
);
// See if they produce identical forces and energies.
State
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state2
.
getPotentialEnergy
(),
state1
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
ASSERT_EQUAL_VEC
(
state2
.
getForces
()[
i
],
state1
.
getForces
()[
i
],
1e-4
);
}
void
testParameters
()
{
// Create a system.
int
numParticles
=
5
;
System
system
;
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*scale1*scale2*scale3*(distance(p1,p2)+distance(p2,p3)+distance(p1,p3))"
);
force
->
addGlobalParameter
(
"C"
,
2.0
);
force
->
addPerParticleParameter
(
"scale"
);
vector
<
double
>
params
(
1
);
vector
<
Vec3
>
positions
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
params
[
0
]
=
i
+
1
;
force
->
addParticle
(
params
);
positions
.
push_back
(
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
)));
system
.
addParticle
(
1.0
);
}
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
CpuPlatform
platform
;
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// See if the energy is correct.
State
state
=
context
.
getState
(
State
::
Energy
);
double
expectedEnergy
=
0
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
i
+
1
;
j
<
numParticles
;
j
++
)
for
(
int
k
=
j
+
1
;
k
<
numParticles
;
k
++
)
{
Vec3
d12
=
positions
[
j
]
-
positions
[
i
];
Vec3
d13
=
positions
[
k
]
-
positions
[
i
];
Vec3
d23
=
positions
[
k
]
-
positions
[
j
];
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
expectedEnergy
+=
2.0
*
(
i
+
1
)
*
(
j
+
1
)
*
(
k
+
1
)
*
(
r12
+
r13
+
r23
);
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
// Modify the parameters.
context
.
setParameter
(
"C"
,
3.5
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
params
[
0
]
=
0.5
*
i
-
0.1
;
force
->
setParticleParameters
(
i
,
params
,
0
);
}
force
->
updateParametersInContext
(
context
);
// See if the energy is still correct.
state
=
context
.
getState
(
State
::
Energy
);
expectedEnergy
=
0
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
i
+
1
;
j
<
numParticles
;
j
++
)
for
(
int
k
=
j
+
1
;
k
<
numParticles
;
k
++
)
{
Vec3
d12
=
positions
[
j
]
-
positions
[
i
];
Vec3
d13
=
positions
[
k
]
-
positions
[
i
];
Vec3
d23
=
positions
[
k
]
-
positions
[
j
];
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
expectedEnergy
+=
3.5
*
(
0.5
*
i
-
0.1
)
*
(
0.5
*
j
-
0.1
)
*
(
0.5
*
k
-
0.1
)
*
(
r12
+
r13
+
r23
);
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
}
void
testTabulatedFunctions
()
{
int
numParticles
=
5
;
// Create two tabulated functions.
vector
<
double
>
values
;
values
.
push_back
(
0.0
);
values
.
push_back
(
50.0
);
Continuous1DFunction
*
f1
=
new
Continuous1DFunction
(
values
,
0
,
100
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
double
>
c
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
c
[
i
]
=
genrand_real2
(
sfmt
);
values
.
resize
(
numParticles
*
numParticles
*
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
0
;
j
<
numParticles
;
j
++
)
for
(
int
k
=
0
;
k
<
numParticles
;
k
++
)
values
[
i
+
numParticles
*
j
+
numParticles
*
numParticles
*
k
]
=
c
[
i
]
+
c
[
j
]
+
c
[
k
];
Discrete3DFunction
*
f2
=
new
Discrete3DFunction
(
numParticles
,
numParticles
,
numParticles
,
values
);
// Create a system.
System
system
;
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"f1(distance(p1,p2)+distance(p2,p3)+distance(p1,p3))*f2(atom1, atom2, atom3)"
);
force
->
addPerParticleParameter
(
"atom"
);
force
->
addTabulatedFunction
(
"f1"
,
f1
);
force
->
addTabulatedFunction
(
"f2"
,
f2
);
vector
<
double
>
params
(
1
);
vector
<
Vec3
>
positions
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
params
[
0
]
=
i
;
force
->
addParticle
(
params
);
positions
.
push_back
(
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
)));
system
.
addParticle
(
1.0
);
}
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
CpuPlatform
platform
;
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// See if the energy is correct.
State
state
=
context
.
getState
(
State
::
Energy
);
double
expectedEnergy
=
0
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
i
+
1
;
j
<
numParticles
;
j
++
)
for
(
int
k
=
j
+
1
;
k
<
numParticles
;
k
++
)
{
Vec3
d12
=
positions
[
j
]
-
positions
[
i
];
Vec3
d13
=
positions
[
k
]
-
positions
[
i
];
Vec3
d23
=
positions
[
k
]
-
positions
[
j
];
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
expectedEnergy
+=
0.5
*
(
r12
+
r13
+
r23
)
*
(
c
[
i
]
+
c
[
j
]
+
c
[
k
]);
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
}
void
testTypeFilters
()
{
// Create a system.
System
system
;
for
(
int
i
=
0
;
i
<
5
;
i
++
)
system
.
addParticle
(
1.0
);
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"c1*(distance(p1,p2)+distance(p1,p3))"
);
force
->
addPerParticleParameter
(
"c"
);
double
c
[]
=
{
1.0
,
2.0
,
1.3
,
1.5
,
-
2.1
};
int
type
[]
=
{
0
,
1
,
0
,
1
,
5
};
vector
<
double
>
params
(
1
);
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
params
[
0
]
=
c
[
i
];
force
->
addParticle
(
params
,
type
[
i
]);
}
vector
<
Vec3
>
positions
;
positions
.
push_back
(
Vec3
(
0
,
0
,
0
));
positions
.
push_back
(
Vec3
(
1
,
0
,
0
));
positions
.
push_back
(
Vec3
(
0
,
1.1
,
0.3
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
set
<
int
>
f1
,
f2
;
f1
.
insert
(
0
);
f2
.
insert
(
1
);
f2
.
insert
(
5
);
force
->
setTypeFilter
(
0
,
f1
);
force
->
setTypeFilter
(
1
,
f2
);
force
->
setTypeFilter
(
2
,
f2
);
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
CpuPlatform
platform
;
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// See if the energy is correct.
State
state
=
context
.
getState
(
State
::
Energy
);
double
expectedEnergy
=
0
;
int
sets
[
6
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
3
,
4
},
{
2
,
1
,
3
},
{
2
,
1
,
4
},
{
2
,
3
,
4
}};
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
int
p1
=
sets
[
i
][
0
];
int
p2
=
sets
[
i
][
1
];
int
p3
=
sets
[
i
][
2
];
Vec3
d12
=
positions
[
p2
]
-
positions
[
p1
];
Vec3
d13
=
positions
[
p3
]
-
positions
[
p1
];
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
expectedEnergy
+=
c
[
p1
]
*
(
r12
+
r13
);
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
}
#include <sys/time.h>
void
benchmark
()
{
int
numParticles
=
5000
;
double
boxSize
=
5.0
;
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*(1+3*cos(theta1)*cos(theta2)*cos(theta3))/(r12*r13*r23)^3;"
"theta1=angle(p1,p2,p3); theta2=angle(p2,p3,p1); theta3=angle(p3,p1,p2);"
"r12=distance(p1,p2); r13=distance(p1,p3); r23=distance(p2,p3)"
);
force
->
addGlobalParameter
(
"C"
,
1.5
);
force
->
setNonbondedMethod
(
CustomManyParticleForce
::
CutoffPeriodic
);
force
->
setCutoffDistance
(
0.6
);
vector
<
double
>
params
;
vector
<
Vec3
>
positions
;
System
system
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
force
->
addParticle
(
params
);
positions
.
push_back
(
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
))
*
boxSize
);
system
.
addParticle
(
1.0
);
}
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
CpuPlatform
platform
;
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
timeval
t1
,
t2
;
gettimeofday
(
&
t1
,
NULL
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
gettimeofday
(
&
t2
,
NULL
);
printf
(
"%g %g
\n
"
,
state
.
getPotentialEnergy
(),
(
t2
.
tv_sec
-
t1
.
tv_sec
)
+
1e-6
*
(
t2
.
tv_usec
-
t1
.
tv_usec
));
}
int
main
()
{
try
{
testNoCutoff
();
testCutoff
();
testPeriodic
();
testExclusions
();
testAllTerms
();
testParameters
();
testTabulatedFunctions
();
testTypeFilters
();
benchmark
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
View file @
0e2ffb4b
...
@@ -192,7 +192,7 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
...
@@ -192,7 +192,7 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
for
(
int
i
=
0
;
i
<
(
int
)
particleTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
particleTerms
.
size
();
i
++
)
{
const
ParticleTermInfo
&
term
=
particleTerms
[
i
];
const
ParticleTermInfo
&
term
=
particleTerms
[
i
];
variables
[
term
.
name
]
=
atomCoordinates
[
term
.
atom
][
term
.
component
];
variables
[
term
.
name
]
=
atomCoordinates
[
permutedParticles
[
term
.
atom
]
]
[
term
.
component
];
}
}
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
...
...
platforms/reference/tests/TestReferenceCustomManyParticleForce.cpp
View file @
0e2ffb4b
...
@@ -39,6 +39,7 @@
...
@@ -39,6 +39,7 @@
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "ReferencePlatform.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/System.h"
#include "openmm/System.h"
#include "openmm/TabulatedFunction.h"
#include "openmm/TabulatedFunction.h"
...
@@ -217,6 +218,72 @@ void testExclusions() {
...
@@ -217,6 +218,72 @@ void testExclusions() {
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
}
}
void
testAllTerms
()
{
int
numParticles
=
4
;
ReferencePlatform
platform
;
// Create a system with a CustomManyParticleForce.
System
system1
;
CustomManyParticleForce
*
force1
=
new
CustomManyParticleForce
(
4
,
"distance(p1,p2)+angle(p1,p4,p3)+dihedral(p1,p3,p2,p4)+x1+y4+z3"
);
system1
.
addForce
(
force1
);
vector
<
double
>
params
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system1
.
addParticle
(
1.0
);
force1
->
addParticle
(
params
,
i
);
}
set
<
int
>
filter
;
filter
.
insert
(
0
);
force1
->
setTypeFilter
(
0
,
filter
);
filter
.
clear
();
filter
.
insert
(
1
);
force1
->
setTypeFilter
(
1
,
filter
);
filter
.
clear
();
filter
.
insert
(
3
);
force1
->
setTypeFilter
(
2
,
filter
);
filter
.
clear
();
filter
.
insert
(
2
);
force1
->
setTypeFilter
(
3
,
filter
);
// Create a system that use a CustomCompoundBondForce to compute exactly the same interactions.
System
system2
;
CustomCompoundBondForce
*
force2
=
new
CustomCompoundBondForce
(
4
,
"distance(p1,p2)+angle(p1,p3,p4)+dihedral(p1,p4,p2,p3)+x1+y3+z4"
);
system2
.
addForce
(
force2
);
vector
<
int
>
particles
;
particles
.
push_back
(
0
);
particles
.
push_back
(
1
);
particles
.
push_back
(
2
);
particles
.
push_back
(
3
);
force2
->
addBond
(
particles
,
params
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system2
.
addParticle
(
1.0
);
// Create contexts for both of them.
vector
<
Vec3
>
positions
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
positions
.
push_back
(
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
)));
VerletIntegrator
integrator1
(
0.001
);
VerletIntegrator
integrator2
(
0.001
);
Context
context1
(
system1
,
integrator1
,
platform
);
Context
context2
(
system2
,
integrator2
,
platform
);
context1
.
setPositions
(
positions
);
context2
.
setPositions
(
positions
);
// See if they produce identical forces and energies.
State
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state2
.
getPotentialEnergy
(),
state1
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
ASSERT_EQUAL_VEC
(
state2
.
getForces
()[
i
],
state1
.
getForces
()[
i
],
1e-4
);
}
void
testParameters
()
{
void
testParameters
()
{
// Create a system.
// Create a system.
...
@@ -403,6 +470,7 @@ int main() {
...
@@ -403,6 +470,7 @@ int main() {
testCutoff
();
testCutoff
();
testPeriodic
();
testPeriodic
();
testExclusions
();
testExclusions
();
testAllTerms
();
testParameters
();
testParameters
();
testTabulatedFunctions
();
testTabulatedFunctions
();
testTypeFilters
();
testTypeFilters
();
...
...
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