CudaKernels.cpp 20.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* -------------------------------------------------------------------------- *
 *                                   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 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.                                     *
 * -------------------------------------------------------------------------- */

32
33
#include "OpenMMContext.h"

34
35
#include "CudaKernels.h"
#include "CudaStreamImpl.h"
36
37
#include "LangevinIntegrator.h"
#include "ReferencePlatform.h"
38
#include "internal/OpenMMContextImpl.h"
39
#include "kernels/gputypes.h"
40
#include "kernels/cudaKernels.h"
41
42
43
44
45
46
47
#include <cmath>

extern "C" int gpuSetConstants( gpuContext gpu );

using namespace OpenMM;
using namespace std;

48
49
50
static void calcForces(OpenMMContextImpl& context, CudaPlatform::PlatformData& data) {
    _gpuContext* gpu = data.gpu;
    if (data.useOBC) {
51
        gpu->bRecalculateBornRadii = true;
52
53
54
55
56
57
58
59
60
61
        kCalculateCDLJObcGbsaForces1(gpu);
        kReduceObcGbsaBornForces(gpu);
        kCalculateObcGbsaForces2(gpu);
    }
    else {
        kClearForces(gpu);
        kCalculateCDLJForces(gpu);
    }
    kCalculateLocalForces(gpu);
    kReduceBornSumAndForces(gpu);
62
63
}

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
static double calcEnergy(OpenMMContextImpl& context, System& system) {
    // We don't currently have GPU kernels to calculate energy, so instead we have the reference
    // platform do it.  This is VERY slow.
    
    LangevinIntegrator integrator(0.0, 1.0, 0.0);
    ReferencePlatform platform;
    OpenMMContext refContext(system, integrator, platform);
    const Stream& positions = context.getPositions();
    double* posData = new double[positions.getSize()*3];
    positions.saveToArray(posData);
    vector<Vec3> pos(positions.getSize());
    for (int i = 0; i < pos.size(); i++)
        pos[i] = Vec3(posData[3*i], posData[3*i+1], posData[3*i+2]);
    delete[] posData;
    refContext.setPositions(pos);
    return refContext.getState(State::Energy).getPotentialEnergy();
}

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

double CudaInitializeForcesKernel::execute(OpenMMContextImpl& context) {
}

88
89
90
91
92
93
94
CudaCalcHarmonicBondForceKernel::~CudaCalcHarmonicBondForceKernel() {
}

void CudaCalcHarmonicBondForceKernel::initialize(const System& system, const HarmonicBondForce& force) {
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasBonds = true;
95
    numBonds = force.getNumBonds();
Peter Eastman's avatar
Peter Eastman committed
96
97
    vector<int> particle1(numBonds);
    vector<int> particle2(numBonds);
98
99
100
101
    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
102
        force.getBondParameters(i, particle1[i], particle2[i], lengthValue, kValue);
103
104
105
        length[i] = (float) lengthValue;
        k[i] = (float) kValue;
    }
Peter Eastman's avatar
Peter Eastman committed
106
    gpuSetBondParameters(data.gpu, particle1, particle2, length, k);
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
}

void CudaCalcHarmonicBondForceKernel::executeForces(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        calcForces(context, data);
}

double CudaCalcHarmonicBondForceKernel::executeEnergy(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        return calcEnergy(context, system);
    return 0.0;
}

CudaCalcHarmonicAngleForceKernel::~CudaCalcHarmonicAngleForceKernel() {
}

void CudaCalcHarmonicAngleForceKernel::initialize(const System& system, const HarmonicAngleForce& force) {
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasAngles = true;
127
    numAngles = force.getNumAngles();
128
    const float RadiansToDegrees = (float) (180.0/3.14159265);
Peter Eastman's avatar
Peter Eastman committed
129
130
131
    vector<int> particle1(numAngles);
    vector<int> particle2(numAngles);
    vector<int> particle3(numAngles);
132
133
134
135
    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
136
        force.getAngleParameters(i, particle1[i], particle2[i], particle3[i], angleValue, kValue);
137
138
        angle[i] = (float) (angleValue*RadiansToDegrees);
        k[i] = (float) kValue;
139
    }
Peter Eastman's avatar
Peter Eastman committed
140
    gpuSetBondAngleParameters(data.gpu, particle1, particle2, particle3, angle, k);
141
}
142

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
void CudaCalcHarmonicAngleForceKernel::executeForces(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        calcForces(context, data);
}

double CudaCalcHarmonicAngleForceKernel::executeEnergy(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        return calcEnergy(context, system);
    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();
    const float RadiansToDegrees = 180.0/3.14159265;
Peter Eastman's avatar
Peter Eastman committed
163
164
165
166
    vector<int> particle1(numTorsions);
    vector<int> particle2(numTorsions);
    vector<int> particle3(numTorsions);
    vector<int> particle4(numTorsions);
167
168
169
170
171
    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
172
        force.getTorsionParameters(i, particle1[i], particle2[i], particle3[i], particle4[i], periodicity[i], phaseValue, kValue);
173
174
        k[i] = (float) kValue;
        phase[i] = (float) (phaseValue*RadiansToDegrees);
175
    }
Peter Eastman's avatar
Peter Eastman committed
176
    gpuSetDihedralParameters(data.gpu, particle1, particle2, particle3, particle4, k, phase, periodicity);
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
}

void CudaCalcPeriodicTorsionForceKernel::executeForces(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        calcForces(context, data);
}

double CudaCalcPeriodicTorsionForceKernel::executeEnergy(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        return calcEnergy(context, system);
    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
198
199
200
201
    vector<int> particle1(numTorsions);
    vector<int> particle2(numTorsions);
    vector<int> particle3(numTorsions);
    vector<int> particle4(numTorsions);
202
203
204
205
206
207
208
209
    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
210
        force.getTorsionParameters(i, particle1[i], particle2[i], particle3[i], particle4[i], c[0], c[1], c[2], c[3], c[4], c[5]);
211
212
213
214
215
216
        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];
217
    }
Peter Eastman's avatar
Peter Eastman committed
218
    gpuSetRbDihedralParameters(data.gpu, particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5);
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
}

void CudaCalcRBTorsionForceKernel::executeForces(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        calcForces(context, data);
}

double CudaCalcRBTorsionForceKernel::executeEnergy(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        return calcEnergy(context, system);
    return 0.0;
}

CudaCalcNonbondedForceKernel::~CudaCalcNonbondedForceKernel() {
}

void CudaCalcNonbondedForceKernel::initialize(const System& system, const NonbondedForce& force, const std::vector<std::set<int> >& exclusions) {
    if (data.primaryKernel == NULL)
        data.primaryKernel = this;
    data.hasNonbonded = true;
Peter Eastman's avatar
Peter Eastman committed
239
    numParticles = force.getNumParticles();
240
241
    num14 = force.getNumNonbonded14();
    _gpuContext* gpu = data.gpu;
242
243
244
    
    // Initialize nonbonded interactions.
    
245
    {
Peter Eastman's avatar
Peter Eastman committed
246
247
248
249
        vector<int> particle(numParticles);
        vector<float> c6(numParticles);
        vector<float> c12(numParticles);
        vector<float> q(numParticles);
250
        vector<char> symbol;
Peter Eastman's avatar
Peter Eastman committed
251
252
        vector<vector<int> > exclusionList(numParticles);
        for (int i = 0; i < numParticles; i++) {
253
            double charge, radius, depth;
Peter Eastman's avatar
Peter Eastman committed
254
255
            force.getParticleParameters(i, charge, radius, depth);
            particle[i] = i;
256
257
258
            q[i] = (float) charge;
            c6[i] = (float) (4*depth*pow(radius, 6.0));
            c12[i] = (float) (4*depth*pow(radius, 12.0));
259
260
261
            exclusionList[i] = vector<int>(exclusions[i].begin(), exclusions[i].end());
            exclusionList[i].push_back(i);
        }
Peter Eastman's avatar
Peter Eastman committed
262
        gpuSetCoulombParameters(gpu, 138.935485f, particle, c6, c12, q, symbol, exclusionList);
263
264
265
266
    }

    // Initialize 1-4 nonbonded interactions.
    
267
    {
Peter Eastman's avatar
Peter Eastman committed
268
269
        vector<int> particle1(num14);
        vector<int> particle2(num14);
270
271
272
273
274
        vector<float> c6(num14);
        vector<float> c12(num14);
        vector<float> q1(num14);
        vector<float> q2(num14);
        for (int i = 0; i < num14; i++) {
275
            double charge, sig, eps;
Peter Eastman's avatar
Peter Eastman committed
276
            force.getNonbonded14Parameters(i, particle1[i], particle2[i], charge, sig, eps);
277
278
            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
279
280
            q1[i] = (float) charge;
            q2[i] = 1.0f;
281
        }
Peter Eastman's avatar
Peter Eastman committed
282
        gpuSetLJ14Parameters(gpu, 138.935485f, 1.0f, particle1, particle2, c6, c12, q1, q2);
283
284
285
    }
}

286
287
288
void CudaCalcNonbondedForceKernel::executeForces(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        calcForces(context, data);
289
290
}

291
292
293
294
double CudaCalcNonbondedForceKernel::executeEnergy(OpenMMContextImpl& context) {
    if (data.primaryKernel == this)
        return calcEnergy(context, system);
    return 0.0;
295
296
}

297
CudaCalcGBSAOBCForceKernel::~CudaCalcGBSAOBCForceKernel() {
298
299
}

300
void CudaCalcGBSAOBCForceKernel::initialize(const System& system, const GBSAOBCForce& force) {
301

Peter Eastman's avatar
Peter Eastman committed
302
    int numParticles = system.getNumParticles();
303
    _gpuContext* gpu = data.gpu;
Peter Eastman's avatar
Peter Eastman committed
304
305
306
307
308
309
310
311
    vector<int> particle(numParticles);
    vector<float> radius(numParticles);
    vector<float> scale(numParticles);
    for (int i = 0; i < numParticles; i++) {
        double charge, particleRadius, scalingFactor;
        force.getParticleParameters(i, charge, particleRadius, scalingFactor);
        particle[i] = i;
        radius[i] = (float) particleRadius;
312
        scale[i] = (float) scalingFactor;
313
    }
314
    gpuSetObcParameters(gpu, (float) force.getSoluteDielectric(), (float) force.getSolventDielectric(), particle, radius, scale);
315
316
317
    data.useOBC = true;
}

318
void CudaCalcGBSAOBCForceKernel::executeForces(OpenMMContextImpl& context) {
319
320
}

321
static void initializeIntegration(const System& system, CudaPlatform::PlatformData& data, const Integrator& integrator) {
322
323
324
    
    // Set masses.
    
325
    _gpuContext* gpu = data.gpu;
Peter Eastman's avatar
Peter Eastman committed
326
327
328
329
    int numParticles = system.getNumParticles();
    vector<float> mass(numParticles);
    for (int i = 0; i < numParticles; i++)
        mass[i] = (float) system.getParticleMass(i);
330
331
332
333
    gpuSetMass(gpu, mass);
    
    // Set constraints.
    
334
    int numConstraints = system.getNumConstraints();
Peter Eastman's avatar
Peter Eastman committed
335
336
    vector<int> particle1(numConstraints);
    vector<int> particle2(numConstraints);
337
338
339
340
    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
341
        int particle1Index, particle2Index;
342
        double constraintDistance;
Peter Eastman's avatar
Peter Eastman committed
343
344
345
        system.getConstraintParameters(i, particle1Index, particle2Index, constraintDistance);
        particle1[i] = particle1Index;
        particle2[i] = particle2Index;
346
        distance[i] = (float) constraintDistance;
Peter Eastman's avatar
Peter Eastman committed
347
348
        invMass1[i] = 1.0f/mass[particle1Index];
        invMass2[i] = 1.0f/mass[particle2Index];
349
    }
350
    gpuSetShakeParameters(gpu, particle1, particle2, distance, invMass1, invMass2, integrator.getConstraintTolerance());
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
    
    // Initialize any terms that haven't already been handled by a Force.
    
    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> >());
        gpuSetLJ14Parameters(gpu, 138.935485f, 1.0f, vector<int>(), vector<int>(), vector<float>(), vector<float>(), vector<float>(), vector<float>());
    }
    
    // Finish initialization.
    
370
371
372
    gpuBuildThreadBlockWorkList(gpu);
    gpuBuildExclusionList(gpu);
    gpuBuildOutputBuffers(gpu);
373
    gpuSetConstants(gpu);
374
375
376
    kClearBornForces(gpu);
    kClearForces(gpu);
    cudaThreadSynchronize();
377
378
}

379
double CudaCalcGBSAOBCForceKernel::executeEnergy(OpenMMContextImpl& context) {
380
	return 0.0;
381
382
383
384
385
386
}

CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() {
}

void CudaIntegrateVerletStepKernel::initialize(const System& system, const VerletIntegrator& integrator) {
387
    initializeIntegration(system, data, integrator);
388
389
390
391
392
393
394
395
396
    prevStepSize = -1.0;
}

void CudaIntegrateVerletStepKernel::execute(OpenMMContextImpl& context, const VerletIntegrator& integrator) {
    _gpuContext* gpu = data.gpu;
    double stepSize = integrator.getStepSize();
    if (stepSize != prevStepSize) {
        // Initialize the GPU parameters.
        
397
        gpuSetVerletIntegrationParameters(gpu, (float) stepSize);
398
399
400
401
402
403
404
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevStepSize = stepSize;
    }
    kVerletUpdatePart1(gpu);
    kApplyFirstShake(gpu);
    if (data.removeCM) {
405
        int step = (int) (context.getTime()/stepSize);
406
407
408
409
410
411
412
413
414
415
        if (step%data.cmMotionFrequency == 0)
            gpu->bCalculateCM = true;
    }
    kVerletUpdatePart2(gpu);
}

CudaIntegrateLangevinStepKernel::~CudaIntegrateLangevinStepKernel() {
}

void CudaIntegrateLangevinStepKernel::initialize(const System& system, const LangevinIntegrator& integrator) {
416
    initializeIntegration(system, data, integrator);
417
418
419
    prevStepSize = -1.0;
}

420
void CudaIntegrateLangevinStepKernel::execute(OpenMMContextImpl& context, const LangevinIntegrator& integrator) {
421
    _gpuContext* gpu = data.gpu;
422
423
424
    double temperature = integrator.getTemperature();
    double friction = integrator.getFriction();
    double stepSize = integrator.getStepSize();
425
426
427
428
    if (temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
        // Initialize the GPU parameters.
        
        double tau = (friction == 0.0 ? 0.0 : 1.0/friction);
429
        gpuSetIntegrationParameters(gpu, (float) tau, (float) stepSize, (float) temperature);
430
431
432
433
434
435
436
437
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevTemp = temperature;
        prevFriction = friction;
        prevStepSize = stepSize;
    }
    kUpdatePart1(gpu);
    kApplyFirstShake(gpu);
438
    if (data.removeCM) {
439
        int step = (int) (context.getTime()/stepSize);
440
441
442
        if (step%data.cmMotionFrequency == 0)
            gpu->bCalculateCM = true;
    }
443
444
445
    kUpdatePart2(gpu);
    kApplySecondShake(gpu);
}
446
447
448
449
450

CudaIntegrateBrownianStepKernel::~CudaIntegrateBrownianStepKernel() {
}

void CudaIntegrateBrownianStepKernel::initialize(const System& system, const BrownianIntegrator& integrator) {
451
    initializeIntegration(system, data, integrator);
452
453
454
455
456
457
458
459
460
461
462
463
    prevStepSize = -1.0;
}

void CudaIntegrateBrownianStepKernel::execute(OpenMMContextImpl& context, const BrownianIntegrator& integrator) {
    _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);
464
        gpuSetBrownianIntegrationParameters(gpu, (float) tau, (float) stepSize, (float) temperature);
465
466
467
468
469
470
471
472
473
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevTemp = temperature;
        prevFriction = friction;
        prevStepSize = stepSize;
    }
    kBrownianUpdatePart1(gpu);
    kApplyFirstShake(gpu);
    if (data.removeCM) {
474
        int step = (int) (context.getTime()/stepSize);
475
476
477
478
479
        if (step%data.cmMotionFrequency == 0)
            gpu->bCalculateCM = true;
    }
    kBrownianUpdatePart2(gpu);
}
480
481
482
483
484
485
486
487
488
489

CudaApplyAndersenThermostatKernel::~CudaApplyAndersenThermostatKernel() {
}

void CudaApplyAndersenThermostatKernel::initialize(const System& system, const AndersenThermostat& thermostat) {
    prevStepSize = -1.0;
}

void CudaApplyAndersenThermostatKernel::execute(OpenMMContextImpl& context) {
    _gpuContext* gpu = data.gpu;
490
491
    double temperature = context.getParameter(AndersenThermostat::Temperature());
    double frequency = context.getParameter(AndersenThermostat::CollisionFrequency());
492
493
494
495
    double stepSize = context.getIntegrator().getStepSize();
    if (temperature != prevTemp || frequency != prevFrequency || stepSize != prevStepSize) {
        // Initialize the GPU parameters.
        
496
        gpuSetAndersenThermostatParameters(gpu, (float) temperature, (float) (frequency*stepSize));
497
498
499
500
501
502
503
504
        gpuSetConstants(gpu);
        kGenerateRandoms(gpu);
        prevTemp = temperature;
        prevFrequency = frequency;
        prevStepSize = stepSize;
    }
    kCalculateAndersenThermostat(gpu);
}
505

506
void CudaCalcKineticEnergyKernel::initialize(const System& system) {
Peter Eastman's avatar
Peter Eastman committed
507
508
    int numParticles = system.getNumParticles();
    masses.resize(numParticles);
509
    for (int i = 0; i < numParticles; ++i)
Peter Eastman's avatar
Peter Eastman committed
510
        masses[i] = system.getParticleMass(i);
511
512
}

513
double CudaCalcKineticEnergyKernel::execute(OpenMMContextImpl& context) {
514
515
516
    // We don't currently have a GPU kernel to do this, so we retrieve the velocities and calculate the energy
    // on the CPU.
    
517
    const Stream& velocities = context.getVelocities();
518
519
520
521
522
523
524
525
    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;
}
526

527
void CudaRemoveCMMotionKernel::initialize(const System& system, const CMMotionRemover& force) {
528
    data.removeCM = true;
529
    data.cmMotionFrequency = force.getFrequency();
530
531
}

532
void CudaRemoveCMMotionKernel::execute(OpenMMContextImpl& context) {
533
}