AmoebaCudaKernels.h 32.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
#ifndef AMOEBA_OPENMM_CUDAKERNELS_H_
#define AMOEBA_OPENMM_CUDAKERNELS_H_

/* -------------------------------------------------------------------------- *
 *                              OpenMMAmoeba                                  *
 * -------------------------------------------------------------------------- *
 * 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) 2008-2018 Stanford University and the Authors.      *
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * Authors: Mark Friedrichs, 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 "openmm/amoebaKernels.h"
#include "openmm/kernels.h"
#include "openmm/System.h"
#include "CudaArray.h"
34
#include "CudaContext.h"
peastman's avatar
peastman committed
35
#include "CudaNonbondedUtilities.h"
36
37
#include "CudaSort.h"
#include <cufft.h>
38
39
40

namespace OpenMM {

41
42
class CudaCalcAmoebaGeneralizedKirkwoodForceKernel;

43
/**
44
 * This kernel is invoked by AmoebaBondForce to calculate the forces acting on the system and the energy of the system.
45
 */
46
class CudaCalcAmoebaBondForceKernel : public CalcAmoebaBondForceKernel {
47
public:
48
    CudaCalcAmoebaBondForceKernel(const std::string& name,
49
50
                                          const Platform& platform,
                                          CudaContext& cu,
51
                                          const System& system);
52
53
54
55
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
56
     * @param force      the AmoebaBondForce this kernel will be used for
57
     */
58
    void initialize(const System& system, const AmoebaBondForce& force);
59
60
61
62
63
64
65
66
67
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
68
69
70
71
72
73
74
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaBondForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaBondForce& force);
75
76
77
78
private:
    class ForceInfo;
    int numBonds;
    CudaContext& cu;
79
    const System& system;
80
    CudaArray params;
81
82
83
};

/**
84
 * This kernel is invoked by AmoebaAngleForce to calculate the forces acting on the system and the energy of the system.
85
 */
86
class CudaCalcAmoebaAngleForceKernel : public CalcAmoebaAngleForceKernel {
87
public:
88
    CudaCalcAmoebaAngleForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
89
90
91
92
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
93
     * @param force      the AmoebaAngleForce this kernel will be used for
94
     */
95
    void initialize(const System& system, const AmoebaAngleForce& force);
96
97
98
99
100
101
102
103
104
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
105
106
107
108
109
110
111
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaAngleForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaAngleForce& force);
112
113
114
115
private:
    class ForceInfo;
    int numAngles;
    CudaContext& cu;
116
    const System& system;
117
    CudaArray params;
118
119
120
};

/**
121
 * This kernel is invoked by AmoebaInPlaneAngleForce to calculate the forces acting on the system and the energy of the system.
122
 */
123
class CudaCalcAmoebaInPlaneAngleForceKernel : public CalcAmoebaInPlaneAngleForceKernel {
124
public:
125
    CudaCalcAmoebaInPlaneAngleForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
126
127
128
129
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
130
     * @param force      the AmoebaInPlaneAngleForce this kernel will be used for
131
     */
132
    void initialize(const System& system, const AmoebaInPlaneAngleForce& force);
133
134
135
136
137
138
139
140
141
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
142
143
144
145
146
147
148
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaInPlaneAngleForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaInPlaneAngleForce& force);
149
150
151
152
private:
    class ForceInfo;
    int numAngles;
    CudaContext& cu;
153
    const System& system;
154
    CudaArray params;
155
156
157
158
159
160
161
};

/**
 * This kernel is invoked by AmoebaPiTorsionForce to calculate the forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaPiTorsionForceKernel : public CalcAmoebaPiTorsionForceKernel {
public:
162
    CudaCalcAmoebaPiTorsionForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the AmoebaPiTorsionForce this kernel will be used for
     */
    void initialize(const System& system, const AmoebaPiTorsionForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
179
180
181
182
183
184
185
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaPiTorsionForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaPiTorsionForce& force);
186
187
188
189
private:
    class ForceInfo;
    int numPiTorsions;
    CudaContext& cu;
190
    const System& system;
191
    CudaArray params;
192
193
194
195
196
197
198
};

/**
 * This kernel is invoked by AmoebaStretchBendForce to calculate the forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaStretchBendForceKernel : public CalcAmoebaStretchBendForceKernel {
public:
199
    CudaCalcAmoebaStretchBendForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the AmoebaStretchBendForce this kernel will be used for
     */
    void initialize(const System& system, const AmoebaStretchBendForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
216
217
218
219
220
221
222
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaStretchBendForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaStretchBendForce& force);
223
224
225
226
private:
    class ForceInfo;
    int numStretchBends;
    CudaContext& cu;
227
    const System& system;
228
229
    CudaArray params1; // Equilibrium values
    CudaArray params2; // force constants
230
231
232
233
234
235
236
};

/**
 * This kernel is invoked by AmoebaOutOfPlaneBendForce to calculate the forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaOutOfPlaneBendForceKernel : public CalcAmoebaOutOfPlaneBendForceKernel {
public:
237
    CudaCalcAmoebaOutOfPlaneBendForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the AmoebaOutOfPlaneBendForce this kernel will be used for
     */
    void initialize(const System& system, const AmoebaOutOfPlaneBendForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
254
255
256
257
258
259
260
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaOutOfPlaneBendForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaOutOfPlaneBendForce& force);
261
262
263
264
private:
    class ForceInfo;
    int numOutOfPlaneBends;
    CudaContext& cu;
265
    const System& system;
266
    CudaArray params;
267
268
269
270
271
272
273
};

/**
 * This kernel is invoked by AmoebaTorsionTorsionForce to calculate the forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaTorsionTorsionForceKernel : public CalcAmoebaTorsionTorsionForceKernel {
public:
274
    CudaCalcAmoebaTorsionTorsionForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the AmoebaTorsionTorsionForce this kernel will be used for
     */
    void initialize(const System& system, const AmoebaTorsionTorsionForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
private:
    class ForceInfo;
    int numTorsionTorsions;
    int numTorsionTorsionGrids;
    CudaContext& cu;
296
    const System& system;
297
298
299
    CudaArray gridValues;
    CudaArray gridParams;
    CudaArray torsionParams;
300
301
302
303
304
305
306
};

/**
 * This kernel is invoked by AmoebaMultipoleForce to calculate the forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaMultipoleForceKernel : public CalcAmoebaMultipoleForceKernel {
public:
307
    CudaCalcAmoebaMultipoleForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
    ~CudaCalcAmoebaMultipoleForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the AmoebaMultipoleForce this kernel will be used for
     */
    void initialize(const System& system, const AmoebaMultipoleForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
325
326
327
328
329
330
     /**
     * Get the LabFrame dipole moments of all particles.
     * 
     * @param context    the Context for which to get the induced dipoles
     * @param dipoles    the induced dipole moment of particle i is stored into the i'th element
     */
331
    void getLabFramePermanentDipoles(ContextImpl& context, std::vector<Vec3>& dipoles);
332
333
334
335
336
337
338
    /**
     * Get the induced dipole moments of all particles.
     * 
     * @param context    the Context for which to get the induced dipoles
     * @param dipoles    the induced dipole moment of particle i is stored into the i'th element
     */
    void getInducedDipoles(ContextImpl& context, std::vector<Vec3>& dipoles);
339
340
341
342
343
344
345
    /**
     * Get the total dipole moments of all particles.
     * 
     * @param context    the Context for which to get the induced dipoles
     * @param dipoles    the induced dipole moment of particle i is stored into the i'th element
     */
    void getTotalDipoles(ContextImpl& context, std::vector<Vec3>& dipoles);
346
347
348
349
350
351
352
353
    /**
     * Execute the kernel to calculate the electrostatic potential
     *
     * @param context        the context in which to execute this kernel
     * @param inputGrid      input grid coordinates
     * @param outputElectrostaticPotential output potential 
     */
    void getElectrostaticPotential(ContextImpl& context, const std::vector< Vec3 >& inputGrid,
354
                                   std::vector< double >& outputElectrostaticPotential);
355
356
357
358
359

   /** 
     * Get the system multipole moments
     *
     * @param context      context
360
361
362
363
     * @param outputMultipoleMoments (charge,
     *                                dipole_x, dipole_y, dipole_z,
     *                                quadrupole_xx, quadrupole_xy, quadrupole_xz,
     *                                quadrupole_yx, quadrupole_yy, quadrupole_yz,
364
     *                                quadrupole_zx, quadrupole_zy, quadrupole_zz)
365
     */
Lee-Ping Wang's avatar
Lee-Ping Wang committed
366
    void getSystemMultipoleMoments(ContextImpl& context, std::vector<double>& outputMultipoleMoments);
367
368
369
370
371
372
373
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaMultipoleForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force);
374
375
376
377
378
379
380
381
382
    /**
     * Get the parameters being used for PME.
     * 
     * @param alpha   the separation parameter
     * @param nx      the number of grid points along the X axis
     * @param ny      the number of grid points along the Y axis
     * @param nz      the number of grid points along the Z axis
     */
    void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
383
384
private:
    class ForceInfo;
385
    void initializeScaleFactors();
386
    void computeInducedField(void** recipBoxVectorPointer);
peastman's avatar
peastman committed
387
    bool iterateDipolesByDIIS(int iteration);
388
    void computeExtrapolatedDipoles(void** recipBoxVectorPointer);
389
    void ensureMultipolesValid(ContextImpl& context);
Lee-Ping Wang's avatar
Lee-Ping Wang committed
390
    template <class T, class T4, class M4> void computeSystemMultipoleMoments(ContextImpl& context, std::vector<double>& outputMultipoleMoments);
391
    int numMultipoles, maxInducedIterations, maxExtrapolationOrder;
392
    int fixedFieldThreads, inducedFieldThreads, electrostaticsThreads;
393
394
    int gridSizeX, gridSizeY, gridSizeZ;
    double alpha, inducedEpsilon;
Peter Eastman's avatar
Peter Eastman committed
395
    bool usePME, hasQuadrupoles, hasInitializedScaleFactors, hasInitializedFFT, multipolesAreValid, hasCreatedEvent;
396
    AmoebaMultipoleForce::PolarizationType polarizationType;
397
    CudaContext& cu;
398
    const System& system;
399
400
    std::vector<int3> covalentFlagValues;
    std::vector<int2> polarizationFlagValues;
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
    CudaArray multipoleParticles;
    CudaArray molecularDipoles;
    CudaArray molecularQuadrupoles;
    CudaArray labFrameDipoles;
    CudaArray labFrameQuadrupoles;
    CudaArray sphericalDipoles;
    CudaArray sphericalQuadrupoles;
    CudaArray fracDipoles;
    CudaArray fracQuadrupoles;
    CudaArray field;
    CudaArray fieldPolar;
    CudaArray inducedField;
    CudaArray inducedFieldPolar;
    CudaArray torque;
    CudaArray dampingAndThole;
    CudaArray inducedDipole;
    CudaArray inducedDipolePolar;
    CudaArray inducedDipoleErrors;
    CudaArray prevDipoles;
    CudaArray prevDipolesPolar;
    CudaArray prevDipolesGk;
    CudaArray prevDipolesGkPolar;
    CudaArray prevErrors;
    CudaArray diisMatrix;
    CudaArray diisCoefficients;
    CudaArray extrapolatedDipole;
    CudaArray extrapolatedDipolePolar;
    CudaArray extrapolatedDipoleGk;
    CudaArray extrapolatedDipoleGkPolar;
    CudaArray inducedDipoleFieldGradient;
    CudaArray inducedDipoleFieldGradientPolar;
    CudaArray inducedDipoleFieldGradientGk;
    CudaArray inducedDipoleFieldGradientGkPolar;
    CudaArray extrapolatedDipoleFieldGradient;
    CudaArray extrapolatedDipoleFieldGradientPolar;
    CudaArray extrapolatedDipoleFieldGradientGk;
    CudaArray extrapolatedDipoleFieldGradientGkPolar;
    CudaArray polarizability;
    CudaArray covalentFlags;
    CudaArray polarizationGroupFlags;
    CudaArray pmeGrid;
    CudaArray pmeBsplineModuliX;
    CudaArray pmeBsplineModuliY;
    CudaArray pmeBsplineModuliZ;
    CudaArray pmePhi;
    CudaArray pmePhid;
    CudaArray pmePhip;
    CudaArray pmePhidp;
    CudaArray pmeCphi;
    CudaArray lastPositions;
451
    cufftHandle fft;
452
    CUfunction computeMomentsKernel, recordInducedDipolesKernel, computeFixedFieldKernel, computeInducedFieldKernel, updateInducedFieldKernel, electrostaticsKernel, mapTorqueKernel;
Peter Eastman's avatar
Peter Eastman committed
453
    CUfunction pmeSpreadFixedMultipolesKernel, pmeSpreadInducedDipolesKernel, pmeFinishSpreadChargeKernel, pmeConvolutionKernel;
454
    CUfunction pmeFixedPotentialKernel, pmeInducedPotentialKernel, pmeFixedForceKernel, pmeInducedForceKernel, pmeRecordInducedFieldDipolesKernel, computePotentialKernel;
Peter Eastman's avatar
Peter Eastman committed
455
    CUfunction recordDIISDipolesKernel, buildMatrixKernel, solveMatrixKernel;
456
    CUfunction initExtrapolatedKernel, iterateExtrapolatedKernel, computeExtrapolatedKernel, addExtrapolatedGradientKernel;
457
    CUfunction pmeTransformMultipolesKernel, pmeTransformPotentialKernel;
Peter Eastman's avatar
Peter Eastman committed
458
    CUevent syncEvent;
459
    CudaCalcAmoebaGeneralizedKirkwoodForceKernel* gkKernel;
460
    static const int PmeOrder = 5;
peastman's avatar
peastman committed
461
    static const int MaxPrevDIISDipoles = 20;
462
463
464
465
466
467
468
};

/**
 * This kernel is invoked by AmoebaMultipoleForce to calculate the forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaGeneralizedKirkwoodForceKernel : public CalcAmoebaGeneralizedKirkwoodForceKernel {
public:
469
    CudaCalcAmoebaGeneralizedKirkwoodForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the AmoebaMultipoleForce this kernel will be used for
     */
    void initialize(const System& system, const AmoebaGeneralizedKirkwoodForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
486
487
488
489
490
491
492
493
    /**
     * Perform the computation of Born radii.
     */
    void computeBornRadii();
    /**
     * Perform the final parts of the force/energy computation.
     */
    void finishComputation(CudaArray& torque, CudaArray& labFrameDipoles, CudaArray& labFrameQuadrupoles, CudaArray& inducedDipole, CudaArray& inducedDipolePolar, CudaArray& dampingAndThole, CudaArray& covalentFlags, CudaArray& polarizationGroupFlags);
494
    CudaArray& getBornRadii() {
495
496
        return bornRadii;
    }
497
    CudaArray& getField() {
498
499
        return field;
    }
500
    CudaArray& getInducedField() {
501
502
        return inducedField;
    }
503
    CudaArray& getInducedFieldPolar() {
504
505
        return inducedFieldPolar;
    }
506
    CudaArray& getInducedDipoles() {
507
508
        return inducedDipoleS;
    }
509
    CudaArray& getInducedDipolesPolar() {
510
511
        return inducedDipolePolarS;
    }
512
513
514
515
516
517
518
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaGeneralizedKirkwoodForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaGeneralizedKirkwoodForce& force);
519
520
521
private:
    class ForceInfo;
    CudaContext& cu;
522
    const System& system;
523
    bool includeSurfaceArea, hasInitializedKernels;
524
    int computeBornSumThreads, gkForceThreads, chainRuleThreads, ediffThreads;
525
    AmoebaMultipoleForce::PolarizationType polarizationType;
526
    std::map<std::string, std::string> defines;
527
528
529
530
531
532
533
534
535
    CudaArray params;
    CudaArray bornSum;
    CudaArray bornRadii;
    CudaArray bornForce;
    CudaArray field;
    CudaArray inducedField;
    CudaArray inducedFieldPolar;
    CudaArray inducedDipoleS;
    CudaArray inducedDipolePolarS;
536
    CUfunction computeBornSumKernel, reduceBornSumKernel, surfaceAreaKernel, gkForceKernel, chainRuleKernel, ediffKernel;
537
538
539
540
541
542
543
};

/**
 * This kernel is invoked to calculate the vdw forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaVdwForceKernel : public CalcAmoebaVdwForceKernel {
public:
544
    CudaCalcAmoebaVdwForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
545
546
547
548
549
    ~CudaCalcAmoebaVdwForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
550
     * @param force      the AmoebaVdwForce this kernel will be used for
551
552
553
554
555
556
557
558
559
560
561
     */
    void initialize(const System& system, const AmoebaVdwForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
562
563
564
565
566
567
568
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaVdwForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaVdwForce& force);
569
570
571
private:
    class ForceInfo;
    CudaContext& cu;
572
    const System& system;
573
    bool hasInitializedNonbonded;
574
575
576
577
578
579
580
581
582
583
584
585

    // True if the AmoebaVdwForce AlchemicalMethod is not None.
    bool hasAlchemical;
    // Pinned host memory; allocated if necessary in initialize, and freed in the destructor.
    void* vdwLambdaPinnedBuffer;
    // Device memory for the alchemical state.
    CudaArray vdwLambda;
    // Only update device memory when lambda changes.
    float currentVdwLambda;
    // Per particle alchemical flag.
    CudaArray isAlchemical;

586
    double dispersionCoefficient;
587
588
589
590
591
    CudaArray sigmaEpsilon;
    CudaArray bondReductionAtoms;
    CudaArray bondReductionFactors;
    CudaArray tempPosq;
    CudaArray tempForces;
592
593
    CudaNonbondedUtilities* nonbonded;
    CUfunction prepareKernel, spreadKernel;
594
595
596
597
598
599
600
};

/**
 * This kernel is invoked to calculate the WCA dispersion forces acting on the system and the energy of the system.
 */
class CudaCalcAmoebaWcaDispersionForceKernel : public CalcAmoebaWcaDispersionForceKernel {
public:
601
    CudaCalcAmoebaWcaDispersionForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the AmoebaMultipoleForce this kernel will be used for
     */
    void initialize(const System& system, const AmoebaWcaDispersionForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
618
619
620
621
622
623
624
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the AmoebaWcaDispersionForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const AmoebaWcaDispersionForce& force);
625
626
627
private:
    class ForceInfo;
    CudaContext& cu;
628
    const System& system;
629
    double totalMaximumDispersionEnergy;
630
    CudaArray radiusEpsilon;
631
    CUfunction forceKernel;
632
633
};

peastman's avatar
peastman committed
634
635
636
637
638
/**
 * This kernel is invoked by HippoNonbondedForce to calculate the forces acting on the system and the energy of the system.
 */
class CudaCalcHippoNonbondedForceKernel : public CalcHippoNonbondedForceKernel {
public:
639
    CudaCalcHippoNonbondedForceKernel(const std::string& name, const Platform& platform, CudaContext& cu, const System& system);
peastman's avatar
peastman committed
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
    ~CudaCalcHippoNonbondedForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the HippoNonbondedForce this kernel will be used for
     */
    void initialize(const System& system, const HippoNonbondedForce& force);
    /**
     * Execute the kernel to calculate the forces and/or energy.
     *
     * @param context        the context in which to execute this kernel
     * @param includeForces  true if forces should be calculated
     * @param includeEnergy  true if the energy should be calculated
     * @return the potential energy due to the force
     */
    double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
    /**
     * Get the induced dipole moments of all particles.
     * 
     * @param context    the Context for which to get the induced dipoles
     * @param dipoles    the induced dipole moment of particle i is stored into the i'th element
     */
    void getInducedDipoles(ContextImpl& context, std::vector<Vec3>& dipoles);
    /**
     * Get the fixed dipole moments of all particles in the global reference frame.
     * 
     * @param context    the Context for which to get the fixed dipoles
     * @param dipoles    the fixed dipole moment of particle i is stored into the i'th element
     */
    void getLabFramePermanentDipoles(ContextImpl& context, std::vector<Vec3>& dipoles);
    /** 
     * Calculate the electrostatic potential given vector of grid coordinates.
     *
     * @param context                      context
     * @param inputGrid                    input grid coordinates
     * @param outputElectrostaticPotential output potential 
     */
    void getElectrostaticPotential(ContextImpl& context, const std::vector< Vec3 >& inputGrid,
                                   std::vector< double >& outputElectrostaticPotential);
    /**
     * Copy changed parameters over to a context.
     *
     * @param context    the context to copy parameters to
     * @param force      the HippoNonbondedForce to copy the parameters from
     */
    void copyParametersToContext(ContextImpl& context, const HippoNonbondedForce& force);
    /**
     * Get the parameters being used for PME.
     * 
     * @param alpha   the separation parameter
     * @param nx      the number of grid points along the X axis
     * @param ny      the number of grid points along the Y axis
     * @param nz      the number of grid points along the Z axis
     */
    void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
    /**
     * Get the parameters being used for dispersion PME.
     * 
     * @param alpha   the separation parameter
     * @param nx      the number of grid points along the X axis
     * @param ny      the number of grid points along the Y axis
     * @param nz      the number of grid points along the Z axis
     */
    void getDPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private:
    class ForceInfo;
    class TorquePostComputation;
    class SortTrait : public CudaSort::SortTrait {
        int getDataSize() const {return 8;}
        int getKeySize() const {return 4;}
        const char* getDataType() const {return "int2";}
        const char* getKeyType() const {return "int";}
        const char* getMinKey() const {return "(-2147483647-1)";}
        const char* getMaxKey() const {return "2147483647";}
        const char* getMaxValue() const {return "make_int2(2147483647, 2147483647)";}
        const char* getSortKey() const {return "value.y";}
    };
    void computeInducedField(void** recipBoxVectorPointer, int optOrder);
    void computeExtrapolatedDipoles(void** recipBoxVectorPointer);
    void ensureMultipolesValid(ContextImpl& context);
    void addTorquesToForces();
    void createFieldKernel(const std::string& interactionSrc, std::vector<CudaArray*> params, CudaArray& fieldBuffer,
        CUfunction& kernel, std::vector<void*>& args, CUfunction& exceptionKernel, std::vector<void*>& exceptionArgs,
        CudaArray& exceptionScale);
    int numParticles, maxExtrapolationOrder, maxTiles;
    int gridSizeX, gridSizeY, gridSizeZ;
    int dispersionGridSizeX, dispersionGridSizeY, dispersionGridSizeZ;
    double pmeAlpha, dpmeAlpha, cutoff;
    bool usePME, hasInitializedKernels, hasInitializedFFT, multipolesAreValid;
    std::vector<double> extrapolationCoefficients;
    CudaContext& cu;
    const System& system;
    CudaArray multipoleParticles;
    CudaArray coreCharge, valenceCharge, alpha, epsilon, damping, c6, pauliK, pauliQ, pauliAlpha, polarizability;
    CudaArray localDipoles, labDipoles, fracDipoles;
    CudaArray localQuadrupoles, labQuadrupoles[5], fracQuadrupoles;
    CudaArray field;
    CudaArray inducedField;
    CudaArray torque;
    CudaArray inducedDipole;
    CudaArray extrapolatedDipole, extrapolatedPhi;
    CudaArray pmeGrid1, pmeGrid2;
    CudaArray pmeAtomGridIndex;
    CudaArray pmeBsplineModuliX, pmeBsplineModuliY, pmeBsplineModuliZ;
    CudaArray dpmeBsplineModuliX, dpmeBsplineModuliY, dpmeBsplineModuliZ;
    CudaArray pmePhi, pmePhidp, pmeCphi;
    CudaArray lastPositions;
748
    CudaArray exceptionScales[6];
peastman's avatar
peastman committed
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
    CudaArray exceptionAtoms;
    CudaSort* sort;
    cufftHandle fftForward, fftBackward, dfftForward, dfftBackward;
    CUfunction computeMomentsKernel, fixedFieldKernel, fixedFieldExceptionKernel, mutualFieldKernel, mutualFieldExceptionKernel, computeExceptionsKernel;
    CUfunction recordInducedDipolesKernel, mapTorqueKernel;
    CUfunction pmeSpreadFixedMultipolesKernel, pmeSpreadInducedDipolesKernel, pmeFinishSpreadChargeKernel, pmeConvolutionKernel;
    CUfunction pmeFixedPotentialKernel, pmeInducedPotentialKernel, pmeFixedForceKernel, pmeInducedForceKernel, pmeRecordInducedFieldDipolesKernel;
    CUfunction pmeSelfEnergyKernel;
    CUfunction dpmeGridIndexKernel, dpmeSpreadChargeKernel, dpmeFinishSpreadChargeKernel, dpmeEvalEnergyKernel, dpmeConvolutionKernel, dpmeInterpolateForceKernel;
    CUfunction initExtrapolatedKernel, iterateExtrapolatedKernel, computeExtrapolatedKernel, polarizationEnergyKernel;
    CUfunction pmeTransformMultipolesKernel, pmeTransformPotentialKernel;
    std::vector<void*> fixedFieldArgs, fixedFieldExceptionArgs, mutualFieldArgs, mutualFieldExceptionArgs, computeExceptionsArgs;
    static const int PmeOrder = 5;
};

764
765
766
} // namespace OpenMM

#endif /*AMOEBA_OPENMM_CUDAKERNELS_H*/