"vscode:/vscode.git/clone" did not exist on "92b6a63b3410db2dcb31a74ed04f273bf2fd1559"
OpenCLNonbondedUtilities.h 12.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
#ifndef OPENMM_OPENCLNONBONDEDUTILITIES_H_
#define OPENMM_OPENCLNONBONDEDUTILITIES_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.               *
 *                                                                            *
12
 * Portions copyright (c) 2009-2010 Stanford University and the Authors.      *
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 * 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 "OpenCLContext.h"
#include "openmm/System.h"
32
#include "OpenCLExpressionUtilities.h"
33
34
35
36
37
38
#include <string>
#include <vector>

namespace OpenMM {

/**
39
 * This class provides a generic interface for calculating nonbonded interactions.  It does this in two
40
 * ways.  First, it can be used to create Kernels that evaluate nonbonded interactions.  Clients
41
42
43
44
45
46
47
48
49
50
51
52
53
 * only need to provide the code for evaluating a single interaction and the list of parameters it depends on.
 * A complete kernel is then synthesized using an appropriate algorithm to evaluate all interactions on all
 * atoms.
 *
 * Second, this class itself creates and invokes a single "default" interaction kernel, allowing several
 * different forces to be evaluated at once for greater efficiency.  Call addInteraction() and addParameter()
 * to add interactions to this default kernel.
 *
 * During each force or energy evaluation, the following sequence of steps takes place:
 *
 * 1. Data structures (e.g. neighbor lists) are calculated to allow nonbonded interactions to be evaluated
 * quickly.
 *
54
 * 2. calcForcesAndEnergy() is called on each ForceImpl in the System.
55
56
57
58
59
 *
 * 3. Finally, the default interaction kernel is invoked to calculate all interactions that were added
 * to it.
 *
 * This sequence means that the default interaction kernel may depend on quantities that were calculated
60
 * by ForceImpls during calcForcesAndEnergy().
61
62
 */

63
class OPENMM_EXPORT OpenCLNonbondedUtilities {
64
public:
65
    class ParameterInfo;
66
67
68
    OpenCLNonbondedUtilities(OpenCLContext& context);
    ~OpenCLNonbondedUtilities();
    /**
69
     * Add a nonbonded interaction to be evaluated by the default interaction kernel.
70
71
72
     *
     * @param usesCutoff     specifies whether a cutoff should be applied to this interaction
     * @param usesPeriodic   specifies whether periodic boundary conditions should be applied to this interaction
73
     * @param usesExclusions specifies whether this interaction uses exclusions.  If this is true, it must have identical exclusions to every other interaction.
74
75
     * @param cutoffDistance the cutoff distance for this interaction (ignored if usesCutoff is false)
     * @param exclusionList  for each atom, specifies the list of other atoms whose interactions should be excluded
76
     * @param kernel         the code to evaluate the interaction
77
     */
78
    void addInteraction(bool usesCutoff, bool usesPeriodic, bool usesExclusions, double cutoffDistance, const std::vector<std::vector<int> >& exclusionList, const std::string& kernel);
79
    /**
80
     * Add a per-atom parameter that the default interaction kernel may depend on.
81
     */
82
    void addParameter(const ParameterInfo& parameter);
83
84
85
86
    /**
     * Add an array (other than a per-atom parameter) that should be passed as an argument to the default interaction kernel.
     */
    void addArgument(const ParameterInfo& parameter);
87
88
89
90
91
92
93
94
95
96
    /**
     * Initialize this object in preparation for a simulation.
     */
    void initialize(const System& system);
    /**
     * Get the number of force buffers required for nonbonded forces.
     */
    int getNumForceBuffers() {
        return numForceBuffers;
    }
97
98
99
100
101
102
    /**
     * Get the number of energy buffers required for nonbonded forces.
     */
    int getNumEnergyBuffers() {
        return numForceThreadBlocks*forceThreadBlockSize;
    }
103
104
105
106
107
108
109
110
111
112
113
114
    /**
     * Get whether a cutoff is being used.
     */
    bool getUseCutoff() {
        return useCutoff;
    }
    /**
     * Get whether periodic boundary conditions are being used.
     */
    bool getUsePeriodic() {
        return usePeriodic;
    }
115
116
117
118
119
120
    /**
     * Get whether there is one force buffer per atom block.
     */
    bool getForceBufferPerAtomBlock() {
        return forceBufferPerAtomBlock;
    }
121
122
123
124
125
126
127
128
129
130
131
132
    /**
     * Get the number of work groups used for computing nonbonded forces.
     */
    int getNumForceThreadBlocks() {
        return numForceThreadBlocks;
    }
    /**
     * Get the size of each work group used for computing nonbonded forces.
     */
    int getForceThreadBlockSize() {
        return forceThreadBlockSize;
    }
133
134
135
136
137
138
    /**
     * Get the cutoff distance.
     */
    double getCutoffDistance() {
        return cutoff;
    }
139
140
141
142
143
    /**
     * Prepare to compute interactions.  This updates the neighbor list.
     */
    void prepareInteractions();
    /**
144
     * Compute the nonbonded interactions.
145
146
     */
    void computeInteractions();
147
148
149
150
    /**
     * Check to see if the neighbor list arrays are large enough, and make them bigger if necessary.
     */
    void updateNeighborListSize();
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    /**
     * Get the array containing the center of each atom block.
     */
    OpenCLArray<mm_float4>& getBlockCenters() {
        return *blockCenter;
    }
    /**
     * Get the array containing the dimensions of each atom block.
     */
    OpenCLArray<mm_float4>& getBlockBoundingBoxes() {
        return *blockBoundingBox;
    }
    /**
     * Get the array whose first element contains the number of tiles with interactions.
     */
    OpenCLArray<cl_uint>& getInteractionCount() {
        return *interactionCount;
    }
    /**
     * Get the array containing tiles with interactions.
     */
172
    OpenCLArray<mm_ushort2>& getInteractingTiles() {
173
174
175
176
177
178
179
180
        return *interactingTiles;
    }
    /**
     * Get the array containing flags for tiles with interactions.
     */
    OpenCLArray<cl_uint>& getInteractionFlags() {
        return *interactionFlags;
    }
181
182
183
184
185
186
187
188
189
190
    /**
     * Get the array containing exclusion flags.
     */
    OpenCLArray<cl_uint>& getExclusions() {
        return *exclusions;
    }
    /**
     * Get the array containing the index into the exclusion array for each tile.
     */
    OpenCLArray<cl_uint>& getExclusionIndices() {
191
192
193
194
195
196
197
        return *exclusionIndices;
    }
    /**
     * Get the array listing where the exclusion data starts for each row.
     */
    OpenCLArray<cl_uint>& getExclusionRowIndices() {
        return *exclusionRowIndices;
198
    }
199
200
201
202
203
204
    /**
     * Get the array which contains flags for reserving force buffers.
     */
    OpenCLArray<cl_uint>& getForceBufferFlags() {
        return *forceBufferFlags;
    }
205
206
207
208
209
210
211
212
213
214
215
216
    /**
     * Get the index of the first tile this context is responsible for processing.
     */
    int getStartTileIndex() const {
        return startTileIndex;
    }
    /**
     * Get the total number of tiles this context is responsible for processing.
     */
    int getNumTiles() const {
        return numTiles;
    }
217
218
219
220
    /**
     * Set the range of tiles that should be processed by this context.
     */
    void setTileRange(int startTileIndex, int numTiles);
221
222
223
224
225
226
227
    /**
     * Create a Kernel for evaluating a nonbonded interaction.  Cutoffs and periodic boundary conditions
     * are assumed to be the same as those for the default interaction Kernel, since this kernel will use
     * the same neighbor list.
     * 
     * @param source        the source code for evaluating the force and energy
     * @param params        the per-atom parameters this kernel may depend on
228
     * @param arguments     arrays (other than per-atom parameters) that should be passed as arguments to the kernel
229
     * @param useExclusions specifies whether exclusions are applied to this interaction
230
     * @param isSymmetric   specifies whether the interaction is symmetric
231
     */
232
    cl::Kernel createInteractionKernel(const std::string& source, const std::vector<ParameterInfo>& params, const std::vector<ParameterInfo>& arguments, bool useExclusions, bool isSymmetric) const;
233
private:
234
    static int findExclusionIndex(int x, int y, const std::vector<cl_uint>& exclusionIndices, const std::vector<cl_uint>& exclusionRowIndices);
235
236
    OpenCLContext& context;
    cl::Kernel forceKernel;
237
238
239
    cl::Kernel findBlockBoundsKernel;
    cl::Kernel findInteractingBlocksKernel;
    cl::Kernel findInteractionsWithinBlocksKernel;
240
    OpenCLArray<cl_uint>* exclusions;
241
242
    OpenCLArray<cl_uint>* exclusionIndices;
    OpenCLArray<cl_uint>* exclusionRowIndices;
243
    OpenCLArray<mm_ushort2>* interactingTiles;
244
245
246
247
    OpenCLArray<cl_uint>* interactionFlags;
    OpenCLArray<cl_uint>* interactionCount;
    OpenCLArray<mm_float4>* blockCenter;
    OpenCLArray<mm_float4>* blockBoundingBox;
248
    OpenCLArray<cl_uint>* forceBufferFlags;
249
250
    std::vector<std::vector<int> > atomExclusions;
    std::vector<ParameterInfo> parameters;
251
    std::vector<ParameterInfo> arguments;
252
    std::string kernelSource;
253
    std::map<std::string, std::string> kernelDefines;
254
    double cutoff;
255
    bool useCutoff, usePeriodic, forceBufferPerAtomBlock, deviceIsCpu;
256
    int numForceBuffers, startTileIndex, numTiles, numForceThreadBlocks, forceThreadBlockSize;
257
258
};

259
260
261
262
/**
 * This class stores information about a per-atom parameter that may be used in a nonbonded kernel.
 */

263
264
class OpenCLNonbondedUtilities::ParameterInfo {
public:
265
266
267
    /**
     * Create a ParameterInfo object.
     *
268
269
270
271
272
     * @param name           the name of the parameter
     * @param type           the data type of the parameter's components
     * @param numComponents  the number of components in the parameter
     * @param size           the size of the parameter in bytes
     * @param memory         the memory containing the parameter values
273
     */
274
275
276
277
278
279
    ParameterInfo(const std::string& name, const std::string& componentType, int numComponents, int size, cl::Memory& memory) :
            name(name), componentType(componentType), numComponents(numComponents), size(size), memory(&memory) {
        if (numComponents == 1)
            type = componentType;
        else
            type = componentType+OpenCLExpressionUtilities::intToString(numComponents);
280
    }
281
282
283
    const std::string& getName() const {
        return name;
    }
284
285
286
    const std::string& getComponentType() const {
        return componentType;
    }
287
288
289
    const std::string& getType() const {
        return type;
    }
290
291
292
    int getNumComponents() const {
        return numComponents;
    }
293
294
295
    int getSize() const {
        return size;
    }
296
297
    cl::Memory& getMemory() const {
        return *memory;
298
299
    }
private:
300
    std::string name;
301
    std::string componentType;
302
    std::string type;
303
    int size, numComponents;
304
    cl::Memory* memory;
305
306
307
308
309
};

} // namespace OpenMM

#endif /*OPENMM_OPENCLNONBONDEDUTILITIES_H_*/