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
0ca8bdee
"vscode:/vscode.git/clone" did not exist on "9179605e1eaa5532e81552e7e7fc92ec32652592"
Commit
0ca8bdee
authored
Aug 06, 2014
by
peastman
Browse files
Finished reference implementation of CustomManyParticleForce
parent
b6e65ad6
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
221 additions
and
21 deletions
+221
-21
openmmapi/include/openmm/internal/CustomManyParticleForceImpl.h
...api/include/openmm/internal/CustomManyParticleForceImpl.h
+16
-0
openmmapi/src/CustomManyParticleForceImpl.cpp
openmmapi/src/CustomManyParticleForceImpl.cpp
+106
-0
platforms/reference/include/ReferenceCustomManyParticleIxn.h
platforms/reference/include/ReferenceCustomManyParticleIxn.h
+4
-1
platforms/reference/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
...nce/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
+43
-20
platforms/reference/tests/TestReferenceCustomManyParticleForce.cpp
.../reference/tests/TestReferenceCustomManyParticleForce.cpp
+52
-0
No files found.
openmmapi/include/openmm/internal/CustomManyParticleForceImpl.h
View file @
0ca8bdee
...
@@ -79,11 +79,27 @@ public:
...
@@ -79,11 +79,27 @@ public:
*/
*/
static
Lepton
::
ParsedExpression
prepareExpression
(
const
CustomManyParticleForce
&
force
,
const
std
::
map
<
std
::
string
,
Lepton
::
CustomFunction
*>&
functions
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
static
Lepton
::
ParsedExpression
prepareExpression
(
const
CustomManyParticleForce
&
force
,
const
std
::
map
<
std
::
string
,
Lepton
::
CustomFunction
*>&
functions
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
/**
* Analyze the type filters for a force and build a set of arrays that can be used for reordering the
* particles in an interaction.
*
* @param force the CustomManyParticleForce to process
* @param numTypes on exit, the number of unique particle types
* @param particleTypes on exit, this contains a type code for each particle. These codes are <i>not</i> necessarily the
* same as the types assigned by the force. They are guaranteed to be successive integers starting from 0,
* whereas the force may have used arbitrary integers.
* @param orderIndex on exit, this contains a lookup table for selecting the particle order for an interaction.
* orderIndex[t1+numTypes*t2+numTypes*numTypes*t3+...] is the index of the order to use, where t1, t2, etc. are the type codes
* of the particles involved in the interaction. If this equals -1, the interaction should be omitted.
* @param particleOrder on exit, particleOrder[i][j] tells which particle to use as the j'th particle, where i is the value found in orderIndex.
*/
static
void
buildFilterArrays
(
const
CustomManyParticleForce
&
force
,
int
&
numTypes
,
std
::
vector
<
int
>&
particleTypes
,
std
::
vector
<
int
>&
orderIndex
,
std
::
vector
<
std
::
vector
<
int
>
>&
particleOrder
);
private:
private:
class
FunctionPlaceholder
;
class
FunctionPlaceholder
;
static
Lepton
::
ExpressionTreeNode
replaceFunctions
(
const
Lepton
::
ExpressionTreeNode
&
node
,
std
::
map
<
std
::
string
,
int
>
atoms
,
static
Lepton
::
ExpressionTreeNode
replaceFunctions
(
const
Lepton
::
ExpressionTreeNode
&
node
,
std
::
map
<
std
::
string
,
int
>
atoms
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
static
void
generatePermutations
(
std
::
vector
<
int
>&
values
,
int
numFixed
,
std
::
vector
<
std
::
vector
<
int
>
>&
result
);
const
CustomManyParticleForce
&
owner
;
const
CustomManyParticleForce
&
owner
;
Kernel
kernel
;
Kernel
kernel
;
};
};
...
...
openmmapi/src/CustomManyParticleForceImpl.cpp
View file @
0ca8bdee
...
@@ -225,3 +225,109 @@ ExpressionTreeNode CustomManyParticleForceImpl::replaceFunctions(const Expressio
...
@@ -225,3 +225,109 @@ ExpressionTreeNode CustomManyParticleForceImpl::replaceFunctions(const Expressio
void
CustomManyParticleForceImpl
::
updateParametersInContext
(
ContextImpl
&
context
)
{
void
CustomManyParticleForceImpl
::
updateParametersInContext
(
ContextImpl
&
context
)
{
kernel
.
getAs
<
CalcCustomManyParticleForceKernel
>
().
copyParametersToContext
(
context
,
owner
);
kernel
.
getAs
<
CalcCustomManyParticleForceKernel
>
().
copyParametersToContext
(
context
,
owner
);
}
}
void
CustomManyParticleForceImpl
::
buildFilterArrays
(
const
CustomManyParticleForce
&
force
,
int
&
numTypes
,
vector
<
int
>&
particleTypes
,
vector
<
int
>&
orderIndex
,
vector
<
vector
<
int
>
>&
particleOrder
)
{
// Build a canonical list of type codes.
int
numParticles
=
force
.
getNumParticles
();
int
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
particleTypes
.
resize
(
numParticles
);
map
<
int
,
int
>
typeMap
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
vector
<
double
>
params
;
int
type
;
force
.
getParticleParameters
(
i
,
params
,
type
);
map
<
int
,
int
>::
const_iterator
element
=
typeMap
.
find
(
type
);
if
(
element
==
typeMap
.
end
())
{
int
newType
=
typeMap
.
size
();
typeMap
[
type
]
=
newType
;
particleTypes
[
i
]
=
newType
;
}
else
particleTypes
[
i
]
=
element
->
second
;
}
numTypes
=
typeMap
.
size
();
int
numIndices
=
1
;
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
numIndices
*=
numTypes
;
orderIndex
.
resize
(
numIndices
,
0
);
// Find the allowed type codes for each particle in an interaction.
vector
<
set
<
int
>
>
allowedTypes
(
numParticlesPerSet
);
bool
anyFilters
=
false
;
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
set
<
int
>
types
;
force
.
getTypeFilter
(
i
,
types
);
if
(
types
.
size
()
==
0
)
for
(
int
j
=
0
;
j
<
numTypes
;
j
++
)
allowedTypes
[
i
].
insert
(
j
);
else
{
for
(
set
<
int
>::
const_iterator
iter
=
types
.
begin
();
iter
!=
types
.
end
();
++
iter
)
if
(
typeMap
.
find
(
*
iter
)
!=
typeMap
.
end
())
allowedTypes
[
i
].
insert
(
typeMap
[
*
iter
]);
if
(
allowedTypes
[
i
].
size
()
<
numTypes
)
anyFilters
=
true
;
}
}
// If there are no filters, reordering is unnecessary.
if
(
!
anyFilters
)
{
particleOrder
.
resize
(
1
);
particleOrder
[
0
].
resize
(
numParticlesPerSet
);
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
particleOrder
[
0
][
i
]
=
i
;
return
;
}
// Build a list of every possible permutation of the particles.
particleOrder
.
clear
();
vector
<
int
>
values
;
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
values
.
push_back
(
i
);
generatePermutations
(
values
,
0
,
particleOrder
);
int
numOrders
=
particleOrder
.
size
();
// Now we need to loop over every possible sequence of type codes, and for each one figure out which order to use.
for
(
int
i
=
0
;
i
<
numIndices
;
i
++
)
{
vector
<
int
>
types
(
numParticlesPerSet
);
int
temp
=
i
;
for
(
int
j
=
0
;
j
<
numParticlesPerSet
;
j
++
)
{
types
[
j
]
=
temp
%
numTypes
;
temp
/=
numTypes
;
}
// Loop over possible orders until we find one that matches the filters.
int
order
=
-
1
;
for
(
int
j
=
0
;
j
<
numOrders
&&
order
==
-
1
;
j
++
)
{
bool
matches
=
true
;
for
(
int
k
=
0
;
k
<
numParticlesPerSet
&&
matches
;
k
++
)
if
(
allowedTypes
[
k
].
find
(
types
[
particleOrder
[
j
][
k
]])
==
allowedTypes
[
k
].
end
())
matches
=
false
;
if
(
matches
)
order
=
j
;
}
orderIndex
[
i
]
=
order
;
}
}
void
CustomManyParticleForceImpl
::
generatePermutations
(
vector
<
int
>&
values
,
int
numFixed
,
vector
<
vector
<
int
>
>&
result
)
{
int
numValues
=
values
.
size
();
if
(
numFixed
==
numValues
)
{
result
.
push_back
(
values
);
return
;
}
for
(
int
i
=
numFixed
;
i
<
numValues
;
i
++
)
{
int
v1
=
values
[
numFixed
];
int
v2
=
values
[
i
];
values
[
numFixed
]
=
v2
;
values
[
i
]
=
v1
;
generatePermutations
(
values
,
numFixed
+
1
,
result
);
values
[
numFixed
]
=
v1
;
values
[
i
]
=
v2
;
}
}
\ No newline at end of file
platforms/reference/include/ReferenceCustomManyParticleIxn.h
View file @
0ca8bdee
...
@@ -43,13 +43,16 @@ class ReferenceCustomManyParticleIxn {
...
@@ -43,13 +43,16 @@ class ReferenceCustomManyParticleIxn {
class
DistanceTermInfo
;
class
DistanceTermInfo
;
class
AngleTermInfo
;
class
AngleTermInfo
;
class
DihedralTermInfo
;
class
DihedralTermInfo
;
int
numParticlesPerSet
,
numPerParticleParameters
;
int
numParticlesPerSet
,
numPerParticleParameters
,
numTypes
;
bool
useCutoff
,
usePeriodic
;
bool
useCutoff
,
usePeriodic
;
RealOpenMM
cutoffDistance
;
RealOpenMM
cutoffDistance
;
RealOpenMM
periodicBoxSize
[
3
];
RealOpenMM
periodicBoxSize
[
3
];
Lepton
::
ExpressionProgram
energyExpression
;
Lepton
::
ExpressionProgram
energyExpression
;
std
::
vector
<
std
::
vector
<
std
::
string
>
>
particleParamNames
;
std
::
vector
<
std
::
vector
<
std
::
string
>
>
particleParamNames
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
int
>
particleTypes
;
std
::
vector
<
int
>
orderIndex
;
std
::
vector
<
std
::
vector
<
int
>
>
particleOrder
;
std
::
vector
<
ParticleTermInfo
>
particleTerms
;
std
::
vector
<
ParticleTermInfo
>
particleTerms
;
std
::
vector
<
DistanceTermInfo
>
distanceTerms
;
std
::
vector
<
DistanceTermInfo
>
distanceTerms
;
std
::
vector
<
AngleTermInfo
>
angleTerms
;
std
::
vector
<
AngleTermInfo
>
angleTerms
;
...
...
platforms/reference/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
View file @
0ca8bdee
...
@@ -97,6 +97,10 @@ ReferenceCustomManyParticleIxn::ReferenceCustomManyParticleIxn(const CustomManyP
...
@@ -97,6 +97,10 @@ ReferenceCustomManyParticleIxn::ReferenceCustomManyParticleIxn(const CustomManyP
exclusions
[
p1
].
insert
(
p2
);
exclusions
[
p1
].
insert
(
p2
);
exclusions
[
p2
].
insert
(
p1
);
exclusions
[
p2
].
insert
(
p1
);
}
}
// Record information about type filters.
CustomManyParticleForceImpl
::
buildFilterArrays
(
force
,
numTypes
,
particleTypes
,
orderIndex
,
particleOrder
);
}
}
ReferenceCustomManyParticleIxn
::~
ReferenceCustomManyParticleIxn
(
){
ReferenceCustomManyParticleIxn
::~
ReferenceCustomManyParticleIxn
(
){
...
@@ -144,12 +148,31 @@ void ReferenceCustomManyParticleIxn::loopOverInteractions(vector<int>& particles
...
@@ -144,12 +148,31 @@ void ReferenceCustomManyParticleIxn::loopOverInteractions(vector<int>& particles
void
ReferenceCustomManyParticleIxn
::
calculateOneIxn
(
const
vector
<
int
>&
particles
,
vector
<
RealVec
>&
atomCoordinates
,
void
ReferenceCustomManyParticleIxn
::
calculateOneIxn
(
const
vector
<
int
>&
particles
,
vector
<
RealVec
>&
atomCoordinates
,
map
<
string
,
double
>&
variables
,
vector
<
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
{
map
<
string
,
double
>&
variables
,
vector
<
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
{
// Select the ordering to use for the particles.
vector
<
int
>
permutedParticles
(
numParticlesPerSet
);
if
(
particleOrder
.
size
()
==
1
)
{
// There are no filters, so we don't need to worry about ordering.
permutedParticles
=
particles
;
}
else
{
int
index
=
0
;
for
(
int
i
=
numParticlesPerSet
-
1
;
i
>=
0
;
i
--
)
index
=
particleTypes
[
particles
[
i
]]
+
numTypes
*
index
;
int
order
=
orderIndex
[
index
];
if
(
order
==
-
1
)
return
;
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
permutedParticles
[
i
]
=
particles
[
particleOrder
[
order
][
i
]];
}
// Decide whether to include this interaction.
// Decide whether to include this interaction.
for
(
int
i
=
0
;
i
<
(
int
)
particles
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
p
ermutedP
articles
.
size
();
i
++
)
{
int
p1
=
particles
[
i
];
int
p1
=
p
ermutedP
articles
[
i
];
for
(
int
j
=
i
+
1
;
j
<
(
int
)
particles
.
size
();
j
++
)
{
for
(
int
j
=
i
+
1
;
j
<
(
int
)
p
ermutedP
articles
.
size
();
j
++
)
{
int
p2
=
particles
[
j
];
int
p2
=
p
ermutedP
articles
[
j
];
if
(
exclusions
[
p1
].
find
(
p2
)
!=
exclusions
[
p1
].
end
())
if
(
exclusions
[
p1
].
find
(
p2
)
!=
exclusions
[
p1
].
end
())
return
;
return
;
if
(
useCutoff
)
{
if
(
useCutoff
)
{
...
@@ -169,20 +192,20 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
...
@@ -169,20 +192,20 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
}
}
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
];
computeDelta
(
particles
[
term
.
p1
],
particles
[
term
.
p2
],
term
.
delta
,
atomCoordinates
);
computeDelta
(
p
ermutedP
articles
[
term
.
p1
],
p
ermutedP
articles
[
term
.
p2
],
term
.
delta
,
atomCoordinates
);
variables
[
term
.
name
]
=
term
.
delta
[
ReferenceForce
::
RIndex
];
variables
[
term
.
name
]
=
term
.
delta
[
ReferenceForce
::
RIndex
];
}
}
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
computeDelta
(
particles
[
term
.
p1
],
particles
[
term
.
p2
],
term
.
delta1
,
atomCoordinates
);
computeDelta
(
p
ermutedP
articles
[
term
.
p1
],
p
ermutedP
articles
[
term
.
p2
],
term
.
delta1
,
atomCoordinates
);
computeDelta
(
particles
[
term
.
p3
],
particles
[
term
.
p2
],
term
.
delta2
,
atomCoordinates
);
computeDelta
(
p
ermutedP
articles
[
term
.
p3
],
p
ermutedP
articles
[
term
.
p2
],
term
.
delta2
,
atomCoordinates
);
variables
[
term
.
name
]
=
computeAngle
(
term
.
delta1
,
term
.
delta2
);
variables
[
term
.
name
]
=
computeAngle
(
term
.
delta1
,
term
.
delta2
);
}
}
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
computeDelta
(
particles
[
term
.
p2
],
particles
[
term
.
p1
],
term
.
delta1
,
atomCoordinates
);
computeDelta
(
p
ermutedP
articles
[
term
.
p2
],
p
ermutedP
articles
[
term
.
p1
],
term
.
delta1
,
atomCoordinates
);
computeDelta
(
particles
[
term
.
p2
],
particles
[
term
.
p3
],
term
.
delta2
,
atomCoordinates
);
computeDelta
(
p
ermutedP
articles
[
term
.
p2
],
p
ermutedP
articles
[
term
.
p3
],
term
.
delta2
,
atomCoordinates
);
computeDelta
(
particles
[
term
.
p4
],
particles
[
term
.
p3
],
term
.
delta3
,
atomCoordinates
);
computeDelta
(
p
ermutedP
articles
[
term
.
p4
],
p
ermutedP
articles
[
term
.
p3
],
term
.
delta3
,
atomCoordinates
);
RealOpenMM
dotDihedral
,
signOfDihedral
;
RealOpenMM
dotDihedral
,
signOfDihedral
;
RealOpenMM
*
crossProduct
[]
=
{
term
.
cross1
,
term
.
cross2
};
RealOpenMM
*
crossProduct
[]
=
{
term
.
cross1
,
term
.
cross2
};
variables
[
term
.
name
]
=
ReferenceBondIxn
::
getDihedralAngleBetweenThreeVectors
(
term
.
delta1
,
term
.
delta2
,
term
.
delta3
,
crossProduct
,
&
dotDihedral
,
term
.
delta1
,
&
signOfDihedral
,
1
);
variables
[
term
.
name
]
=
ReferenceBondIxn
::
getDihedralAngleBetweenThreeVectors
(
term
.
delta1
,
term
.
delta2
,
term
.
delta3
,
crossProduct
,
&
dotDihedral
,
term
.
delta1
,
&
signOfDihedral
,
1
);
...
@@ -192,7 +215,7 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
...
@@ -192,7 +215,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
];
forces
[
particles
[
term
.
atom
]][
term
.
component
]
-=
term
.
forceExpression
.
evaluate
(
variables
);
forces
[
p
ermutedP
articles
[
term
.
atom
]][
term
.
component
]
-=
term
.
forceExpression
.
evaluate
(
variables
);
}
}
// Apply forces based on distances.
// Apply forces based on distances.
...
@@ -202,8 +225,8 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
...
@@ -202,8 +225,8 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
RealOpenMM
dEdR
=
(
RealOpenMM
)
(
term
.
forceExpression
.
evaluate
(
variables
)
/
(
term
.
delta
[
ReferenceForce
::
RIndex
]));
RealOpenMM
dEdR
=
(
RealOpenMM
)
(
term
.
forceExpression
.
evaluate
(
variables
)
/
(
term
.
delta
[
ReferenceForce
::
RIndex
]));
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
RealOpenMM
force
=
-
dEdR
*
term
.
delta
[
i
];
RealOpenMM
force
=
-
dEdR
*
term
.
delta
[
i
];
forces
[
particles
[
term
.
p1
]][
i
]
-=
force
;
forces
[
p
ermutedP
articles
[
term
.
p1
]][
i
]
-=
force
;
forces
[
particles
[
term
.
p2
]][
i
]
+=
force
;
forces
[
p
ermutedP
articles
[
term
.
p2
]][
i
]
+=
force
;
}
}
}
}
...
@@ -228,9 +251,9 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
...
@@ -228,9 +251,9 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
deltaCrossP
[
1
][
i
]
=
-
(
deltaCrossP
[
0
][
i
]
+
deltaCrossP
[
2
][
i
]);
deltaCrossP
[
1
][
i
]
=
-
(
deltaCrossP
[
0
][
i
]
+
deltaCrossP
[
2
][
i
]);
}
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
forces
[
particles
[
term
.
p1
]][
i
]
+=
deltaCrossP
[
0
][
i
];
forces
[
p
ermutedP
articles
[
term
.
p1
]][
i
]
+=
deltaCrossP
[
0
][
i
];
forces
[
particles
[
term
.
p2
]][
i
]
+=
deltaCrossP
[
1
][
i
];
forces
[
p
ermutedP
articles
[
term
.
p2
]][
i
]
+=
deltaCrossP
[
1
][
i
];
forces
[
particles
[
term
.
p3
]][
i
]
+=
deltaCrossP
[
2
][
i
];
forces
[
p
ermutedP
articles
[
term
.
p3
]][
i
]
+=
deltaCrossP
[
2
][
i
];
}
}
}
}
...
@@ -258,10 +281,10 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
...
@@ -258,10 +281,10 @@ void ReferenceCustomManyParticleIxn::calculateOneIxn(const vector<int>& particle
internalF
[
2
][
i
]
=
internalF
[
3
][
i
]
+
s
;
internalF
[
2
][
i
]
=
internalF
[
3
][
i
]
+
s
;
}
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
forces
[
particles
[
term
.
p1
]][
i
]
+=
internalF
[
0
][
i
];
forces
[
p
ermutedP
articles
[
term
.
p1
]][
i
]
+=
internalF
[
0
][
i
];
forces
[
particles
[
term
.
p2
]][
i
]
-=
internalF
[
1
][
i
];
forces
[
p
ermutedP
articles
[
term
.
p2
]][
i
]
-=
internalF
[
1
][
i
];
forces
[
particles
[
term
.
p3
]][
i
]
-=
internalF
[
2
][
i
];
forces
[
p
ermutedP
articles
[
term
.
p3
]][
i
]
-=
internalF
[
2
][
i
];
forces
[
particles
[
term
.
p4
]][
i
]
+=
internalF
[
3
][
i
];
forces
[
p
ermutedP
articles
[
term
.
p4
]][
i
]
+=
internalF
[
3
][
i
];
}
}
}
}
...
...
platforms/reference/tests/TestReferenceCustomManyParticleForce.cpp
View file @
0ca8bdee
...
@@ -345,6 +345,57 @@ void testTabulatedFunctions() {
...
@@ -345,6 +345,57 @@ void testTabulatedFunctions() {
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
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
,
"distance(p1,p2)+distance(p1,p3)"
);
vector
<
double
>
params
;
force
->
addParticle
(
params
,
0
);
force
->
addParticle
(
params
,
1
);
force
->
addParticle
(
params
,
0
);
force
->
addParticle
(
params
,
1
);
force
->
addParticle
(
params
,
5
);
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
);
ReferencePlatform
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
+=
r12
+
r13
;
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-5
);
}
int
main
()
{
int
main
()
{
try
{
try
{
testNoCutoff
();
testNoCutoff
();
...
@@ -353,6 +404,7 @@ int main() {
...
@@ -353,6 +404,7 @@ int main() {
testExclusions
();
testExclusions
();
testParameters
();
testParameters
();
testTabulatedFunctions
();
testTabulatedFunctions
();
testTypeFilters
();
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment