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
855ece90
Commit
855ece90
authored
Oct 17, 2013
by
leeping
Browse files
Merge branch 'master' of
https://github.com/SimTk/openmm
parents
471bea82
a42c55ad
Changes
115
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
3782 additions
and
8 deletions
+3782
-8
platforms/cpu/include/CpuNeighborList.h
platforms/cpu/include/CpuNeighborList.h
+45
-0
platforms/cpu/include/CpuNonbondedForce.h
platforms/cpu/include/CpuNonbondedForce.h
+237
-0
platforms/cpu/include/CpuPlatform.h
platforms/cpu/include/CpuPlatform.h
+58
-0
platforms/cpu/include/windowsExportCpu.h
platforms/cpu/include/windowsExportCpu.h
+41
-0
platforms/cpu/sharedTarget/CMakeLists.txt
platforms/cpu/sharedTarget/CMakeLists.txt
+12
-0
platforms/cpu/src/CpuKernelFactory.cpp
platforms/cpu/src/CpuKernelFactory.cpp
+45
-0
platforms/cpu/src/CpuKernels.cpp
platforms/cpu/src/CpuKernels.cpp
+324
-0
platforms/cpu/src/CpuNeighborList.cpp
platforms/cpu/src/CpuNeighborList.cpp
+270
-0
platforms/cpu/src/CpuNonbondedForce.cpp
platforms/cpu/src/CpuNonbondedForce.cpp
+579
-0
platforms/cpu/src/CpuPlatform.cpp
platforms/cpu/src/CpuPlatform.cpp
+69
-0
platforms/cpu/tests/CMakeLists.txt
platforms/cpu/tests/CMakeLists.txt
+25
-0
platforms/cpu/tests/TestCpuEwald.cpp
platforms/cpu/tests/TestCpuEwald.cpp
+273
-0
platforms/cpu/tests/TestCpuNeighborList.cpp
platforms/cpu/tests/TestCpuNeighborList.cpp
+112
-0
platforms/cpu/tests/TestCpuNonbondedForce.cpp
platforms/cpu/tests/TestCpuNonbondedForce.cpp
+650
-0
platforms/cpu/tests/nacl_amorph.dat
platforms/cpu/tests/nacl_amorph.dat
+894
-0
platforms/cuda/src/CudaIntegrationUtilities.cpp
platforms/cuda/src/CudaIntegrationUtilities.cpp
+14
-8
platforms/cuda/tests/TestCudaBrownianIntegrator.cpp
platforms/cuda/tests/TestCudaBrownianIntegrator.cpp
+32
-0
platforms/cuda/tests/TestCudaCustomIntegrator.cpp
platforms/cuda/tests/TestCudaCustomIntegrator.cpp
+38
-0
platforms/cuda/tests/TestCudaLangevinIntegrator.cpp
platforms/cuda/tests/TestCudaLangevinIntegrator.cpp
+32
-0
platforms/cuda/tests/TestCudaVariableLangevinIntegrator.cpp
platforms/cuda/tests/TestCudaVariableLangevinIntegrator.cpp
+32
-0
No files found.
platforms/cpu/include/CpuNeighborList.h
0 → 100644
View file @
855ece90
#ifndef OPENMM_CPU_NEIGHBORLIST_H_
#define OPENMM_CPU_NEIGHBORLIST_H_
#include "windowsExportCpu.h"
#include <pthread.h>
#include <set>
#include <utility>
#include <vector>
namespace
OpenMM
{
class
OPENMM_EXPORT_CPU
CpuNeighborList
{
public:
class
ThreadData
;
class
VoxelHash
;
CpuNeighborList
();
~
CpuNeighborList
();
void
computeNeighborList
(
int
numAtoms
,
const
std
::
vector
<
float
>&
atomLocations
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
const
float
*
periodicBoxSize
,
bool
usePeriodic
,
float
maxDistance
);
const
std
::
vector
<
std
::
pair
<
int
,
int
>
>&
getNeighbors
();
/**
* This routine contains the code executed by each thread.
*/
void
runThread
(
int
index
,
std
::
vector
<
std
::
pair
<
int
,
int
>
>&
threadNeighbors
);
private:
bool
isDeleted
;
int
numThreads
,
waitCount
;
std
::
vector
<
std
::
pair
<
int
,
int
>
>
neighbors
;
std
::
vector
<
pthread_t
>
thread
;
std
::
vector
<
ThreadData
*>
threadData
;
pthread_cond_t
startCondition
,
endCondition
;
pthread_mutex_t
lock
;
// The following variables are used to make information accessible to the individual threads.
VoxelHash
*
voxelHash
;
const
std
::
vector
<
std
::
set
<
int
>
>*
exclusions
;
const
float
*
atomLocations
;
const
float
*
periodicBoxSize
;
int
numAtoms
;
bool
usePeriodic
;
float
maxDistance
;
};
}
// namespace OpenMM
#endif // OPENMM_REFERENCE_NEIGHBORLIST_H_
platforms/
reference/include/ReferenceShakeAlgorithm
.h
→
platforms/
cpu/include/CpuNonbondedForce
.h
View file @
855ece90
/* Portions copyright (c) 2006-20
09
Stanford University and Simbios.
/* Portions copyright (c) 2006-20
13
Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
...
...
@@ -22,44 +22,28 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ReferenceShakeAlgorithm_H__
#define __ReferenceShakeAlgorithm_H__
#include "ReferenceConstraintAlgorithm.h"
#ifndef OPENMM_CPU_NONBONDED_FORCE_H__
#define OPENMM_CPU_NONBONDED_FORCE_H__
#include "ReferencePairIxn.h"
#include <pthread.h>
#include <set>
#include <utility>
#include <vector>
#include <smmintrin.h>
// ---------------------------------------------------------------------------------------
class
ReferenceShakeAlgorithm
:
public
ReferenceConstraintAlgorithm
{
protected:
int
_maximumNumberOfIterations
;
RealOpenMM
_tolerance
;
int
_numberOfConstraints
;
int
**
_atomIndices
;
RealOpenMM
*
_distance
;
RealOpenMM
**
_r_ij
;
RealOpenMM
*
_d_ij2
;
RealOpenMM
*
_distanceTolerance
;
RealOpenMM
*
_reducedMasses
;
bool
_hasInitializedMasses
;
public:
class
CpuNonbondedForce
{
public:
class
ThreadData
;
/**---------------------------------------------------------------------------------------
ReferenceShakeAlgorithm constructor
@param numberOfConstraints number of constraints
@param atomIndices atom indices for contraints
@param distance distances for constraints
@param tolerance constraint tolerance
Constructor
--------------------------------------------------------------------------------------- */
ReferenceShakeAlgorithm
(
int
numberOfConstraints
,
int
**
atomIndices
,
RealOpenMM
*
distance
,
RealOpenMM
toleran
ce
);
CpuNonbondedFor
ce
(
);
/**---------------------------------------------------------------------------------------
...
...
@@ -67,107 +51,187 @@ class ReferenceShakeAlgorithm : public ReferenceConstraintAlgorithm {
--------------------------------------------------------------------------------------- */
~
ReferenceShakeAlgorithm
(
);
~
CpuNonbondedForce
(
);
/**---------------------------------------------------------------------------------------
G
et
number of constraints
S
et
the force to use a cutoff.
@return number of constraints
@param distance the cutoff distance
@param neighbors the neighbor list to use
@param solventDielectric the dielectric constant of the bulk solvent
--------------------------------------------------------------------------------------- */
int
getNumberOfConstraints
(
void
)
const
;
void
setUseCutoff
(
float
distance
,
const
std
::
vector
<
std
::
pair
<
int
,
int
>
>&
neighbors
,
float
solventDielectric
)
;
/**---------------------------------------------------------------------------------------
Get maximum number of
iteration
s
Set the force to use a switching function on the Lennard-Jones
i
n
tera
c
tion
.
@
return maximum number of iterations
@
param distance the switching distance
--------------------------------------------------------------------------------------- */
int
getMaximumNumberOfIterations
(
void
)
const
;
void
setUseSwitchingFunction
(
float
distance
)
;
/**---------------------------------------------------------------------------------------
Set maximum number of iterations
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
maximumNumberOfIterations new maximum number of iterations
@param
boxSize the X, Y, and Z widths of the periodic box
--------------------------------------------------------------------------------------- */
void
set
MaximumNumberOfIterations
(
int
maximumNumberOfIterations
);
void
set
Periodic
(
float
*
periodicBoxSize
);
/**---------------------------------------------------------------------------------------
G
et t
olerance
S
et t
he force to use Ewald summation.
@return tolerance
@param alpha the Ewald separation parameter
@param kmaxx the largest wave vector in the x direction
@param kmaxy the largest wave vector in the y direction
@param kmaxz the largest wave vector in the z direction
--------------------------------------------------------------------------------------- */
RealOpenMM
getTolerance
(
void
)
const
;
void
setUseEwald
(
float
alpha
,
int
kmaxx
,
int
kmaxy
,
int
kmaxz
);
/**---------------------------------------------------------------------------------------
Set t
olerance
Set t
he force to use Particle-Mesh Ewald (PME) summation.
@param tolerance new tolerance
@param alpha the Ewald separation parameter
@param gridSize the dimensions of the mesh
--------------------------------------------------------------------------------------- */
void
set
Tolerance
(
RealOpenMM
tolerance
);
void
set
UsePME
(
float
alpha
,
int
meshSize
[
3
]
);
/**---------------------------------------------------------------------------------------
Apply Shake algorithm
Calculate Ewald ixn
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param atomCoordinatesP atom coordinates prime
@param inverseMasses 1/mass
@return SimTKOpenMMCommon::DefaultReturn if converge; else
return SimTKOpenMMCommon::ErrorReturn
@param posq atom coordinates and charges
@param atomCoordinates atom coordinates (in format needed by PME)
@param atomParameters atom parameters (sigma/2, 2*sqrt(epsilon))
@param exclusions atom exclusion indices
exclusions[atomIndex] contains the list of exclusions for that atom
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void
calculateReciprocalIxn
(
int
numberOfAtoms
,
float
*
posq
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
const
std
::
vector
<
std
::
pair
<
float
,
float
>
>&
atomParameters
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
float
*
totalEnergy
)
const
;
int
apply
(
int
numberOfAtoms
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinatesP
,
std
::
vector
<
RealOpenMM
>&
inverseMasses
);
/**---------------------------------------------------------------------------------------
Apply constraint algorithm to velocities.
Calculate LJ Coulomb pair ixn
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param velocities atom velocities
@param inverseMasses 1/mass
@return SimTKOpenMMCommon::DefaultReturn if converge; else
return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int
applyToVelocities
(
int
numberOfAtoms
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
RealVec
>&
velocities
,
std
::
vector
<
RealOpenMM
>&
inverseMasses
);
@param posq atom coordinates and charges
@param atomParameters atom parameters (sigma/2, 2*sqrt(epsilon))
@param exclusions atom exclusion indices
exclusions[atomIndex] contains the list of exclusions for that atom
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void
calculateDirectIxn
(
int
numberOfAtoms
,
float
*
posq
,
const
std
::
vector
<
std
::
pair
<
float
,
float
>
>&
atomParameters
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
float
*
forces
,
float
*
totalEnergy
);
/**
* This routine contains the code executed by each thread.
*/
void
runThread
(
int
index
,
std
::
vector
<
float
>&
threadForce
,
double
&
threadEnergy
);
private:
bool
cutoff
;
bool
useSwitch
;
bool
periodic
;
bool
ewald
;
bool
pme
;
const
std
::
vector
<
std
::
pair
<
int
,
int
>
>*
neighborList
;
float
periodicBoxSize
[
3
];
float
cutoffDistance
,
switchingDistance
;
float
krf
,
crf
;
float
alphaEwald
;
int
numRx
,
numRy
,
numRz
;
int
meshDim
[
3
];
std
::
vector
<
float
>
ewaldScaleX
,
ewaldScaleY
,
ewaldScaleDeriv
;
float
ewaldDX
,
ewaldDXInv
;
bool
isDeleted
;
int
numThreads
,
waitCount
;
std
::
vector
<
pthread_t
>
thread
;
std
::
vector
<
ThreadData
*>
threadData
;
pthread_cond_t
startCondition
,
endCondition
;
pthread_mutex_t
lock
;
// The following variables are used to make information accessible to the individual threads.
int
numberOfAtoms
;
float
*
posq
;
std
::
pair
<
float
,
float
>
const
*
atomParameters
;
std
::
set
<
int
>
const
*
exclusions
;
bool
includeEnergy
;
static
const
float
TWO_OVER_SQRT_PI
;
static
const
int
NUM_TABLE_POINTS
;
/**---------------------------------------------------------------------------------------
Report any violated constraint
s
Calculate LJ Coulomb pair ixn between two atom
s
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param message report
@param atom1 the index of the first atom
@param atom2 the index of the second atom
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void
calculateOneIxn
(
int
atom1
,
int
atom2
,
float
*
forces
,
double
*
totalEnergy
,
const
__m128
&
boxSize
,
const
__m128
&
invBoxSize
);
/**---------------------------------------------------------------------------------------
@return number of violated constraint
s
Calculate LJ Coulomb pair ixn between two atom
s
@param atom1 the index of the first atom
@param atom2 the index of the second atom
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
int
reportShake
(
int
numberOfAtoms
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
stringstream
&
message
);
void
calculateOneEwaldIxn
(
int
atom1
,
int
atom2
,
float
*
forces
,
double
*
totalEnergy
,
const
__m128
&
boxSize
,
const
__m128
&
invBoxSize
);
/**
* Compute the displacement and squared distance between two points, optionally using
* periodic boundary conditions.
*/
void
getDeltaR
(
const
__m128
&
posI
,
const
__m128
&
posJ
,
__m128
&
deltaR
,
float
&
r2
,
bool
periodic
,
const
__m128
&
boxSize
,
const
__m128
&
invBoxSize
)
const
;
/**
* Compute a fast approximation to erfc(x).
*/
static
float
erfcApprox
(
float
x
);
/**
* Create a lookup table for the scale factor used with Ewald and PME.
*/
void
tabulateEwaldScaleFactor
();
/**
* Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI)
*/
float
ewaldScaleFunction
(
float
x
);
};
// ---------------------------------------------------------------------------------------
#endif //
__ReferenceShakeAlgorithm
_H__
#endif //
OPENMM_CPU_NONBONDED_FORCE
_H__
platforms/cpu/include/CpuPlatform.h
0 → 100644
View file @
855ece90
#ifndef OPENMM_CPUPLATFORM_H_
#define OPENMM_CPUPLATFORM_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) 2013 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 "ReferencePlatform.h"
#include "windowsExportCpu.h"
namespace
OpenMM
{
/**
* This Platform subclass uses CPU implementations of the OpenMM kernels.
*/
class
OPENMM_EXPORT_CPU
CpuPlatform
:
public
ReferencePlatform
{
public:
CpuPlatform
();
const
std
::
string
&
getName
()
const
{
static
const
std
::
string
name
=
"CPU"
;
return
name
;
}
double
getSpeed
()
const
;
bool
supportsDoublePrecision
()
const
;
static
bool
isProcessorSupported
();
};
}
// namespace OpenMM
#endif
/*OPENMM_CPUPLATFORM_H_*/
platforms/cpu/include/windowsExportCpu.h
0 → 100644
View file @
855ece90
#ifndef OPENMM_WINDOWSEXPORTCPU_H_
#define OPENMM_WINDOWSEXPORTCPU_H_
/*
* Shared libraries are messy in Visual Studio. We have to distinguish three
* cases:
* (1) this header is being used to build the OpenMM shared library
* (dllexport)
* (2) this header is being used by a *client* of the OpenMM shared
* library (dllimport)
* (3) we are building the OpenMM static library, or the client is
* being compiled with the expectation of linking with the
* OpenMM static library (nothing special needed)
* In the CMake script for building this library, we define one of the symbols
* OPENMM_CPU_BUILDING_{SHARED|STATIC}_LIBRARY
* Client code normally has no special symbol defined, in which case we'll
* assume it wants to use the shared library. However, if the client defines
* the symbol OPENMM_USE_STATIC_LIBRARIES we'll suppress the dllimport so
* that the client code can be linked with static libraries. Note that
* the client symbol is not library dependent, while the library symbols
* affect only the OpenMM library, meaning that other libraries can
* be clients of this one. However, we are assuming all-static or all-shared.
*/
#ifdef _MSC_VER
// We don't want to hear about how sprintf is "unsafe".
#pragma warning(disable:4996)
// Keep MS VC++ quiet about lack of dll export of private members.
#pragma warning(disable:4251)
#if defined(OPENMM_CPU_BUILDING_SHARED_LIBRARY)
#define OPENMM_EXPORT_CPU __declspec(dllexport)
#elif defined(OPENMM_CPU_BUILDING_STATIC_LIBRARY) || defined(OPENMM_CPU_USE_STATIC_LIBRARIES)
#define OPENMM_EXPORT_CPU
#else
#define OPENMM_EXPORT_CPU __declspec(dllimport) // i.e., a client of a shared library
#endif
#else
#define OPENMM_EXPORT_CPU // Linux, Mac
#endif
#endif // OPENMM_WINDOWSEXPORTCPU_H_
platforms/cpu/sharedTarget/CMakeLists.txt
0 → 100644
View file @
855ece90
SET_SOURCE_FILES_PROPERTIES
(
${
SOURCE_FILES
}
PROPERTIES COMPILE_FLAGS
"-msse4.1"
)
ADD_LIBRARY
(
${
SHARED_TARGET
}
SHARED
${
SOURCE_FILES
}
${
SOURCE_INCLUDE_FILES
}
${
API_ABS_INCLUDE_FILES
}
)
IF
(
UNIX AND CMAKE_BUILD_TYPE MATCHES Debug
)
SET
(
MAIN_OPENMM_LIB
${
OPENMM_LIBRARY_NAME
}
_d
)
ELSE
(
UNIX AND CMAKE_BUILD_TYPE MATCHES Debug
)
SET
(
MAIN_OPENMM_LIB
${
OPENMM_LIBRARY_NAME
}
)
ENDIF
(
UNIX AND CMAKE_BUILD_TYPE MATCHES Debug
)
TARGET_LINK_LIBRARIES
(
${
SHARED_TARGET
}
${
MAIN_OPENMM_LIB
}
${
PTHREADS_LIB
}
)
SET_TARGET_PROPERTIES
(
${
SHARED_TARGET
}
PROPERTIES COMPILE_FLAGS
"-DOPENMM_CPU_BUILDING_SHARED_LIBRARY"
)
INSTALL_TARGETS
(
/lib/plugins RUNTIME_DIRECTORY /lib/plugins
${
SHARED_TARGET
}
)
platforms/cpu/src/CpuKernelFactory.cpp
0 → 100644
View file @
855ece90
/* -------------------------------------------------------------------------- *
* 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) 2013 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 "CpuKernelFactory.h"
#include "CpuKernels.h"
#include "CpuPlatform.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/OpenMMException.h"
using
namespace
OpenMM
;
KernelImpl
*
CpuKernelFactory
::
createKernelImpl
(
std
::
string
name
,
const
Platform
&
platform
,
ContextImpl
&
context
)
const
{
ReferencePlatform
::
PlatformData
&
data
=
*
static_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
if
(
name
==
CalcNonbondedForceKernel
::
Name
())
return
new
CpuCalcNonbondedForceKernel
(
name
,
platform
);
throw
OpenMMException
((
std
::
string
(
"Tried to create kernel with illegal kernel name '"
)
+
name
+
"'"
).
c_str
());
}
platforms/cpu/src/CpuKernels.cpp
0 → 100644
View file @
855ece90
/* -------------------------------------------------------------------------- *
* 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) 2013 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 "CpuKernels.h"
#include "ReferenceBondForce.h"
#include "ReferenceLJCoulomb14.h"
#include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "RealVec.h"
using
namespace
OpenMM
;
using
namespace
std
;
static
vector
<
RealVec
>&
extractPositions
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
((
vector
<
RealVec
>*
)
data
->
positions
);
}
static
vector
<
RealVec
>&
extractVelocities
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
((
vector
<
RealVec
>*
)
data
->
velocities
);
}
static
vector
<
RealVec
>&
extractForces
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
((
vector
<
RealVec
>*
)
data
->
forces
);
}
static
RealVec
&
extractBoxSize
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
(
RealVec
*
)
data
->
periodicBoxSize
;
}
class
CpuCalcNonbondedForceKernel
::
PmeIO
:
public
CalcPmeReciprocalForceKernel
::
IO
{
public:
PmeIO
(
float
*
posq
,
float
*
force
,
int
numParticles
)
:
posq
(
posq
),
force
(
force
),
numParticles
(
numParticles
)
{
}
float
*
getPosq
()
{
return
posq
;
}
void
setForce
(
float
*
f
)
{
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
force
[
4
*
i
]
+=
f
[
4
*
i
];
force
[
4
*
i
+
1
]
+=
f
[
4
*
i
+
1
];
force
[
4
*
i
+
2
]
+=
f
[
4
*
i
+
2
];
}
}
private:
float
*
posq
;
float
*
force
;
int
numParticles
;
};
CpuCalcNonbondedForceKernel
::~
CpuCalcNonbondedForceKernel
()
{
if
(
bonded14ParamArray
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
num14
;
i
++
)
{
delete
[]
bonded14IndexArray
[
i
];
delete
[]
bonded14ParamArray
[
i
];
}
delete
bonded14IndexArray
;
delete
bonded14ParamArray
;
}
}
void
CpuCalcNonbondedForceKernel
::
initialize
(
const
System
&
system
,
const
NonbondedForce
&
force
)
{
// Identify which exceptions are 1-4 interactions.
numParticles
=
force
.
getNumParticles
();
posq
.
resize
(
4
*
numParticles
,
0
);
forces
.
resize
(
4
*
numParticles
,
0
);
exclusions
.
resize
(
numParticles
);
vector
<
int
>
nb14s
;
for
(
int
i
=
0
;
i
<
force
.
getNumExceptions
();
i
++
)
{
int
particle1
,
particle2
;
double
chargeProd
,
sigma
,
epsilon
;
force
.
getExceptionParameters
(
i
,
particle1
,
particle2
,
chargeProd
,
sigma
,
epsilon
);
exclusions
[
particle1
].
insert
(
particle2
);
exclusions
[
particle2
].
insert
(
particle1
);
if
(
chargeProd
!=
0.0
||
epsilon
!=
0.0
)
nb14s
.
push_back
(
i
);
}
// Record the particle parameters.
num14
=
nb14s
.
size
();
bonded14IndexArray
=
new
int
*
[
num14
];
for
(
int
i
=
0
;
i
<
num14
;
i
++
)
bonded14IndexArray
[
i
]
=
new
int
[
2
];
bonded14ParamArray
=
new
double
*
[
num14
];
for
(
int
i
=
0
;
i
<
num14
;
i
++
)
bonded14ParamArray
[
i
]
=
new
double
[
3
];
particleParams
.
resize
(
numParticles
);
double
sumSquaredCharges
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
double
charge
,
radius
,
depth
;
force
.
getParticleParameters
(
i
,
charge
,
radius
,
depth
);
posq
[
4
*
i
+
3
]
=
(
float
)
charge
;
particleParams
[
i
]
=
make_pair
((
float
)
(
0.5
*
radius
),
(
float
)
(
2.0
*
sqrt
(
depth
)));
sumSquaredCharges
+=
charge
*
charge
;
}
// Recorded exception parameters.
for
(
int
i
=
0
;
i
<
num14
;
++
i
)
{
int
particle1
,
particle2
;
double
charge
,
radius
,
depth
;
force
.
getExceptionParameters
(
nb14s
[
i
],
particle1
,
particle2
,
charge
,
radius
,
depth
);
bonded14IndexArray
[
i
][
0
]
=
particle1
;
bonded14IndexArray
[
i
][
1
]
=
particle2
;
bonded14ParamArray
[
i
][
0
]
=
static_cast
<
RealOpenMM
>
(
radius
);
bonded14ParamArray
[
i
][
1
]
=
static_cast
<
RealOpenMM
>
(
4.0
*
depth
);
bonded14ParamArray
[
i
][
2
]
=
static_cast
<
RealOpenMM
>
(
charge
);
}
// Record other parameters.
nonbondedMethod
=
CalcNonbondedForceKernel
::
NonbondedMethod
(
force
.
getNonbondedMethod
());
nonbondedCutoff
=
force
.
getCutoffDistance
();
if
(
nonbondedMethod
==
NoCutoff
)
useSwitchingFunction
=
false
;
else
{
useSwitchingFunction
=
force
.
getUseSwitchingFunction
();
switchingDistance
=
force
.
getSwitchingDistance
();
}
if
(
nonbondedMethod
==
Ewald
)
{
double
alpha
;
NonbondedForceImpl
::
calcEwaldParameters
(
system
,
force
,
alpha
,
kmax
[
0
],
kmax
[
1
],
kmax
[
2
]);
ewaldAlpha
=
alpha
;
}
else
if
(
nonbondedMethod
==
PME
)
{
double
alpha
;
NonbondedForceImpl
::
calcPMEParameters
(
system
,
force
,
alpha
,
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
]);
ewaldAlpha
=
alpha
;
}
if
(
nonbondedMethod
==
Ewald
||
nonbondedMethod
==
PME
)
ewaldSelfEnergy
=
-
ONE_4PI_EPS0
*
ewaldAlpha
*
sumSquaredCharges
/
sqrt
(
M_PI
);
else
ewaldSelfEnergy
=
0.0
;
rfDielectric
=
force
.
getReactionFieldDielectric
();
if
(
force
.
getUseDispersionCorrection
())
dispersionCoefficient
=
NonbondedForceImpl
::
calcDispersionCorrection
(
system
,
force
);
else
dispersionCoefficient
=
0.0
;
lastPositions
.
resize
(
numParticles
,
Vec3
(
1e10
,
1e10
,
1e10
));
}
double
CpuCalcNonbondedForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
,
bool
includeDirect
,
bool
includeReciprocal
)
{
if
(
!
hasInitializedPme
)
{
hasInitializedPme
=
true
;
useOptimizedPme
=
false
;
if
(
nonbondedMethod
==
PME
)
{
// If available, use the optimized PME implementation.
try
{
optimizedPme
=
getPlatform
().
createKernel
(
CalcPmeReciprocalForceKernel
::
Name
(),
context
);
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
initialize
(
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
],
numParticles
,
ewaldAlpha
);
useOptimizedPme
=
true
;
}
catch
(
OpenMMException
&
ex
)
{
// The CPU PME plugin isn't available.
}
}
}
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealVec
boxSize
=
extractBoxSize
(
context
);
float
floatBoxSize
[
3
]
=
{(
float
)
boxSize
[
0
],
(
float
)
boxSize
[
1
],
(
float
)
boxSize
[
2
]};
double
energy
=
ewaldSelfEnergy
;
bool
periodic
=
(
nonbondedMethod
==
CutoffPeriodic
);
bool
ewald
=
(
nonbondedMethod
==
Ewald
);
bool
pme
=
(
nonbondedMethod
==
PME
);
// Convert the positions to single precision.
if
(
periodic
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
RealOpenMM
x
=
posData
[
i
][
j
];
double
base
=
floor
(
x
/
boxSize
[
j
]
+
0.5
)
*
boxSize
[
j
];
posq
[
4
*
i
+
j
]
=
(
float
)
(
x
-
base
);
}
else
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
posq
[
4
*
i
]
=
(
float
)
posData
[
i
][
0
];
posq
[
4
*
i
+
1
]
=
(
float
)
posData
[
i
][
1
];
posq
[
4
*
i
+
2
]
=
(
float
)
posData
[
i
][
2
];
}
for
(
int
i
=
0
;
i
<
4
*
numParticles
;
i
++
)
forces
[
i
]
=
0.0
f
;
if
(
nonbondedMethod
!=
NoCutoff
)
{
// Determine whether we need to recompute the neighbor list.
double
padding
=
0.1
*
nonbondedCutoff
;
bool
needRecompute
=
false
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
RealVec
delta
=
posData
[
i
]
-
lastPositions
[
i
];
if
(
delta
.
dot
(
delta
)
>
0.25
*
padding
*
padding
)
{
needRecompute
=
true
;
break
;
}
}
if
(
needRecompute
)
{
neighborList
.
computeNeighborList
(
numParticles
,
posq
,
exclusions
,
floatBoxSize
,
periodic
||
ewald
||
pme
,
nonbondedCutoff
+
padding
);
lastPositions
=
posData
;
}
nonbonded
.
setUseCutoff
(
nonbondedCutoff
,
neighborList
.
getNeighbors
(),
rfDielectric
);
}
if
(
periodic
||
ewald
||
pme
)
{
double
minAllowedSize
=
1.999999
*
nonbondedCutoff
;
if
(
boxSize
[
0
]
<
minAllowedSize
||
boxSize
[
1
]
<
minAllowedSize
||
boxSize
[
2
]
<
minAllowedSize
)
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
nonbonded
.
setPeriodic
(
floatBoxSize
);
}
if
(
ewald
)
nonbonded
.
setUseEwald
(
ewaldAlpha
,
kmax
[
0
],
kmax
[
1
],
kmax
[
2
]);
if
(
pme
)
nonbonded
.
setUsePME
(
ewaldAlpha
,
gridSize
);
if
(
useSwitchingFunction
)
nonbonded
.
setUseSwitchingFunction
(
switchingDistance
);
float
nonbondedEnergy
=
0
;
if
(
includeDirect
)
nonbonded
.
calculateDirectIxn
(
numParticles
,
&
posq
[
0
],
particleParams
,
exclusions
,
&
forces
[
0
],
includeEnergy
?
&
nonbondedEnergy
:
NULL
);
if
(
includeReciprocal
)
{
if
(
useOptimizedPme
)
{
PmeIO
io
(
&
posq
[
0
],
&
forces
[
0
],
numParticles
);
Vec3
periodicBoxSize
(
boxSize
[
0
],
boxSize
[
1
],
boxSize
[
2
]);
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
beginComputation
(
io
,
periodicBoxSize
,
includeEnergy
);
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
finishComputation
(
io
);
}
else
nonbonded
.
calculateReciprocalIxn
(
numParticles
,
&
posq
[
0
],
posData
,
particleParams
,
exclusions
,
forceData
,
includeEnergy
?
&
nonbondedEnergy
:
NULL
);
}
energy
+=
nonbondedEnergy
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
forceData
[
i
][
0
]
+=
forces
[
4
*
i
];
forceData
[
i
][
1
]
+=
forces
[
4
*
i
+
1
];
forceData
[
i
][
2
]
+=
forces
[
4
*
i
+
2
];
}
if
(
includeDirect
)
{
ReferenceBondForce
refBondForce
;
ReferenceLJCoulomb14
nonbonded14
;
refBondForce
.
calculateForce
(
num14
,
bonded14IndexArray
,
posData
,
bonded14ParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
nonbonded14
);
if
(
periodic
||
ewald
||
pme
)
energy
+=
dispersionCoefficient
/
(
boxSize
[
0
]
*
boxSize
[
1
]
*
boxSize
[
2
]);
}
return
energy
;
}
void
CpuCalcNonbondedForceKernel
::
copyParametersToContext
(
ContextImpl
&
context
,
const
NonbondedForce
&
force
)
{
if
(
force
.
getNumParticles
()
!=
numParticles
)
throw
OpenMMException
(
"updateParametersInContext: The number of particles has changed"
);
vector
<
int
>
nb14s
;
for
(
int
i
=
0
;
i
<
force
.
getNumExceptions
();
i
++
)
{
int
particle1
,
particle2
;
double
chargeProd
,
sigma
,
epsilon
;
force
.
getExceptionParameters
(
i
,
particle1
,
particle2
,
chargeProd
,
sigma
,
epsilon
);
if
(
chargeProd
!=
0.0
||
epsilon
!=
0.0
)
nb14s
.
push_back
(
i
);
}
if
(
nb14s
.
size
()
!=
num14
)
throw
OpenMMException
(
"updateParametersInContext: The number of non-excluded exceptions has changed"
);
// Record the values.
double
sumSquaredCharges
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
double
charge
,
radius
,
depth
;
force
.
getParticleParameters
(
i
,
charge
,
radius
,
depth
);
posq
[
4
*
i
+
3
]
=
(
float
)
charge
;
particleParams
[
i
]
=
make_pair
((
float
)
(
0.5
*
radius
),
(
float
)
(
2.0
*
sqrt
(
depth
)));
sumSquaredCharges
+=
charge
*
charge
;
}
if
(
nonbondedMethod
==
Ewald
||
nonbondedMethod
==
PME
)
ewaldSelfEnergy
=
-
ONE_4PI_EPS0
*
ewaldAlpha
*
sumSquaredCharges
/
sqrt
(
M_PI
);
else
ewaldSelfEnergy
=
0.0
;
for
(
int
i
=
0
;
i
<
num14
;
++
i
)
{
int
particle1
,
particle2
;
double
charge
,
radius
,
depth
;
force
.
getExceptionParameters
(
nb14s
[
i
],
particle1
,
particle2
,
charge
,
radius
,
depth
);
bonded14IndexArray
[
i
][
0
]
=
particle1
;
bonded14IndexArray
[
i
][
1
]
=
particle2
;
bonded14ParamArray
[
i
][
0
]
=
static_cast
<
RealOpenMM
>
(
radius
);
bonded14ParamArray
[
i
][
1
]
=
static_cast
<
RealOpenMM
>
(
4.0
*
depth
);
bonded14ParamArray
[
i
][
2
]
=
static_cast
<
RealOpenMM
>
(
charge
);
}
// Recompute the coefficient for the dispersion correction.
NonbondedForce
::
NonbondedMethod
method
=
force
.
getNonbondedMethod
();
if
(
force
.
getUseDispersionCorrection
()
&&
(
method
==
NonbondedForce
::
CutoffPeriodic
||
method
==
NonbondedForce
::
Ewald
||
method
==
NonbondedForce
::
PME
))
dispersionCoefficient
=
NonbondedForceImpl
::
calcDispersionCorrection
(
context
.
getSystem
(),
force
);
}
platforms/cpu/src/CpuNeighborList.cpp
0 → 100644
View file @
855ece90
#include "CpuNeighborList.h"
#include "openmm/internal/hardware.h"
#include <set>
#include <map>
#include <cmath>
#include <smmintrin.h>
using
namespace
std
;
namespace
OpenMM
{
class
VoxelIndex
{
public:
VoxelIndex
(
int
xx
,
int
yy
,
int
zz
)
:
x
(
xx
),
y
(
yy
),
z
(
zz
)
{
}
// operator<() needed for map
bool
operator
<
(
const
VoxelIndex
&
other
)
const
{
if
(
x
<
other
.
x
)
return
true
;
else
if
(
x
>
other
.
x
)
return
false
;
else
if
(
y
<
other
.
y
)
return
true
;
else
if
(
y
>
other
.
y
)
return
false
;
else
if
(
z
<
other
.
z
)
return
true
;
else
return
false
;
}
int
x
;
int
y
;
int
z
;
};
typedef
pair
<
const
float
*
,
int
>
VoxelItem
;
typedef
vector
<
VoxelItem
>
Voxel
;
class
CpuNeighborList
::
VoxelHash
{
public:
VoxelHash
(
float
vsx
,
float
vsy
,
float
vsz
,
const
float
*
periodicBoxSize
,
bool
usePeriodic
)
:
voxelSizeX
(
vsx
),
voxelSizeY
(
vsy
),
voxelSizeZ
(
vsz
),
periodicBoxSize
(
periodicBoxSize
),
usePeriodic
(
usePeriodic
)
{
if
(
usePeriodic
)
{
nx
=
(
int
)
floorf
(
periodicBoxSize
[
0
]
/
voxelSizeX
+
0.5
f
);
ny
=
(
int
)
floorf
(
periodicBoxSize
[
1
]
/
voxelSizeY
+
0.5
f
);
nz
=
(
int
)
floorf
(
periodicBoxSize
[
2
]
/
voxelSizeZ
+
0.5
f
);
voxelSizeX
=
periodicBoxSize
[
0
]
/
nx
;
voxelSizeY
=
periodicBoxSize
[
1
]
/
ny
;
voxelSizeZ
=
periodicBoxSize
[
2
]
/
nz
;
}
}
void
insert
(
const
int
&
item
,
const
float
*
location
)
{
VoxelIndex
voxelIndex
=
getVoxelIndex
(
location
);
if
(
voxelMap
.
find
(
voxelIndex
)
==
voxelMap
.
end
())
voxelMap
[
voxelIndex
]
=
Voxel
();
Voxel
&
voxel
=
voxelMap
.
find
(
voxelIndex
)
->
second
;
voxel
.
push_back
(
VoxelItem
(
location
,
item
));
}
VoxelIndex
getVoxelIndex
(
const
float
*
location
)
const
{
float
xperiodic
,
yperiodic
,
zperiodic
;
if
(
!
usePeriodic
)
{
xperiodic
=
location
[
0
];
yperiodic
=
location
[
1
];
zperiodic
=
location
[
2
];
}
else
{
xperiodic
=
location
[
0
]
-
periodicBoxSize
[
0
]
*
floorf
(
location
[
0
]
/
periodicBoxSize
[
0
]);
yperiodic
=
location
[
1
]
-
periodicBoxSize
[
1
]
*
floorf
(
location
[
1
]
/
periodicBoxSize
[
1
]);
zperiodic
=
location
[
2
]
-
periodicBoxSize
[
2
]
*
floorf
(
location
[
2
]
/
periodicBoxSize
[
2
]);
}
int
x
=
int
(
floorf
(
xperiodic
/
voxelSizeX
));
int
y
=
int
(
floorf
(
yperiodic
/
voxelSizeY
));
int
z
=
int
(
floorf
(
zperiodic
/
voxelSizeZ
));
return
VoxelIndex
(
x
,
y
,
z
);
}
void
getNeighbors
(
vector
<
pair
<
int
,
int
>
>&
neighbors
,
const
VoxelItem
&
referencePoint
,
const
vector
<
set
<
int
>
>&
exclusions
,
float
maxDistance
)
const
{
// Loop over neighboring voxels
// TODO use more clever selection of neighboring voxels
const
int
atomI
=
referencePoint
.
second
;
const
float
*
locationI
=
referencePoint
.
first
;
__m128
posI
=
_mm_loadu_ps
(
locationI
);
__m128
boxSize
=
_mm_set_ps
(
0
,
periodicBoxSize
[
2
],
periodicBoxSize
[
1
],
periodicBoxSize
[
0
]);
__m128
invBoxSize
=
_mm_set_ps
(
0
,
(
1
/
periodicBoxSize
[
2
]),
(
1
/
periodicBoxSize
[
1
]),
(
1
/
periodicBoxSize
[
0
]));
__m128
half
=
_mm_set1_ps
(
0.5
);
float
maxDistanceSquared
=
maxDistance
*
maxDistance
;
int
dIndexX
=
int
(
maxDistance
/
voxelSizeX
)
+
1
;
// How may voxels away do we have to look?
int
dIndexY
=
int
(
maxDistance
/
voxelSizeY
)
+
1
;
int
dIndexZ
=
int
(
maxDistance
/
voxelSizeZ
)
+
1
;
VoxelIndex
centerVoxelIndex
=
getVoxelIndex
(
locationI
);
int
lastx
=
centerVoxelIndex
.
x
+
dIndexX
;
int
lasty
=
centerVoxelIndex
.
y
+
dIndexY
;
int
lastz
=
centerVoxelIndex
.
z
+
dIndexZ
;
if
(
usePeriodic
)
{
lastx
=
min
(
lastx
,
centerVoxelIndex
.
x
-
dIndexX
+
nx
-
1
);
lasty
=
min
(
lasty
,
centerVoxelIndex
.
y
-
dIndexY
+
ny
-
1
);
lastz
=
min
(
lastz
,
centerVoxelIndex
.
z
-
dIndexZ
+
nz
-
1
);
}
VoxelIndex
voxelIndex
(
0
,
0
,
0
);
for
(
int
x
=
centerVoxelIndex
.
x
-
dIndexX
;
x
<=
lastx
;
++
x
)
{
voxelIndex
.
x
=
x
;
if
(
usePeriodic
)
voxelIndex
.
x
=
(
x
<
0
?
x
+
nx
:
(
x
>=
nx
?
x
-
nx
:
x
));
for
(
int
y
=
centerVoxelIndex
.
y
-
dIndexY
;
y
<=
lasty
;
++
y
)
{
voxelIndex
.
y
=
y
;
if
(
usePeriodic
)
voxelIndex
.
y
=
(
y
<
0
?
y
+
ny
:
(
y
>=
ny
?
y
-
ny
:
y
));
for
(
int
z
=
centerVoxelIndex
.
z
-
dIndexZ
;
z
<=
lastz
;
++
z
)
{
voxelIndex
.
z
=
z
;
if
(
usePeriodic
)
voxelIndex
.
z
=
(
z
<
0
?
z
+
nz
:
(
z
>=
nz
?
z
-
nz
:
z
));
const
map
<
VoxelIndex
,
Voxel
>::
const_iterator
voxelEntry
=
voxelMap
.
find
(
voxelIndex
);
if
(
voxelEntry
==
voxelMap
.
end
())
continue
;
// no such voxel; skip
const
Voxel
&
voxel
=
voxelEntry
->
second
;
for
(
Voxel
::
const_iterator
itemIter
=
voxel
.
begin
();
itemIter
!=
voxel
.
end
();
++
itemIter
)
{
const
int
atomJ
=
itemIter
->
second
;
// Avoid duplicate entries.
if
(
atomJ
>=
atomI
)
break
;
__m128
posJ
=
_mm_loadu_ps
(
itemIter
->
first
);
__m128
delta
=
_mm_sub_ps
(
posJ
,
posI
);
if
(
usePeriodic
)
{
__m128
base
=
_mm_mul_ps
(
_mm_floor_ps
(
_mm_add_ps
(
_mm_mul_ps
(
delta
,
invBoxSize
),
half
)),
boxSize
);
delta
=
_mm_sub_ps
(
delta
,
base
);
}
float
dSquared
=
_mm_cvtss_f32
(
_mm_dp_ps
(
delta
,
delta
,
0x71
));
if
(
dSquared
>
maxDistanceSquared
)
continue
;
// Ignore exclusions.
if
(
exclusions
[
atomI
].
find
(
atomJ
)
!=
exclusions
[
atomI
].
end
())
continue
;
neighbors
.
push_back
(
make_pair
(
atomI
,
atomJ
));
}
}
}
}
}
private:
float
voxelSizeX
,
voxelSizeY
,
voxelSizeZ
;
int
nx
,
ny
,
nz
;
const
float
*
periodicBoxSize
;
const
bool
usePeriodic
;
map
<
VoxelIndex
,
Voxel
>
voxelMap
;
};
class
CpuNeighborList
::
ThreadData
{
public:
ThreadData
(
int
index
,
CpuNeighborList
&
owner
)
:
index
(
index
),
owner
(
owner
)
{
}
int
index
;
CpuNeighborList
&
owner
;
vector
<
pair
<
int
,
int
>
>
threadNeighbors
;
};
static
void
*
threadBody
(
void
*
args
)
{
CpuNeighborList
::
ThreadData
&
data
=
*
reinterpret_cast
<
CpuNeighborList
::
ThreadData
*>
(
args
);
data
.
owner
.
runThread
(
data
.
index
,
data
.
threadNeighbors
);
delete
&
data
;
return
0
;
}
CpuNeighborList
::
CpuNeighborList
()
{
isDeleted
=
false
;
numThreads
=
getNumProcessors
();
pthread_cond_init
(
&
startCondition
,
NULL
);
pthread_cond_init
(
&
endCondition
,
NULL
);
pthread_mutex_init
(
&
lock
,
NULL
);
thread
.
resize
(
numThreads
);
pthread_mutex_lock
(
&
lock
);
waitCount
=
0
;
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
{
ThreadData
*
data
=
new
ThreadData
(
i
,
*
this
);
threadData
.
push_back
(
data
);
pthread_create
(
&
thread
[
i
],
NULL
,
threadBody
,
data
);
}
while
(
waitCount
<
numThreads
)
pthread_cond_wait
(
&
endCondition
,
&
lock
);
pthread_mutex_unlock
(
&
lock
);
}
CpuNeighborList
::~
CpuNeighborList
()
{
isDeleted
=
true
;
pthread_mutex_lock
(
&
lock
);
pthread_cond_broadcast
(
&
startCondition
);
pthread_mutex_unlock
(
&
lock
);
for
(
int
i
=
0
;
i
<
(
int
)
thread
.
size
();
i
++
)
pthread_join
(
thread
[
i
],
NULL
);
pthread_mutex_destroy
(
&
lock
);
pthread_cond_destroy
(
&
startCondition
);
pthread_cond_destroy
(
&
endCondition
);
}
void
CpuNeighborList
::
computeNeighborList
(
int
numAtoms
,
const
vector
<
float
>&
atomLocations
,
const
vector
<
set
<
int
>
>&
exclusions
,
const
float
*
periodicBoxSize
,
bool
usePeriodic
,
float
maxDistance
)
{
// Build the voxel hash.
float
edgeSizeX
,
edgeSizeY
,
edgeSizeZ
;
if
(
!
usePeriodic
)
edgeSizeX
=
edgeSizeY
=
edgeSizeZ
=
maxDistance
;
// TODO - adjust this as needed
else
{
edgeSizeX
=
0.5
f
*
periodicBoxSize
[
0
]
/
floorf
(
periodicBoxSize
[
0
]
/
maxDistance
);
edgeSizeY
=
0.5
f
*
periodicBoxSize
[
1
]
/
floorf
(
periodicBoxSize
[
1
]
/
maxDistance
);
edgeSizeZ
=
0.5
f
*
periodicBoxSize
[
2
]
/
floorf
(
periodicBoxSize
[
2
]
/
maxDistance
);
}
VoxelHash
voxelHash
(
edgeSizeX
,
edgeSizeY
,
edgeSizeZ
,
periodicBoxSize
,
usePeriodic
);
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
voxelHash
.
insert
(
i
,
&
atomLocations
[
4
*
i
]);
// Record the parameters for the threads.
this
->
voxelHash
=
&
voxelHash
;
this
->
exclusions
=
&
exclusions
;
this
->
atomLocations
=
&
atomLocations
[
0
];
this
->
periodicBoxSize
=
periodicBoxSize
;
this
->
numAtoms
=
numAtoms
;
this
->
usePeriodic
=
usePeriodic
;
this
->
maxDistance
=
maxDistance
;
// Signal the threads to start running and wait for them to finish.
pthread_mutex_lock
(
&
lock
);
waitCount
=
0
;
pthread_cond_broadcast
(
&
startCondition
);
while
(
waitCount
<
numThreads
)
pthread_cond_wait
(
&
endCondition
,
&
lock
);
pthread_mutex_unlock
(
&
lock
);
// Combine the results from all the threads.
neighbors
.
clear
();
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
neighbors
.
insert
(
neighbors
.
end
(),
threadData
[
i
]
->
threadNeighbors
.
begin
(),
threadData
[
i
]
->
threadNeighbors
.
end
());
}
const
vector
<
pair
<
int
,
int
>
>&
CpuNeighborList
::
getNeighbors
()
{
return
neighbors
;
}
void
CpuNeighborList
::
runThread
(
int
index
,
vector
<
pair
<
int
,
int
>
>&
threadNeighbors
)
{
while
(
true
)
{
// Wait for the signal to start running.
pthread_mutex_lock
(
&
lock
);
waitCount
++
;
pthread_cond_signal
(
&
endCondition
);
pthread_cond_wait
(
&
startCondition
,
&
lock
);
pthread_mutex_unlock
(
&
lock
);
if
(
isDeleted
)
break
;
// Compute this thread's subset of neighbors.
threadNeighbors
.
clear
();
for
(
int
i
=
index
;
i
<
numAtoms
;
i
+=
numThreads
)
voxelHash
->
getNeighbors
(
threadNeighbors
,
VoxelItem
(
&
atomLocations
[
4
*
i
],
i
),
*
exclusions
,
maxDistance
);
}
}
}
// namespace OpenMM
platforms/cpu/src/CpuNonbondedForce.cpp
0 → 100644
View file @
855ece90
This diff is collapsed.
Click to expand it.
platforms/cpu/src/CpuPlatform.cpp
0 → 100644
View file @
855ece90
/* -------------------------------------------------------------------------- *
* 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) 2013 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 "CpuPlatform.h"
#include "CpuKernelFactory.h"
#include "CpuKernels.h"
#include "openmm/internal/hardware.h"
using
namespace
OpenMM
;
extern
"C"
OPENMM_EXPORT_CPU
void
registerPlatforms
()
{
// Only register this platform if the CPU supports SSE 4.1.
if
(
CpuPlatform
::
isProcessorSupported
())
Platform
::
registerPlatform
(
new
CpuPlatform
());
}
CpuPlatform
::
CpuPlatform
()
{
CpuKernelFactory
*
factory
=
new
CpuKernelFactory
();
registerKernelFactory
(
CalcNonbondedForceKernel
::
Name
(),
factory
);
}
double
CpuPlatform
::
getSpeed
()
const
{
return
10
;
}
bool
CpuPlatform
::
supportsDoublePrecision
()
const
{
return
false
;
}
bool
CpuPlatform
::
isProcessorSupported
()
{
// Make sure the CPU supports SSE 4.1.
int
cpuInfo
[
4
];
cpuid
(
cpuInfo
,
0
);
if
(
cpuInfo
[
0
]
>=
1
)
{
cpuid
(
cpuInfo
,
1
);
return
((
cpuInfo
[
2
]
&
((
int
)
1
<<
19
))
!=
0
);
}
return
false
;
}
platforms/cpu/tests/CMakeLists.txt
0 → 100644
View file @
855ece90
#
# Testing
#
ENABLE_TESTING
()
SET
(
INCLUDE_SERIALIZATION FALSE
)
#SET( INCLUDE_SERIALIZATION TRUE )
IF
(
INCLUDE_SERIALIZATION
)
INCLUDE_DIRECTORIES
(
${
OPENMM_DIR
}
/serialization/include
)
SET
(
SHARED_OPENMM_SERIALIZATION
"OpenMMSerialization"
)
ENDIF
(
INCLUDE_SERIALIZATION
)
# Automatically create tests using files named "Test*.cpp"
FILE
(
GLOB TEST_PROGS
"*Test*.cpp"
)
FOREACH
(
TEST_PROG
${
TEST_PROGS
}
)
GET_FILENAME_COMPONENT
(
TEST_ROOT
${
TEST_PROG
}
NAME_WE
)
# Link with shared library
ADD_EXECUTABLE
(
${
TEST_ROOT
}
${
TEST_PROG
}
)
TARGET_LINK_LIBRARIES
(
${
TEST_ROOT
}
${
SHARED_TARGET
}
)
ADD_TEST
(
${
TEST_ROOT
}
${
EXECUTABLE_OUTPUT_PATH
}
/
${
TEST_ROOT
}
single
)
ENDFOREACH
(
TEST_PROG
${
TEST_PROGS
}
)
platforms/cpu/tests/TestCpuEwald.cpp
0 → 100644
View file @
855ece90
/* -------------------------------------------------------------------------- *
* 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-2013 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 Ewald summation method CPU implementation of NonbondedForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "CpuPlatform.h"
#include "ReferencePlatform.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/internal/ContextImpl.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
CpuPlatform
platform
;
const
double
TOL
=
1e-5
;
void
testEwaldPME
(
bool
includeExceptions
)
{
// Use amorphous NaCl system for the tests
const
int
numParticles
=
894
;
const
double
cutoff
=
1.2
;
const
double
boxSize
=
3.00646
;
double
tol
=
1e-5
;
ReferencePlatform
reference
;
System
system
;
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
Ewald
);
nonbonded
->
setCutoffDistance
(
cutoff
);
nonbonded
->
setEwaldErrorTolerance
(
tol
);
for
(
int
i
=
0
;
i
<
numParticles
/
2
;
i
++
)
system
.
addParticle
(
22.99
);
for
(
int
i
=
0
;
i
<
numParticles
/
2
;
i
++
)
system
.
addParticle
(
35.45
);
for
(
int
i
=
0
;
i
<
numParticles
/
2
;
i
++
)
nonbonded
->
addParticle
(
1.0
,
1.0
,
0.0
);
for
(
int
i
=
0
;
i
<
numParticles
/
2
;
i
++
)
nonbonded
->
addParticle
(
-
1.0
,
1.0
,
0.0
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
system
.
addForce
(
nonbonded
);
vector
<
Vec3
>
positions
(
numParticles
);
#include "nacl_amorph.dat"
if
(
includeExceptions
)
{
// Add some exclusions.
for
(
int
i
=
0
;
i
<
numParticles
-
1
;
i
++
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
i
+
1
];
if
(
sqrt
(
delta
.
dot
(
delta
))
<
0.5
*
cutoff
)
nonbonded
->
addException
(
i
,
i
+
1
,
i
%
2
==
0
?
0.0
:
0.5
,
1.0
,
0.0
);
}
}
// (1) Check whether the Reference and CPU platforms agree when using Ewald Method
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
cpuContext
(
system
,
integrator1
,
platform
);
Context
referenceContext
(
system
,
integrator2
,
reference
);
cpuContext
.
setPositions
(
positions
);
referenceContext
.
setPositions
(
positions
);
State
cpuState
=
cpuContext
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
referenceState
=
referenceContext
.
getState
(
State
::
Forces
|
State
::
Energy
);
tol
=
1e-2
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
referenceState
.
getForces
()[
i
],
cpuState
.
getForces
()[
i
],
tol
);
}
tol
=
1e-5
;
ASSERT_EQUAL_TOL
(
referenceState
.
getPotentialEnergy
(),
cpuState
.
getPotentialEnergy
(),
tol
);
// (2) Check whether Ewald method in CPU is self-consistent
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
Vec3
f
=
cpuState
.
getForces
()[
i
];
norm
+=
f
[
0
]
*
f
[
0
]
+
f
[
1
]
*
f
[
1
]
+
f
[
2
]
*
f
[
2
];
}
norm
=
std
::
sqrt
(
norm
);
const
double
delta
=
5e-3
;
double
step
=
delta
/
norm
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
cpuState
.
getForces
()[
i
];
positions
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
}
VerletIntegrator
integrator3
(
0.01
);
Context
cpuContext2
(
system
,
integrator3
,
platform
);
cpuContext2
.
setPositions
(
positions
);
tol
=
1e-2
;
State
cpuState2
=
cpuContext2
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
cpuState2
.
getPotentialEnergy
()
-
cpuState
.
getPotentialEnergy
())
/
delta
,
tol
)
// (3) Check whether the Reference and CPU platforms agree when using PME
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
cpuContext
.
reinitialize
();
referenceContext
.
reinitialize
();
cpuContext
.
setPositions
(
positions
);
referenceContext
.
setPositions
(
positions
);
cpuState
=
cpuContext
.
getState
(
State
::
Forces
|
State
::
Energy
);
referenceState
=
referenceContext
.
getState
(
State
::
Forces
|
State
::
Energy
);
tol
=
1e-2
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
referenceState
.
getForces
()[
i
],
cpuState
.
getForces
()[
i
],
tol
);
}
tol
=
1e-5
;
ASSERT_EQUAL_TOL
(
referenceState
.
getPotentialEnergy
(),
cpuState
.
getPotentialEnergy
(),
tol
);
// (4) Check whether PME method in CPU is self-consistent
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
Vec3
f
=
cpuState
.
getForces
()[
i
];
norm
+=
f
[
0
]
*
f
[
0
]
+
f
[
1
]
*
f
[
1
]
+
f
[
2
]
*
f
[
2
];
}
norm
=
std
::
sqrt
(
norm
);
step
=
delta
/
norm
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
cpuState
.
getForces
()[
i
];
positions
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
}
VerletIntegrator
integrator4
(
0.01
);
Context
cpuContext3
(
system
,
integrator4
,
platform
);
cpuContext3
.
setPositions
(
positions
);
tol
=
1e-2
;
State
cpuState3
=
cpuContext3
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
cpuState3
.
getPotentialEnergy
()
-
cpuState
.
getPotentialEnergy
())
/
delta
,
tol
)
}
void
testEwald2Ions
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
nonbonded
->
addParticle
(
1.0
,
1
,
0
);
nonbonded
->
addParticle
(
-
1.0
,
1
,
0
);
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
Ewald
);
const
double
cutoff
=
2.0
;
nonbonded
->
setCutoffDistance
(
cutoff
);
nonbonded
->
setEwaldErrorTolerance
(
TOL
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
6
,
0
,
0
),
Vec3
(
0
,
6
,
0
),
Vec3
(
0
,
0
,
6
));
system
.
addForce
(
nonbonded
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
3.048000
,
2.764000
,
3.156000
);
positions
[
1
]
=
Vec3
(
2.809000
,
2.888000
,
2.571000
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
-
123.711
,
64.1877
,
-
302.716
),
forces
[
0
],
10
*
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
123.711
,
-
64.1877
,
302.716
),
forces
[
1
],
10
*
TOL
);
ASSERT_EQUAL_TOL
(
-
217.276
,
state
.
getPotentialEnergy
(),
0.01
/*10*TOL*/
);
}
void
testErrorTolerance
(
NonbondedForce
::
NonbondedMethod
method
)
{
// Create a cloud of random point charges.
const
int
numParticles
=
51
;
const
double
boxWidth
=
5.0
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxWidth
,
0
,
0
),
Vec3
(
0
,
boxWidth
,
0
),
Vec3
(
0
,
0
,
boxWidth
));
NonbondedForce
*
force
=
new
NonbondedForce
();
system
.
addForce
(
force
);
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
force
->
addParticle
(
-
1.0
+
i
*
2.0
/
(
numParticles
-
1
),
1.0
,
0.0
);
positions
[
i
]
=
Vec3
(
boxWidth
*
genrand_real2
(
sfmt
),
boxWidth
*
genrand_real2
(
sfmt
),
boxWidth
*
genrand_real2
(
sfmt
));
}
force
->
setNonbondedMethod
(
method
);
// For various values of the cutoff and error tolerance, see if the actual error is reasonable.
for
(
double
cutoff
=
1.0
;
cutoff
<
boxWidth
/
2
;
cutoff
*=
1.2
)
{
force
->
setCutoffDistance
(
cutoff
);
vector
<
Vec3
>
refForces
;
double
norm
=
0.0
;
for
(
double
tol
=
5e-5
;
tol
<
1e-3
;
tol
*=
2.0
)
{
force
->
setEwaldErrorTolerance
(
tol
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
);
if
(
refForces
.
size
()
==
0
)
{
refForces
=
state
.
getForces
();
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
norm
+=
refForces
[
i
].
dot
(
refForces
[
i
]);
norm
=
sqrt
(
norm
);
}
else
{
double
diff
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
Vec3
delta
=
refForces
[
i
]
-
state
.
getForces
()[
i
];
diff
+=
delta
.
dot
(
delta
);
}
diff
=
sqrt
(
diff
)
/
norm
;
ASSERT
(
diff
<
2
*
tol
);
}
}
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
if
(
!
CpuPlatform
::
isProcessorSupported
())
{
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
return
0
;
}
testEwaldPME
(
false
);
testEwaldPME
(
true
);
// testEwald2Ions();
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
PME
);
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/cpu/tests/TestCpuNeighborList.cpp
0 → 100644
View file @
855ece90
/* -------------------------------------------------------------------------- *
* 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) 2013 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 all the CPU implementation of neighbor list construction.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "CpuNeighborList.h"
#include "CpuPlatform.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <set>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
void
testNeighborList
(
bool
periodic
)
{
const
int
numParticles
=
500
;
const
float
cutoff
=
2.0
f
;
const
float
boxSize
[
3
]
=
{
20.0
f
,
15.0
f
,
22.0
f
};
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
float
>
positions
(
4
*
numParticles
);
for
(
int
i
=
0
;
i
<
4
*
numParticles
;
i
++
)
if
(
i
%
4
<
3
)
positions
[
i
]
=
boxSize
[
i
%
4
]
*
genrand_real2
(
sfmt
);
vector
<
set
<
int
>
>
exclusions
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
int
num
=
min
(
i
+
1
,
10
);
for
(
int
j
=
0
;
j
<
num
;
j
++
)
{
exclusions
[
i
].
insert
(
i
-
j
);
exclusions
[
i
-
j
].
insert
(
i
);
}
}
CpuNeighborList
neighborList
;
neighborList
.
computeNeighborList
(
numParticles
,
positions
,
exclusions
,
boxSize
,
periodic
,
cutoff
);
// Convert the neighbor list to a set for faster lookup.
set
<
pair
<
int
,
int
>
>
neighbors
;
for
(
int
i
=
0
;
i
<
(
int
)
neighborList
.
getNeighbors
().
size
();
i
++
)
{
pair
<
int
,
int
>
entry
=
neighborList
.
getNeighbors
()[
i
];
ASSERT
(
neighbors
.
find
(
entry
)
==
neighbors
.
end
()
&&
neighbors
.
find
(
make_pair
(
entry
.
second
,
entry
.
first
))
==
neighbors
.
end
());
// No duplicates
neighbors
.
insert
(
entry
);
}
// Check each particle pair and figure out whether they should be in the neighbor list.
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
0
;
j
<=
i
;
j
++
)
{
bool
shouldInclude
=
(
exclusions
[
i
].
find
(
j
)
==
exclusions
[
i
].
end
());
float
dx
=
positions
[
4
*
i
]
-
positions
[
4
*
j
];
float
dy
=
positions
[
4
*
i
+
1
]
-
positions
[
4
*
j
+
1
];
float
dz
=
positions
[
4
*
i
+
2
]
-
positions
[
4
*
j
+
2
];
if
(
periodic
)
{
dx
-=
floor
(
dx
/
boxSize
[
0
]
+
0.5
f
)
*
boxSize
[
0
];
dy
-=
floor
(
dy
/
boxSize
[
1
]
+
0.5
f
)
*
boxSize
[
1
];
dz
-=
floor
(
dz
/
boxSize
[
2
]
+
0.5
f
)
*
boxSize
[
2
];
}
if
(
dx
*
dx
+
dy
*
dy
+
dz
*
dz
>
cutoff
*
cutoff
)
shouldInclude
=
false
;
bool
isIncluded
=
(
neighbors
.
find
(
make_pair
(
i
,
j
))
!=
neighbors
.
end
()
||
neighbors
.
find
(
make_pair
(
j
,
i
))
!=
neighbors
.
end
());
ASSERT_EQUAL
(
shouldInclude
,
isIncluded
);
}
}
int
main
()
{
try
{
if
(
!
CpuPlatform
::
isProcessorSupported
())
{
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
return
0
;
}
testNeighborList
(
false
);
testNeighborList
(
true
);
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/cpu/tests/TestCpuNonbondedForce.cpp
0 → 100644
View file @
855ece90
This diff is collapsed.
Click to expand it.
platforms/cpu/tests/nacl_amorph.dat
0 → 100644
View file @
855ece90
This diff is collapsed.
Click to expand it.
platforms/cuda/src/CudaIntegrationUtilities.cpp
View file @
855ece90
...
...
@@ -123,15 +123,21 @@ CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const S
// Record the set of constraints and how many constraints each atom is involved in.
int
numConstraints
=
system
.
getNumConstraints
();
vector
<
int
>
atom1
(
numConstraints
);
vector
<
int
>
atom2
(
numConstraints
);
vector
<
double
>
distance
(
numConstraints
);
vector
<
int
>
atom1
;
vector
<
int
>
atom2
;
vector
<
double
>
distance
;
vector
<
int
>
constraintCount
(
context
.
getNumAtoms
(),
0
);
for
(
int
i
=
0
;
i
<
numConstraints
;
i
++
)
{
system
.
getConstraintParameters
(
i
,
atom1
[
i
],
atom2
[
i
],
distance
[
i
]);
constraintCount
[
atom1
[
i
]]
++
;
constraintCount
[
atom2
[
i
]]
++
;
for
(
int
i
=
0
;
i
<
system
.
getNumConstraints
();
i
++
)
{
int
p1
,
p2
;
double
d
;
system
.
getConstraintParameters
(
i
,
p1
,
p2
,
d
);
if
(
system
.
getParticleMass
(
p1
)
!=
0
||
system
.
getParticleMass
(
p2
)
!=
0
)
{
atom1
.
push_back
(
p1
);
atom2
.
push_back
(
p2
);
distance
.
push_back
(
d
);
constraintCount
[
p1
]
++
;
constraintCount
[
p2
]
++
;
}
}
// Identify clusters of three atoms that can be treated with SETTLE. First, for every
...
...
platforms/cuda/tests/TestCudaBrownianIntegrator.cpp
View file @
855ece90
...
...
@@ -172,6 +172,37 @@ void testConstraints() {
}
}
void
testConstrainedMasslessParticles
()
{
System
system
;
system
.
addParticle
(
0.0
);
system
.
addParticle
(
1.0
);
system
.
addConstraint
(
0
,
1
,
1.5
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
BrownianIntegrator
integrator
(
300.0
,
2.0
,
0.01
);
bool
failed
=
false
;
try
{
// This should throw an exception.
Context
context
(
system
,
integrator
,
platform
);
}
catch
(
exception
&
ex
)
{
failed
=
true
;
}
ASSERT
(
failed
);
// Now make both particles massless, which should work.
system
.
setParticleMass
(
1
,
0.0
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
300.0
);
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Velocities
);
ASSERT_EQUAL
(
0.0
,
state
.
getVelocities
()[
0
][
0
]);
}
void
testRandomSeed
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
...
...
@@ -237,6 +268,7 @@ int main(int argc, char* argv[]) {
testSingleBond
();
testTemperature
();
testConstraints
();
testConstrainedMasslessParticles
();
testRandomSeed
();
}
catch
(
const
exception
&
e
)
{
...
...
platforms/cuda/tests/TestCudaCustomIntegrator.cpp
View file @
855ece90
...
...
@@ -233,6 +233,43 @@ void testVelocityConstraints() {
}
}
void
testConstrainedMasslessParticles
()
{
System
system
;
system
.
addParticle
(
0.0
);
system
.
addParticle
(
1.0
);
system
.
addConstraint
(
0
,
1
,
1.5
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
CustomIntegrator
integrator
(
0.002
);
integrator
.
addPerDofVariable
(
"oldx"
,
0
);
integrator
.
addComputePerDof
(
"v"
,
"v+dt*f/m"
);
integrator
.
addComputePerDof
(
"oldx"
,
"x"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
integrator
.
addConstrainPositions
();
integrator
.
addComputePerDof
(
"v"
,
"(x-oldx)/dt"
);
bool
failed
=
false
;
try
{
// This should throw an exception.
Context
context
(
system
,
integrator
,
platform
);
}
catch
(
exception
&
ex
)
{
failed
=
true
;
}
ASSERT
(
failed
);
// Now make both particles massless, which should work.
system
.
setParticleMass
(
1
,
0.0
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
300.0
);
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Velocities
|
State
::
Positions
);
ASSERT_EQUAL
(
0.0
,
state
.
getVelocities
()[
0
][
0
]);
}
/**
* Test an integrator with an AndersenThermostat to see if updateContextState()
* is being handled correctly.
...
...
@@ -724,6 +761,7 @@ int main(int argc, char* argv[]) {
testSingleBond
();
testConstraints
();
testVelocityConstraints
();
testConstrainedMasslessParticles
();
testWithThermostat
();
testMonteCarlo
();
testSum
();
...
...
platforms/cuda/tests/TestCudaLangevinIntegrator.cpp
View file @
855ece90
...
...
@@ -177,6 +177,37 @@ void testConstraints() {
}
}
void
testConstrainedMasslessParticles
()
{
System
system
;
system
.
addParticle
(
0.0
);
system
.
addParticle
(
1.0
);
system
.
addConstraint
(
0
,
1
,
1.5
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
LangevinIntegrator
integrator
(
300.0
,
2.0
,
0.01
);
bool
failed
=
false
;
try
{
// This should throw an exception.
Context
context
(
system
,
integrator
,
platform
);
}
catch
(
exception
&
ex
)
{
failed
=
true
;
}
ASSERT
(
failed
);
// Now make both particles massless, which should work.
system
.
setParticleMass
(
1
,
0.0
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
300.0
);
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Velocities
);
ASSERT_EQUAL
(
0.0
,
state
.
getVelocities
()[
0
][
0
]);
}
void
testRandomSeed
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
...
...
@@ -241,6 +272,7 @@ int main(int argc, char* argv[]) {
testSingleBond
();
testTemperature
();
testConstraints
();
testConstrainedMasslessParticles
();
testRandomSeed
();
}
catch
(
const
exception
&
e
)
{
...
...
platforms/cuda/tests/TestCudaVariableLangevinIntegrator.cpp
View file @
855ece90
...
...
@@ -172,6 +172,37 @@ void testConstraints() {
}
}
void
testConstrainedMasslessParticles
()
{
System
system
;
system
.
addParticle
(
0.0
);
system
.
addParticle
(
1.0
);
system
.
addConstraint
(
0
,
1
,
1.5
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
VariableLangevinIntegrator
integrator
(
300.0
,
2.0
,
0.01
);
bool
failed
=
false
;
try
{
// This should throw an exception.
Context
context
(
system
,
integrator
,
platform
);
}
catch
(
exception
&
ex
)
{
failed
=
true
;
}
ASSERT
(
failed
);
// Now make both particles massless, which should work.
system
.
setParticleMass
(
1
,
0.0
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
300.0
);
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Velocities
);
ASSERT_EQUAL
(
0.0
,
state
.
getVelocities
()[
0
][
0
]);
}
void
testRandomSeed
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
...
...
@@ -295,6 +326,7 @@ int main(int argc, char* argv[]) {
testSingleBond
();
testTemperature
();
testConstraints
();
testConstrainedMasslessParticles
();
testRandomSeed
();
testArgonBox
();
}
...
...
Prev
1
2
3
4
5
6
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