"platforms/hip/tests/TestHipCustomCPPForce.cpp" did not exist on "58b094cec72f74db91e131277804e82e168c16e0"
CudaKernels.cpp 31.2 KB
Newer Older
1
2
3
4
5
6
7
8
/* -------------------------------------------------------------------------- *
 *                                   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.               *
 *                                                                            *
9
 * Portions copyright (c) 2008-2009 Stanford University and the Authors.      *
10
11
12
 * Authors: Peter Eastman                                                     *
 * Contributors:                                                              *
 *                                                                            *
13
14
15
16
 * 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.                                        *
17
 *                                                                            *
18
19
20
21
 * 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.                        *
22
 *                                                                            *
23
24
 * 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/>.      *
25
26
27
28
 * -------------------------------------------------------------------------- */

#include "CudaKernels.h"
#include "CudaStreamImpl.h"
29
#include "openmm/LangevinIntegrator.h"
30
#include "openmm/Context.h"
31
#include "ReferencePlatform.h"
32
#include "openmm/internal/ContextImpl.h"
33
#include "kernels/gputypes.h"
34
#include "kernels/cudaKernels.h"
35
36
37
38
39
40
41
#include <cmath>

extern "C" int gpuSetConstants( gpuContext gpu );

using namespace OpenMM;
using namespace std;

42
static void calcForces(ContextImpl& context, CudaPlatform::PlatformData& data) {
43
    _gpuContext* gpu = data.gpu;
44
    if (data.nonbondedMethod != NO_CUTOFF && data.computeForceCount%100 == 0)
45
        gpuReorderAtoms(gpu);
46
    data.computeForceCount++;
47
48
    kClearForces(gpu);
    if (gpu->bIncludeGBSA) {
49
        gpu->bRecalculateBornRadii = true;
50
51
52
53
        kCalculateCDLJObcGbsaForces1(gpu);
        kReduceObcGbsaBornForces(gpu);
        kCalculateObcGbsaForces2(gpu);
    }
54
    else if (data.hasNonbonded)
55
        kCalculateCDLJForces(gpu);
56
57
    if (data.hasCustomNonbonded)
        kCalculateCustomNonbondedForces(gpu, data.hasNonbonded);
58
    kCalculateLocalForces(gpu);
59
    kReduceForces(gpu);
60
61
}

62
63
static double calcEnergy(ContextImpl& context, CudaPlatform::PlatformData& data, System& system) {
    _gpuContext* gpu = data.gpu;
64
65
66
67
68
69
70
71
72
    if (data.nonbondedMethod != NO_CUTOFF && data.stepCount%100 == 0)
        gpuReorderAtoms(gpu);
    data.stepCount++;
    kClearEnergy(gpu);
    if (gpu->bIncludeGBSA) {
        gpu->bRecalculateBornRadii = true;
        kCalculateCDLJObcGbsaForces1(gpu);
        kReduceObcGbsaBornForces(gpu);
        kCalculateObcGbsaForces2(gpu);
73
    }
74
75
76
77
78
79
80
81
    else if (data.hasNonbonded)
        kCalculateCDLJForces(gpu);
    if (data.hasCustomNonbonded)
        kCalculateCustomNonbondedForces(gpu, data.hasNonbonded);
    kCalculateLocalForces(gpu);
    if (gpu->bIncludeGBSA)
        kReduceBornSumAndForces(gpu);
    return kReduceEnergy(gpu)+data.ewaldSelfEnergy;
82
83
}

84
85
86
void CudaInitializeForcesKernel::initialize(const System& system) {
}

87
void CudaInitializeForcesKernel::execute(ContextImpl& context) {
88
89
}

90
91
92
void CudaUpdateTimeKernel::initialize(const System& system) {
}

93
double CudaUpdateTimeKernel::getTime(const ContextImpl& context) const {
94
95
96
    return data.time;
}

97
void CudaUpdateTimeKernel::setTime(ContextImpl& context, double time) {
98
99
100
    data.time = time;
}

101
102
103
104
105
106
107
CudaCalcHarmonicBondForceKernel::~CudaCalcHarmonicBondForceKernel() {
}

void CudaCalcHarmonicBondForceKernel::initialize(const System& system, const HarmonicBondForce& force) {
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasBonds = true;
108
    numBonds = force.getNumBonds();
Peter Eastman's avatar
Peter Eastman committed
109
110
    vector<int> particle1(numBonds);
    vector<int> particle2(numBonds);
111
112
113
114
    vector<float> length(numBonds);
    vector<float> k(numBonds);
    for (int i = 0; i < numBonds; i++) {
        double lengthValue, kValue;
Peter Eastman's avatar
Peter Eastman committed
115
        force.getBondParameters(i, particle1[i], particle2[i], lengthValue, kValue);
116
117
118
        length[i] = (float) lengthValue;
        k[i] = (float) kValue;
    }
Peter Eastman's avatar
Peter Eastman committed
119
    gpuSetBondParameters(data.gpu, particle1, particle2, length, k);
120
121
}

122
void CudaCalcHarmonicBondForceKernel::executeForces(ContextImpl& context) {
123
124
125
126
    if (data.primaryKernel == this)
        calcForces(context, data);
}

127
double CudaCalcHarmonicBondForceKernel::executeEnergy(ContextImpl& context) {
128
    if (data.primaryKernel == this)
129
        return calcEnergy(context, data, system);
130
131
132
133
134
135
136
137
138
139
    return 0.0;
}

CudaCalcHarmonicAngleForceKernel::~CudaCalcHarmonicAngleForceKernel() {
}

void CudaCalcHarmonicAngleForceKernel::initialize(const System& system, const HarmonicAngleForce& force) {
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasAngles = true;
140
    numAngles = force.getNumAngles();
141
    const float RadiansToDegrees = (float) (180.0/3.14159265);
Peter Eastman's avatar
Peter Eastman committed
142
143
144
    vector<int> particle1(numAngles);
    vector<int> particle2(numAngles);
    vector<int> particle3(numAngles);
145
146
147
148
    vector<float> angle(numAngles);
    vector<float> k(numAngles);
    for (int i = 0; i < numAngles; i++) {
        double angleValue, kValue;
Peter Eastman's avatar
Peter Eastman committed
149
        force.getAngleParameters(i, particle1[i], particle2[i], particle3[i], angleValue, kValue);
150
151
        angle[i] = (float) (angleValue*RadiansToDegrees);
        k[i] = (float) kValue;
152
    }
Peter Eastman's avatar
Peter Eastman committed
153
    gpuSetBondAngleParameters(data.gpu, particle1, particle2, particle3, angle, k);
154
}
155

156
void CudaCalcHarmonicAngleForceKernel::executeForces(ContextImpl& context) {
157
158
159
160
    if (data.primaryKernel == this)
        calcForces(context, data);
}

161
double CudaCalcHarmonicAngleForceKernel::executeEnergy(ContextImpl& context) {
162
    if (data.primaryKernel == this)
163
        return calcEnergy(context, data, system);
164
165
166
167
168
169
170
171
172
173
174
    return 0.0;
}

CudaCalcPeriodicTorsionForceKernel::~CudaCalcPeriodicTorsionForceKernel() {
}

void CudaCalcPeriodicTorsionForceKernel::initialize(const System& system, const PeriodicTorsionForce& force) {
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasPeriodicTorsions = true;
    numTorsions = force.getNumTorsions();
175
    const float RadiansToDegrees = (float)(180.0/3.14159265);
Peter Eastman's avatar
Peter Eastman committed
176
177
178
179
    vector<int> particle1(numTorsions);
    vector<int> particle2(numTorsions);
    vector<int> particle3(numTorsions);
    vector<int> particle4(numTorsions);
180
181
182
183
184
    vector<float> k(numTorsions);
    vector<float> phase(numTorsions);
    vector<int> periodicity(numTorsions);
    for (int i = 0; i < numTorsions; i++) {
        double kValue, phaseValue;
Peter Eastman's avatar
Peter Eastman committed
185
        force.getTorsionParameters(i, particle1[i], particle2[i], particle3[i], particle4[i], periodicity[i], phaseValue, kValue);
186
187
        k[i] = (float) kValue;
        phase[i] = (float) (phaseValue*RadiansToDegrees);
188
    }
Peter Eastman's avatar
Peter Eastman committed
189
    gpuSetDihedralParameters(data.gpu, particle1, particle2, particle3, particle4, k, phase, periodicity);
190
191
}

192
void CudaCalcPeriodicTorsionForceKernel::executeForces(ContextImpl& context) {
193
194
195
196
    if (data.primaryKernel == this)
        calcForces(context, data);
}

197
double CudaCalcPeriodicTorsionForceKernel::executeEnergy(ContextImpl& context) {
198
    if (data.primaryKernel == this)
199
        return calcEnergy(context, data, system);
200
201
202
203
204
205
206
207
208
209
210
    return 0.0;
}

CudaCalcRBTorsionForceKernel::~CudaCalcRBTorsionForceKernel() {
}

void CudaCalcRBTorsionForceKernel::initialize(const System& system, const RBTorsionForce& force) {
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasRB = true;
    numTorsions = force.getNumTorsions();
Peter Eastman's avatar
Peter Eastman committed
211
212
213
214
    vector<int> particle1(numTorsions);
    vector<int> particle2(numTorsions);
    vector<int> particle3(numTorsions);
    vector<int> particle4(numTorsions);
215
216
217
218
219
220
221
222
    vector<float> c0(numTorsions);
    vector<float> c1(numTorsions);
    vector<float> c2(numTorsions);
    vector<float> c3(numTorsions);
    vector<float> c4(numTorsions);
    vector<float> c5(numTorsions);
    for (int i = 0; i < numTorsions; i++) {
        double c[6];
Peter Eastman's avatar
Peter Eastman committed
223
        force.getTorsionParameters(i, particle1[i], particle2[i], particle3[i], particle4[i], c[0], c[1], c[2], c[3], c[4], c[5]);
224
225
226
227
228
229
        c0[i] = (float) c[0];
        c1[i] = (float) c[1];
        c2[i] = (float) c[2];
        c3[i] = (float) c[3];
        c4[i] = (float) c[4];
        c5[i] = (float) c[5];
230
    }
Peter Eastman's avatar
Peter Eastman committed
231
    gpuSetRbDihedralParameters(data.gpu, particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5);
232
233
}

234
void CudaCalcRBTorsionForceKernel::executeForces(ContextImpl& context) {
235
236
237
238
    if (data.primaryKernel == this)
        calcForces(context, data);
}

239
double CudaCalcRBTorsionForceKernel::executeEnergy(ContextImpl& context) {
240
    if (data.primaryKernel == this)
241
        return calcEnergy(context, data, system);
242
243
244
245
246
247
    return 0.0;
}

CudaCalcNonbondedForceKernel::~CudaCalcNonbondedForceKernel() {
}

248
void CudaCalcNonbondedForceKernel::initialize(const System& system, const NonbondedForce& force) {
249
250
251
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasNonbonded = true;
Peter Eastman's avatar
Peter Eastman committed
252
    numParticles = force.getNumParticles();
253
    _gpuContext* gpu = data.gpu;
254
255
256
257

    // Identify which exceptions are 1-4 interactions.

    vector<pair<int, int> > exclusions;
258
    vector<int> exceptions;
259
260
261
262
263
264
    for (int i = 0; i < force.getNumExceptions(); i++) {
        int particle1, particle2;
        double chargeProd, sigma, epsilon;
        force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon);
        exclusions.push_back(pair<int, int>(particle1, particle2));
        if (chargeProd != 0.0 || epsilon != 0.0)
265
            exceptions.push_back(i);
266
267
    }

268
269
    // Initialize nonbonded interactions.
    
270
    {
Peter Eastman's avatar
Peter Eastman committed
271
272
273
274
        vector<int> particle(numParticles);
        vector<float> c6(numParticles);
        vector<float> c12(numParticles);
        vector<float> q(numParticles);
275
        vector<char> symbol;
Peter Eastman's avatar
Peter Eastman committed
276
277
        vector<vector<int> > exclusionList(numParticles);
        for (int i = 0; i < numParticles; i++) {
278
            double charge, radius, depth;
Peter Eastman's avatar
Peter Eastman committed
279
280
            force.getParticleParameters(i, charge, radius, depth);
            particle[i] = i;
281
282
283
            q[i] = (float) charge;
            c6[i] = (float) (4*depth*pow(radius, 6.0));
            c12[i] = (float) (4*depth*pow(radius, 12.0));
284
285
            exclusionList[i].push_back(i);
        }
286
        for (int i = 0; i < (int)exclusions.size(); i++) {
287
288
289
            exclusionList[exclusions[i].first].push_back(exclusions[i].second);
            exclusionList[exclusions[i].second].push_back(exclusions[i].first);
        }
290
291
        CudaNonbondedMethod method = NO_CUTOFF;
        if (force.getNonbondedMethod() != NonbondedForce::NoCutoff) {
292
            gpuSetNonbondedCutoff(gpu, (float)force.getCutoffDistance(), force.getReactionFieldDielectric());
293
294
295
296
297
            method = CUTOFF;
        }
        if (force.getNonbondedMethod() == NonbondedForce::CutoffPeriodic) {
            Vec3 boxVectors[3];
            force.getPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
298
            gpuSetPeriodicBoxSize(gpu, (float)boxVectors[0][0], (float)boxVectors[1][1], (float)boxVectors[2][2]);
299
300
            method = PERIODIC;
        }
301
302
303
        if (force.getNonbondedMethod() == NonbondedForce::Ewald) {
            Vec3 boxVectors[3];
            force.getPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
304
            gpuSetPeriodicBoxSize(gpu, (float)boxVectors[0][0], (float)boxVectors[1][1], (float)boxVectors[2][2]);
305
306
307
308
309
310
            double ewaldErrorTol = force.getEwaldErrorTolerance();
            double alpha = (1.0/force.getCutoffDistance())*std::sqrt(-std::log(ewaldErrorTol));
            double mx = boxVectors[0][0]/force.getCutoffDistance();
            double my = boxVectors[1][1]/force.getCutoffDistance();
            double mz = boxVectors[2][2]/force.getCutoffDistance();
            double pi = 3.1415926535897932385;
311
312
313
            int kmaxx = (int)std::ceil(-(mx/pi)*std::log(ewaldErrorTol));
            int kmaxy = (int)std::ceil(-(my/pi)*std::log(ewaldErrorTol));
            int kmaxz = (int)std::ceil(-(mz/pi)*std::log(ewaldErrorTol));
314
315
316
317
318
319
            if (kmaxx%2 == 0)
                kmaxx++;
            if (kmaxy%2 == 0)
                kmaxy++;
            if (kmaxz%2 == 0)
                kmaxz++;
320
            gpuSetEwaldParameters(gpu, (float)alpha, kmaxx, kmaxy, kmaxz);
321
322
            method = EWALD;
        }
323
324
        data.nonbondedMethod = method;
        gpuSetCoulombParameters(gpu, 138.935485f, particle, c6, c12, q, symbol, exclusionList, method);
325
326
327
328
329
330
331
332

        // Compute the Ewald self energy.

        data.ewaldSelfEnergy = 0.0;
        double selfEnergyScale = gpu->sim.epsfac*gpu->sim.alphaEwald/std::sqrt(PI);
        if (force.getNonbondedMethod() == NonbondedForce::Ewald)
            for (int i = 0; i < numParticles; i++)
                data.ewaldSelfEnergy -= selfEnergyScale*q[i]*q[i];
333
334
335
336
    }

    // Initialize 1-4 nonbonded interactions.
    
337
    {
338
339
340
341
342
343
344
345
        int numExceptions = exceptions.size();
        vector<int> particle1(numExceptions);
        vector<int> particle2(numExceptions);
        vector<float> c6(numExceptions);
        vector<float> c12(numExceptions);
        vector<float> q1(numExceptions);
        vector<float> q2(numExceptions);
        for (int i = 0; i < numExceptions; i++) {
346
            double charge, sig, eps;
347
            force.getExceptionParameters(exceptions[i], particle1[i], particle2[i], charge, sig, eps);
348
349
            c6[i] = (float) (4*eps*pow(sig, 6.0));
            c12[i] = (float) (4*eps*pow(sig, 12.0));
Peter Eastman's avatar
Peter Eastman committed
350
351
            q1[i] = (float) charge;
            q2[i] = 1.0f;
352
        }
Peter Eastman's avatar
Peter Eastman committed
353
        gpuSetLJ14Parameters(gpu, 138.935485f, 1.0f, particle1, particle2, c6, c12, q1, q2);
354
355
356
    }
}

357
void CudaCalcNonbondedForceKernel::executeForces(ContextImpl& context) {
358
359
    if (data.primaryKernel == this)
        calcForces(context, data);
360
361
}

362
double CudaCalcNonbondedForceKernel::executeEnergy(ContextImpl& context) {
363
    if (data.primaryKernel == this)
364
        return calcEnergy(context, data, system);
365
    return 0.0;
366
367
}

368
369
370
371
CudaCalcCustomNonbondedForceKernel::~CudaCalcCustomNonbondedForceKernel() {
}

void CudaCalcCustomNonbondedForceKernel::initialize(const System& system, const CustomNonbondedForce& force) {
372
    data.primaryKernel = this; // This must always be the primary kernel so it can update the global parameters
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
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
    data.hasCustomNonbonded = true;
    numParticles = force.getNumParticles();
    _gpuContext* gpu = data.gpu;

    // Identify which exceptions are actual interactions.

    vector<pair<int, int> > exclusions;
    vector<int> exceptions;
    {
        vector<double> parameters;
        for (int i = 0; i < force.getNumExceptions(); i++) {
            int particle1, particle2;
            force.getExceptionParameters(i, particle1, particle2, parameters);
            exclusions.push_back(pair<int, int>(particle1, particle2));
            if (parameters.size() > 0)
                exceptions.push_back(i);
        }
    }

    // Initialize nonbonded interactions.

    vector<int> particle(numParticles);
    vector<vector<double> > parameters(numParticles);
    vector<vector<int> > exclusionList(numParticles);
    for (int i = 0; i < numParticles; i++) {
        force.getParticleParameters(i, parameters[i]);
        particle[i] = i;
        exclusionList[i].push_back(i);
    }
    for (int i = 0; i < (int)exclusions.size(); i++) {
        exclusionList[exclusions[i].first].push_back(exclusions[i].second);
        exclusionList[exclusions[i].second].push_back(exclusions[i].first);
    }
    CudaNonbondedMethod method = NO_CUTOFF;
    if (force.getNonbondedMethod() != CustomNonbondedForce::NoCutoff)
        method = CUTOFF;
    if (force.getNonbondedMethod() == CustomNonbondedForce::CutoffPeriodic) {
        Vec3 boxVectors[3];
        force.getPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
        gpuSetPeriodicBoxSize(gpu, (float)boxVectors[0][0], (float)boxVectors[1][1], (float)boxVectors[2][2]);
        method = PERIODIC;
    }
    data.customNonbondedMethod = method;

    // Initialize exceptions.

    int numExceptions = exceptions.size();
    vector<int> exceptionParticle1(numExceptions);
    vector<int> exceptionParticle2(numExceptions);
    vector<vector<double> > exceptionParams(numExceptions);
    for (int i = 0; i < numExceptions; i++)
        force.getExceptionParameters(exceptions[i], exceptionParticle1[i], exceptionParticle2[i], exceptionParams[i]);

    // Record information for the expressions.

    vector<string> paramNames;
    vector<string> combiningRules;
    for (int i = 0; i < force.getNumParameters(); i++) {
        paramNames.push_back(force.getParameterName(i));
        combiningRules.push_back(force.getParameterCombiningRule(i));
    }
434
435
436
437
438
439
    globalParamNames.resize(force.getNumGlobalParameters());
    globalParamValues.resize(force.getNumGlobalParameters());
    for (int i = 0; i < force.getNumGlobalParameters(); i++) {
        globalParamNames[i] = force.getGlobalParameterName(i);
        globalParamValues[i] = force.getGlobalParameterDefaultValue(i);
    }
440
    gpuSetCustomNonbondedParameters(gpu, parameters, exclusionList, exceptionParticle1, exceptionParticle2, exceptionParams, method,
441
442
443
            (float)force.getCutoffDistance(), force.getEnergyFunction(), combiningRules, paramNames, globalParamNames);
    if (globalParamValues.size() > 0)
        SetCustomNonbondedGlobalParams(globalParamValues);
444
445
446
}

void CudaCalcCustomNonbondedForceKernel::executeForces(ContextImpl& context) {
447
448
    if (data.primaryKernel == this) {
        updateGlobalParams(context);
449
        calcForces(context, data);
450
    }
451
452
453
}

double CudaCalcCustomNonbondedForceKernel::executeEnergy(ContextImpl& context) {
454
455
    if (data.primaryKernel == this) {
        updateGlobalParams(context);
456
        return calcEnergy(context, data, system);
457
    }
458
459
460
    return 0.0;
}

461
462
463
464
465
466
467
468
469
470
471
472
void CudaCalcCustomNonbondedForceKernel::updateGlobalParams(ContextImpl& context) {
    bool changed = false;
    for (int i = 0; i < globalParamNames.size(); i++) {
        float value = (float) context.getParameter(globalParamNames[i]);
        if (value != globalParamValues[i])
            changed = true;
        globalParamValues[i] = value;
    }
    if (changed)
        SetCustomNonbondedGlobalParams(globalParamValues);
}

473
CudaCalcGBSAOBCForceKernel::~CudaCalcGBSAOBCForceKernel() {
474
475
}

476
void CudaCalcGBSAOBCForceKernel::initialize(const System& system, const GBSAOBCForce& force) {
477

Peter Eastman's avatar
Peter Eastman committed
478
    int numParticles = system.getNumParticles();
479
    _gpuContext* gpu = data.gpu;
Peter Eastman's avatar
Peter Eastman committed
480
481
    vector<float> radius(numParticles);
    vector<float> scale(numParticles);
482
    vector<float> charge(numParticles);
Peter Eastman's avatar
Peter Eastman committed
483
    for (int i = 0; i < numParticles; i++) {
484
485
        double particleCharge, particleRadius, scalingFactor;
        force.getParticleParameters(i, particleCharge, particleRadius, scalingFactor);
Peter Eastman's avatar
Peter Eastman committed
486
        radius[i] = (float) particleRadius;
487
        scale[i] = (float) scalingFactor;
488
        charge[i] = (float) particleCharge;
489
    }
490
    gpuSetObcParameters(gpu, (float) force.getSoluteDielectric(), (float) force.getSolventDielectric(), radius, scale, charge);
491
492
}

493
void CudaCalcGBSAOBCForceKernel::executeForces(ContextImpl& context) {
494
495
}

496
static void initializeIntegration(const System& system, CudaPlatform::PlatformData& data, const Integrator& integrator) {
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513

    // Initialize any terms that haven't already been handled by a Force.

    _gpuContext* gpu = data.gpu;
    if (!data.hasBonds)
        gpuSetBondParameters(gpu, vector<int>(), vector<int>(), vector<float>(), vector<float>());
    if (!data.hasAngles)
        gpuSetBondAngleParameters(gpu, vector<int>(), vector<int>(), vector<int>(), vector<float>(), vector<float>());
    if (!data.hasPeriodicTorsions)
        gpuSetDihedralParameters(gpu, vector<int>(), vector<int>(), vector<int>(), vector<int>(), vector<float>(), vector<float>(), vector<int>());
    if (!data.hasRB)
        gpuSetRbDihedralParameters(gpu, vector<int>(), vector<int>(), vector<int>(), vector<int>(), vector<float>(), vector<float>(),
                vector<float>(), vector<float>(), vector<float>(), vector<float>());
    if (!data.hasNonbonded) {
        gpuSetCoulombParameters(gpu, 138.935485f, vector<int>(), vector<float>(), vector<float>(), vector<float>(), vector<char>(), vector<vector<int> >(), NO_CUTOFF);
        gpuSetLJ14Parameters(gpu, 138.935485f, 1.0f, vector<int>(), vector<int>(), vector<float>(), vector<float>(), vector<float>(), vector<float>());
    }
514
515
516
    
    // Set masses.
    
Peter Eastman's avatar
Peter Eastman committed
517
518
519
520
    int numParticles = system.getNumParticles();
    vector<float> mass(numParticles);
    for (int i = 0; i < numParticles; i++)
        mass[i] = (float) system.getParticleMass(i);
521
522
523
524
    gpuSetMass(gpu, mass);
    
    // Set constraints.
    
525
    int numConstraints = system.getNumConstraints();
Peter Eastman's avatar
Peter Eastman committed
526
527
    vector<int> particle1(numConstraints);
    vector<int> particle2(numConstraints);
528
529
530
531
    vector<float> distance(numConstraints);
    vector<float> invMass1(numConstraints);
    vector<float> invMass2(numConstraints);
    for (int i = 0; i < numConstraints; i++) {
Peter Eastman's avatar
Peter Eastman committed
532
        int particle1Index, particle2Index;
533
        double constraintDistance;
Peter Eastman's avatar
Peter Eastman committed
534
535
536
        system.getConstraintParameters(i, particle1Index, particle2Index, constraintDistance);
        particle1[i] = particle1Index;
        particle2[i] = particle2Index;
537
        distance[i] = (float) constraintDistance;
Peter Eastman's avatar
Peter Eastman committed
538
539
        invMass1[i] = 1.0f/mass[particle1Index];
        invMass2[i] = 1.0f/mass[particle2Index];
540
    }
541
    gpuSetConstraintParameters(gpu, particle1, particle2, distance, invMass1, invMass2, (float)integrator.getConstraintTolerance());
542
543
    
    // Finish initialization.
544

545
546
547
    gpuBuildThreadBlockWorkList(gpu);
    gpuBuildExclusionList(gpu);
    gpuBuildOutputBuffers(gpu);
548
    gpuSetConstants(gpu);
549
550
551
    kClearBornForces(gpu);
    kClearForces(gpu);
    cudaThreadSynchronize();
552
553
}

554
double CudaCalcGBSAOBCForceKernel::executeEnergy(ContextImpl& context) {
555
	return 0.0;
556
557
558
559
560
561
}

CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() {
}

void CudaIntegrateVerletStepKernel::initialize(const System& system, const VerletIntegrator& integrator) {
562
    initializeIntegration(system, data, integrator);
563
564
565
    prevStepSize = -1.0;
}

566
void CudaIntegrateVerletStepKernel::execute(ContextImpl& context, const VerletIntegrator& integrator) {
567
568
569
570
571
    _gpuContext* gpu = data.gpu;
    double stepSize = integrator.getStepSize();
    if (stepSize != prevStepSize) {
        // Initialize the GPU parameters.
        
572
        gpuSetVerletIntegrationParameters(gpu, (float) stepSize, 0.0f);
573
574
575
576
577
        gpuSetConstants(gpu);
        prevStepSize = stepSize;
    }
    kVerletUpdatePart1(gpu);
    kApplyFirstShake(gpu);
578
    kApplyFirstSettle(gpu);
579
    kApplyFirstCCMA(gpu);
580
581
    if (data.removeCM)
        if (data.stepCount%data.cmMotionFrequency == 0)
582
583
            gpu->bCalculateCM = true;
    kVerletUpdatePart2(gpu);
584
    data.time += stepSize;
585
    data.stepCount++;
586
587
588
589
590
591
}

CudaIntegrateLangevinStepKernel::~CudaIntegrateLangevinStepKernel() {
}

void CudaIntegrateLangevinStepKernel::initialize(const System& system, const LangevinIntegrator& integrator) {
592
    initializeIntegration(system, data, integrator);
593
594
595
    _gpuContext* gpu = data.gpu;
    gpu->seed = (unsigned long) integrator.getRandomNumberSeed();
    gpuInitializeRandoms(gpu);
596
597
598
    prevStepSize = -1.0;
}

599
void CudaIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) {
600
    _gpuContext* gpu = data.gpu;
601
602
603
    double temperature = integrator.getTemperature();
    double friction = integrator.getFriction();
    double stepSize = integrator.getStepSize();
604
605
606
607
    if (temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
        // Initialize the GPU parameters.
        
        double tau = (friction == 0.0 ? 0.0 : 1.0/friction);
608
        gpuSetLangevinIntegrationParameters(gpu, (float) tau, (float) stepSize, (float) temperature, 0.0f);
609
610
611
612
613
614
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevTemp = temperature;
        prevFriction = friction;
        prevStepSize = stepSize;
    }
615
    kLangevinUpdatePart1(gpu);
616
    kApplyFirstShake(gpu);
617
    kApplyFirstSettle(gpu);
618
    kApplyFirstCCMA(gpu);
619
620
    if (data.removeCM)
        if (data.stepCount%data.cmMotionFrequency == 0)
621
            gpu->bCalculateCM = true;
622
    kLangevinUpdatePart2(gpu);
623
    kApplySecondShake(gpu);
624
    kApplySecondSettle(gpu);
625
    kApplySecondCCMA(gpu);
626
    data.time += stepSize;
627
    data.stepCount++;
628
}
629
630
631
632
633

CudaIntegrateBrownianStepKernel::~CudaIntegrateBrownianStepKernel() {
}

void CudaIntegrateBrownianStepKernel::initialize(const System& system, const BrownianIntegrator& integrator) {
634
    initializeIntegration(system, data, integrator);
635
636
637
    _gpuContext* gpu = data.gpu;
    gpu->seed = (unsigned long) integrator.getRandomNumberSeed();
    gpuInitializeRandoms(gpu);
638
639
640
    prevStepSize = -1.0;
}

641
void CudaIntegrateBrownianStepKernel::execute(ContextImpl& context, const BrownianIntegrator& integrator) {
642
643
644
645
646
647
648
649
    _gpuContext* gpu = data.gpu;
    double temperature = integrator.getTemperature();
    double friction = integrator.getFriction();
    double stepSize = integrator.getStepSize();
    if (temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
        // Initialize the GPU parameters.
        
        double tau = (friction == 0.0 ? 0.0 : 1.0/friction);
650
        gpuSetBrownianIntegrationParameters(gpu, (float) tau, (float) stepSize, (float) temperature);
651
652
653
654
655
656
657
658
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevTemp = temperature;
        prevFriction = friction;
        prevStepSize = stepSize;
    }
    kBrownianUpdatePart1(gpu);
    kApplyFirstShake(gpu);
659
    kApplyFirstSettle(gpu);
660
    kApplyFirstCCMA(gpu);
661
662
    if (data.removeCM)
        if (data.stepCount%data.cmMotionFrequency == 0)
663
664
            gpu->bCalculateCM = true;
    kBrownianUpdatePart2(gpu);
665
    data.time += stepSize;
666
667
668
669
670
671
672
673
674
675
676
    data.stepCount++;
}

CudaIntegrateVariableVerletStepKernel::~CudaIntegrateVariableVerletStepKernel() {
}

void CudaIntegrateVariableVerletStepKernel::initialize(const System& system, const VariableVerletIntegrator& integrator) {
    initializeIntegration(system, data, integrator);
    prevErrorTol = -1.0;
}

677
void CudaIntegrateVariableVerletStepKernel::execute(ContextImpl& context, const VariableVerletIntegrator& integrator, double maxTime) {
678
679
680
681
682
683
684
685
686
    _gpuContext* gpu = data.gpu;
    double errorTol = integrator.getErrorTolerance();
    if (errorTol != prevErrorTol) {
        // Initialize the GPU parameters.

        gpuSetVerletIntegrationParameters(gpu, 0.0f, (float) errorTol);
        gpuSetConstants(gpu);
        prevErrorTol = errorTol;
    }
687
    float maxStepSize = (float)(maxTime-data.time);
688
    kSelectVerletStepSize(gpu, maxStepSize);
689
690
691
692
693
694
695
696
697
698
    kVerletUpdatePart1(gpu);
    kApplyFirstShake(gpu);
    kApplyFirstSettle(gpu);
    kApplyFirstCCMA(gpu);
    if (data.removeCM)
        if (data.stepCount%data.cmMotionFrequency == 0)
            gpu->bCalculateCM = true;
    kVerletUpdatePart2(gpu);
    gpu->psStepSize->Download();
    data.time += (*gpu->psStepSize)[0].y;
699
700
    if ((*gpu->psStepSize)[0].y == maxStepSize)
        data.time = maxTime; // Avoid round-off error
701
    data.stepCount++;
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
748
749
750
CudaIntegrateVariableLangevinStepKernel::~CudaIntegrateVariableLangevinStepKernel() {
}

void CudaIntegrateVariableLangevinStepKernel::initialize(const System& system, const VariableLangevinIntegrator& integrator) {
    initializeIntegration(system, data, integrator);
    _gpuContext* gpu = data.gpu;
    gpu->seed = (unsigned long) integrator.getRandomNumberSeed();
    gpuInitializeRandoms(gpu);
    prevErrorTol = -1.0;
}

void CudaIntegrateVariableLangevinStepKernel::execute(ContextImpl& context, const VariableLangevinIntegrator& integrator, double maxTime) {
    _gpuContext* gpu = data.gpu;
    double temperature = integrator.getTemperature();
    double friction = integrator.getFriction();
    double errorTol = integrator.getErrorTolerance();
    if (temperature != prevTemp || friction != prevFriction || errorTol != prevErrorTol) {
        // Initialize the GPU parameters.

        double tau = (friction == 0.0 ? 0.0 : 1.0/friction);
        gpuSetLangevinIntegrationParameters(gpu, (float) tau, 0.0f, (float) temperature, errorTol);
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevTemp = temperature;
        prevFriction = friction;
        prevErrorTol = errorTol;
    }
    float maxStepSize = (float)(maxTime-data.time);
    kSelectLangevinStepSize(gpu, maxStepSize);
    kLangevinUpdatePart1(gpu);
    kApplyFirstShake(gpu);
    kApplyFirstSettle(gpu);
    kApplyFirstCCMA(gpu);
    if (data.removeCM)
        if (data.stepCount%data.cmMotionFrequency == 0)
            gpu->bCalculateCM = true;
    kLangevinUpdatePart2(gpu);
    kApplySecondShake(gpu);
    kApplySecondSettle(gpu);
    kApplySecondCCMA(gpu);
    gpu->psStepSize->Download();
    data.time += (*gpu->psStepSize)[0].y;
    if ((*gpu->psStepSize)[0].y == maxStepSize)
        data.time = maxTime; // Avoid round-off error
    data.stepCount++;
}

751
752
753
754
CudaApplyAndersenThermostatKernel::~CudaApplyAndersenThermostatKernel() {
}

void CudaApplyAndersenThermostatKernel::initialize(const System& system, const AndersenThermostat& thermostat) {
755
756
757
    _gpuContext* gpu = data.gpu;
    gpu->seed = (unsigned long) thermostat.getRandomNumberSeed();
    gpuInitializeRandoms(gpu);
758
759
760
    prevStepSize = -1.0;
}

761
void CudaApplyAndersenThermostatKernel::execute(ContextImpl& context) {
762
    _gpuContext* gpu = data.gpu;
763
764
    double temperature = context.getParameter(AndersenThermostat::Temperature());
    double frequency = context.getParameter(AndersenThermostat::CollisionFrequency());
765
766
767
768
    double stepSize = context.getIntegrator().getStepSize();
    if (temperature != prevTemp || frequency != prevFrequency || stepSize != prevStepSize) {
        // Initialize the GPU parameters.
        
769
        gpuSetAndersenThermostatParameters(gpu, (float) temperature, frequency);
770
771
772
773
774
775
776
777
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevTemp = temperature;
        prevFrequency = frequency;
        prevStepSize = stepSize;
    }
    kCalculateAndersenThermostat(gpu);
}
778

779
void CudaCalcKineticEnergyKernel::initialize(const System& system) {
Peter Eastman's avatar
Peter Eastman committed
780
781
    int numParticles = system.getNumParticles();
    masses.resize(numParticles);
782
    for (int i = 0; i < numParticles; ++i)
Peter Eastman's avatar
Peter Eastman committed
783
        masses[i] = system.getParticleMass(i);
784
785
}

786
double CudaCalcKineticEnergyKernel::execute(ContextImpl& context) {
787
788
789
    // We don't currently have a GPU kernel to do this, so we retrieve the velocities and calculate the energy
    // on the CPU.
    
790
    const Stream& velocities = context.getVelocities();
791
792
793
794
795
796
797
798
    double* v = new double[velocities.getSize()*3];
    velocities.saveToArray(v);
    double energy = 0.0;
    for (size_t i = 0; i < masses.size(); ++i)
        energy += masses[i]*(v[i*3]*v[i*3]+v[i*3+1]*v[i*3+1]+v[i*3+2]*v[i*3+2]);
    delete v;
    return 0.5*energy;
}
799

800
void CudaRemoveCMMotionKernel::initialize(const System& system, const CMMotionRemover& force) {
801
    data.removeCM = true;
802
    data.cmMotionFrequency = force.getFrequency();
803
804
}

805
void CudaRemoveCMMotionKernel::execute(ContextImpl& context) {
806
}