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
e1a378b7
Commit
e1a378b7
authored
Aug 05, 2014
by
peastman
Browse files
Began implementing CustomManyParticleForce
parent
d20e4edd
Changes
14
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1907 additions
and
10 deletions
+1907
-10
olla/include/openmm/kernels.h
olla/include/openmm/kernels.h
+41
-0
openmmapi/include/openmm/CustomManyParticleForce.h
openmmapi/include/openmm/CustomManyParticleForce.h
+505
-0
openmmapi/include/openmm/internal/CustomManyParticleForceImpl.h
...api/include/openmm/internal/CustomManyParticleForceImpl.h
+93
-0
openmmapi/src/CustomManyParticleForce.cpp
openmmapi/src/CustomManyParticleForce.cpp
+216
-0
openmmapi/src/CustomManyParticleForceImpl.cpp
openmmapi/src/CustomManyParticleForceImpl.cpp
+227
-0
platforms/reference/include/ReferenceBondIxn.h
platforms/reference/include/ReferenceBondIxn.h
+7
-7
platforms/reference/include/ReferenceCustomManyParticleIxn.h
platforms/reference/include/ReferenceCustomManyParticleIxn.h
+190
-0
platforms/reference/include/ReferenceKernels.h
platforms/reference/include/ReferenceKernels.h
+41
-0
platforms/reference/src/ReferenceKernelFactory.cpp
platforms/reference/src/ReferenceKernelFactory.cpp
+2
-0
platforms/reference/src/ReferenceKernels.cpp
platforms/reference/src/ReferenceKernels.cpp
+87
-0
platforms/reference/src/ReferencePlatform.cpp
platforms/reference/src/ReferencePlatform.cpp
+1
-0
platforms/reference/src/SimTKReference/ReferenceBondIxn.cpp
platforms/reference/src/SimTKReference/ReferenceBondIxn.cpp
+3
-3
platforms/reference/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
...nce/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
+245
-0
platforms/reference/tests/TestReferenceCustomManyParticleForce.cpp
.../reference/tests/TestReferenceCustomManyParticleForce.cpp
+249
-0
No files found.
olla/include/openmm/kernels.h
View file @
e1a378b7
...
@@ -44,6 +44,7 @@
...
@@ -44,6 +44,7 @@
#include "openmm/CustomHbondForce.h"
#include "openmm/CustomHbondForce.h"
#include "openmm/CustomIntegrator.h"
#include "openmm/CustomIntegrator.h"
#include "openmm/CustomNonbondedForce.h"
#include "openmm/CustomNonbondedForce.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/CustomTorsionForce.h"
#include "openmm/CustomTorsionForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/GBVIForce.h"
#include "openmm/GBVIForce.h"
...
@@ -826,6 +827,46 @@ public:
...
@@ -826,6 +827,46 @@ public:
virtual
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomCompoundBondForce
&
force
)
=
0
;
virtual
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomCompoundBondForce
&
force
)
=
0
;
};
};
/**
* This kernel is invoked by CustomManyParticleForce to calculate the forces acting on the system and the energy of the system.
*/
class
CalcCustomManyParticleForceKernel
:
public
KernelImpl
{
public:
enum
NonbondedMethod
{
NoCutoff
=
0
,
CutoffNonPeriodic
=
1
,
CutoffPeriodic
=
2
};
static
std
::
string
Name
()
{
return
"CalcCustomManyParticleForce"
;
}
CalcCustomManyParticleForceKernel
(
std
::
string
name
,
const
Platform
&
platform
)
:
KernelImpl
(
name
,
platform
)
{
}
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the CustomManyParticleForce this kernel will be used for
*/
virtual
void
initialize
(
const
System
&
system
,
const
CustomManyParticleForce
&
force
)
=
0
;
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @return the potential energy due to the force
*/
virtual
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
=
0
;
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the CustomManyParticleForce to copy the parameters from
*/
virtual
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomManyParticleForce
&
force
)
=
0
;
};
/**
/**
* This kernel is invoked by VerletIntegrator to take one time step.
* This kernel is invoked by VerletIntegrator to take one time step.
*/
*/
...
...
openmmapi/include/openmm/CustomManyParticleForce.h
0 → 100644
View file @
e1a378b7
This diff is collapsed.
Click to expand it.
openmmapi/include/openmm/internal/CustomManyParticleForceImpl.h
0 → 100644
View file @
e1a378b7
#ifndef OPENMM_CUSTOMMANYPARTICLEFORCEIMPL_H_
#define OPENMM_CUSTOMMANYPARTICLEFORCEIMPL_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-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. *
* -------------------------------------------------------------------------- */
#include "ForceImpl.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/Kernel.h"
#include "lepton/CustomFunction.h"
#include "lepton/ExpressionTreeNode.h"
#include "lepton/ParsedExpression.h"
#include <utility>
#include <map>
#include <string>
namespace
OpenMM
{
/**
* This is the internal implementation of CustomManyParticleForce.
*/
class
OPENMM_EXPORT
CustomManyParticleForceImpl
:
public
ForceImpl
{
public:
CustomManyParticleForceImpl
(
const
CustomManyParticleForce
&
owner
);
~
CustomManyParticleForceImpl
();
void
initialize
(
ContextImpl
&
context
);
const
CustomManyParticleForce
&
getOwner
()
const
{
return
owner
;
}
void
updateContextState
(
ContextImpl
&
context
)
{
// This force field doesn't update the state directly.
}
double
calcForcesAndEnergy
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
,
int
groups
);
std
::
map
<
std
::
string
,
double
>
getDefaultParameters
();
std
::
vector
<
std
::
string
>
getKernelNames
();
void
updateParametersInContext
(
ContextImpl
&
context
);
/**
* This is a utility routine that parses the energy expression, identifies the angles and dihedrals
* in it, and replaces them with variables.
*
* @param force the CustomManyParticleForce to process
* @param functions definitions of custom function that may appear in the expression
* @param distances on exit, this will contain an entry for each distance used in the expression. The key is the name
* of the corresponding variable, and the value is the list of particle indices.
* @param angles on exit, this will contain an entry for each angle used in the expression. The key is the name
* of the corresponding variable, and the value is the list of particle indices.
* @param dihedrals on exit, this will contain an entry for each dihedral used in the expression. The key is the name
* of the corresponding variable, and the value is the list of particle indices.
* @return a Parsed expression for the energy
*/
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
);
private:
class
FunctionPlaceholder
;
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
>
>&
dihedrals
);
const
CustomManyParticleForce
&
owner
;
Kernel
kernel
;
};
}
// namespace OpenMM
#endif
/*OPENMM_CUSTOMMANYPARTICLEFORCEIMPL_H_*/
openmmapi/src/CustomManyParticleForce.cpp
0 → 100644
View file @
e1a378b7
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-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. *
* -------------------------------------------------------------------------- */
#include "openmm/Force.h"
#include "openmm/OpenMMException.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include <cmath>
#include <map>
#include <set>
#include <sstream>
#include <utility>
using
namespace
OpenMM
;
using
namespace
std
;
CustomManyParticleForce
::
CustomManyParticleForce
(
int
particlesPerSet
,
const
string
&
energy
)
:
particlesPerSet
(
particlesPerSet
),
energyExpression
(
energy
),
typeFilters
(
particlesPerSet
)
{
}
CustomManyParticleForce
::~
CustomManyParticleForce
()
{
for
(
int
i
=
0
;
i
<
(
int
)
functions
.
size
();
i
++
)
delete
functions
[
i
].
function
;
}
const
string
&
CustomManyParticleForce
::
getEnergyFunction
()
const
{
return
energyExpression
;
}
void
CustomManyParticleForce
::
setEnergyFunction
(
const
string
&
energy
)
{
energyExpression
=
energy
;
}
CustomManyParticleForce
::
NonbondedMethod
CustomManyParticleForce
::
getNonbondedMethod
()
const
{
return
nonbondedMethod
;
}
void
CustomManyParticleForce
::
setNonbondedMethod
(
NonbondedMethod
method
)
{
nonbondedMethod
=
method
;
}
double
CustomManyParticleForce
::
getCutoffDistance
()
const
{
return
cutoffDistance
;
}
void
CustomManyParticleForce
::
setCutoffDistance
(
double
distance
)
{
cutoffDistance
=
distance
;
}
int
CustomManyParticleForce
::
addPerParticleParameter
(
const
string
&
name
)
{
particleParameters
.
push_back
(
ParticleParameterInfo
(
name
));
return
particleParameters
.
size
()
-
1
;
}
const
string
&
CustomManyParticleForce
::
getPerParticleParameterName
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
particleParameters
);
return
particleParameters
[
index
].
name
;
}
void
CustomManyParticleForce
::
setPerParticleParameterName
(
int
index
,
const
string
&
name
)
{
ASSERT_VALID_INDEX
(
index
,
particleParameters
);
particleParameters
[
index
].
name
=
name
;
}
int
CustomManyParticleForce
::
addGlobalParameter
(
const
string
&
name
,
double
defaultValue
)
{
globalParameters
.
push_back
(
GlobalParameterInfo
(
name
,
defaultValue
));
return
globalParameters
.
size
()
-
1
;
}
const
string
&
CustomManyParticleForce
::
getGlobalParameterName
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
return
globalParameters
[
index
].
name
;
}
void
CustomManyParticleForce
::
setGlobalParameterName
(
int
index
,
const
string
&
name
)
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
globalParameters
[
index
].
name
=
name
;
}
double
CustomManyParticleForce
::
getGlobalParameterDefaultValue
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
return
globalParameters
[
index
].
defaultValue
;
}
void
CustomManyParticleForce
::
setGlobalParameterDefaultValue
(
int
index
,
double
defaultValue
)
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
globalParameters
[
index
].
defaultValue
=
defaultValue
;
}
int
CustomManyParticleForce
::
addParticle
(
const
vector
<
double
>&
parameters
,
int
type
)
{
particles
.
push_back
(
ParticleInfo
(
parameters
,
type
));
return
particles
.
size
()
-
1
;
}
void
CustomManyParticleForce
::
getParticleParameters
(
int
index
,
vector
<
double
>&
parameters
,
int
&
type
)
const
{
ASSERT_VALID_INDEX
(
index
,
particles
);
parameters
=
particles
[
index
].
parameters
;
type
=
particles
[
index
].
type
;
}
void
CustomManyParticleForce
::
setParticleParameters
(
int
index
,
const
vector
<
double
>&
parameters
,
int
type
)
{
ASSERT_VALID_INDEX
(
index
,
particles
);
particles
[
index
].
parameters
=
parameters
;
particles
[
index
].
type
=
type
;
}
int
CustomManyParticleForce
::
addExclusion
(
int
particle1
,
int
particle2
)
{
exclusions
.
push_back
(
ExclusionInfo
(
particle1
,
particle2
));
return
exclusions
.
size
()
-
1
;
}
void
CustomManyParticleForce
::
getExclusionParticles
(
int
index
,
int
&
particle1
,
int
&
particle2
)
const
{
ASSERT_VALID_INDEX
(
index
,
exclusions
);
particle1
=
exclusions
[
index
].
particle1
;
particle2
=
exclusions
[
index
].
particle2
;
}
void
CustomManyParticleForce
::
setExclusionParticles
(
int
index
,
int
particle1
,
int
particle2
)
{
ASSERT_VALID_INDEX
(
index
,
exclusions
);
exclusions
[
index
].
particle1
=
particle1
;
exclusions
[
index
].
particle2
=
particle2
;
}
void
CustomManyParticleForce
::
createExclusionsFromBonds
(
const
vector
<
pair
<
int
,
int
>
>&
bonds
,
int
bondCutoff
)
{
if
(
bondCutoff
<
1
)
return
;
vector
<
set
<
int
>
>
exclusions
(
particles
.
size
());
vector
<
set
<
int
>
>
bonded12
(
exclusions
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
bonds
.
size
();
++
i
)
{
int
p1
=
bonds
[
i
].
first
;
int
p2
=
bonds
[
i
].
second
;
exclusions
[
p1
].
insert
(
p2
);
exclusions
[
p2
].
insert
(
p1
);
bonded12
[
p1
].
insert
(
p2
);
bonded12
[
p2
].
insert
(
p1
);
}
for
(
int
level
=
0
;
level
<
bondCutoff
-
1
;
level
++
)
{
vector
<
set
<
int
>
>
currentExclusions
=
exclusions
;
for
(
int
i
=
0
;
i
<
(
int
)
particles
.
size
();
i
++
)
{
for
(
set
<
int
>::
const_iterator
iter
=
currentExclusions
[
i
].
begin
();
iter
!=
currentExclusions
[
i
].
end
();
++
iter
)
exclusions
[
*
iter
].
insert
(
bonded12
[
i
].
begin
(),
bonded12
[
i
].
end
());
}
}
for
(
int
i
=
0
;
i
<
(
int
)
exclusions
.
size
();
++
i
)
for
(
set
<
int
>::
const_iterator
iter
=
exclusions
[
i
].
begin
();
iter
!=
exclusions
[
i
].
end
();
++
iter
)
if
(
*
iter
<
i
)
addExclusion
(
*
iter
,
i
);
}
void
CustomManyParticleForce
::
getTypeFilter
(
int
index
,
set
<
int
>&
types
)
const
{
if
(
index
<
0
||
index
>=
particlesPerSet
)
throw
OpenMMException
(
"CustomManyParticleForce: index to getTypeFilter out of range"
);
types
=
typeFilters
[
index
];
}
void
CustomManyParticleForce
::
setTypeFilter
(
int
index
,
const
set
<
int
>&
types
)
{
if
(
index
<
0
||
index
>=
particlesPerSet
)
throw
OpenMMException
(
"CustomManyParticleForce: index to setTypeFilter out of range"
);
typeFilters
[
index
]
=
types
;
}
int
CustomManyParticleForce
::
addTabulatedFunction
(
const
string
&
name
,
TabulatedFunction
*
function
)
{
functions
.
push_back
(
FunctionInfo
(
name
,
function
));
return
functions
.
size
()
-
1
;
}
const
TabulatedFunction
&
CustomManyParticleForce
::
getTabulatedFunction
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
functions
);
return
*
functions
[
index
].
function
;
}
TabulatedFunction
&
CustomManyParticleForce
::
getTabulatedFunction
(
int
index
)
{
ASSERT_VALID_INDEX
(
index
,
functions
);
return
*
functions
[
index
].
function
;
}
const
string
&
CustomManyParticleForce
::
getTabulatedFunctionName
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
functions
);
return
functions
[
index
].
name
;
}
ForceImpl
*
CustomManyParticleForce
::
createImpl
()
const
{
return
new
CustomManyParticleForceImpl
(
*
this
);
}
void
CustomManyParticleForce
::
updateParametersInContext
(
Context
&
context
)
{
dynamic_cast
<
CustomManyParticleForceImpl
&>
(
getImplInContext
(
context
)).
updateParametersInContext
(
getContextImpl
(
context
));
}
openmmapi/src/CustomManyParticleForceImpl.cpp
0 → 100644
View file @
e1a378b7
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-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. *
* -------------------------------------------------------------------------- */
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "openmm/kernels.h"
#include "lepton/Operation.h"
#include "lepton/Parser.h"
#include <sstream>
using
namespace
OpenMM
;
using
Lepton
::
CustomFunction
;
using
Lepton
::
ExpressionTreeNode
;
using
Lepton
::
Operation
;
using
Lepton
::
ParsedExpression
;
using
std
::
map
;
using
std
::
pair
;
using
std
::
vector
;
using
std
::
set
;
using
std
::
string
;
using
std
::
stringstream
;
/**
* This class serves as a placeholder for angles and dihedrals in expressions.
*/
class
CustomManyParticleForceImpl
::
FunctionPlaceholder
:
public
CustomFunction
{
public:
int
numArguments
;
FunctionPlaceholder
(
int
numArguments
)
:
numArguments
(
numArguments
)
{
}
int
getNumArguments
()
const
{
return
numArguments
;
}
double
evaluate
(
const
double
*
arguments
)
const
{
return
0.0
;
}
double
evaluateDerivative
(
const
double
*
arguments
,
const
int
*
derivOrder
)
const
{
return
0.0
;
}
CustomFunction
*
clone
()
const
{
return
new
FunctionPlaceholder
(
numArguments
);
}
};
CustomManyParticleForceImpl
::
CustomManyParticleForceImpl
(
const
CustomManyParticleForce
&
owner
)
:
owner
(
owner
)
{
}
CustomManyParticleForceImpl
::~
CustomManyParticleForceImpl
()
{
}
void
CustomManyParticleForceImpl
::
initialize
(
ContextImpl
&
context
)
{
kernel
=
context
.
getPlatform
().
createKernel
(
CalcCustomManyParticleForceKernel
::
Name
(),
context
);
// Check for errors in the specification of parameters and exclusions.
const
System
&
system
=
context
.
getSystem
();
if
(
owner
.
getNumParticles
()
!=
system
.
getNumParticles
())
throw
OpenMMException
(
"CustomManyParticleForce must have exactly as many particles as the System it belongs to."
);
vector
<
set
<
int
>
>
exclusions
(
owner
.
getNumParticles
());
vector
<
double
>
parameters
;
int
type
;
int
numParameters
=
owner
.
getNumPerParticleParameters
();
for
(
int
i
=
0
;
i
<
owner
.
getNumParticles
();
i
++
)
{
owner
.
getParticleParameters
(
i
,
parameters
,
type
);
if
(
parameters
.
size
()
!=
numParameters
)
{
stringstream
msg
;
msg
<<
"CustomManyParticleForce: Wrong number of parameters for particle "
;
msg
<<
i
;
throw
OpenMMException
(
msg
.
str
());
}
}
for
(
int
i
=
0
;
i
<
owner
.
getNumExclusions
();
i
++
)
{
int
particle1
,
particle2
;
owner
.
getExclusionParticles
(
i
,
particle1
,
particle2
);
if
(
particle1
<
0
||
particle1
>=
owner
.
getNumParticles
())
{
stringstream
msg
;
msg
<<
"CustomManyParticleForce: Illegal particle index for an exclusion: "
;
msg
<<
particle1
;
throw
OpenMMException
(
msg
.
str
());
}
if
(
particle2
<
0
||
particle2
>=
owner
.
getNumParticles
())
{
stringstream
msg
;
msg
<<
"CustomManyParticleForce: Illegal particle index for an exclusion: "
;
msg
<<
particle2
;
throw
OpenMMException
(
msg
.
str
());
}
if
(
exclusions
[
particle1
].
count
(
particle2
)
>
0
||
exclusions
[
particle2
].
count
(
particle1
)
>
0
)
{
stringstream
msg
;
msg
<<
"CustomManyParticleForce: Multiple exclusions are specified for particles "
;
msg
<<
particle1
;
msg
<<
" and "
;
msg
<<
particle2
;
throw
OpenMMException
(
msg
.
str
());
}
exclusions
[
particle1
].
insert
(
particle2
);
exclusions
[
particle2
].
insert
(
particle1
);
}
if
(
owner
.
getNonbondedMethod
()
==
CustomManyParticleForce
::
CutoffPeriodic
)
{
Vec3
boxVectors
[
3
];
system
.
getDefaultPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
double
cutoff
=
owner
.
getCutoffDistance
();
if
(
cutoff
>
0.5
*
boxVectors
[
0
][
0
]
||
cutoff
>
0.5
*
boxVectors
[
1
][
1
]
||
cutoff
>
0.5
*
boxVectors
[
2
][
2
])
throw
OpenMMException
(
"CustomManyParticleForce: The cutoff distance cannot be greater than half the periodic box size."
);
}
kernel
.
getAs
<
CalcCustomManyParticleForceKernel
>
().
initialize
(
context
.
getSystem
(),
owner
);
}
double
CustomManyParticleForceImpl
::
calcForcesAndEnergy
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
,
int
groups
)
{
if
((
groups
&
(
1
<<
owner
.
getForceGroup
()))
!=
0
)
return
kernel
.
getAs
<
CalcCustomManyParticleForceKernel
>
().
execute
(
context
,
includeForces
,
includeEnergy
);
return
0.0
;
}
vector
<
string
>
CustomManyParticleForceImpl
::
getKernelNames
()
{
vector
<
string
>
names
;
names
.
push_back
(
CalcCustomManyParticleForceKernel
::
Name
());
return
names
;
}
map
<
string
,
double
>
CustomManyParticleForceImpl
::
getDefaultParameters
()
{
map
<
string
,
double
>
parameters
;
for
(
int
i
=
0
;
i
<
owner
.
getNumGlobalParameters
();
i
++
)
parameters
[
owner
.
getGlobalParameterName
(
i
)]
=
owner
.
getGlobalParameterDefaultValue
(
i
);
return
parameters
;
}
ParsedExpression
CustomManyParticleForceImpl
::
prepareExpression
(
const
CustomManyParticleForce
&
force
,
const
map
<
string
,
CustomFunction
*>&
customFunctions
,
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
CustomManyParticleForceImpl
::
FunctionPlaceholder
custom
(
1
);
CustomManyParticleForceImpl
::
FunctionPlaceholder
distance
(
2
);
CustomManyParticleForceImpl
::
FunctionPlaceholder
angle
(
3
);
CustomManyParticleForceImpl
::
FunctionPlaceholder
dihedral
(
4
);
map
<
string
,
CustomFunction
*>
functions
=
customFunctions
;
functions
[
"distance"
]
=
&
distance
;
functions
[
"angle"
]
=
&
angle
;
functions
[
"dihedral"
]
=
&
dihedral
;
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
);
map
<
string
,
int
>
atoms
;
for
(
int
i
=
0
;
i
<
force
.
getNumParticlesPerSet
();
i
++
)
{
stringstream
name
;
name
<<
'p'
<<
(
i
+
1
);
atoms
[
name
.
str
()]
=
i
;
}
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
atoms
,
distances
,
angles
,
dihedrals
)).
optimize
();
}
ExpressionTreeNode
CustomManyParticleForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
atoms
,
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
const
Operation
&
op
=
node
.
getOperation
();
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
(
op
.
getName
()
!=
"distance"
&&
op
.
getName
()
!=
"angle"
&&
op
.
getName
()
!=
"dihedral"
))
{
// This is not an angle or dihedral, so process its children.
vector
<
ExpressionTreeNode
>
children
;
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
atoms
,
distances
,
angles
,
dihedrals
));
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
}
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
// Identify the atoms this term is based on.
int
numArgs
=
custom
.
getNumArguments
();
vector
<
int
>
indices
(
numArgs
);
for
(
int
i
=
0
;
i
<
numArgs
;
i
++
)
{
map
<
string
,
int
>::
const_iterator
iter
=
atoms
.
find
(
node
.
getChildren
()[
i
].
getOperation
().
getName
());
if
(
iter
==
atoms
.
end
())
throw
OpenMMException
(
"CustomManyParticleForce: Unknown particle '"
+
node
.
getChildren
()[
i
].
getOperation
().
getName
()
+
"'"
);
indices
[
i
]
=
iter
->
second
;
}
// Select a name for the variable and add it to the appropriate map.
stringstream
variable
;
if
(
numArgs
==
2
)
variable
<<
"distance"
;
else
if
(
numArgs
==
3
)
variable
<<
"angle"
;
else
variable
<<
"dihedral"
;
for
(
int
i
=
0
;
i
<
numArgs
;
i
++
)
variable
<<
indices
[
i
];
string
name
=
variable
.
str
();
if
(
numArgs
==
2
)
distances
[
name
]
=
indices
;
else
if
(
numArgs
==
3
)
angles
[
name
]
=
indices
;
else
dihedrals
[
name
]
=
indices
;
// Return a new node that represents it as a simple variable.
return
ExpressionTreeNode
(
new
Operation
::
Variable
(
name
));
}
void
CustomManyParticleForceImpl
::
updateParametersInContext
(
ContextImpl
&
context
)
{
kernel
.
getAs
<
CalcCustomManyParticleForceKernel
>
().
copyParametersToContext
(
context
,
owner
);
}
platforms/reference/include/ReferenceBondIxn.h
View file @
e1a378b7
...
@@ -82,7 +82,7 @@ class OPENMM_EXPORT ReferenceBondIxn {
...
@@ -82,7 +82,7 @@ class OPENMM_EXPORT ReferenceBondIxn {
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
RealOpenMM
getNormedDotProduct
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
int
hasREntry
)
const
;
static
RealOpenMM
getNormedDotProduct
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
int
hasREntry
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -98,8 +98,8 @@ class OPENMM_EXPORT ReferenceBondIxn {
...
@@ -98,8 +98,8 @@ class OPENMM_EXPORT ReferenceBondIxn {
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
RealOpenMM
getAngleBetweenTwoVectors
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
static
RealOpenMM
getAngleBetweenTwoVectors
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
RealOpenMM
*
outputDotProduct
,
int
hasREntry
)
const
;
RealOpenMM
*
outputDotProduct
,
int
hasREntry
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -119,10 +119,10 @@ class OPENMM_EXPORT ReferenceBondIxn {
...
@@ -119,10 +119,10 @@ class OPENMM_EXPORT ReferenceBondIxn {
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
RealOpenMM
getDihedralAngleBetweenThreeVectors
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
static
RealOpenMM
getDihedralAngleBetweenThreeVectors
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
RealOpenMM
*
vector3
,
RealOpenMM
**
outputCrossProduct
,
RealOpenMM
*
vector3
,
RealOpenMM
**
outputCrossProduct
,
RealOpenMM
*
cosineOfAngle
,
RealOpenMM
*
signVector
,
RealOpenMM
*
cosineOfAngle
,
RealOpenMM
*
signVector
,
RealOpenMM
*
signOfAngle
,
int
hasREntry
)
const
;
RealOpenMM
*
signOfAngle
,
int
hasREntry
);
};
};
...
...
platforms/reference/include/ReferenceCustomManyParticleIxn.h
0 → 100644
View file @
e1a378b7
/* Portions copyright (c) 2009-2014 Stanford University and Simbios.
* Contributors: Peter Eastman
*
* 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.
*/
#ifndef __ReferenceCustomManyParticleIxn_H__
#define __ReferenceCustomManyParticleIxn_H__
#include "ReferenceBondIxn.h"
#include "lepton/ExpressionProgram.h"
#include "lepton/ParsedExpression.h"
#include <map>
#include <vector>
// ---------------------------------------------------------------------------------------
class
ReferenceCustomManyParticleIxn
{
private:
class
ParticleTermInfo
;
class
DistanceTermInfo
;
class
AngleTermInfo
;
class
DihedralTermInfo
;
int
numParticlesPerSet
,
numPerParticleParameters
;
bool
useCutoff
,
usePeriodic
;
RealOpenMM
cutoffDistance
;
RealOpenMM
periodicBoxSize
[
3
];
Lepton
::
ExpressionProgram
energyExpression
;
std
::
vector
<
std
::
vector
<
std
::
string
>
>
particleParamNames
;
std
::
vector
<
ParticleTermInfo
>
particleTerms
;
std
::
vector
<
DistanceTermInfo
>
distanceTerms
;
std
::
vector
<
AngleTermInfo
>
angleTerms
;
std
::
vector
<
DihedralTermInfo
>
dihedralTerms
;
void
loopOverInteractions
(
std
::
vector
<
int
>&
particles
,
int
loopIndex
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
std
::
map
<
std
::
string
,
double
>&
variables
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
;
/**---------------------------------------------------------------------------------------
Calculate custom interaction for one set of particles
@param particles the indices of the particles
@param atomCoordinates atom coordinates
@param variables the values of variables that may appear in expressions
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void
calculateOneIxn
(
const
std
::
vector
<
int
>&
particles
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
map
<
std
::
string
,
double
>&
variables
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
;
void
computeDelta
(
int
atom1
,
int
atom2
,
RealOpenMM
*
delta
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
)
const
;
static
RealOpenMM
computeAngle
(
RealOpenMM
*
vec1
,
RealOpenMM
*
vec2
);
public:
/**---------------------------------------------------------------------------------------
Constructor
--------------------------------------------------------------------------------------- */
ReferenceCustomManyParticleIxn
(
int
numParticlesPerSet
,
const
Lepton
::
ParsedExpression
&
energyExpression
,
const
std
::
vector
<
std
::
string
>&
particleParameterNames
,
const
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
const
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
const
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~
ReferenceCustomManyParticleIxn
();
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
@param distance the cutoff distance
--------------------------------------------------------------------------------------- */
void
setUseCutoff
(
RealOpenMM
distance
);
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param boxSize the X, Y, and Z widths of the periodic box
--------------------------------------------------------------------------------------- */
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
/**---------------------------------------------------------------------------------------
Calculate the interaction
@param atomCoordinates atom coordinates
@param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
@param globalParameters the values of global parameters
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void
calculateIxn
(
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
const
std
::
map
<
std
::
string
,
double
>&
globalParameters
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
;
// ---------------------------------------------------------------------------------------
};
class
ReferenceCustomManyParticleIxn
::
ParticleTermInfo
{
public:
std
::
string
name
;
int
atom
,
component
;
Lepton
::
ExpressionProgram
forceExpression
;
ParticleTermInfo
(
const
std
::
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
ExpressionProgram
&
forceExpression
)
:
name
(
name
),
atom
(
atom
),
component
(
component
),
forceExpression
(
forceExpression
)
{
}
};
class
ReferenceCustomManyParticleIxn
::
DistanceTermInfo
{
public:
std
::
string
name
;
int
p1
,
p2
;
Lepton
::
ExpressionProgram
forceExpression
;
mutable
RealOpenMM
delta
[
ReferenceForce
::
LastDeltaRIndex
];
DistanceTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
ExpressionProgram
&
forceExpression
)
:
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
forceExpression
(
forceExpression
)
{
}
};
class
ReferenceCustomManyParticleIxn
::
AngleTermInfo
{
public:
std
::
string
name
;
int
p1
,
p2
,
p3
;
Lepton
::
ExpressionProgram
forceExpression
;
mutable
RealOpenMM
delta1
[
ReferenceForce
::
LastDeltaRIndex
];
mutable
RealOpenMM
delta2
[
ReferenceForce
::
LastDeltaRIndex
];
AngleTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
ExpressionProgram
&
forceExpression
)
:
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
forceExpression
(
forceExpression
)
{
}
};
class
ReferenceCustomManyParticleIxn
::
DihedralTermInfo
{
public:
std
::
string
name
;
int
p1
,
p2
,
p3
,
p4
;
Lepton
::
ExpressionProgram
forceExpression
;
mutable
RealOpenMM
delta1
[
ReferenceForce
::
LastDeltaRIndex
];
mutable
RealOpenMM
delta2
[
ReferenceForce
::
LastDeltaRIndex
];
mutable
RealOpenMM
delta3
[
ReferenceForce
::
LastDeltaRIndex
];
mutable
RealOpenMM
cross1
[
3
];
mutable
RealOpenMM
cross2
[
3
];
DihedralTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
ExpressionProgram
&
forceExpression
)
:
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
p4
(
atoms
[
3
]),
forceExpression
(
forceExpression
)
{
}
};
#endif // __ReferenceCustomManyParticleIxn_H__
platforms/reference/include/ReferenceKernels.h
View file @
e1a378b7
...
@@ -44,6 +44,7 @@ class CpuGBVI;
...
@@ -44,6 +44,7 @@ class CpuGBVI;
class
ReferenceAndersenThermostat
;
class
ReferenceAndersenThermostat
;
class
ReferenceCustomCompoundBondIxn
;
class
ReferenceCustomCompoundBondIxn
;
class
ReferenceCustomHbondIxn
;
class
ReferenceCustomHbondIxn
;
class
ReferenceCustomManyParticleIxn
;
class
ReferenceBrownianDynamics
;
class
ReferenceBrownianDynamics
;
class
ReferenceStochasticDynamics
;
class
ReferenceStochasticDynamics
;
class
ReferenceConstraintAlgorithm
;
class
ReferenceConstraintAlgorithm
;
...
@@ -861,6 +862,46 @@ private:
...
@@ -861,6 +862,46 @@ private:
std
::
vector
<
std
::
string
>
globalParameterNames
;
std
::
vector
<
std
::
string
>
globalParameterNames
;
};
};
/**
* This kernel is invoked by CustomManyParticleForce to calculate the forces acting on the system and the energy of the system.
*/
class
ReferenceCalcCustomManyParticleForceKernel
:
public
CalcCustomManyParticleForceKernel
{
public:
ReferenceCalcCustomManyParticleForceKernel
(
std
::
string
name
,
const
Platform
&
platform
)
:
CalcCustomManyParticleForceKernel
(
name
,
platform
),
ixn
(
NULL
)
{
}
~
ReferenceCalcCustomManyParticleForceKernel
();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the CustomManyParticleForce this kernel will be used for
*/
void
initialize
(
const
System
&
system
,
const
CustomManyParticleForce
&
force
);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @return the potential energy due to the force
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the CustomManyParticleForce to copy the parameters from
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomManyParticleForce
&
force
);
private:
int
numParticles
;
RealOpenMM
cutoffDistance
;
RealOpenMM
**
particleParamArray
;
ReferenceCustomManyParticleIxn
*
ixn
;
std
::
vector
<
std
::
string
>
globalParameterNames
;
NonbondedMethod
nonbondedMethod
;
};
/**
/**
* This kernel is invoked by VerletIntegrator to take one time step.
* This kernel is invoked by VerletIntegrator to take one time step.
*/
*/
...
...
platforms/reference/src/ReferenceKernelFactory.cpp
View file @
e1a378b7
...
@@ -80,6 +80,8 @@ KernelImpl* ReferenceKernelFactory::createKernelImpl(std::string name, const Pla
...
@@ -80,6 +80,8 @@ KernelImpl* ReferenceKernelFactory::createKernelImpl(std::string name, const Pla
return
new
ReferenceCalcCustomHbondForceKernel
(
name
,
platform
);
return
new
ReferenceCalcCustomHbondForceKernel
(
name
,
platform
);
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
return
new
ReferenceCalcCustomCompoundBondForceKernel
(
name
,
platform
);
return
new
ReferenceCalcCustomCompoundBondForceKernel
(
name
,
platform
);
if
(
name
==
CalcCustomManyParticleForceKernel
::
Name
())
return
new
ReferenceCalcCustomManyParticleForceKernel
(
name
,
platform
);
if
(
name
==
IntegrateVerletStepKernel
::
Name
())
if
(
name
==
IntegrateVerletStepKernel
::
Name
())
return
new
ReferenceIntegrateVerletStepKernel
(
name
,
platform
,
data
);
return
new
ReferenceIntegrateVerletStepKernel
(
name
,
platform
,
data
);
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
...
...
platforms/reference/src/ReferenceKernels.cpp
View file @
e1a378b7
...
@@ -47,6 +47,7 @@
...
@@ -47,6 +47,7 @@
#include "ReferenceCustomGBIxn.h"
#include "ReferenceCustomGBIxn.h"
#include "ReferenceCustomHbondIxn.h"
#include "ReferenceCustomHbondIxn.h"
#include "ReferenceCustomNonbondedIxn.h"
#include "ReferenceCustomNonbondedIxn.h"
#include "ReferenceCustomManyParticleIxn.h"
#include "ReferenceCustomTorsionIxn.h"
#include "ReferenceCustomTorsionIxn.h"
#include "ReferenceHarmonicBondIxn.h"
#include "ReferenceHarmonicBondIxn.h"
#include "ReferenceLJCoulomb14.h"
#include "ReferenceLJCoulomb14.h"
...
@@ -67,6 +68,7 @@
...
@@ -67,6 +68,7 @@
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "openmm/internal/CMAPTorsionForceImpl.h"
#include "openmm/internal/CMAPTorsionForceImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
...
@@ -1615,6 +1617,91 @@ void ReferenceCalcCustomCompoundBondForceKernel::copyParametersToContext(Context
...
@@ -1615,6 +1617,91 @@ void ReferenceCalcCustomCompoundBondForceKernel::copyParametersToContext(Context
}
}
}
}
ReferenceCalcCustomManyParticleForceKernel
::~
ReferenceCalcCustomManyParticleForceKernel
()
{
disposeRealArray
(
particleParamArray
,
numParticles
);
if
(
ixn
!=
NULL
)
delete
ixn
;
}
void
ReferenceCalcCustomManyParticleForceKernel
::
initialize
(
const
System
&
system
,
const
CustomManyParticleForce
&
force
)
{
// Build the arrays.
numParticles
=
system
.
getNumParticles
();
int
numParticleParameters
=
force
.
getNumPerParticleParameters
();
particleParamArray
=
allocateRealArray
(
numParticles
,
numParticleParameters
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
vector
<
double
>
parameters
;
int
type
;
force
.
getParticleParameters
(
i
,
parameters
,
type
);
for
(
int
j
=
0
;
j
<
numParticleParameters
;
j
++
)
particleParamArray
[
i
][
j
]
=
parameters
[
j
];
}
// Create custom functions for the tabulated functions.
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
for
(
int
i
=
0
;
i
<
force
.
getNumTabulatedFunctions
();
i
++
)
functions
[
force
.
getTabulatedFunctionName
(
i
)]
=
createReferenceTabulatedFunction
(
force
.
getTabulatedFunction
(
i
));
// Parse the expression and create the object used to calculate the interaction.
map
<
string
,
vector
<
int
>
>
distances
;
map
<
string
,
vector
<
int
>
>
angles
;
map
<
string
,
vector
<
int
>
>
dihedrals
;
Lepton
::
ParsedExpression
energyExpression
=
CustomManyParticleForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
vector
<
string
>
particleParameterNames
;
for
(
int
i
=
0
;
i
<
numParticleParameters
;
i
++
)
particleParameterNames
.
push_back
(
force
.
getPerParticleParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
ixn
=
new
ReferenceCustomManyParticleIxn
(
force
.
getNumParticlesPerSet
(),
energyExpression
,
particleParameterNames
,
distances
,
angles
,
dihedrals
);
nonbondedMethod
=
CalcCustomManyParticleForceKernel
::
NonbondedMethod
(
force
.
getNonbondedMethod
());
cutoffDistance
=
force
.
getCutoffDistance
();
if
(
nonbondedMethod
!=
NoCutoff
)
ixn
->
setUseCutoff
(
cutoffDistance
);
// Delete the custom functions.
for
(
map
<
string
,
Lepton
::
CustomFunction
*>::
iterator
iter
=
functions
.
begin
();
iter
!=
functions
.
end
();
iter
++
)
delete
iter
->
second
;
}
double
ReferenceCalcCustomManyParticleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealOpenMM
energy
=
0
;
map
<
string
,
double
>
globalParameters
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
if
(
nonbondedMethod
==
CutoffPeriodic
)
{
RealVec
&
box
=
extractBoxSize
(
context
);
double
minAllowedSize
=
2
*
cutoffDistance
;
if
(
box
[
0
]
<
minAllowedSize
||
box
[
1
]
<
minAllowedSize
||
box
[
2
]
<
minAllowedSize
)
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
ixn
->
setPeriodic
(
box
);
}
ixn
->
calculateIxn
(
posData
,
particleParamArray
,
globalParameters
,
forceData
,
includeEnergy
?
&
energy
:
NULL
);
return
energy
;
}
void
ReferenceCalcCustomManyParticleForceKernel
::
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomManyParticleForce
&
force
)
{
if
(
numParticles
!=
force
.
getNumParticles
())
throw
OpenMMException
(
"updateParametersInContext: The number of particles has changed"
);
// Record the values.
int
numParameters
=
force
.
getNumPerParticleParameters
();
vector
<
double
>
params
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
vector
<
double
>
parameters
;
int
type
;
force
.
getParticleParameters
(
i
,
parameters
,
type
);
for
(
int
j
=
0
;
j
<
numParameters
;
j
++
)
particleParamArray
[
i
][
j
]
=
static_cast
<
RealOpenMM
>
(
parameters
[
j
]);
}
}
ReferenceIntegrateVerletStepKernel
::~
ReferenceIntegrateVerletStepKernel
()
{
ReferenceIntegrateVerletStepKernel
::~
ReferenceIntegrateVerletStepKernel
()
{
if
(
dynamics
)
if
(
dynamics
)
delete
dynamics
;
delete
dynamics
;
...
...
platforms/reference/src/ReferencePlatform.cpp
View file @
e1a378b7
...
@@ -63,6 +63,7 @@ ReferencePlatform::ReferencePlatform() {
...
@@ -63,6 +63,7 @@ ReferencePlatform::ReferencePlatform() {
registerKernelFactory
(
CalcCustomExternalForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomExternalForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomHbondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomHbondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCompoundBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCompoundBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateBrownianStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateBrownianStepKernel
::
Name
(),
factory
);
...
...
platforms/reference/src/SimTKReference/ReferenceBondIxn.cpp
View file @
e1a378b7
...
@@ -105,7 +105,7 @@ ReferenceBondIxn::~ReferenceBondIxn( ){
...
@@ -105,7 +105,7 @@ ReferenceBondIxn::~ReferenceBondIxn( ){
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
RealOpenMM
ReferenceBondIxn
::
getNormedDotProduct
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
RealOpenMM
ReferenceBondIxn
::
getNormedDotProduct
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
int
hasREntry
=
0
)
const
{
int
hasREntry
=
0
)
{
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
...
@@ -187,7 +187,7 @@ RealOpenMM ReferenceBondIxn::getNormedDotProduct( RealOpenMM* vector1, RealOpenM
...
@@ -187,7 +187,7 @@ RealOpenMM ReferenceBondIxn::getNormedDotProduct( RealOpenMM* vector1, RealOpenM
RealOpenMM
ReferenceBondIxn
::
getAngleBetweenTwoVectors
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
RealOpenMM
ReferenceBondIxn
::
getAngleBetweenTwoVectors
(
RealOpenMM
*
vector1
,
RealOpenMM
*
vector2
,
RealOpenMM
*
outputDotProduct
=
NULL
,
RealOpenMM
*
outputDotProduct
=
NULL
,
int
hasREntry
=
0
)
const
{
int
hasREntry
=
0
)
{
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
...
@@ -249,7 +249,7 @@ RealOpenMM ReferenceBondIxn::getDihedralAngleBetweenThreeVectors( RealOpenMM* v
...
@@ -249,7 +249,7 @@ RealOpenMM ReferenceBondIxn::getDihedralAngleBetweenThreeVectors( RealOpenMM* v
RealOpenMM
*
cosineOfAngle
=
NULL
,
RealOpenMM
*
cosineOfAngle
=
NULL
,
RealOpenMM
*
signVector
=
NULL
,
RealOpenMM
*
signVector
=
NULL
,
RealOpenMM
*
signOfAngle
=
NULL
,
RealOpenMM
*
signOfAngle
=
NULL
,
int
hasREntry
=
0
)
const
{
int
hasREntry
=
0
)
{
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
...
...
platforms/reference/src/SimTKReference/ReferenceCustomManyParticleIxn.cpp
0 → 100644
View file @
e1a378b7
/* Portions copyright (c) 2009-2014 Stanford University and Simbios.
* Contributors: Peter Eastman
*
* 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.
*/
#include <string.h>
#include <sstream>
#include <utility>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
#include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h"
#include "ReferenceCustomManyParticleIxn.h"
using
std
::
map
;
using
std
::
pair
;
using
std
::
string
;
using
std
::
stringstream
;
using
std
::
vector
;
using
OpenMM
::
RealVec
;
ReferenceCustomManyParticleIxn
::
ReferenceCustomManyParticleIxn
(
int
numParticlesPerSet
,
const
Lepton
::
ParsedExpression
&
energyExpression
,
const
vector
<
string
>&
particleParameterNames
,
const
map
<
string
,
vector
<
int
>
>&
distances
,
const
map
<
string
,
vector
<
int
>
>&
angles
,
const
map
<
string
,
vector
<
int
>
>&
dihedrals
)
:
numParticlesPerSet
(
numParticlesPerSet
),
energyExpression
(
energyExpression
.
createProgram
()),
useCutoff
(
false
),
usePeriodic
(
false
)
{
particleParamNames
.
resize
(
numParticlesPerSet
);
numPerParticleParameters
=
particleParameterNames
.
size
();
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
(
ReferenceCustomManyParticleIxn
::
ParticleTermInfo
(
xname
.
str
(),
i
,
0
,
energyExpression
.
differentiate
(
xname
.
str
()).
optimize
().
createProgram
()));
particleTerms
.
push_back
(
ReferenceCustomManyParticleIxn
::
ParticleTermInfo
(
yname
.
str
(),
i
,
1
,
energyExpression
.
differentiate
(
yname
.
str
()).
optimize
().
createProgram
()));
particleTerms
.
push_back
(
ReferenceCustomManyParticleIxn
::
ParticleTermInfo
(
zname
.
str
(),
i
,
2
,
energyExpression
.
differentiate
(
zname
.
str
()).
optimize
().
createProgram
()));
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
{
stringstream
paramname
;
paramname
<<
particleParameterNames
[
j
]
<<
(
i
+
1
);
particleParamNames
[
i
].
push_back
(
paramname
.
str
());
}
}
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
)
distanceTerms
.
push_back
(
ReferenceCustomManyParticleIxn
::
DistanceTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpression
.
differentiate
(
iter
->
first
).
optimize
().
createProgram
()));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
)
angleTerms
.
push_back
(
ReferenceCustomManyParticleIxn
::
AngleTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpression
.
differentiate
(
iter
->
first
).
optimize
().
createProgram
()));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
)
dihedralTerms
.
push_back
(
ReferenceCustomManyParticleIxn
::
DihedralTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpression
.
differentiate
(
iter
->
first
).
optimize
().
createProgram
()));
}
ReferenceCustomManyParticleIxn
::~
ReferenceCustomManyParticleIxn
(
){
}
void
ReferenceCustomManyParticleIxn
::
calculateIxn
(
vector
<
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
const
map
<
string
,
double
>&
globalParameters
,
vector
<
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
{
map
<
string
,
double
>
variables
=
globalParameters
;
vector
<
int
>
particles
(
numParticlesPerSet
);
loopOverInteractions
(
particles
,
0
,
atomCoordinates
,
particleParameters
,
variables
,
forces
,
totalEnergy
);
}
void
ReferenceCustomManyParticleIxn
::
setUseCutoff
(
RealOpenMM
distance
)
{
useCutoff
=
true
;
cutoffDistance
=
distance
;
}
void
ReferenceCustomManyParticleIxn
::
setPeriodic
(
RealVec
&
boxSize
)
{
assert
(
cutoff
);
assert
(
boxSize
[
0
]
>=
2.0
*
cutoffDistance
);
assert
(
boxSize
[
1
]
>=
2.0
*
cutoffDistance
);
assert
(
boxSize
[
2
]
>=
2.0
*
cutoffDistance
);
usePeriodic
=
true
;
periodicBoxSize
[
0
]
=
boxSize
[
0
];
periodicBoxSize
[
1
]
=
boxSize
[
1
];
periodicBoxSize
[
2
]
=
boxSize
[
2
];
}
void
ReferenceCustomManyParticleIxn
::
loopOverInteractions
(
vector
<
int
>&
particles
,
int
loopIndex
,
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
RealOpenMM
**
particleParameters
,
map
<
string
,
double
>&
variables
,
vector
<
OpenMM
::
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
{
int
numParticles
=
atomCoordinates
.
size
();
int
start
=
(
loopIndex
==
0
?
0
:
particles
[
loopIndex
-
1
]
+
1
);
for
(
int
i
=
start
;
i
<
numParticles
;
i
++
)
{
particles
[
loopIndex
]
=
i
;
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
variables
[
particleParamNames
[
loopIndex
][
j
]]
=
particleParameters
[
i
][
j
];
if
(
loopIndex
==
numParticlesPerSet
-
1
)
calculateOneIxn
(
particles
,
atomCoordinates
,
variables
,
forces
,
totalEnergy
);
else
loopOverInteractions
(
particles
,
loopIndex
+
1
,
atomCoordinates
,
particleParameters
,
variables
,
forces
,
totalEnergy
);
}
}
void
ReferenceCustomManyParticleIxn
::
calculateOneIxn
(
const
vector
<
int
>&
particles
,
vector
<
RealVec
>&
atomCoordinates
,
map
<
string
,
double
>&
variables
,
vector
<
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
{
// Compute all of the variables the energy can depend on.
for
(
int
i
=
0
;
i
<
(
int
)
particleTerms
.
size
();
i
++
)
{
const
ParticleTermInfo
&
term
=
particleTerms
[
i
];
variables
[
term
.
name
]
=
atomCoordinates
[
term
.
atom
][
term
.
component
];
}
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
computeDelta
(
particles
[
term
.
p1
],
particles
[
term
.
p2
],
term
.
delta
,
atomCoordinates
);
variables
[
term
.
name
]
=
term
.
delta
[
ReferenceForce
::
RIndex
];
if
(
useCutoff
&&
term
.
delta
[
ReferenceForce
::
RIndex
]
>
cutoffDistance
)
return
;
}
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
computeDelta
(
particles
[
term
.
p1
],
particles
[
term
.
p2
],
term
.
delta1
,
atomCoordinates
);
computeDelta
(
particles
[
term
.
p3
],
particles
[
term
.
p2
],
term
.
delta2
,
atomCoordinates
);
variables
[
term
.
name
]
=
computeAngle
(
term
.
delta1
,
term
.
delta2
);
}
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
computeDelta
(
particles
[
term
.
p2
],
particles
[
term
.
p1
],
term
.
delta1
,
atomCoordinates
);
computeDelta
(
particles
[
term
.
p2
],
particles
[
term
.
p3
],
term
.
delta2
,
atomCoordinates
);
computeDelta
(
particles
[
term
.
p4
],
particles
[
term
.
p3
],
term
.
delta3
,
atomCoordinates
);
RealOpenMM
dotDihedral
,
signOfDihedral
;
RealOpenMM
*
crossProduct
[]
=
{
term
.
cross1
,
term
.
cross2
};
variables
[
term
.
name
]
=
ReferenceBondIxn
::
getDihedralAngleBetweenThreeVectors
(
term
.
delta1
,
term
.
delta2
,
term
.
delta3
,
crossProduct
,
&
dotDihedral
,
term
.
delta1
,
&
signOfDihedral
,
1
);
}
// Apply forces based on individual particle coordinates.
for
(
int
i
=
0
;
i
<
(
int
)
particleTerms
.
size
();
i
++
)
{
const
ParticleTermInfo
&
term
=
particleTerms
[
i
];
forces
[
particles
[
term
.
atom
]][
term
.
component
]
-=
term
.
forceExpression
.
evaluate
(
variables
);
}
// Apply forces based on distances.
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
RealOpenMM
dEdR
=
(
RealOpenMM
)
(
term
.
forceExpression
.
evaluate
(
variables
)
/
(
term
.
delta
[
ReferenceForce
::
RIndex
]));
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
RealOpenMM
force
=
-
dEdR
*
term
.
delta
[
i
];
forces
[
particles
[
term
.
p1
]][
i
]
-=
force
;
forces
[
particles
[
term
.
p2
]][
i
]
+=
force
;
}
}
// Apply forces based on angles.
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
(
variables
);
RealOpenMM
thetaCross
[
ReferenceForce
::
LastDeltaRIndex
];
SimTKOpenMMUtilities
::
crossProductVector3
(
term
.
delta1
,
term
.
delta2
,
thetaCross
);
RealOpenMM
lengthThetaCross
=
SQRT
(
DOT3
(
thetaCross
,
thetaCross
));
if
(
lengthThetaCross
<
1.0e-06
)
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
[
particles
[
term
.
p1
]][
i
]
+=
deltaCrossP
[
0
][
i
];
forces
[
particles
[
term
.
p2
]][
i
]
+=
deltaCrossP
[
1
][
i
];
forces
[
particles
[
term
.
p3
]][
i
]
+=
deltaCrossP
[
2
][
i
];
}
}
// Apply forces based on dihedrals.
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
(
variables
);
RealOpenMM
internalF
[
4
][
3
];
RealOpenMM
forceFactors
[
4
];
RealOpenMM
normCross1
=
DOT3
(
term
.
cross1
,
term
.
cross1
);
RealOpenMM
normBC
=
term
.
delta2
[
ReferenceForce
::
RIndex
];
forceFactors
[
0
]
=
(
-
dEdTheta
*
normBC
)
/
normCross1
;
RealOpenMM
normCross2
=
DOT3
(
term
.
cross2
,
term
.
cross2
);
forceFactors
[
3
]
=
(
dEdTheta
*
normBC
)
/
normCross2
;
forceFactors
[
1
]
=
DOT3
(
term
.
delta1
,
term
.
delta2
);
forceFactors
[
1
]
/=
term
.
delta2
[
ReferenceForce
::
R2Index
];
forceFactors
[
2
]
=
DOT3
(
term
.
delta3
,
term
.
delta2
);
forceFactors
[
2
]
/=
term
.
delta2
[
ReferenceForce
::
R2Index
];
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
internalF
[
0
][
i
]
=
forceFactors
[
0
]
*
term
.
cross1
[
i
];
internalF
[
3
][
i
]
=
forceFactors
[
3
]
*
term
.
cross2
[
i
];
RealOpenMM
s
=
forceFactors
[
1
]
*
internalF
[
0
][
i
]
-
forceFactors
[
2
]
*
internalF
[
3
][
i
];
internalF
[
1
][
i
]
=
internalF
[
0
][
i
]
-
s
;
internalF
[
2
][
i
]
=
internalF
[
3
][
i
]
+
s
;
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
forces
[
particles
[
term
.
p1
]][
i
]
+=
internalF
[
0
][
i
];
forces
[
particles
[
term
.
p2
]][
i
]
-=
internalF
[
1
][
i
];
forces
[
particles
[
term
.
p3
]][
i
]
-=
internalF
[
2
][
i
];
forces
[
particles
[
term
.
p4
]][
i
]
+=
internalF
[
3
][
i
];
}
}
// Add the energy
if
(
totalEnergy
)
*
totalEnergy
+=
(
RealOpenMM
)
energyExpression
.
evaluate
(
variables
);
}
void
ReferenceCustomManyParticleIxn
::
computeDelta
(
int
atom1
,
int
atom2
,
RealOpenMM
*
delta
,
vector
<
RealVec
>&
atomCoordinates
)
const
{
if
(
usePeriodic
)
ReferenceForce
::
getDeltaRPeriodic
(
atomCoordinates
[
atom1
],
atomCoordinates
[
atom2
],
periodicBoxSize
,
delta
);
else
ReferenceForce
::
getDeltaR
(
atomCoordinates
[
atom1
],
atomCoordinates
[
atom2
],
delta
);
}
RealOpenMM
ReferenceCustomManyParticleIxn
::
computeAngle
(
RealOpenMM
*
vec1
,
RealOpenMM
*
vec2
)
{
RealOpenMM
dot
=
DOT3
(
vec1
,
vec2
);
RealOpenMM
cosine
=
dot
/
SQRT
((
vec1
[
ReferenceForce
::
R2Index
]
*
vec2
[
ReferenceForce
::
R2Index
]));
RealOpenMM
angle
;
if
(
cosine
>=
1
)
angle
=
0
;
else
if
(
cosine
<=
-
1
)
angle
=
PI_M
;
else
angle
=
ACOS
(
cosine
);
return
angle
;
}
platforms/reference/tests/TestReferenceCustomManyParticleForce.cpp
0 → 100644
View file @
e1a378b7
/* -------------------------------------------------------------------------- *
* 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 reference 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 "ReferencePlatform.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
const
double
TOL
=
1e-5
;
void
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
);
ReferencePlatform
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
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
);
ReferencePlatform
platform
;
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// See if the energy is correct.
State
state1
=
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
,
state1
.
getPotentialEnergy
(),
1e-5
);
}
int
main
()
{
try
{
testNoCutoff
();
testCutoff
();
testPeriodic
();
testParameters
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment