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
7cdd6d16
Commit
7cdd6d16
authored
Jun 28, 2017
by
peastman
Committed by
GitHub
Jun 28, 2017
Browse files
Merge pull request #1837 from peastman/cv
Created CustomCVForce
parents
ad5cc98c
711c3a5a
Changes
54
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1085 additions
and
59 deletions
+1085
-59
docs-source/usersguide/theory.rst
docs-source/usersguide/theory.rst
+15
-0
olla/include/openmm/Platform.h
olla/include/openmm/Platform.h
+8
-0
olla/include/openmm/kernels.h
olla/include/openmm/kernels.h
+38
-0
olla/src/Platform.cpp
olla/src/Platform.cpp
+11
-0
openmmapi/include/OpenMM.h
openmmapi/include/OpenMM.h
+2
-1
openmmapi/include/openmm/Context.h
openmmapi/include/openmm/Context.h
+3
-0
openmmapi/include/openmm/CustomCVForce.h
openmmapi/include/openmm/CustomCVForce.h
+320
-0
openmmapi/include/openmm/internal/ContextImpl.h
openmmapi/include/openmm/internal/ContextImpl.h
+12
-1
openmmapi/include/openmm/internal/CustomCVForceImpl.h
openmmapi/include/openmm/internal/CustomCVForceImpl.h
+77
-0
openmmapi/include/openmm/internal/ForceImpl.h
openmmapi/include/openmm/internal/ForceImpl.h
+8
-0
openmmapi/src/Context.cpp
openmmapi/src/Context.cpp
+10
-0
openmmapi/src/ContextImpl.cpp
openmmapi/src/ContextImpl.cpp
+17
-7
openmmapi/src/CustomCVForce.cpp
openmmapi/src/CustomCVForce.cpp
+160
-0
openmmapi/src/CustomCVForceImpl.cpp
openmmapi/src/CustomCVForceImpl.cpp
+110
-0
platforms/cuda/include/CudaContext.h
platforms/cuda/include/CudaContext.h
+9
-1
platforms/cuda/include/CudaKernels.h
platforms/cuda/include/CudaKernels.h
+49
-0
platforms/cuda/include/CudaPlatform.h
platforms/cuda/include/CudaPlatform.h
+2
-1
platforms/cuda/src/CudaContext.cpp
platforms/cuda/src/CudaContext.cpp
+60
-33
platforms/cuda/src/CudaKernelFactory.cpp
platforms/cuda/src/CudaKernelFactory.cpp
+2
-0
platforms/cuda/src/CudaKernels.cpp
platforms/cuda/src/CudaKernels.cpp
+172
-15
No files found.
docs-source/usersguide/theory.rst
View file @
7cdd6d16
...
@@ -1158,6 +1158,21 @@ specified in three ways:
...
@@ -1158,6 +1158,21 @@ specified in three ways:
* Per-donor parameters are defined by specifying a value for each donor group.
* Per-donor parameters are defined by specifying a value for each donor group.
* Per-acceptor parameters are defined by specifying a value for each acceptor group.
* Per-acceptor parameters are defined by specifying a value for each acceptor group.
CustomCVForce
*************
CustomCVForce computes an energy as a function of "collective variables". A
collective variable may be any scalar valued function of the particle positions
and other parameters. Each one is defined by a :code:`Force` object, so any
function that can be defined via any force class (either standard or custom) can
be used as a collective variable. The energy is then computed as
.. math::
E=f(...)
where *f*\ (...) is a user supplied mathematical expression of the collective
variables. It also may depend on user defined global parameters.
.. _writing-custom-expressions:
.. _writing-custom-expressions:
...
...
olla/include/openmm/Platform.h
View file @
7cdd6d16
...
@@ -127,6 +127,14 @@ public:
...
@@ -127,6 +127,14 @@ public:
* @param properties a set of values for platform-specific properties. Keys are the property names.
* @param properties a set of values for platform-specific properties. Keys are the property names.
*/
*/
virtual
void
contextCreated
(
ContextImpl
&
context
,
const
std
::
map
<
std
::
string
,
std
::
string
>&
properties
)
const
;
virtual
void
contextCreated
(
ContextImpl
&
context
,
const
std
::
map
<
std
::
string
,
std
::
string
>&
properties
)
const
;
/**
* This is called whenever a new Context is created using ContextImpl::createLinkedContext(). It gives the
* Platform a chance to initialize the context and store platform-specific data in it.
*
* @param context the newly created context
* @param originalContext the original context it is linked to
*/
virtual
void
linkedContextCreated
(
ContextImpl
&
context
,
ContextImpl
&
originalContext
)
const
;
/**
/**
* This is called whenever a Context is deleted. It gives the Platform a chance to clean up
* This is called whenever a Context is deleted. It gives the Platform a chance to clean up
* any platform-specific data that was stored in it.
* any platform-specific data that was stored in it.
...
...
olla/include/openmm/kernels.h
View file @
7cdd6d16
...
@@ -39,6 +39,7 @@
...
@@ -39,6 +39,7 @@
#include "openmm/CustomAngleForce.h"
#include "openmm/CustomAngleForce.h"
#include "openmm/CustomBondForce.h"
#include "openmm/CustomBondForce.h"
#include "openmm/CustomCentroidBondForce.h"
#include "openmm/CustomCentroidBondForce.h"
#include "openmm/CustomCVForce.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/CustomGBForce.h"
#include "openmm/CustomGBForce.h"
...
@@ -943,6 +944,43 @@ public:
...
@@ -943,6 +944,43 @@ public:
virtual
void
copyParametersToContext
(
ContextImpl
&
context
,
const
GayBerneForce
&
force
)
=
0
;
virtual
void
copyParametersToContext
(
ContextImpl
&
context
,
const
GayBerneForce
&
force
)
=
0
;
};
};
/**
* This kernel is invoked by CustomCVForce to calculate the forces acting on the system and the energy of the system.
*/
class
CalcCustomCVForceKernel
:
public
KernelImpl
{
public:
static
std
::
string
Name
()
{
return
"CalcCustomCVForce"
;
}
CalcCustomCVForceKernel
(
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 CustomCVForce this kernel will be used for
* @param innerContext the context created by the CustomCVForce for computing collective variables
*/
virtual
void
initialize
(
const
System
&
system
,
const
CustomCVForce
&
force
,
ContextImpl
&
innerContext
)
=
0
;
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param innerContext the context created by the CustomCVForce for computing collective variables
* @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
,
ContextImpl
&
innerContext
,
bool
includeForces
,
bool
includeEnergy
)
=
0
;
/**
* Copy state information to the inner context.
*
* @param context the context in which to execute this kernel
* @param innerContext the context created by the CustomCVForce for computing collective variables
*/
virtual
void
copyState
(
ContextImpl
&
context
,
ContextImpl
&
innerContext
)
=
0
;
};
/**
/**
* This kernel is invoked by VerletIntegrator to take one time step.
* This kernel is invoked by VerletIntegrator to take one time step.
*/
*/
...
...
olla/src/Platform.cpp
View file @
7cdd6d16
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
#include "openmm/OpenMMException.h"
#include "openmm/OpenMMException.h"
#include "openmm/Kernel.h"
#include "openmm/Kernel.h"
#include "openmm/KernelFactory.h"
#include "openmm/KernelFactory.h"
#include "openmm/internal/ContextImpl.h"
#ifdef WIN32
#ifdef WIN32
#include <windows.h>
#include <windows.h>
#include <sstream>
#include <sstream>
...
@@ -113,6 +114,16 @@ void Platform::setPropertyDefaultValue(const string& property, const string& val
...
@@ -113,6 +114,16 @@ void Platform::setPropertyDefaultValue(const string& property, const string& val
void
Platform
::
contextCreated
(
ContextImpl
&
context
,
const
map
<
string
,
string
>&
properties
)
const
{
void
Platform
::
contextCreated
(
ContextImpl
&
context
,
const
map
<
string
,
string
>&
properties
)
const
{
}
}
void
Platform
::
linkedContextCreated
(
ContextImpl
&
context
,
ContextImpl
&
originalContext
)
const
{
// The default implementation just copies over the properties and calls contextCreated().
// Subclasses may override this to do something different.
map
<
string
,
string
>
properties
;
for
(
auto
&
name
:
getPropertyNames
())
properties
[
name
]
=
getPropertyValue
(
originalContext
.
getOwner
(),
name
);
contextCreated
(
context
,
properties
);
}
void
Platform
::
contextDestroyed
(
ContextImpl
&
context
)
const
{
void
Platform
::
contextDestroyed
(
ContextImpl
&
context
)
const
{
}
}
...
...
openmmapi/include/OpenMM.h
View file @
7cdd6d16
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2009-201
6
Stanford University and the Authors. *
* Portions copyright (c) 2009-201
7
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -43,6 +43,7 @@
...
@@ -43,6 +43,7 @@
#include "openmm/CustomAngleForce.h"
#include "openmm/CustomAngleForce.h"
#include "openmm/CustomTorsionForce.h"
#include "openmm/CustomTorsionForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/CustomCVForce.h"
#include "openmm/CustomGBForce.h"
#include "openmm/CustomGBForce.h"
#include "openmm/CustomHbondForce.h"
#include "openmm/CustomHbondForce.h"
#include "openmm/CustomIntegrator.h"
#include "openmm/CustomIntegrator.h"
...
...
openmmapi/include/openmm/Context.h
View file @
7cdd6d16
...
@@ -263,8 +263,11 @@ public:
...
@@ -263,8 +263,11 @@ public:
*/
*/
const
std
::
vector
<
std
::
vector
<
int
>
>&
getMolecules
()
const
;
const
std
::
vector
<
std
::
vector
<
int
>
>&
getMolecules
()
const
;
private:
private:
friend
class
ContextImpl
;
friend
class
Force
;
friend
class
Force
;
friend
class
ForceImpl
;
friend
class
Platform
;
friend
class
Platform
;
Context
(
const
System
&
system
,
Integrator
&
integrator
,
ContextImpl
&
linked
);
ContextImpl
&
getImpl
();
ContextImpl
&
getImpl
();
const
ContextImpl
&
getImpl
()
const
;
const
ContextImpl
&
getImpl
()
const
;
ContextImpl
*
impl
;
ContextImpl
*
impl
;
...
...
openmmapi/include/openmm/CustomCVForce.h
0 → 100644
View file @
7cdd6d16
#ifndef OPENMM_CUSTOMCVFORCE_H_
#define OPENMM_CUSTOMCVFORCE_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-2017 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 "Force.h"
#include "TabulatedFunction.h"
#include "internal/windowsExport.h"
#include <string>
#include <vector>
namespace
OpenMM
{
/**
* This class supports energy functions that depend on collective variables. To use it,
* you define a set of collective variables (scalar valued functions that depend on the
* particle positions), and an algebraic expression for the energy as a function of the
* collective variables. The expression also may involve tabulated functions, and may
* depend on arbitrary global parameters.
*
* Each collective variable is defined by a Force object. The Force's potential energy
* is computed, and that becomes the value of the variable. This provides enormous
* flexibility in defining collective variables, especially by using custom forces.
* Anything that can be computed as a potential function can also be used as a collective
* variable.
*
* To use this class, create a CustomCVForce object, passing an algebraic expression to the
* constructor that defines the potential energy. Then call addCollectiveVariable() to define
* collective variables and addGlobalParameter() to define global parameters. The values
* of global parameters may be modified during a simulation by calling Context::setParameter().
*
* This class also has the ability to compute derivatives of the potential energy with respect to global parameters.
* Call addEnergyParameterDerivative() to request that the derivative with respect to a particular parameter be
* computed. You can then query its value in a Context by calling getState() on it.
*
* Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following
* functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions
* are defined in radians, and log is the natural logarithm. step(x) = 0 if x is less than 0, 1 otherwise. delta(x) = 1 if x is 0, 0 otherwise.
* select(x,y,z) = z if x = 0, y otherwise.
*
* In addition, you can call addTabulatedFunction() to define a new function based on tabulated values. You specify the function by
* creating a TabulatedFunction object. That function can then appear in the expression.
*/
class
OPENMM_EXPORT
CustomCVForce
:
public
Force
{
public:
/**
* Create a CustomCVForce.
*
* @param energy an algebraic expression giving the energy of the system as a function
* of the collective variables and global parameters
*/
explicit
CustomCVForce
(
const
std
::
string
&
energy
);
~
CustomCVForce
();
/**
* Get the number of collective variables that the interaction depends on.
*/
int
getNumCollectiveVariables
()
const
{
return
variables
.
size
();
}
/**
* Get the number of global parameters that the interaction depends on.
*/
int
getNumGlobalParameters
()
const
{
return
globalParameters
.
size
();
}
/**
* Get the number of global parameters with respect to which the derivative of the energy
* should be computed.
*/
int
getNumEnergyParameterDerivatives
()
const
{
return
energyParameterDerivatives
.
size
();
}
/**
* Get the number of tabulated functions that have been defined.
*/
int
getNumTabulatedFunctions
()
const
{
return
functions
.
size
();
}
/**
* Get the algebraic expression that gives the energy of the system
*/
const
std
::
string
&
getEnergyFunction
()
const
;
/**
* Set the algebraic expression that gives the energy of the system
*/
void
setEnergyFunction
(
const
std
::
string
&
energy
);
/**
* Add a collective variable that the force may depend on. The collective variable
* is represented by a Force object, which should have been created on the heap with the
* "new" operator. The CustomCVForce takes over ownership of it, and deletes the Force when the
* CustomCVForce itself is deleted.
*
* @param name the name of the collective variable, as it will appear in the energy expression
* @param variable the collective variable, represented by a Force object. The value of the
* variable is the energy computed by the Force.
* @return the index within the Force of the variable that was added
*/
int
addCollectiveVariable
(
const
std
::
string
&
name
,
Force
*
variable
);
/**
* Get the name of a collective variable.
*
* @param index the index of the collective variable for which to get the name
* @return the variable name
*/
const
std
::
string
&
getCollectiveVariableName
(
int
index
)
const
;
/**
* Get a writable reference to the Force object that computes a collective variable.
*
* @param index the index of the collective variable to get
* @return the Force object
*/
Force
&
getCollectiveVariable
(
int
index
);
/**
* Get a const reference to the Force object that computes a collective variable.
*
* @param index the index of the collective variable to get
* @return the Force object
*/
const
Force
&
getCollectiveVariable
(
int
index
)
const
;
/**
* Add a new global parameter that the interaction may depend on.
*
* @param name the name of the parameter
* @param defaultValue the default value of the parameter
* @return the index of the parameter that was added
*/
int
addGlobalParameter
(
const
std
::
string
&
name
,
double
defaultValue
);
/**
* Get the name of a global parameter.
*
* @param index the index of the parameter for which to get the name
* @return the parameter name
*/
const
std
::
string
&
getGlobalParameterName
(
int
index
)
const
;
/**
* Set the name of a global parameter.
*
* @param index the index of the parameter for which to set the name
* @param name the name of the parameter
*/
void
setGlobalParameterName
(
int
index
,
const
std
::
string
&
name
);
/**
* Get the default value of a global parameter.
*
* @param index the index of the parameter for which to get the default value
* @return the parameter default value
*/
double
getGlobalParameterDefaultValue
(
int
index
)
const
;
/**
* Set the default value of a global parameter.
*
* @param index the index of the parameter for which to set the default value
* @param defaultValue the default value of the parameter
*/
void
setGlobalParameterDefaultValue
(
int
index
,
double
defaultValue
);
/**
* Request that this Force compute the derivative of its energy with respect to a global parameter.
* The parameter must have already been added with addGlobalParameter().
*
* @param name the name of the parameter
*/
void
addEnergyParameterDerivative
(
const
std
::
string
&
name
);
/**
* Get the name of a global parameter with respect to which this Force should compute the
* derivative of the energy.
*
* @param index the index of the parameter derivative, between 0 and getNumEnergyParameterDerivatives()
* @return the parameter name
*/
const
std
::
string
&
getEnergyParameterDerivativeName
(
int
index
)
const
;
/**
* Add a tabulated function that may appear in the energy expression.
*
* @param name the name of the function as it appears in expressions
* @param function a TabulatedFunction object defining the function. The TabulatedFunction
* should have been created on the heap with the "new" operator. The
* Force takes over ownership of it, and deletes it when the Force itself is deleted.
* @return the index of the function that was added
*/
int
addTabulatedFunction
(
const
std
::
string
&
name
,
TabulatedFunction
*
function
);
/**
* Get a const reference to a tabulated function that may appear in the energy expression.
*
* @param index the index of the function to get
* @return the TabulatedFunction object defining the function
*/
const
TabulatedFunction
&
getTabulatedFunction
(
int
index
)
const
;
/**
* Get a reference to a tabulated function that may appear in the energy expression.
*
* @param index the index of the function to get
* @return the TabulatedFunction object defining the function
*/
TabulatedFunction
&
getTabulatedFunction
(
int
index
);
/**
* Get the name of a tabulated function that may appear in the energy expression.
*
* @param index the index of the function to get
* @return the name of the function as it appears in expressions
*/
const
std
::
string
&
getTabulatedFunctionName
(
int
index
)
const
;
/**
* Get the current values of the collective variables in a Context.
*
* @param context the Context for which to get the values
* @param[out] values the values of the collective variables are computed and
* stored into this
*/
void
getCollectiveVariableValues
(
Context
&
context
,
std
::
vector
<
double
>&
values
);
/**
* Get the inner Context used for evaluating collective variables.
*
* When you create a Context for a System that contains a CustomCVForce, internally
* it creates a new System, adds the Forces that define the CVs to it, creates a new
* Context for that System, and uses it to evaluate the variables. In most cases you
* can ignore all of this. It is just an implementation detail. However, there are
* a few cases where you need to directly access that internal Context. For example,
* if you want to modify one of the Forces that defines a collective variable and
* call updateParametersInContext() on it, you need to pass that inner Context to it.
* This method returns a reference to it.
*
* @param context the Context containing the CustomCVForce
* @return the inner Context used to evaluate the collective variables
*/
Context
&
getInnerContext
(
Context
&
context
);
/**
* Returns whether or not this force makes use of periodic boundary
* conditions.
*
* @returns true if force uses PBC and false otherwise
*/
bool
usesPeriodicBoundaryConditions
()
const
;
protected:
ForceImpl
*
createImpl
()
const
;
private:
class
GlobalParameterInfo
;
class
VariableInfo
;
class
FunctionInfo
;
std
::
string
energyExpression
;
std
::
vector
<
GlobalParameterInfo
>
globalParameters
;
std
::
vector
<
VariableInfo
>
variables
;
std
::
vector
<
FunctionInfo
>
functions
;
std
::
vector
<
int
>
energyParameterDerivatives
;
};
/**
* This is an internal class used to record information about a global parameter.
* @private
*/
class
CustomCVForce
::
GlobalParameterInfo
{
public:
std
::
string
name
;
double
defaultValue
;
GlobalParameterInfo
()
{
}
GlobalParameterInfo
(
const
std
::
string
&
name
,
double
defaultValue
)
:
name
(
name
),
defaultValue
(
defaultValue
)
{
}
};
/**
* This is an internal class used to record information about a tabulated function.
* @private
*/
class
CustomCVForce
::
VariableInfo
{
public:
std
::
string
name
;
Force
*
variable
;
VariableInfo
()
{
}
VariableInfo
(
const
std
::
string
&
name
,
Force
*
variable
)
:
name
(
name
),
variable
(
variable
)
{
}
};
/**
* This is an internal class used to record information about a tabulated function.
* @private
*/
class
CustomCVForce
::
FunctionInfo
{
public:
std
::
string
name
;
TabulatedFunction
*
function
;
FunctionInfo
()
{
}
FunctionInfo
(
const
std
::
string
&
name
,
TabulatedFunction
*
function
)
:
name
(
name
),
function
(
function
)
{
}
};
}
// namespace OpenMM
#endif
/*OPENMM_CUSTOMCVFORCE_H_*/
openmmapi/include/openmm/internal/ContextImpl.h
View file @
7cdd6d16
...
@@ -55,7 +55,8 @@ public:
...
@@ -55,7 +55,8 @@ public:
/**
/**
* Create an ContextImpl for a Context;
* Create an ContextImpl for a Context;
*/
*/
ContextImpl
(
Context
&
owner
,
const
System
&
system
,
Integrator
&
integrator
,
Platform
*
platform
,
const
std
::
map
<
std
::
string
,
std
::
string
>&
properties
);
ContextImpl
(
Context
&
owner
,
const
System
&
system
,
Integrator
&
integrator
,
Platform
*
platform
,
const
std
::
map
<
std
::
string
,
std
::
string
>&
properties
,
ContextImpl
*
originalContext
=
NULL
);
~
ContextImpl
();
~
ContextImpl
();
/**
/**
* Get the Context for which this is the implementation.
* Get the Context for which this is the implementation.
...
@@ -264,8 +265,18 @@ public:
...
@@ -264,8 +265,18 @@ public:
* you should never call it. It is exposed here because the same logic is useful to other classes too.
* you should never call it. It is exposed here because the same logic is useful to other classes too.
*/
*/
static
std
::
vector
<
std
::
vector
<
int
>
>
findMolecules
(
int
numParticles
,
std
::
vector
<
std
::
vector
<
int
>
>&
particleBonds
);
static
std
::
vector
<
std
::
vector
<
int
>
>
findMolecules
(
int
numParticles
,
std
::
vector
<
std
::
vector
<
int
>
>&
particleBonds
);
/**
* Create a new Context based on this one. The new context will use the same Platform, device, and property
* values as this one. With the CUDA and OpenCL platforms, it also shares the same GPU context, allowing data
* to be transferred between them without leaving the GPU.
*
* This method exists for very specialized purposes. If you aren't certain whether you should use it, that probably
* means you shouldn't.
*/
Context
*
createLinkedContext
(
const
System
&
system
,
Integrator
&
integrator
);
private:
private:
friend
class
Context
;
friend
class
Context
;
void
initialize
();
Context
&
owner
;
Context
&
owner
;
const
System
&
system
;
const
System
&
system
;
Integrator
&
integrator
;
Integrator
&
integrator
;
...
...
openmmapi/include/openmm/internal/CustomCVForceImpl.h
0 → 100644
View file @
7cdd6d16
#ifndef OPENMM_CUSTOMCVFORCEIMPL_H_
#define OPENMM_CUSTOMCVFORCEIMPL_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-2017 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/Context.h"
#include "openmm/CustomCVForce.h"
#include "openmm/Kernel.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include <map>
#include <string>
#include <vector>
namespace
OpenMM
{
/**
* This is the internal implementation of CustomCVForce.
*/
class
OPENMM_EXPORT
CustomCVForceImpl
:
public
ForceImpl
{
public:
CustomCVForceImpl
(
const
CustomCVForce
&
owner
);
~
CustomCVForceImpl
();
void
initialize
(
ContextImpl
&
context
);
const
CustomCVForce
&
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
getCollectiveVariableValues
(
ContextImpl
&
context
,
std
::
vector
<
double
>&
values
);
Context
&
getInnerContext
();
private:
const
CustomCVForce
&
owner
;
Kernel
kernel
;
System
innerSystem
;
VerletIntegrator
innerIntegrator
;
Context
*
innerContext
;
};
}
// namespace OpenMM
#endif
/*OPENMM_CUSTOMCVFORCEIMPL_H_*/
openmmapi/include/openmm/internal/ForceImpl.h
View file @
7cdd6d16
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "openmm/Context.h"
#include "openmm/internal/windowsExport.h"
#include "openmm/internal/windowsExport.h"
#include <map>
#include <map>
#include <string>
#include <string>
...
@@ -104,6 +105,13 @@ public:
...
@@ -104,6 +105,13 @@ public:
virtual
std
::
vector
<
std
::
pair
<
int
,
int
>
>
getBondedParticles
()
const
{
virtual
std
::
vector
<
std
::
pair
<
int
,
int
>
>
getBondedParticles
()
const
{
return
std
::
vector
<
std
::
pair
<
int
,
int
>
>
(
0
);
return
std
::
vector
<
std
::
pair
<
int
,
int
>
>
(
0
);
}
}
protected:
/**
* Get the ContextImpl corresponding to a Context.
*/
ContextImpl
&
getContextImpl
(
Context
&
context
)
{
return
context
.
getImpl
();
}
};
};
}
// namespace OpenMM
}
// namespace OpenMM
...
...
openmmapi/src/Context.cpp
View file @
7cdd6d16
...
@@ -40,16 +40,25 @@
...
@@ -40,16 +40,25 @@
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
Context
::
Context
(
const
System
&
system
,
Integrator
&
integrator
,
ContextImpl
&
linked
)
:
properties
(
linked
.
getOwner
().
properties
)
{
// This is used by ContextImpl::createLinkedContext().
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
&
linked
.
getPlatform
(),
properties
,
&
linked
);
impl
->
initialize
();
}
Context
::
Context
(
const
System
&
system
,
Integrator
&
integrator
)
:
properties
(
map
<
string
,
string
>
())
{
Context
::
Context
(
const
System
&
system
,
Integrator
&
integrator
)
:
properties
(
map
<
string
,
string
>
())
{
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
0
,
properties
);
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
0
,
properties
);
impl
->
initialize
();
}
}
Context
::
Context
(
const
System
&
system
,
Integrator
&
integrator
,
Platform
&
platform
)
:
properties
(
map
<
string
,
string
>
())
{
Context
::
Context
(
const
System
&
system
,
Integrator
&
integrator
,
Platform
&
platform
)
:
properties
(
map
<
string
,
string
>
())
{
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
&
platform
,
properties
);
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
&
platform
,
properties
);
impl
->
initialize
();
}
}
Context
::
Context
(
const
System
&
system
,
Integrator
&
integrator
,
Platform
&
platform
,
const
map
<
string
,
string
>&
properties
)
:
properties
(
properties
)
{
Context
::
Context
(
const
System
&
system
,
Integrator
&
integrator
,
Platform
&
platform
,
const
map
<
string
,
string
>&
properties
)
:
properties
(
properties
)
{
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
&
platform
,
properties
);
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
&
platform
,
properties
);
impl
->
initialize
();
}
}
Context
::~
Context
()
{
Context
::~
Context
()
{
...
@@ -240,6 +249,7 @@ void Context::reinitialize() {
...
@@ -240,6 +249,7 @@ void Context::reinitialize() {
integrator
.
cleanup
();
integrator
.
cleanup
();
delete
impl
;
delete
impl
;
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
&
platform
,
properties
);
impl
=
new
ContextImpl
(
*
this
,
system
,
integrator
,
&
platform
,
properties
);
impl
->
initialize
();
}
}
void
Context
::
createCheckpoint
(
ostream
&
stream
)
{
void
Context
::
createCheckpoint
(
ostream
&
stream
)
{
...
...
openmmapi/src/ContextImpl.cpp
View file @
7cdd6d16
...
@@ -53,7 +53,7 @@ using namespace std;
...
@@ -53,7 +53,7 @@ using namespace std;
const
static
char
CHECKPOINT_MAGIC_BYTES
[]
=
"OpenMM Binary Checkpoint
\n
"
;
const
static
char
CHECKPOINT_MAGIC_BYTES
[]
=
"OpenMM Binary Checkpoint
\n
"
;
ContextImpl
::
ContextImpl
(
Context
&
owner
,
const
System
&
system
,
Integrator
&
integrator
,
Platform
*
platform
,
const
map
<
string
,
string
>&
properties
)
:
ContextImpl
::
ContextImpl
(
Context
&
owner
,
const
System
&
system
,
Integrator
&
integrator
,
Platform
*
platform
,
const
map
<
string
,
string
>&
properties
,
ContextImpl
*
originalContext
)
:
owner
(
owner
),
system
(
system
),
integrator
(
integrator
),
hasInitializedForces
(
false
),
hasSetPositions
(
false
),
integratorIsDeleted
(
false
),
owner
(
owner
),
system
(
system
),
integrator
(
integrator
),
hasInitializedForces
(
false
),
hasSetPositions
(
false
),
integratorIsDeleted
(
false
),
lastForceGroups
(
-
1
),
platform
(
platform
),
platformData
(
NULL
)
{
lastForceGroups
(
-
1
),
platform
(
platform
),
platformData
(
NULL
)
{
int
numParticles
=
system
.
getNumParticles
();
int
numParticles
=
system
.
getNumParticles
();
...
@@ -119,8 +119,6 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
...
@@ -119,8 +119,6 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
kernelNames
.
push_back
(
VirtualSitesKernel
::
Name
());
kernelNames
.
push_back
(
VirtualSitesKernel
::
Name
());
for
(
int
i
=
0
;
i
<
system
.
getNumForces
();
++
i
)
{
for
(
int
i
=
0
;
i
<
system
.
getNumForces
();
++
i
)
{
forceImpls
.
push_back
(
system
.
getForce
(
i
).
createImpl
());
forceImpls
.
push_back
(
system
.
getForce
(
i
).
createImpl
());
map
<
string
,
double
>
forceParameters
=
forceImpls
[
forceImpls
.
size
()
-
1
]
->
getDefaultParameters
();
parameters
.
insert
(
forceParameters
.
begin
(),
forceParameters
.
end
());
vector
<
string
>
forceKernels
=
forceImpls
[
forceImpls
.
size
()
-
1
]
->
getKernelNames
();
vector
<
string
>
forceKernels
=
forceImpls
[
forceImpls
.
size
()
-
1
]
->
getKernelNames
();
kernelNames
.
insert
(
kernelNames
.
begin
(),
forceKernels
.
begin
(),
forceKernels
.
end
());
kernelNames
.
insert
(
kernelNames
.
begin
(),
forceKernels
.
begin
(),
forceKernels
.
end
());
}
}
...
@@ -154,7 +152,10 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
...
@@ -154,7 +152,10 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
for
(
int
i
=
candidatePlatforms
.
size
()
-
1
;
i
>=
0
;
i
--
)
{
for
(
int
i
=
candidatePlatforms
.
size
()
-
1
;
i
>=
0
;
i
--
)
{
try
{
try
{
this
->
platform
=
platform
=
candidatePlatforms
[
i
].
second
;
this
->
platform
=
platform
=
candidatePlatforms
[
i
].
second
;
if
(
originalContext
==
NULL
)
platform
->
contextCreated
(
*
this
,
validatedProperties
);
platform
->
contextCreated
(
*
this
,
validatedProperties
);
else
platform
->
linkedContextCreated
(
*
this
,
*
originalContext
);
break
;
break
;
}
}
catch
(...)
{
catch
(...)
{
...
@@ -163,7 +164,9 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
...
@@ -163,7 +164,9 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
throw
;
throw
;
}
}
}
}
}
void
ContextImpl
::
initialize
()
{
// Create and initialize kernels and other objects.
// Create and initialize kernels and other objects.
initializeForcesKernel
=
platform
->
createKernel
(
CalcForcesAndEnergyKernel
::
Name
(),
*
this
);
initializeForcesKernel
=
platform
->
createKernel
(
CalcForcesAndEnergyKernel
::
Name
(),
*
this
);
...
@@ -177,10 +180,13 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
...
@@ -177,10 +180,13 @@ ContextImpl::ContextImpl(Context& owner, const System& system, Integrator& integ
Vec3
periodicBoxVectors
[
3
];
Vec3
periodicBoxVectors
[
3
];
system
.
getDefaultPeriodicBoxVectors
(
periodicBoxVectors
[
0
],
periodicBoxVectors
[
1
],
periodicBoxVectors
[
2
]);
system
.
getDefaultPeriodicBoxVectors
(
periodicBoxVectors
[
0
],
periodicBoxVectors
[
1
],
periodicBoxVectors
[
2
]);
updateStateDataKernel
.
getAs
<
UpdateStateDataKernel
>
().
setPeriodicBoxVectors
(
*
this
,
periodicBoxVectors
[
0
],
periodicBoxVectors
[
1
],
periodicBoxVectors
[
2
]);
updateStateDataKernel
.
getAs
<
UpdateStateDataKernel
>
().
setPeriodicBoxVectors
(
*
this
,
periodicBoxVectors
[
0
],
periodicBoxVectors
[
1
],
periodicBoxVectors
[
2
]);
for
(
size_t
i
=
0
;
i
<
forceImpls
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
forceImpls
.
size
();
++
i
)
{
forceImpls
[
i
]
->
initialize
(
*
this
);
forceImpls
[
i
]
->
initialize
(
*
this
);
map
<
string
,
double
>
forceParameters
=
forceImpls
[
i
]
->
getDefaultParameters
();
parameters
.
insert
(
forceParameters
.
begin
(),
forceParameters
.
end
());
}
integrator
.
initialize
(
*
this
);
integrator
.
initialize
(
*
this
);
updateStateDataKernel
.
getAs
<
UpdateStateDataKernel
>
().
setVelocities
(
*
this
,
vector
<
Vec3
>
(
n
umParticles
));
updateStateDataKernel
.
getAs
<
UpdateStateDataKernel
>
().
setVelocities
(
*
this
,
vector
<
Vec3
>
(
system
.
getN
umParticles
()
));
}
}
ContextImpl
::~
ContextImpl
()
{
ContextImpl
::~
ContextImpl
()
{
...
@@ -478,3 +484,7 @@ void ContextImpl::loadCheckpoint(istream& stream) {
...
@@ -478,3 +484,7 @@ void ContextImpl::loadCheckpoint(istream& stream) {
void
ContextImpl
::
systemChanged
()
{
void
ContextImpl
::
systemChanged
()
{
integrator
.
stateChanged
(
State
::
Energy
);
integrator
.
stateChanged
(
State
::
Energy
);
}
}
Context
*
ContextImpl
::
createLinkedContext
(
const
System
&
system
,
Integrator
&
integrator
)
{
return
new
Context
(
system
,
integrator
,
*
this
);
}
openmmapi/src/CustomCVForce.cpp
0 → 100644
View file @
7cdd6d16
/* -------------------------------------------------------------------------- *
* 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-2017 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/CustomCVForce.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/CustomCVForceImpl.h"
#include <cmath>
#include <map>
#include <set>
#include <utility>
using
namespace
OpenMM
;
using
namespace
std
;
CustomCVForce
::
CustomCVForce
(
const
string
&
energy
)
:
energyExpression
(
energy
)
{
}
CustomCVForce
::~
CustomCVForce
()
{
for
(
auto
variable
:
variables
)
delete
variable
.
variable
;
for
(
auto
function
:
functions
)
delete
function
.
function
;
}
const
string
&
CustomCVForce
::
getEnergyFunction
()
const
{
return
energyExpression
;
}
void
CustomCVForce
::
setEnergyFunction
(
const
std
::
string
&
energy
)
{
energyExpression
=
energy
;
}
int
CustomCVForce
::
addCollectiveVariable
(
const
std
::
string
&
name
,
Force
*
variable
)
{
if
(
variables
.
size
()
>=
32
)
throw
OpenMMException
(
"CustomCVForce cannot have more than 32 collective variables"
);
variables
.
push_back
(
VariableInfo
(
name
,
variable
));
return
variables
.
size
()
-
1
;
}
const
string
&
CustomCVForce
::
getCollectiveVariableName
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
variables
);
return
variables
[
index
].
name
;
}
Force
&
CustomCVForce
::
getCollectiveVariable
(
int
index
)
{
ASSERT_VALID_INDEX
(
index
,
variables
);
return
*
variables
[
index
].
variable
;
}
const
Force
&
CustomCVForce
::
getCollectiveVariable
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
variables
);
return
*
variables
[
index
].
variable
;
}
int
CustomCVForce
::
addGlobalParameter
(
const
string
&
name
,
double
defaultValue
)
{
globalParameters
.
push_back
(
GlobalParameterInfo
(
name
,
defaultValue
));
return
globalParameters
.
size
()
-
1
;
}
const
string
&
CustomCVForce
::
getGlobalParameterName
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
return
globalParameters
[
index
].
name
;
}
void
CustomCVForce
::
setGlobalParameterName
(
int
index
,
const
string
&
name
)
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
globalParameters
[
index
].
name
=
name
;
}
double
CustomCVForce
::
getGlobalParameterDefaultValue
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
return
globalParameters
[
index
].
defaultValue
;
}
void
CustomCVForce
::
setGlobalParameterDefaultValue
(
int
index
,
double
defaultValue
)
{
ASSERT_VALID_INDEX
(
index
,
globalParameters
);
globalParameters
[
index
].
defaultValue
=
defaultValue
;
}
void
CustomCVForce
::
addEnergyParameterDerivative
(
const
string
&
name
)
{
for
(
int
i
=
0
;
i
<
globalParameters
.
size
();
i
++
)
if
(
name
==
globalParameters
[
i
].
name
)
{
energyParameterDerivatives
.
push_back
(
i
);
return
;
}
throw
OpenMMException
(
string
(
"addEnergyParameterDerivative: Unknown global parameter '"
+
name
+
"'"
));
}
const
string
&
CustomCVForce
::
getEnergyParameterDerivativeName
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
energyParameterDerivatives
);
return
globalParameters
[
energyParameterDerivatives
[
index
]].
name
;
}
int
CustomCVForce
::
addTabulatedFunction
(
const
std
::
string
&
name
,
TabulatedFunction
*
function
)
{
functions
.
push_back
(
FunctionInfo
(
name
,
function
));
return
functions
.
size
()
-
1
;
}
const
TabulatedFunction
&
CustomCVForce
::
getTabulatedFunction
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
functions
);
return
*
functions
[
index
].
function
;
}
TabulatedFunction
&
CustomCVForce
::
getTabulatedFunction
(
int
index
)
{
ASSERT_VALID_INDEX
(
index
,
functions
);
return
*
functions
[
index
].
function
;
}
const
string
&
CustomCVForce
::
getTabulatedFunctionName
(
int
index
)
const
{
ASSERT_VALID_INDEX
(
index
,
functions
);
return
functions
[
index
].
name
;
}
void
CustomCVForce
::
getCollectiveVariableValues
(
Context
&
context
,
vector
<
double
>&
values
)
{
dynamic_cast
<
CustomCVForceImpl
&>
(
getImplInContext
(
context
)).
getCollectiveVariableValues
(
getContextImpl
(
context
),
values
);
}
ForceImpl
*
CustomCVForce
::
createImpl
()
const
{
return
new
CustomCVForceImpl
(
*
this
);
}
Context
&
CustomCVForce
::
getInnerContext
(
Context
&
context
)
{
return
dynamic_cast
<
CustomCVForceImpl
&>
(
getImplInContext
(
context
)).
getInnerContext
();
}
bool
CustomCVForce
::
usesPeriodicBoundaryConditions
()
const
{
for
(
auto
&
variable
:
variables
)
if
(
variable
.
variable
->
usesPeriodicBoundaryConditions
())
return
true
;
return
false
;
}
openmmapi/src/CustomCVForceImpl.cpp
0 → 100644
View file @
7cdd6d16
/* -------------------------------------------------------------------------- *
* 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-2017 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/NonbondedForce.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/CustomCVForceImpl.h"
#include "openmm/kernels.h"
#include "openmm/serialization/XmlSerializer.h"
#include <map>
using
namespace
OpenMM
;
using
namespace
std
;
CustomCVForceImpl
::
CustomCVForceImpl
(
const
CustomCVForce
&
owner
)
:
owner
(
owner
),
innerIntegrator
(
1.0
),
innerContext
(
NULL
)
{
}
CustomCVForceImpl
::~
CustomCVForceImpl
()
{
if
(
innerContext
!=
NULL
)
delete
innerContext
;
}
void
CustomCVForceImpl
::
initialize
(
ContextImpl
&
context
)
{
// Construct the inner system used to evaluate collective variables.
const
System
&
system
=
context
.
getSystem
();
for
(
int
i
=
0
;
i
<
system
.
getNumParticles
();
i
++
)
innerSystem
.
addParticle
(
system
.
getParticleMass
(
i
));
for
(
int
i
=
0
;
i
<
owner
.
getNumCollectiveVariables
();
i
++
)
{
Force
*
variable
=
XmlSerializer
::
clone
<
Force
>
(
owner
.
getCollectiveVariable
(
i
));
variable
->
setForceGroup
(
i
);
NonbondedForce
*
nonbonded
=
dynamic_cast
<
NonbondedForce
*>
(
variable
);
if
(
nonbonded
!=
NULL
)
nonbonded
->
setReciprocalSpaceForceGroup
(
-
1
);
innerSystem
.
addForce
(
variable
);
}
// Create the inner context.
innerContext
=
context
.
createLinkedContext
(
innerSystem
,
innerIntegrator
);
vector
<
Vec3
>
positions
(
system
.
getNumParticles
(),
Vec3
());
innerContext
->
setPositions
(
positions
);
// Create the kernel.
kernel
=
context
.
getPlatform
().
createKernel
(
CalcCustomCVForceKernel
::
Name
(),
context
);
kernel
.
getAs
<
CalcCustomCVForceKernel
>
().
initialize
(
context
.
getSystem
(),
owner
,
getContextImpl
(
*
innerContext
));
}
double
CustomCVForceImpl
::
calcForcesAndEnergy
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
,
int
groups
)
{
if
((
groups
&
(
1
<<
owner
.
getForceGroup
()))
!=
0
)
return
kernel
.
getAs
<
CalcCustomCVForceKernel
>
().
execute
(
context
,
getContextImpl
(
*
innerContext
),
includeForces
,
includeEnergy
);
return
0.0
;
}
vector
<
string
>
CustomCVForceImpl
::
getKernelNames
()
{
vector
<
string
>
names
;
names
.
push_back
(
CalcCustomCVForceKernel
::
Name
());
return
names
;
}
map
<
string
,
double
>
CustomCVForceImpl
::
getDefaultParameters
()
{
map
<
string
,
double
>
parameters
;
parameters
.
insert
(
innerContext
->
getParameters
().
begin
(),
innerContext
->
getParameters
().
end
());
for
(
int
i
=
0
;
i
<
owner
.
getNumGlobalParameters
();
i
++
)
parameters
[
owner
.
getGlobalParameterName
(
i
)]
=
owner
.
getGlobalParameterDefaultValue
(
i
);
return
parameters
;
}
void
CustomCVForceImpl
::
getCollectiveVariableValues
(
ContextImpl
&
context
,
vector
<
double
>&
values
)
{
kernel
.
getAs
<
CalcCustomCVForceKernel
>
().
copyState
(
context
,
getContextImpl
(
*
innerContext
));
values
.
clear
();
for
(
int
i
=
0
;
i
<
innerSystem
.
getNumForces
();
i
++
)
{
double
value
=
innerContext
->
getState
(
State
::
Energy
,
false
,
1
<<
i
).
getPotentialEnergy
();
values
.
push_back
(
value
);
}
}
Context
&
CustomCVForceImpl
::
getInnerContext
()
{
return
*
innerContext
;
}
platforms/cuda/include/CudaContext.h
View file @
7cdd6d16
...
@@ -77,7 +77,8 @@ public:
...
@@ -77,7 +77,8 @@ public:
static
const
int
ThreadBlockSize
;
static
const
int
ThreadBlockSize
;
static
const
int
TileSize
;
static
const
int
TileSize
;
CudaContext
(
const
System
&
system
,
int
deviceIndex
,
bool
useBlockingSync
,
const
std
::
string
&
precision
,
CudaContext
(
const
System
&
system
,
int
deviceIndex
,
bool
useBlockingSync
,
const
std
::
string
&
precision
,
const
std
::
string
&
compiler
,
const
std
::
string
&
tempDir
,
const
std
::
string
&
hostCompiler
,
CudaPlatform
::
PlatformData
&
platformData
);
const
std
::
string
&
compiler
,
const
std
::
string
&
tempDir
,
const
std
::
string
&
hostCompiler
,
CudaPlatform
::
PlatformData
&
platformData
,
CudaContext
*
originalContext
);
~
CudaContext
();
~
CudaContext
();
/**
/**
* This is called to initialize internal data structures after all Forces in the system
* This is called to initialize internal data structures after all Forces in the system
...
@@ -284,6 +285,10 @@ public:
...
@@ -284,6 +285,10 @@ public:
* Clear all buffers that have been registered with addAutoclearBuffer().
* Clear all buffers that have been registered with addAutoclearBuffer().
*/
*/
void
clearAutoclearBuffers
();
void
clearAutoclearBuffers
();
/**
* Sum the buffer containing energy.
*/
double
reduceEnergy
();
/**
/**
* Get the current simulation time.
* Get the current simulation time.
*/
*/
...
@@ -622,6 +627,7 @@ private:
...
@@ -622,6 +627,7 @@ private:
int
numAtomBlocks
;
int
numAtomBlocks
;
int
numThreadBlocks
;
int
numThreadBlocks
;
bool
useBlockingSync
,
useDoublePrecision
,
useMixedPrecision
,
contextIsValid
,
atomsWereReordered
,
boxIsTriclinic
,
hasCompilerKernel
,
isNvccAvailable
,
forcesValid
;
bool
useBlockingSync
,
useDoublePrecision
,
useMixedPrecision
,
contextIsValid
,
atomsWereReordered
,
boxIsTriclinic
,
hasCompilerKernel
,
isNvccAvailable
,
forcesValid
;
bool
isLinkedContext
;
std
::
string
compiler
,
tempDir
,
cacheDir
,
gpuArchitecture
;
std
::
string
compiler
,
tempDir
,
cacheDir
,
gpuArchitecture
;
float4
periodicBoxVecXFloat
,
periodicBoxVecYFloat
,
periodicBoxVecZFloat
,
periodicBoxSizeFloat
,
invPeriodicBoxSizeFloat
;
float4
periodicBoxVecXFloat
,
periodicBoxVecYFloat
,
periodicBoxVecZFloat
,
periodicBoxSizeFloat
,
invPeriodicBoxSizeFloat
;
double4
periodicBoxVecX
,
periodicBoxVecY
,
periodicBoxVecZ
,
periodicBoxSize
,
invPeriodicBoxSize
;
double4
periodicBoxVecX
,
periodicBoxVecY
,
periodicBoxVecZ
,
periodicBoxSize
,
invPeriodicBoxSize
;
...
@@ -636,6 +642,7 @@ private:
...
@@ -636,6 +642,7 @@ private:
CUfunction
clearFourBuffersKernel
;
CUfunction
clearFourBuffersKernel
;
CUfunction
clearFiveBuffersKernel
;
CUfunction
clearFiveBuffersKernel
;
CUfunction
clearSixBuffersKernel
;
CUfunction
clearSixBuffersKernel
;
CUfunction
reduceEnergyKernel
;
CUfunction
setChargesKernel
;
CUfunction
setChargesKernel
;
std
::
vector
<
CudaForceInfo
*>
forces
;
std
::
vector
<
CudaForceInfo
*>
forces
;
std
::
vector
<
Molecule
>
molecules
;
std
::
vector
<
Molecule
>
molecules
;
...
@@ -647,6 +654,7 @@ private:
...
@@ -647,6 +654,7 @@ private:
CudaArray
*
velm
;
CudaArray
*
velm
;
CudaArray
*
force
;
CudaArray
*
force
;
CudaArray
*
energyBuffer
;
CudaArray
*
energyBuffer
;
CudaArray
*
energySum
;
CudaArray
*
energyParamDerivBuffer
;
CudaArray
*
energyParamDerivBuffer
;
CudaArray
*
atomIndexDevice
;
CudaArray
*
atomIndexDevice
;
CudaArray
*
chargeBuffer
;
CudaArray
*
chargeBuffer
;
...
...
platforms/cuda/include/CudaKernels.h
View file @
7cdd6d16
...
@@ -38,6 +38,7 @@
...
@@ -38,6 +38,7 @@
#include "openmm/internal/CompiledExpressionSet.h"
#include "openmm/internal/CompiledExpressionSet.h"
#include "openmm/internal/CustomIntegratorUtilities.h"
#include "openmm/internal/CustomIntegratorUtilities.h"
#include "lepton/CompiledExpression.h"
#include "lepton/CompiledExpression.h"
#include "lepton/ExpressionProgram.h"
#include <cufft.h>
#include <cufft.h>
namespace
OpenMM
{
namespace
OpenMM
{
...
@@ -1229,6 +1230,54 @@ private:
...
@@ -1229,6 +1230,54 @@ private:
CUevent
event
;
CUevent
event
;
};
};
/**
* This kernel is invoked by CustomCVForce to calculate the forces acting on the system and the energy of the system.
*/
class
CudaCalcCustomCVForceKernel
:
public
CalcCustomCVForceKernel
{
public:
CudaCalcCustomCVForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
CudaContext
&
cu
)
:
CalcCustomCVForceKernel
(
name
,
platform
),
cu
(
cu
),
hasInitializedListeners
(
false
),
invAtomOrder
(
NULL
),
innerInvAtomOrder
(
NULL
)
{
}
~
CudaCalcCustomCVForceKernel
();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the CustomCVForce this kernel will be used for
* @param innerContext the context created by the CustomCVForce for computing collective variables
*/
void
initialize
(
const
System
&
system
,
const
CustomCVForce
&
force
,
ContextImpl
&
innerContext
);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param innerContext the context created by the CustomCVForce for computing collective variables
* @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
,
ContextImpl
&
innerContext
,
bool
includeForces
,
bool
includeEnergy
);
/**
* Copy state information to the inner context.
*
* @param context the context in which to execute this kernel
* @param innerContext the context created by the CustomCVForce for computing collective variables
*/
void
copyState
(
ContextImpl
&
context
,
ContextImpl
&
innerContext
);
private:
class
ReorderListener
;
CudaContext
&
cu
;
bool
hasInitializedListeners
;
Lepton
::
ExpressionProgram
energyExpression
;
std
::
vector
<
std
::
string
>
variableNames
,
paramDerivNames
,
globalParameterNames
;
std
::
vector
<
Lepton
::
ExpressionProgram
>
variableDerivExpressions
;
std
::
vector
<
Lepton
::
ExpressionProgram
>
paramDerivExpressions
;
std
::
vector
<
CudaArray
*>
cvForces
;
CudaArray
*
invAtomOrder
;
CudaArray
*
innerInvAtomOrder
;
CUfunction
copyStateKernel
,
copyForcesKernel
,
addForcesKernel
;
};
/**
/**
* This kernel is invoked by VerletIntegrator to take one time step.
* This kernel is invoked by VerletIntegrator to take one time step.
*/
*/
...
...
platforms/cuda/include/CudaPlatform.h
View file @
7cdd6d16
...
@@ -53,6 +53,7 @@ public:
...
@@ -53,6 +53,7 @@ public:
const
std
::
string
&
getPropertyValue
(
const
Context
&
context
,
const
std
::
string
&
property
)
const
;
const
std
::
string
&
getPropertyValue
(
const
Context
&
context
,
const
std
::
string
&
property
)
const
;
void
setPropertyValue
(
Context
&
context
,
const
std
::
string
&
property
,
const
std
::
string
&
value
)
const
;
void
setPropertyValue
(
Context
&
context
,
const
std
::
string
&
property
,
const
std
::
string
&
value
)
const
;
void
contextCreated
(
ContextImpl
&
context
,
const
std
::
map
<
std
::
string
,
std
::
string
>&
properties
)
const
;
void
contextCreated
(
ContextImpl
&
context
,
const
std
::
map
<
std
::
string
,
std
::
string
>&
properties
)
const
;
void
linkedContextCreated
(
ContextImpl
&
context
,
ContextImpl
&
originalContext
)
const
;
void
contextDestroyed
(
ContextImpl
&
context
)
const
;
void
contextDestroyed
(
ContextImpl
&
context
)
const
;
/**
/**
* This is the name of the parameter for selecting which CUDA device or devices to use.
* This is the name of the parameter for selecting which CUDA device or devices to use.
...
@@ -130,7 +131,7 @@ class OPENMM_EXPORT_CUDA CudaPlatform::PlatformData {
...
@@ -130,7 +131,7 @@ class OPENMM_EXPORT_CUDA CudaPlatform::PlatformData {
public:
public:
PlatformData
(
ContextImpl
*
context
,
const
System
&
system
,
const
std
::
string
&
deviceIndexProperty
,
const
std
::
string
&
blockingProperty
,
const
std
::
string
&
precisionProperty
,
PlatformData
(
ContextImpl
*
context
,
const
System
&
system
,
const
std
::
string
&
deviceIndexProperty
,
const
std
::
string
&
blockingProperty
,
const
std
::
string
&
precisionProperty
,
const
std
::
string
&
cpuPmeProperty
,
const
std
::
string
&
compilerProperty
,
const
std
::
string
&
tempProperty
,
const
std
::
string
&
hostCompilerProperty
,
const
std
::
string
&
cpuPmeProperty
,
const
std
::
string
&
compilerProperty
,
const
std
::
string
&
tempProperty
,
const
std
::
string
&
hostCompilerProperty
,
const
std
::
string
&
pmeStreamProperty
,
const
std
::
string
&
deterministicForcesProperty
,
int
numThreads
);
const
std
::
string
&
pmeStreamProperty
,
const
std
::
string
&
deterministicForcesProperty
,
int
numThreads
,
ContextImpl
*
originalContext
);
~
PlatformData
();
~
PlatformData
();
void
initializeContexts
(
const
System
&
system
);
void
initializeContexts
(
const
System
&
system
);
void
syncContexts
();
void
syncContexts
();
...
...
platforms/cuda/src/CudaContext.cpp
View file @
7cdd6d16
...
@@ -106,9 +106,9 @@ static int executeInWindows(const string &command) {
...
@@ -106,9 +106,9 @@ static int executeInWindows(const string &command) {
#endif
#endif
CudaContext
::
CudaContext
(
const
System
&
system
,
int
deviceIndex
,
bool
useBlockingSync
,
const
string
&
precision
,
const
string
&
compiler
,
CudaContext
::
CudaContext
(
const
System
&
system
,
int
deviceIndex
,
bool
useBlockingSync
,
const
string
&
precision
,
const
string
&
compiler
,
const
string
&
tempDir
,
const
std
::
string
&
hostCompiler
,
CudaPlatform
::
PlatformData
&
platformData
)
:
system
(
system
),
currentStream
(
0
),
const
string
&
tempDir
,
const
std
::
string
&
hostCompiler
,
CudaPlatform
::
PlatformData
&
platformData
,
CudaContext
*
originalContext
)
:
system
(
system
),
currentStream
(
0
),
time
(
0.0
),
platformData
(
platformData
),
stepCount
(
0
),
computeForceCount
(
0
),
stepsSinceReorder
(
99999
),
contextIsValid
(
false
),
atomsWereReordered
(
false
),
hasCompilerKernel
(
false
),
isNvccAvailable
(
false
),
time
(
0.0
),
platformData
(
platformData
),
stepCount
(
0
),
computeForceCount
(
0
),
stepsSinceReorder
(
99999
),
contextIsValid
(
false
),
atomsWereReordered
(
false
),
hasCompilerKernel
(
false
),
isNvccAvailable
(
false
),
pinnedBuffer
(
NULL
),
posq
(
NULL
),
posqCorrection
(
NULL
),
velm
(
NULL
),
force
(
NULL
),
energyBuffer
(
NULL
),
energyParamDerivBuffer
(
NULL
),
atomIndexDevice
(
NULL
),
chargeBuffer
(
NULL
),
pinnedBuffer
(
NULL
),
posq
(
NULL
),
posqCorrection
(
NULL
),
velm
(
NULL
),
force
(
NULL
),
energyBuffer
(
NULL
),
energySum
(
NULL
),
energyParamDerivBuffer
(
NULL
),
atomIndexDevice
(
NULL
),
chargeBuffer
(
NULL
),
integration
(
NULL
),
expression
(
NULL
),
bonded
(
NULL
),
nonbonded
(
NULL
),
thread
(
NULL
)
{
integration
(
NULL
),
expression
(
NULL
),
bonded
(
NULL
),
nonbonded
(
NULL
),
thread
(
NULL
)
{
// Determine what compiler to use.
// Determine what compiler to use.
...
@@ -173,8 +173,10 @@ CudaContext::CudaContext(const System& system, int deviceIndex, bool useBlocking
...
@@ -173,8 +173,10 @@ CudaContext::CudaContext(const System& system, int deviceIndex, bool useBlocking
cacheDir
=
cacheDir
+
"/"
;
cacheDir
=
cacheDir
+
"/"
;
#endif
#endif
contextIndex
=
platformData
.
contexts
.
size
();
contextIndex
=
platformData
.
contexts
.
size
();
int
numDevices
;
string
errorMessage
=
"Error initializing Context"
;
string
errorMessage
=
"Error initializing Context"
;
if
(
originalContext
==
NULL
)
{
isLinkedContext
=
false
;
int
numDevices
;
CHECK_RESULT
(
cuDeviceGetCount
(
&
numDevices
));
CHECK_RESULT
(
cuDeviceGetCount
(
&
numDevices
));
if
(
deviceIndex
<
-
1
||
deviceIndex
>=
numDevices
)
if
(
deviceIndex
<
-
1
||
deviceIndex
>=
numDevices
)
throw
OpenMMException
(
"Illegal value for DeviceIndex: "
+
intToString
(
deviceIndex
));
throw
OpenMMException
(
"Illegal value for DeviceIndex: "
+
intToString
(
deviceIndex
));
...
@@ -207,6 +209,13 @@ CudaContext::CudaContext(const System& system, int deviceIndex, bool useBlocking
...
@@ -207,6 +209,13 @@ CudaContext::CudaContext(const System& system, int deviceIndex, bool useBlocking
throw
OpenMMException
(
"The requested CUDA device could not be loaded"
);
throw
OpenMMException
(
"The requested CUDA device could not be loaded"
);
else
else
throw
OpenMMException
(
"No compatible CUDA device is available"
);
throw
OpenMMException
(
"No compatible CUDA device is available"
);
}
else
{
isLinkedContext
=
true
;
context
=
originalContext
->
context
;
this
->
deviceIndex
=
originalContext
->
deviceIndex
;
this
->
device
=
originalContext
->
device
;
}
int
major
,
minor
;
int
major
,
minor
;
CHECK_RESULT
(
cuDeviceComputeCapability
(
&
major
,
&
minor
,
device
));
CHECK_RESULT
(
cuDeviceComputeCapability
(
&
major
,
&
minor
,
device
));
...
@@ -298,6 +307,7 @@ CudaContext::CudaContext(const System& system, int deviceIndex, bool useBlocking
...
@@ -298,6 +307,7 @@ CudaContext::CudaContext(const System& system, int deviceIndex, bool useBlocking
clearFourBuffersKernel
=
getKernel
(
utilities
,
"clearFourBuffers"
);
clearFourBuffersKernel
=
getKernel
(
utilities
,
"clearFourBuffers"
);
clearFiveBuffersKernel
=
getKernel
(
utilities
,
"clearFiveBuffers"
);
clearFiveBuffersKernel
=
getKernel
(
utilities
,
"clearFiveBuffers"
);
clearSixBuffersKernel
=
getKernel
(
utilities
,
"clearSixBuffers"
);
clearSixBuffersKernel
=
getKernel
(
utilities
,
"clearSixBuffers"
);
reduceEnergyKernel
=
getKernel
(
utilities
,
"reduceEnergy"
);
setChargesKernel
=
getKernel
(
utilities
,
"setCharges"
);
setChargesKernel
=
getKernel
(
utilities
,
"setCharges"
);
// Set defines based on the requested precision.
// Set defines based on the requested precision.
...
@@ -411,6 +421,8 @@ CudaContext::~CudaContext() {
...
@@ -411,6 +421,8 @@ CudaContext::~CudaContext() {
delete
force
;
delete
force
;
if
(
energyBuffer
!=
NULL
)
if
(
energyBuffer
!=
NULL
)
delete
energyBuffer
;
delete
energyBuffer
;
if
(
energySum
!=
NULL
)
delete
energySum
;
if
(
energyParamDerivBuffer
!=
NULL
)
if
(
energyParamDerivBuffer
!=
NULL
)
delete
energyParamDerivBuffer
;
delete
energyParamDerivBuffer
;
if
(
atomIndexDevice
!=
NULL
)
if
(
atomIndexDevice
!=
NULL
)
...
@@ -428,7 +440,7 @@ CudaContext::~CudaContext() {
...
@@ -428,7 +440,7 @@ CudaContext::~CudaContext() {
if
(
thread
!=
NULL
)
if
(
thread
!=
NULL
)
delete
thread
;
delete
thread
;
string
errorMessage
=
"Error deleting Context"
;
string
errorMessage
=
"Error deleting Context"
;
if
(
contextIsValid
)
{
if
(
contextIsValid
&&
!
isLinkedContext
)
{
cuProfilerStop
();
cuProfilerStop
();
CHECK_RESULT
(
cuCtxDestroy
(
context
));
CHECK_RESULT
(
cuCtxDestroy
(
context
));
}
}
...
@@ -441,16 +453,19 @@ void CudaContext::initialize() {
...
@@ -441,16 +453,19 @@ void CudaContext::initialize() {
int
numEnergyBuffers
=
max
(
numThreadBlocks
*
ThreadBlockSize
,
nonbonded
->
getNumEnergyBuffers
());
int
numEnergyBuffers
=
max
(
numThreadBlocks
*
ThreadBlockSize
,
nonbonded
->
getNumEnergyBuffers
());
if
(
useDoublePrecision
)
{
if
(
useDoublePrecision
)
{
energyBuffer
=
CudaArray
::
create
<
double
>
(
*
this
,
numEnergyBuffers
,
"energyBuffer"
);
energyBuffer
=
CudaArray
::
create
<
double
>
(
*
this
,
numEnergyBuffers
,
"energyBuffer"
);
energySum
=
CudaArray
::
create
<
double
>
(
*
this
,
1
,
"energySum"
);
int
pinnedBufferSize
=
max
(
paddedNumAtoms
*
4
,
numEnergyBuffers
);
int
pinnedBufferSize
=
max
(
paddedNumAtoms
*
4
,
numEnergyBuffers
);
CHECK_RESULT
(
cuMemHostAlloc
(
&
pinnedBuffer
,
pinnedBufferSize
*
sizeof
(
double
),
0
));
CHECK_RESULT
(
cuMemHostAlloc
(
&
pinnedBuffer
,
pinnedBufferSize
*
sizeof
(
double
),
0
));
}
}
else
if
(
useMixedPrecision
)
{
else
if
(
useMixedPrecision
)
{
energyBuffer
=
CudaArray
::
create
<
double
>
(
*
this
,
numEnergyBuffers
,
"energyBuffer"
);
energyBuffer
=
CudaArray
::
create
<
double
>
(
*
this
,
numEnergyBuffers
,
"energyBuffer"
);
energySum
=
CudaArray
::
create
<
double
>
(
*
this
,
1
,
"energySum"
);
int
pinnedBufferSize
=
max
(
paddedNumAtoms
*
4
,
numEnergyBuffers
);
int
pinnedBufferSize
=
max
(
paddedNumAtoms
*
4
,
numEnergyBuffers
);
CHECK_RESULT
(
cuMemHostAlloc
(
&
pinnedBuffer
,
pinnedBufferSize
*
sizeof
(
double
),
0
));
CHECK_RESULT
(
cuMemHostAlloc
(
&
pinnedBuffer
,
pinnedBufferSize
*
sizeof
(
double
),
0
));
}
}
else
{
else
{
energyBuffer
=
CudaArray
::
create
<
float
>
(
*
this
,
numEnergyBuffers
,
"energyBuffer"
);
energyBuffer
=
CudaArray
::
create
<
float
>
(
*
this
,
numEnergyBuffers
,
"energyBuffer"
);
energySum
=
CudaArray
::
create
<
float
>
(
*
this
,
1
,
"energySum"
);
int
pinnedBufferSize
=
max
(
paddedNumAtoms
*
6
,
numEnergyBuffers
);
int
pinnedBufferSize
=
max
(
paddedNumAtoms
*
6
,
numEnergyBuffers
);
CHECK_RESULT
(
cuMemHostAlloc
(
&
pinnedBuffer
,
pinnedBufferSize
*
sizeof
(
float
),
0
));
CHECK_RESULT
(
cuMemHostAlloc
(
&
pinnedBuffer
,
pinnedBufferSize
*
sizeof
(
float
),
0
));
}
}
...
@@ -870,6 +885,18 @@ void CudaContext::clearAutoclearBuffers() {
...
@@ -870,6 +885,18 @@ void CudaContext::clearAutoclearBuffers() {
}
}
}
}
double
CudaContext
::
reduceEnergy
()
{
int
bufferSize
=
energyBuffer
->
getSize
();
int
workGroupSize
=
512
;
void
*
args
[]
=
{
&
energyBuffer
->
getDevicePointer
(),
&
energySum
->
getDevicePointer
(),
&
bufferSize
,
&
workGroupSize
};
executeKernel
(
reduceEnergyKernel
,
args
,
workGroupSize
,
workGroupSize
,
workGroupSize
*
energyBuffer
->
getElementSize
());
energySum
->
download
(
pinnedBuffer
);
if
(
getUseDoublePrecision
()
||
getUseMixedPrecision
())
return
*
((
double
*
)
pinnedBuffer
);
else
return
*
((
float
*
)
pinnedBuffer
);
}
void
CudaContext
::
setCharges
(
const
vector
<
double
>&
charges
)
{
void
CudaContext
::
setCharges
(
const
vector
<
double
>&
charges
)
{
if
(
chargeBuffer
==
NULL
)
if
(
chargeBuffer
==
NULL
)
chargeBuffer
=
new
CudaArray
(
*
this
,
numAtoms
,
useDoublePrecision
?
sizeof
(
double
)
:
sizeof
(
float
),
"chargeBuffer"
);
chargeBuffer
=
new
CudaArray
(
*
this
,
numAtoms
,
useDoublePrecision
?
sizeof
(
double
)
:
sizeof
(
float
),
"chargeBuffer"
);
...
...
platforms/cuda/src/CudaKernelFactory.cpp
View file @
7cdd6d16
...
@@ -108,6 +108,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
...
@@ -108,6 +108,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
return
new
CudaCalcCustomCentroidBondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
return
new
CudaCalcCustomCentroidBondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
if
(
name
==
CalcCustomCompoundBondForceKernel
::
Name
())
return
new
CudaCalcCustomCompoundBondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
return
new
CudaCalcCustomCompoundBondForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
if
(
name
==
CalcCustomCVForceKernel
::
Name
())
return
new
CudaCalcCustomCVForceKernel
(
name
,
platform
,
cu
);
if
(
name
==
CalcCustomManyParticleForceKernel
::
Name
())
if
(
name
==
CalcCustomManyParticleForceKernel
::
Name
())
return
new
CudaCalcCustomManyParticleForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
return
new
CudaCalcCustomManyParticleForceKernel
(
name
,
platform
,
cu
,
context
.
getSystem
());
if
(
name
==
CalcGayBerneForceKernel
::
Name
())
if
(
name
==
CalcGayBerneForceKernel
::
Name
())
...
...
platforms/cuda/src/CudaKernels.cpp
View file @
7cdd6d16
...
@@ -115,21 +115,8 @@ double CudaCalcForcesAndEnergyKernel::finishComputation(ContextImpl& context, bo
...
@@ -115,21 +115,8 @@ double CudaCalcForcesAndEnergyKernel::finishComputation(ContextImpl& context, bo
for (auto computation : cu.getPostComputations())
for (auto computation : cu.getPostComputations())
sum += computation->computeForceAndEnergy(includeForces, includeEnergy, groups);
sum += computation->computeForceAndEnergy(includeForces, includeEnergy, groups);
cu.getIntegrationUtilities().distributeForcesFromVirtualSites();
cu.getIntegrationUtilities().distributeForcesFromVirtualSites();
if
(
includeEnergy
)
{
if (includeEnergy)
CudaArray
&
energyArray
=
cu
.
getEnergyBuffer
();
sum += cu.reduceEnergy();
if
(
cu
.
getUseDoublePrecision
()
||
cu
.
getUseMixedPrecision
())
{
double
*
energy
=
(
double
*
)
cu
.
getPinnedBuffer
();
energyArray
.
download
(
energy
);
for
(
int
i
=
0
;
i
<
energyArray
.
getSize
();
i
++
)
sum
+=
energy
[
i
];
}
else
{
float
*
energy
=
(
float
*
)
cu
.
getPinnedBuffer
();
energyArray
.
download
(
energy
);
for
(
int
i
=
0
;
i
<
energyArray
.
getSize
();
i
++
)
sum
+=
energy
[
i
];
}
}
if (!cu.getForcesValid())
if (!cu.getForcesValid())
valid = false;
valid = false;
return sum;
return sum;
...
@@ -6609,6 +6596,176 @@ void CudaCalcGayBerneForceKernel::sortAtoms() {
...
@@ -6609,6 +6596,176 @@ void CudaCalcGayBerneForceKernel::sortAtoms() {
exclusionStartIndex->upload(startIndexVec);
exclusionStartIndex->upload(startIndexVec);
}
}
class CudaCalcCustomCVForceKernel::ReorderListener : public CudaContext::ReorderListener {
public:
ReorderListener(CudaContext& cu, CudaArray& invAtomOrder) : cu(cu), invAtomOrder(invAtomOrder) {
}
void execute() {
vector<int> invOrder(cu.getPaddedNumAtoms());
const vector<int>& order = cu.getAtomIndex();
for (int i = 0; i < order.size(); i++)
invOrder[order[i]] = i;
invAtomOrder.upload(invOrder);
}
private:
CudaContext& cu;
CudaArray& invAtomOrder;
};
CudaCalcCustomCVForceKernel::~CudaCalcCustomCVForceKernel() {
for (auto force : cvForces)
delete force;
if (invAtomOrder != NULL)
delete invAtomOrder;
if (innerInvAtomOrder != NULL)
delete innerInvAtomOrder;
}
void CudaCalcCustomCVForceKernel::initialize(const System& system, const CustomCVForce& force, ContextImpl& innerContext) {
int numCVs = force.getNumCollectiveVariables();
for (int i = 0; i < force.getNumGlobalParameters(); i++)
globalParameterNames.push_back(force.getGlobalParameterName(i));
// Create custom functions for the tabulated functions.
map<string, Lepton::CustomFunction*> functions;
for (int i = 0; i < (int) force.getNumTabulatedFunctions(); i++)
functions[force.getTabulatedFunctionName(i)] = createReferenceTabulatedFunction(force.getTabulatedFunction(i));
// Create the expressions.
Lepton::ParsedExpression energyExpr = Lepton::Parser::parse(force.getEnergyFunction(), functions);
energyExpression = energyExpr.createProgram();
for (int i = 0; i < numCVs; i++) {
string name = force.getCollectiveVariableName(i);
variableNames.push_back(name);
variableDerivExpressions.push_back(energyExpr.differentiate(name).optimize().createProgram());
}
for (int i = 0; i < force.getNumEnergyParameterDerivatives(); i++) {
string name = force.getEnergyParameterDerivativeName(i);
paramDerivNames.push_back(name);
paramDerivExpressions.push_back(energyExpr.differentiate(name).optimize().createProgram());
cu.addEnergyParameterDerivative(name);
}
// Delete the custom functions.
for (auto& function : functions)
delete function.second;
// Copy parameter derivatives from the inner context.
CudaContext& cu2 = *reinterpret_cast<CudaPlatform::PlatformData*>(innerContext.getPlatformData())->contexts[0];
for (auto& param : cu2.getEnergyParamDerivNames())
cu.addEnergyParameterDerivative(param);
// Create arrays for storing information.
int elementSize = (cu.getUseDoublePrecision() || cu.getUseMixedPrecision() ? sizeof(double) : sizeof(float));
for (int i = 0; i < numCVs; i++)
cvForces.push_back(CudaArray::create<long long>(cu, 3*cu.getPaddedNumAtoms(), "cvForce"));
invAtomOrder = CudaArray::create<int>(cu, cu.getPaddedNumAtoms(), "invAtomOrder");
innerInvAtomOrder = CudaArray::create<int>(cu, cu.getPaddedNumAtoms(), "innerInvAtomOrder");
// Create the kernels.
stringstream args, add;
for (int i = 0; i < numCVs; i++) {
args << ", long long* __restrict__ force" << i << ", real dEdV" << i;
add << "forces[i] += (long long) (force" << i << "[i]*dEdV" << i << ");\n";
}
map<string, string> replacements;
replacements["PARAMETER_ARGUMENTS"] = args.str();
replacements["ADD_FORCES"] = add.str();
CUmodule module = cu.createModule(cu.replaceStrings(CudaKernelSources::vectorOps+CudaKernelSources::customCVForce, replacements));
copyStateKernel = cu.getKernel(module, "copyState");
copyForcesKernel = cu.getKernel(module, "copyForces");
addForcesKernel = cu.getKernel(module, "addForces");
}
double CudaCalcCustomCVForceKernel::execute(ContextImpl& context, ContextImpl& innerContext, bool includeForces, bool includeEnergy) {
copyState(context, innerContext);
int numCVs = variableNames.size();
int numAtoms = cu.getNumAtoms();
int paddedNumAtoms = cu.getPaddedNumAtoms();
CudaContext& cu2 = *reinterpret_cast<CudaPlatform::PlatformData*>(innerContext.getPlatformData())->contexts[0];
vector<double> cvValues;
vector<map<string, double> > cvDerivs(numCVs);
void* copyForcesArgs[] = {NULL, &invAtomOrder->getDevicePointer(), &cu2.getForce().getDevicePointer(), &cu2.getAtomIndexArray().getDevicePointer(), &numAtoms, &paddedNumAtoms};
for (int i = 0; i < numCVs; i++) {
cvValues.push_back(innerContext.calcForcesAndEnergy(true, true, 1<<i));
copyForcesArgs[0] = &cvForces[i]->getDevicePointer();
cu.executeKernel(copyForcesKernel, copyForcesArgs, numAtoms);
innerContext.getEnergyParameterDerivatives(cvDerivs[i]);
}
// Compute the energy and forces.
map<string, double> variables;
for (auto& name : globalParameterNames)
variables[name] = context.getParameter(name);
for (int i = 0; i < numCVs; i++)
variables[variableNames[i]] = cvValues[i];
double energy = energyExpression.evaluate(variables);
int bufferSize = cu.getForce().getSize();
vector<void*> addForcesArgs;
addForcesArgs.push_back(&cu.getForce().getDevicePointer());
addForcesArgs.push_back(&bufferSize);
vector<double> dEdV(numCVs);
vector<float> dEdVFloat(numCVs);
for (int i = 0; i < numCVs; i++) {
dEdV[i] = variableDerivExpressions[i].evaluate(variables);
dEdVFloat[i] = (float) dEdV[i];
addForcesArgs.push_back(&cvForces[i]->getDevicePointer());
if (cu.getUseDoublePrecision())
addForcesArgs.push_back(&dEdV[i]);
else
addForcesArgs.push_back(&dEdVFloat[i]);
}
cu.executeKernel(addForcesKernel, &addForcesArgs[0], numAtoms);
// Compute the energy parameter derivatives.
map<string, double>& energyParamDerivs = cu.getEnergyParamDerivWorkspace();
for (int i = 0; i < paramDerivExpressions.size(); i++)
energyParamDerivs[paramDerivNames[i]] += paramDerivExpressions[i].evaluate(variables);
for (int i = 0; i < numCVs; i++) {
double dEdV = variableDerivExpressions[i].evaluate(variables);
for (auto& deriv : cvDerivs[i])
energyParamDerivs[deriv.first] += dEdV*deriv.second;
}
return energy;
}
void CudaCalcCustomCVForceKernel::copyState(ContextImpl& context, ContextImpl& innerContext) {
int numAtoms = cu.getNumAtoms();
CudaContext& cu2 = *reinterpret_cast<CudaPlatform::PlatformData*>(innerContext.getPlatformData())->contexts[0];
if (!hasInitializedListeners) {
hasInitializedListeners = true;
// Initialize the listeners.
ReorderListener* listener1 = new ReorderListener(cu, *invAtomOrder);
ReorderListener* listener2 = new ReorderListener(cu2, *innerInvAtomOrder);
cu.addReorderListener(listener1);
cu2.addReorderListener(listener2);
listener1->execute();
listener2->execute();
}
CUdeviceptr posCorrection = (cu.getUseMixedPrecision() ? cu.getPosqCorrection().getDevicePointer() : 0);
CUdeviceptr posCorrection2 = (cu2.getUseMixedPrecision() ? cu2.getPosqCorrection().getDevicePointer() : 0);
void* copyStateArgs[] = {&cu.getPosq().getDevicePointer(), &posCorrection, &cu.getVelm().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(),
&cu2.getPosq().getDevicePointer(), &posCorrection2,& cu2.getVelm().getDevicePointer(), &innerInvAtomOrder->getDevicePointer(), &numAtoms};
cu.executeKernel(copyStateKernel, copyStateArgs, numAtoms);
Vec3 a, b, c;
context.getPeriodicBoxVectors(a, b, c);
innerContext.setPeriodicBoxVectors(a, b, c);
innerContext.setTime(context.getTime());
map<string, double> innerParameters = innerContext.getParameters();
for (auto& param : innerParameters)
innerContext.setParameter(param.first, context.getParameter(param.first));
}
CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() {
CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() {
}
}
...
...
Prev
1
2
3
Next
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