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
ad4e1203
".github/vscode:/vscode.git/clone" did not exist on "dfc9ef1c3d730b005c8a5041fe5a7dc66b8af213"
Commit
ad4e1203
authored
Sep 24, 2009
by
Peter Eastman
Browse files
Continuing implementation of OpenCL platform.
parent
dca7d339
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
553 additions
and
99 deletions
+553
-99
platforms/opencl/src/OpenCLArray.h
platforms/opencl/src/OpenCLArray.h
+8
-2
platforms/opencl/src/OpenCLContext.cpp
platforms/opencl/src/OpenCLContext.cpp
+63
-20
platforms/opencl/src/OpenCLContext.h
platforms/opencl/src/OpenCLContext.h
+85
-5
platforms/opencl/src/OpenCLForceInfo.cpp
platforms/opencl/src/OpenCLForceInfo.cpp
+46
-0
platforms/opencl/src/OpenCLForceInfo.h
platforms/opencl/src/OpenCLForceInfo.h
+87
-0
platforms/opencl/src/OpenCLKernelFactory.cpp
platforms/opencl/src/OpenCLKernelFactory.cpp
+2
-2
platforms/opencl/src/OpenCLKernels.cpp
platforms/opencl/src/OpenCLKernels.cpp
+84
-34
platforms/opencl/src/OpenCLKernels.h
platforms/opencl/src/OpenCLKernels.h
+41
-35
platforms/opencl/src/OpenCLPlatform.cpp
platforms/opencl/src/OpenCLPlatform.cpp
+1
-1
platforms/opencl/src/kernels/harmonicBondForce.cl
platforms/opencl/src/kernels/harmonicBondForce.cl
+29
-0
platforms/opencl/src/kernels/utilities.cl
platforms/opencl/src/kernels/utilities.cl
+21
-0
platforms/opencl/tests/TestOpenCLHarmonicBondForce.cpp
platforms/opencl/tests/TestOpenCLHarmonicBondForce.cpp
+86
-0
No files found.
platforms/opencl/src/OpenCLArray.h
View file @
ad4e1203
...
@@ -83,6 +83,12 @@ public:
...
@@ -83,6 +83,12 @@ public:
int
getSize
()
{
int
getSize
()
{
return
size
;
return
size
;
}
}
/**
* Get the name of the array.
*/
const
std
::
string
&
getName
()
{
return
name
;
}
/**
/**
* Get the OpenCL Buffer object.
* Get the OpenCL Buffer object.
*/
*/
...
@@ -111,13 +117,13 @@ public:
...
@@ -111,13 +117,13 @@ public:
* Copy the values in a vector to the Buffer.
* Copy the values in a vector to the Buffer.
*/
*/
void
upload
(
std
::
vector
<
T
>&
data
)
{
void
upload
(
std
::
vector
<
T
>&
data
)
{
context
.
getQueue
().
enqueueWriteBuffer
(
*
buffer
,
true
,
0
,
size
*
sizeof
(
T
),
&
data
[
0
]);
context
.
getQueue
().
enqueueWriteBuffer
(
*
buffer
,
CL_TRUE
,
0
,
size
*
sizeof
(
T
),
&
data
[
0
]);
}
}
/**
/**
* Copy the values in the Buffer to a vector.
* Copy the values in the Buffer to a vector.
*/
*/
void
download
(
std
::
vector
<
T
>&
data
)
const
{
void
download
(
std
::
vector
<
T
>&
data
)
const
{
context
.
getQueue
().
enqueueReadBuffer
(
*
buffer
,
true
,
0
,
size
*
sizeof
(
T
),
&
data
[
0
]);
context
.
getQueue
().
enqueueReadBuffer
(
*
buffer
,
CL_TRUE
,
0
,
size
*
sizeof
(
T
),
&
data
[
0
]);
}
}
/**
/**
* Copy the values in the host buffer to the OpenCL Buffer.
* Copy the values in the host buffer to the OpenCL Buffer.
...
...
platforms/opencl/src/OpenCLContext.cpp
View file @
ad4e1203
...
@@ -26,16 +26,19 @@
...
@@ -26,16 +26,19 @@
#include "OpenCLContext.h"
#include "OpenCLContext.h"
#include "OpenCLArray.h"
#include "OpenCLArray.h"
#include "OpenCLForceInfo.h"
#include "openmm/Platform.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include <fstream>
#include <fstream>
#include <iostream>
#include <iostream>
#include <sstream>
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
OpenCLContext
::
OpenCLContext
(
int
numParticles
,
int
platformIndex
,
int
deviceIndex
)
{
OpenCLContext
::
OpenCLContext
(
int
numParticles
,
int
platformIndex
,
int
deviceIndex
)
{
// TODO Select the platform and device correctly
// TODO Select the platform and device correctly
context
=
cl
::
Context
(
CL_DEVICE_TYPE_
C
PU
);
context
=
cl
::
Context
(
CL_DEVICE_TYPE_
G
PU
);
device
=
context
.
getInfo
<
CL_CONTEXT_DEVICES
>
()[
0
];
device
=
context
.
getInfo
<
CL_CONTEXT_DEVICES
>
()[
0
];
queue
=
cl
::
CommandQueue
(
context
,
device
);
queue
=
cl
::
CommandQueue
(
context
,
device
);
numAtoms
=
numParticles
;
numAtoms
=
numParticles
;
...
@@ -43,36 +46,55 @@ OpenCLContext::OpenCLContext(int numParticles, int platformIndex, int deviceInde
...
@@ -43,36 +46,55 @@ OpenCLContext::OpenCLContext(int numParticles, int platformIndex, int deviceInde
numAtomBlocks
=
(
paddedNumAtoms
+
(
TileSize
-
1
))
/
TileSize
;
numAtomBlocks
=
(
paddedNumAtoms
+
(
TileSize
-
1
))
/
TileSize
;
numTiles
=
numAtomBlocks
*
(
numAtomBlocks
+
1
)
/
2
;
numTiles
=
numAtomBlocks
*
(
numAtomBlocks
+
1
)
/
2
;
numThreadBlocks
=
8
*
device
.
getInfo
<
CL_DEVICE_MAX_COMPUTE_UNITS
>
();
numThreadBlocks
=
8
*
device
.
getInfo
<
CL_DEVICE_MAX_COMPUTE_UNITS
>
();
forceBufferPerWarp
=
true
;
numForceBuffers
=
numThreadBlocks
*
ThreadBlockSize
/
TileSize
;
if
(
numForceBuffers
>=
numAtomBlocks
)
{
// For small systems, it is more efficient to have one force buffer per block of 32 atoms instead of one per warp.
forceBufferPerWarp
=
false
;
numForceBuffers
=
numAtomBlocks
;
}
posq
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
paddedNumAtoms
,
"posq"
,
true
);
velm
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
paddedNumAtoms
,
"velm"
,
true
);
forceBuffers
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
paddedNumAtoms
*
numForceBuffers
,
"forceBuffers"
,
false
);
force
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
&
forceBuffers
->
getDeviceBuffer
(),
paddedNumAtoms
,
"force"
,
true
);
atomIndex
=
new
OpenCLArray
<
cl_int
>
(
*
this
,
paddedNumAtoms
,
"atomIndex"
,
true
);
for
(
int
i
=
0
;
i
<
paddedNumAtoms
;
++
i
)
atomIndex
->
set
(
i
,
i
);
atomIndex
->
upload
();
// Create utility kernels that are used in multiple places.
// Create utility kernels that are used in multiple places.
utilities
=
createProgram
(
loadSourceFromFile
(
"utilities.cl"
));
utilities
=
createProgram
(
loadSourceFromFile
(
"utilities.cl"
));
clearBufferKernel
=
cl
::
Kernel
(
utilities
,
"clearBuffer"
);
clearBufferKernel
=
cl
::
Kernel
(
utilities
,
"clearBuffer"
);
reduceFloat4Kernel
=
cl
::
Kernel
(
utilities
,
"reduceFloat4Buffer"
);
}
}
OpenCLContext
::~
OpenCLContext
()
{
OpenCLContext
::~
OpenCLContext
()
{
for
(
int
i
=
0
;
i
<
(
int
)
forces
.
size
();
i
++
)
delete
forces
[
i
];
delete
posq
;
delete
posq
;
delete
velm
;
delete
velm
;
delete
force
;
delete
force
;
delete
forceBuffers
;
delete
energyBuffer
;
delete
atomIndex
;
delete
atomIndex
;
}
}
void
OpenCLContext
::
initialize
(
const
System
&
system
)
{
// forceBufferPerWarp = true;
// numForceBuffers = numThreadBlocks*ThreadBlockSize/TileSize;
// if (numForceBuffers >= numAtomBlocks) {
// // For small systems, it is more efficient to have one force buffer per block of 32 atoms instead of one per warp.
//
// forceBufferPerWarp = false;
// numForceBuffers = numAtomBlocks;
// }
posq
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
paddedNumAtoms
,
"posq"
,
true
);
velm
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
paddedNumAtoms
,
"velm"
,
true
);
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
(
*
velm
)[
i
].
w
=
system
.
getParticleMass
(
i
);
velm
->
upload
();
numForceBuffers
=
1
;
for
(
int
i
=
0
;
i
<
(
int
)
forces
.
size
();
i
++
)
numForceBuffers
=
std
::
max
(
numForceBuffers
,
forces
[
i
]
->
getRequiredForceBuffers
());
forceBuffers
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
paddedNumAtoms
*
numForceBuffers
,
"forceBuffers"
,
false
);
force
=
new
OpenCLArray
<
mm_float4
>
(
*
this
,
&
forceBuffers
->
getDeviceBuffer
(),
paddedNumAtoms
,
"force"
,
true
);
energyBuffer
=
new
OpenCLArray
<
cl_float
>
(
*
this
,
numThreadBlocks
*
ThreadBlockSize
,
"energyBuffer"
,
true
);
atomIndex
=
new
OpenCLArray
<
cl_int
>
(
*
this
,
paddedNumAtoms
,
"atomIndex"
,
true
);
for
(
int
i
=
0
;
i
<
paddedNumAtoms
;
++
i
)
(
*
atomIndex
)[
i
]
=
i
;
atomIndex
->
upload
();
}
void
OpenCLContext
::
addForce
(
OpenCLForceInfo
*
force
)
{
forces
.
push_back
(
force
);
}
string
OpenCLContext
::
loadSourceFromFile
(
const
string
&
filename
)
const
{
string
OpenCLContext
::
loadSourceFromFile
(
const
string
&
filename
)
const
{
ifstream
file
((
Platform
::
getDefaultPluginsDirectory
()
+
"/opencl/"
+
filename
).
c_str
());
ifstream
file
((
Platform
::
getDefaultPluginsDirectory
()
+
"/opencl/"
+
filename
).
c_str
());
if
(
!
file
.
is_open
())
if
(
!
file
.
is_open
())
...
@@ -99,14 +121,35 @@ cl::Program OpenCLContext::createProgram(const std::string source) {
...
@@ -99,14 +121,35 @@ cl::Program OpenCLContext::createProgram(const std::string source) {
return
program
;
return
program
;
}
}
void
OpenCLContext
::
executeKernel
(
cl
::
Kernel
&
kernel
,
int
workUnits
)
{
int
size
=
std
::
min
((
workUnits
+
ThreadBlockSize
-
1
)
/
ThreadBlockSize
,
numThreadBlocks
)
*
ThreadBlockSize
;
try
{
queue
.
enqueueNDRangeKernel
(
kernel
,
cl
::
NullRange
,
cl
::
NDRange
(
size
),
cl
::
NDRange
(
ThreadBlockSize
));
}
catch
(
cl
::
Error
err
)
{
stringstream
str
;
str
<<
"Error invoking kernel "
;
str
<<
kernel
.
getInfo
<
CL_KERNEL_FUNCTION_NAME
>
()
<<
": "
<<
err
.
what
()
<<
" ("
<<
err
.
err
()
<<
")"
;
throw
OpenMMException
(
str
.
str
());
}
}
void
OpenCLContext
::
clearBuffer
(
OpenCLArray
<
float
>&
array
)
{
void
OpenCLContext
::
clearBuffer
(
OpenCLArray
<
float
>&
array
)
{
clearBufferKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
array
.
getDeviceBuffer
());
clearBufferKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
array
.
getDeviceBuffer
());
clearBufferKernel
.
setArg
<
cl_int
>
(
1
,
array
.
getSize
());
clearBufferKernel
.
setArg
<
cl_int
>
(
1
,
array
.
getSize
());
queue
.
enqueueNDRang
eKernel
(
clearBufferKernel
,
cl
::
NullRange
,
cl
::
NDRange
(
numThreadBlocks
*
ThreadBlockSize
),
cl
::
NDRange
(
ThreadBlock
Size
));
execut
eKernel
(
clearBufferKernel
,
array
.
get
Size
(
));
}
}
void
OpenCLContext
::
clearBuffer
(
OpenCLArray
<
mm_float4
>&
array
)
{
void
OpenCLContext
::
clearBuffer
(
OpenCLArray
<
mm_float4
>&
array
)
{
clearBufferKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
array
.
getDeviceBuffer
());
clearBufferKernel
.
setArg
<
cl
::
Buffer
>
(
0
,
array
.
getDeviceBuffer
());
clearBufferKernel
.
setArg
<
cl_int
>
(
1
,
array
.
getSize
()
*
4
);
clearBufferKernel
.
setArg
<
cl_int
>
(
1
,
array
.
getSize
()
*
4
);
queue
.
enqueueNDRangeKernel
(
clearBufferKernel
,
cl
::
NullRange
,
cl
::
NDRange
(
numThreadBlocks
*
ThreadBlockSize
),
cl
::
NDRange
(
ThreadBlockSize
));
executeKernel
(
clearBufferKernel
,
array
.
getSize
()
*
4
);
}
}
\ No newline at end of file
void
OpenCLContext
::
reduceBuffer
(
OpenCLArray
<
mm_float4
>&
array
,
int
numBuffers
)
{
int
bufferSize
=
array
.
getSize
()
/
numBuffers
;
reduceFloat4Kernel
.
setArg
<
cl
::
Buffer
>
(
0
,
array
.
getDeviceBuffer
());
reduceFloat4Kernel
.
setArg
<
cl_int
>
(
1
,
bufferSize
);
reduceFloat4Kernel
.
setArg
<
cl_int
>
(
2
,
numBuffers
);
executeKernel
(
reduceFloat4Kernel
,
bufferSize
);
}
platforms/opencl/src/OpenCLContext.h
View file @
ad4e1203
...
@@ -34,16 +34,27 @@ namespace OpenMM {
...
@@ -34,16 +34,27 @@ namespace OpenMM {
template
<
class
T
>
template
<
class
T
>
class
OpenCLArray
;
class
OpenCLArray
;
class
OpenCLForceInfo
;
class
System
;
/**
/**
* We can't use cl_float4, since different OpenCL implementations currently define
it in
* We can't use
predefined vector types like
cl_float4, since different OpenCL implementations currently define
* incompatible ways. Hopefully that will be fixed in the future. In the mean time, we
*
them in
incompatible ways. Hopefully that will be fixed in the future. In the mean time, we
define our own
*
define our own
type to represent
float4
on the host.
* type
s
to represent
them
on the host.
*/
*/
typedef
struct
{
cl_float
x
,
y
;
}
mm_float2
;
typedef
struct
{
typedef
struct
{
cl_float
x
,
y
,
z
,
w
;
cl_float
x
,
y
,
z
,
w
;
}
mm_float4
;
}
mm_float4
;
typedef
struct
{
cl_int
x
,
y
;
}
mm_int2
;
typedef
struct
{
cl_int
x
,
y
,
z
,
w
;
}
mm_int4
;
/**
/**
* This class contains the information associated with a Context by the OpenCL Platform.
* This class contains the information associated with a Context by the OpenCL Platform.
...
@@ -55,6 +66,15 @@ public:
...
@@ -55,6 +66,15 @@ public:
static
const
int
TileSize
=
32
;
static
const
int
TileSize
=
32
;
OpenCLContext
(
int
numParticles
,
int
platformIndex
,
int
deviceIndex
);
OpenCLContext
(
int
numParticles
,
int
platformIndex
,
int
deviceIndex
);
~
OpenCLContext
();
~
OpenCLContext
();
/**
* This is called to initialize internal data structures after all Forces in the system
* have been initialized.
*/
void
initialize
(
const
System
&
system
);
/**
* Add an OpenCLForce to this context.
*/
void
addForce
(
OpenCLForceInfo
*
force
);
/**
/**
* Get the cl::Context associated with this object.
* Get the cl::Context associated with this object.
*/
*/
...
@@ -91,6 +111,12 @@ public:
...
@@ -91,6 +111,12 @@ public:
OpenCLArray
<
mm_float4
>&
getForceBuffers
()
{
OpenCLArray
<
mm_float4
>&
getForceBuffers
()
{
return
*
forceBuffers
;
return
*
forceBuffers
;
}
}
/**
* Get the array which contains the buffer in which energy is computed.
*/
OpenCLArray
<
cl_float
>&
getEnergyBuffer
()
{
return
*
energyBuffer
;
}
/**
/**
* Get the array which contains the index of each atom.
* Get the array which contains the index of each atom.
*/
*/
...
@@ -105,6 +131,13 @@ public:
...
@@ -105,6 +131,13 @@ public:
* Create an OpenCL Program from source code.
* Create an OpenCL Program from source code.
*/
*/
cl
::
Program
createProgram
(
const
std
::
string
source
);
cl
::
Program
createProgram
(
const
std
::
string
source
);
/**
* Execute a kernel.
*
* @param kernel the kernel to execute
* @param workUnits the maximum number of work units that should be used
*/
void
executeKernel
(
cl
::
Kernel
&
kernel
,
int
workUnits
);
/**
/**
* Set all elements of an array to 0.
* Set all elements of an array to 0.
*/
*/
...
@@ -113,23 +146,70 @@ public:
...
@@ -113,23 +146,70 @@ public:
* Set all elements of an array to 0.
* Set all elements of an array to 0.
*/
*/
void
clearBuffer
(
OpenCLArray
<
mm_float4
>&
array
);
void
clearBuffer
(
OpenCLArray
<
mm_float4
>&
array
);
/**
* Given a collection of buffers packed into an array, sum them and store
* the sum in the first buffer.
*
* @param array the array containing the buffers to reduce
* @param numBuffers the number of buffers packed into the array
*/
void
reduceBuffer
(
OpenCLArray
<
mm_float4
>&
array
,
int
numBuffers
);
/**
* Get the number of atoms.
*/
int
getNumAtoms
()
const
{
return
numAtoms
;
}
/**
* Get the number of atoms, rounded up to a multiple of TileSize. This is the actual size of
* most arrays with one element per atom.
*/
int
getPaddedNumAtoms
()
const
{
return
paddedNumAtoms
;
}
/**
* Get the number of blocks of TileSize atoms.
*/
int
getNumAtomBlocks
()
const
{
return
numAtomBlocks
;
}
/**
* Get the standard number of thread blocks to use when executing kernels.
*/
int
getNumThreadBlocks
()
const
{
return
numThreadBlocks
;
}
/**
* Get the total number of tiles used for nonbonded computation.
*/
int
getNumTiles
()
const
{
return
numTiles
;
}
/**
* Get the number of force buffers.
*/
int
getNumForceBuffers
()
const
{
return
numForceBuffers
;
}
private:
int
numAtoms
;
int
numAtoms
;
int
paddedNumAtoms
;
int
paddedNumAtoms
;
int
numAtomBlocks
;
int
numAtomBlocks
;
int
numTiles
;
int
numTiles
;
int
numThreadBlocks
;
int
numThreadBlocks
;
int
numForceBuffers
;
int
numForceBuffers
;
bool
forceBufferPerWarp
;
private:
cl
::
Context
context
;
cl
::
Context
context
;
cl
::
Device
device
;
cl
::
Device
device
;
cl
::
CommandQueue
queue
;
cl
::
CommandQueue
queue
;
cl
::
Program
utilities
;
cl
::
Program
utilities
;
cl
::
Kernel
clearBufferKernel
;
cl
::
Kernel
clearBufferKernel
;
cl
::
Kernel
reduceFloat4Kernel
;
std
::
vector
<
OpenCLForceInfo
*>
forces
;
OpenCLArray
<
mm_float4
>*
posq
;
OpenCLArray
<
mm_float4
>*
posq
;
OpenCLArray
<
mm_float4
>*
velm
;
OpenCLArray
<
mm_float4
>*
velm
;
OpenCLArray
<
mm_float4
>*
force
;
OpenCLArray
<
mm_float4
>*
force
;
OpenCLArray
<
mm_float4
>*
forceBuffers
;
OpenCLArray
<
mm_float4
>*
forceBuffers
;
OpenCLArray
<
cl_float
>*
energyBuffer
;
OpenCLArray
<
cl_int
>*
atomIndex
;
OpenCLArray
<
cl_int
>*
atomIndex
;
};
};
...
...
platforms/opencl/src/OpenCLForceInfo.cpp
0 → 100644
View file @
ad4e1203
/* -------------------------------------------------------------------------- *
* 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) 2009 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "OpenCLForceInfo.h"
using
namespace
OpenMM
;
using
namespace
std
;
bool
OpenCLForceInfo
::
areParticlesIdentical
()
{
return
true
;
}
int
OpenCLForceInfo
::
getNumParticleGroups
()
{
return
0
;
}
void
OpenCLForceInfo
::
getParticlesInGroup
(
int
index
,
vector
<
int
>&
particles
)
{
return
;
}
bool
OpenCLForceInfo
::
areGroupsIdentical
(
int
group1
,
int
group2
)
{
return
true
;
}
platforms/opencl/src/OpenCLForceInfo.h
0 → 100644
View file @
ad4e1203
#ifndef OPENMM_OPENCLFORCEINFO_H_
#define OPENMM_OPENCLFORCEINFO_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) 2009 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include <vector>
namespace
OpenMM
{
/**
* This class is used by the OpenCL implementation of a Force class to convey information
* about the behavior and requirements of that force.
*/
class
OpenCLForceInfo
{
public:
OpenCLForceInfo
(
int
requiredForceBuffers
,
bool
usesNeighborList
,
double
cutoffDistance
)
:
requiredForceBuffers
(
requiredForceBuffers
),
usesNeighborList
(
usesNeighborList
),
cutoffDistance
(
cutoffDistance
)
{
}
/**
* Get the number of force buffers this force requires.
*/
int
getRequiredForceBuffers
()
{
return
requiredForceBuffers
;
}
/**
* Get whether or not this force makes use of the neighbor list.
*/
bool
getUsesNeighborList
()
{
return
usesNeighborList
;
}
/**
* Get the cutoff distance used by this force. If usesNeighborList() returns false,
* the return value from this method is ignored.
*/
double
getCutoffDistance
()
{
return
cutoffDistance
;
}
/**
* Get whether or not two particles have identical force field parameters.
*/
virtual
bool
areParticlesIdentical
();
/**
* Get the number of particle groups defined by this force.
*/
virtual
int
getNumParticleGroups
();
/**
* Get the list of particles in a particular group.
*/
virtual
void
getParticlesInGroup
(
int
index
,
std
::
vector
<
int
>&
particles
);
/**
* Get whether two particle groups are identical.
*/
virtual
bool
areGroupsIdentical
(
int
group1
,
int
group2
);
private:
int
requiredForceBuffers
;
bool
usesNeighborList
;
double
cutoffDistance
;
};
}
// namespace OpenMM
#endif
/*OPENMM_OPENCLFORCEINFO_H_*/
platforms/opencl/src/OpenCLKernelFactory.cpp
View file @
ad4e1203
...
@@ -37,8 +37,8 @@ KernelImpl* OpenCLKernelFactory::createKernelImpl(std::string name, const Platfo
...
@@ -37,8 +37,8 @@ KernelImpl* OpenCLKernelFactory::createKernelImpl(std::string name, const Platfo
return
new
OpenCLCalcForcesAndEnergyKernel
(
name
,
platform
,
data
);
return
new
OpenCLCalcForcesAndEnergyKernel
(
name
,
platform
,
data
);
if
(
name
==
UpdateStateDataKernel
::
Name
())
if
(
name
==
UpdateStateDataKernel
::
Name
())
return
new
OpenCLUpdateStateDataKernel
(
name
,
platform
,
data
);
return
new
OpenCLUpdateStateDataKernel
(
name
,
platform
,
data
);
//
if (name == CalcHarmonicBondForceKernel::Name())
if
(
name
==
CalcHarmonicBondForceKernel
::
Name
())
//
return new OpenCLCalcHarmonicBondForceKernel(name, platform, data, context.getSystem());
return
new
OpenCLCalcHarmonicBondForceKernel
(
name
,
platform
,
data
,
context
.
getSystem
());
// if (name == CalcHarmonicAngleForceKernel::Name())
// if (name == CalcHarmonicAngleForceKernel::Name())
// return new OpenCLCalcHarmonicAngleForceKernel(name, platform, data, context.getSystem());
// return new OpenCLCalcHarmonicAngleForceKernel(name, platform, data, context.getSystem());
// if (name == CalcPeriodicTorsionForceKernel::Name())
// if (name == CalcPeriodicTorsionForceKernel::Name())
...
...
platforms/opencl/src/OpenCLKernels.cpp
View file @
ad4e1203
...
@@ -24,9 +24,8 @@
...
@@ -24,9 +24,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "OpenCLArray.h"
#include "OpenCLKernels.h"
#include "OpenCLKernels.h"
#include "OpenCL
Context
.h"
#include "OpenCL
ForceInfo
.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/Context.h"
#include "openmm/Context.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/ContextImpl.h"
...
@@ -43,13 +42,20 @@ void OpenCLCalcForcesAndEnergyKernel::beginForceComputation(ContextImpl& context
...
@@ -43,13 +42,20 @@ void OpenCLCalcForcesAndEnergyKernel::beginForceComputation(ContextImpl& context
}
}
void
OpenCLCalcForcesAndEnergyKernel
::
finishForceComputation
(
ContextImpl
&
context
)
{
void
OpenCLCalcForcesAndEnergyKernel
::
finishForceComputation
(
ContextImpl
&
context
)
{
data
.
context
->
reduceBuffer
(
data
.
context
->
getForceBuffers
(),
data
.
context
->
getNumForceBuffers
());
}
}
void
OpenCLCalcForcesAndEnergyKernel
::
beginEnergyComputation
(
ContextImpl
&
context
)
{
void
OpenCLCalcForcesAndEnergyKernel
::
beginEnergyComputation
(
ContextImpl
&
context
)
{
data
.
context
->
clearBuffer
(
data
.
context
->
getEnergyBuffer
());
}
}
double
OpenCLCalcForcesAndEnergyKernel
::
finishEnergyComputation
(
ContextImpl
&
context
)
{
double
OpenCLCalcForcesAndEnergyKernel
::
finishEnergyComputation
(
ContextImpl
&
context
)
{
return
0.0
;
OpenCLArray
<
cl_float
>&
energy
=
data
.
context
->
getEnergyBuffer
();
energy
.
download
();
double
sum
=
0.0
f
;
for
(
int
i
=
0
;
i
<
energy
.
getSize
();
i
++
)
sum
+=
energy
[
i
];
return
sum
;
}
}
void
OpenCLUpdateStateDataKernel
::
initialize
(
const
System
&
system
)
{
void
OpenCLUpdateStateDataKernel
::
initialize
(
const
System
&
system
)
{
...
@@ -131,37 +137,80 @@ void OpenCLUpdateStateDataKernel::getForces(ContextImpl& context, std::vector<Ve
...
@@ -131,37 +137,80 @@ void OpenCLUpdateStateDataKernel::getForces(ContextImpl& context, std::vector<Ve
}
}
}
}
//OpenCLCalcHarmonicBondForceKernel::~OpenCLCalcHarmonicBondForceKernel() {
OpenCLCalcHarmonicBondForceKernel
::~
OpenCLCalcHarmonicBondForceKernel
()
{
//}
if
(
params
!=
NULL
)
//
delete
params
;
//void OpenCLCalcHarmonicBondForceKernel::initialize(const System& system, const HarmonicBondForce& force) {
if
(
indices
!=
NULL
)
// if (data.primaryKernel == NULL)
delete
indices
;
// data.primaryKernel = this;
}
// data.hasBonds = true;
// numBonds = force.getNumBonds();
class
OpenCLBondForceInfo
:
public
OpenCLForceInfo
{
// vector<int> particle1(numBonds);
public:
// vector<int> particle2(numBonds);
OpenCLBondForceInfo
(
int
requiredBuffers
,
const
HarmonicBondForce
&
force
)
:
OpenCLForceInfo
(
requiredBuffers
,
false
,
0.0
),
force
(
force
)
{
// vector<float> length(numBonds);
}
// vector<float> k(numBonds);
int
getNumParticleGroups
()
{
// for (int i = 0; i < numBonds; i++) {
return
force
.
getNumBonds
();
// double lengthValue, kValue;
}
// force.getBondParameters(i, particle1[i], particle2[i], lengthValue, kValue);
void
getParticlesInGroup
(
int
index
,
std
::
vector
<
int
>&
particles
)
{
// length[i] = (float) lengthValue;
int
particle1
,
particle2
;
// k[i] = (float) kValue;
double
length
,
k
;
// }
force
.
getBondParameters
(
index
,
particle1
,
particle2
,
length
,
k
);
// gpuSetBondParameters(data.gpu, particle1, particle2, length, k);
particles
.
resize
(
2
);
//}
particles
[
0
]
=
particle1
;
//
particles
[
1
]
=
particle2
;
//void OpenCLCalcHarmonicBondForceKernel::executeForces(ContextImpl& context) {
}
// if (data.primaryKernel == this)
bool
areGroupsIdentical
(
int
group1
,
int
group2
)
{
// calcForces(context, data);
int
particle1
,
particle2
;
//}
double
length1
,
length2
,
k1
,
k2
;
//
force
.
getBondParameters
(
group1
,
particle1
,
particle2
,
length1
,
k1
);
//double OpenCLCalcHarmonicBondForceKernel::executeEnergy(ContextImpl& context) {
force
.
getBondParameters
(
group2
,
particle1
,
particle2
,
length2
,
k2
);
// if (data.primaryKernel == this)
return
(
length1
==
length2
&&
k1
==
k2
);
// return calcEnergy(context, data, system);
}
// return 0.0;
private:
//}
const
HarmonicBondForce
&
force
;
};
void
OpenCLCalcHarmonicBondForceKernel
::
initialize
(
const
System
&
system
,
const
HarmonicBondForce
&
force
)
{
numBonds
=
force
.
getNumBonds
();
params
=
new
OpenCLArray
<
mm_float2
>
(
*
data
.
context
,
numBonds
,
"BondParams"
);
indices
=
new
OpenCLArray
<
mm_int4
>
(
*
data
.
context
,
numBonds
,
"BondIndices"
);
vector
<
int
>
forceBufferCounter
(
system
.
getNumParticles
(),
0
);
vector
<
mm_float2
>
paramVector
(
numBonds
);
vector
<
mm_int4
>
indicesVector
(
numBonds
);
for
(
int
i
=
0
;
i
<
numBonds
;
i
++
)
{
int
particle1
,
particle2
;
double
length
,
k
;
force
.
getBondParameters
(
i
,
particle1
,
particle2
,
length
,
k
);
paramVector
[
i
]
=
(
mm_float2
)
{
length
,
k
};
indicesVector
[
i
]
=
(
mm_int4
)
{
particle1
,
particle2
,
forceBufferCounter
[
particle1
]
++
,
forceBufferCounter
[
particle2
]
++
};
}
params
->
upload
(
paramVector
);
indices
->
upload
(
indicesVector
);
int
maxBuffers
=
1
;
for
(
int
i
=
0
;
i
<
forceBufferCounter
.
size
();
i
++
)
{
maxBuffers
=
max
(
maxBuffers
,
forceBufferCounter
[
i
]);
}
data
.
context
->
addForce
(
new
OpenCLBondForceInfo
(
maxBuffers
,
force
));
cl
::
Program
program
=
data
.
context
->
createProgram
(
data
.
context
->
loadSourceFromFile
(
"harmonicBondForce.cl"
));
kernel
=
cl
::
Kernel
(
program
,
"calcHarmonicBondForce"
);
}
void
OpenCLCalcHarmonicBondForceKernel
::
executeForces
(
ContextImpl
&
context
)
{
kernel
.
setArg
<
cl_int
>
(
0
,
data
.
context
->
getPaddedNumAtoms
());
kernel
.
setArg
<
cl_int
>
(
1
,
numBonds
);
kernel
.
setArg
<
cl
::
Buffer
>
(
2
,
data
.
context
->
getForceBuffers
().
getDeviceBuffer
());
kernel
.
setArg
<
cl
::
Buffer
>
(
3
,
data
.
context
->
getEnergyBuffer
().
getDeviceBuffer
());
kernel
.
setArg
<
cl
::
Buffer
>
(
4
,
data
.
context
->
getPosq
().
getDeviceBuffer
());
kernel
.
setArg
<
cl
::
Buffer
>
(
5
,
params
->
getDeviceBuffer
());
kernel
.
setArg
<
cl
::
Buffer
>
(
6
,
indices
->
getDeviceBuffer
());
data
.
context
->
executeKernel
(
kernel
,
numBonds
);
}
double
OpenCLCalcHarmonicBondForceKernel
::
executeEnergy
(
ContextImpl
&
context
)
{
executeForces
(
context
);
return
0.0
;
}
//
//
//OpenCLCalcHarmonicAngleForceKernel::~OpenCLCalcHarmonicAngleForceKernel() {
//OpenCLCalcHarmonicAngleForceKernel::~OpenCLCalcHarmonicAngleForceKernel() {
//}
//}
...
@@ -625,6 +674,7 @@ OpenCLIntegrateVerletStepKernel::~OpenCLIntegrateVerletStepKernel() {
...
@@ -625,6 +674,7 @@ OpenCLIntegrateVerletStepKernel::~OpenCLIntegrateVerletStepKernel() {
void
OpenCLIntegrateVerletStepKernel
::
initialize
(
const
System
&
system
,
const
VerletIntegrator
&
integrator
)
{
void
OpenCLIntegrateVerletStepKernel
::
initialize
(
const
System
&
system
,
const
VerletIntegrator
&
integrator
)
{
// initializeIntegration(system, data, integrator);
// initializeIntegration(system, data, integrator);
data
.
context
->
initialize
(
system
);
prevStepSize
=
-
1.0
;
prevStepSize
=
-
1.0
;
}
}
...
...
platforms/opencl/src/OpenCLKernels.h
View file @
ad4e1203
...
@@ -28,6 +28,8 @@
...
@@ -28,6 +28,8 @@
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "OpenCLPlatform.h"
#include "OpenCLPlatform.h"
#include "OpenCLArray.h"
#include "OpenCLContext.h"
#include "openmm/kernels.h"
#include "openmm/kernels.h"
#include "openmm/System.h"
#include "openmm/System.h"
...
@@ -142,41 +144,45 @@ public:
...
@@ -142,41 +144,45 @@ public:
private:
private:
OpenCLPlatform
::
PlatformData
&
data
;
OpenCLPlatform
::
PlatformData
&
data
;
};
};
//
///**
/**
// * This kernel is invoked by HarmonicBondForce to calculate the forces acting on the system and the energy of the system.
* This kernel is invoked by HarmonicBondForce to calculate the forces acting on the system and the energy of the system.
// */
*/
//class OpenCLCalcHarmonicBondForceKernel : public CalcHarmonicBondForceKernel {
class
OpenCLCalcHarmonicBondForceKernel
:
public
CalcHarmonicBondForceKernel
{
//public:
public:
// OpenCLCalcHarmonicBondForceKernel(std::string name, const Platform& platform, OpenCLPlatform::PlatformData& data, System& system) : CalcHarmonicBondForceKernel(name, platform), data(data), system(system) {
OpenCLCalcHarmonicBondForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
OpenCLPlatform
::
PlatformData
&
data
,
System
&
system
)
:
// }
CalcHarmonicBondForceKernel
(
name
,
platform
),
data
(
data
),
system
(
system
),
params
(
NULL
),
indices
(
NULL
)
{
// ~OpenCLCalcHarmonicBondForceKernel();
}
// /**
~
OpenCLCalcHarmonicBondForceKernel
();
// * Initialize the kernel.
/**
// *
* Initialize the kernel.
// * @param system the System this kernel will be applied to
*
// * @param force the HarmonicBondForce this kernel will be used for
* @param system the System this kernel will be applied to
// */
* @param force the HarmonicBondForce this kernel will be used for
// void initialize(const System& system, const HarmonicBondForce& force);
*/
// /**
void
initialize
(
const
System
&
system
,
const
HarmonicBondForce
&
force
);
// * Execute the kernel to calculate the forces.
/**
// *
* Execute the kernel to calculate the forces.
// * @param context the context in which to execute this kernel
*
// */
* @param context the context in which to execute this kernel
// void executeForces(ContextImpl& context);
*/
// /**
void
executeForces
(
ContextImpl
&
context
);
// * Execute the kernel to calculate the energy.
/**
// *
* Execute the kernel to calculate the energy.
// * @param context the context in which to execute this kernel
*
// * @return the potential energy due to the HarmonicBondForce
* @param context the context in which to execute this kernel
// */
* @return the potential energy due to the HarmonicBondForce
// double executeEnergy(ContextImpl& context);
*/
//private:
double
executeEnergy
(
ContextImpl
&
context
);
// int numBonds;
private:
// OpenCLPlatform::PlatformData& data;
int
numBonds
;
// System& system;
OpenCLPlatform
::
PlatformData
&
data
;
//};
System
&
system
;
//
OpenCLArray
<
mm_float2
>*
params
;
OpenCLArray
<
mm_int4
>*
indices
;
cl
::
Kernel
kernel
;
};
///**
///**
// * This kernel is invoked by HarmonicAngleForce to calculate the forces acting on the system and the energy of the system.
// * This kernel is invoked by HarmonicAngleForce to calculate the forces acting on the system and the energy of the system.
// */
// */
...
...
platforms/opencl/src/OpenCLPlatform.cpp
View file @
ad4e1203
...
@@ -47,7 +47,7 @@ OpenCLPlatform::OpenCLPlatform() {
...
@@ -47,7 +47,7 @@ OpenCLPlatform::OpenCLPlatform() {
OpenCLKernelFactory
*
factory
=
new
OpenCLKernelFactory
();
OpenCLKernelFactory
*
factory
=
new
OpenCLKernelFactory
();
registerKernelFactory
(
CalcForcesAndEnergyKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcForcesAndEnergyKernel
::
Name
(),
factory
);
registerKernelFactory
(
UpdateStateDataKernel
::
Name
(),
factory
);
registerKernelFactory
(
UpdateStateDataKernel
::
Name
(),
factory
);
//
registerKernelFactory(CalcHarmonicBondForceKernel::Name(), factory);
registerKernelFactory
(
CalcHarmonicBondForceKernel
::
Name
(),
factory
);
// registerKernelFactory(CalcHarmonicAngleForceKernel::Name(), factory);
// registerKernelFactory(CalcHarmonicAngleForceKernel::Name(), factory);
// registerKernelFactory(CalcPeriodicTorsionForceKernel::Name(), factory);
// registerKernelFactory(CalcPeriodicTorsionForceKernel::Name(), factory);
// registerKernelFactory(CalcRBTorsionForceKernel::Name(), factory);
// registerKernelFactory(CalcRBTorsionForceKernel::Name(), factory);
...
...
platforms/opencl/src/kernels/harmonicBondForce.cl
0 → 100644
View file @
ad4e1203
/**
*
Evaluate
the
forces
due
to
harmonic
bonds.
*/
__kernel
void
calcHarmonicBondForce
(
int
numAtoms,
int
numBonds,
__global
float4*
forceBuffers,
__global
float*
energyBuffer,
__global
float4*
posq,
__global
float2*
params,
__global
int4*
indices
)
{
int
index
=
get_global_id
(
0
)
;
float
energy
=
0.0f
;
while
(
index
<
numBonds
)
{
int4
atoms
=
indices[index]
;
float4
delta
=
posq[atoms.y]-posq[atoms.x]
;
float2
bondParams
=
params[index]
;
float
r
=
sqrt
(
delta.x*delta.x
+
delta.y*delta.y
+
delta.z*delta.z
)
;
float
deltaIdeal
=
r-bondParams.x
;
energy
+=
0.5f
*
bondParams.y*deltaIdeal*deltaIdeal
;
float
dEdR
=
bondParams.y
*
deltaIdeal
;
dEdR
=
(
r
>
0.0f
)
?
(
dEdR
/
r
)
:
0.0f
;
delta.xyz
*=
dEdR
;
unsigned
int
offsetA
=
atoms.x+atoms.z*numAtoms
;
unsigned
int
offsetB
=
atoms.y+atoms.w*numAtoms
;
float4
forceA
=
forceBuffers[offsetA]
;
float4
forceB
=
forceBuffers[offsetB]
;
forceA.xyz
+=
delta.xyz
;
forceB.xyz
-=
delta.xyz
;
forceBuffers[offsetA]
=
forceA
;
forceBuffers[offsetB]
=
forceB
;
index
+=
get_global_size
(
0
)
;
}
energyBuffer[get_global_id
(
0
)
]
+=
energy
;
}
platforms/opencl/src/kernels/utilities.cl
View file @
ad4e1203
/**
*
Fill
a
buffer
with
0.
*/
__kernel
void
clearBuffer
(
__global
float*
buffer,
int
size
)
{
__kernel
void
clearBuffer
(
__global
float*
buffer,
int
size
)
{
int
index
=
get_global_id
(
0
)
;
int
index
=
get_global_id
(
0
)
;
int
step
=
get_global_size
(
0
)
;
int
step
=
get_global_size
(
0
)
;
...
@@ -11,3 +15,20 @@ __kernel void clearBuffer(__global float* buffer, int size) {
...
@@ -11,3 +15,20 @@ __kernel void clearBuffer(__global float* buffer, int size) {
for
(
int
i
=
sizeDiv4*4
; i < size; i++)
for
(
int
i
=
sizeDiv4*4
; i < size; i++)
buffer[i]
=
0.0f
;
buffer[i]
=
0.0f
;
}
}
/**
*
Sum
a
collection
of
buffers
into
the
first
one.
*/
__kernel
void
reduceFloat4Buffer
(
__global
float4*
buffer,
int
bufferSize,
int
numBuffers
)
{
int
index
=
get_global_id
(
0
)
;
int
step
=
get_global_size
(
0
)
;
int
totalSize
=
bufferSize*numBuffers
;
while
(
index
<
bufferSize
)
{
float4
sum
=
buffer[index]
;
for
(
int
i
=
index+bufferSize
; i < totalSize; i += bufferSize)
sum
+=
buffer[i]
;
buffer[index]
=
sum
;
index
+=
step
;
}
}
platforms/opencl/tests/TestOpenCLHarmonicBondForce.cpp
0 → 100644
View file @
ad4e1203
/* -------------------------------------------------------------------------- *
* 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-2009 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 OpenCL implementation of HarmonicBondForce.
*/
#include "../../../tests/AssertionUtilities.h"
#include "openmm/Context.h"
#include "OpenCLPlatform.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
const
double
TOL
=
1e-5
;
void
testBonds
()
{
OpenCLPlatform
platform
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
HarmonicBondForce
*
forceField
=
new
HarmonicBondForce
();
forceField
->
addBond
(
0
,
1
,
1.5
,
0.8
);
forceField
->
addBond
(
1
,
2
,
1.2
,
0.7
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
3
);
positions
[
0
]
=
Vec3
(
0
,
2
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
positions
[
2
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
-
0.8
*
0.5
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.7
*
0.2
,
0
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
forces
[
0
][
0
]
-
forces
[
2
][
0
],
-
forces
[
0
][
1
]
-
forces
[
2
][
1
],
-
forces
[
0
][
2
]
-
forces
[
2
][
2
]),
forces
[
1
],
TOL
);
ASSERT_EQUAL_TOL
(
0.5
*
0.8
*
0.5
*
0.5
+
0.5
*
0.7
*
0.2
*
0.2
,
state
.
getPotentialEnergy
(),
TOL
);
}
int
main
()
{
try
{
testBonds
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment