ReferenceKernels.h 22.2 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
32
33
34
#ifndef OPENMM_REFERENCEKERNELS_H_
#define OPENMM_REFERENCEKERNELS_H_

/* -------------------------------------------------------------------------- *
 *                                   OpenMM                                   *
 * -------------------------------------------------------------------------- *
 * This is part of the OpenMM molecular simulation toolkit originating from   *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
 * Portions copyright (c) 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.                                     *
 * -------------------------------------------------------------------------- */

35
#include "ReferencePlatform.h"
36
#include "openmm/kernels.h"
37
#include "SimTKUtilities/SimTKOpenMMRealType.h"
38
#include "SimTKReference/ReferenceNeighborList.h"
39

40
class CpuObc;
Mark Friedrichs's avatar
Mark Friedrichs committed
41
class CpuGBVI;
42
class ReferenceAndersenThermostat;
43
class ReferenceBrownianDynamics;
44
class ReferenceStochasticDynamics;
45
class ReferenceConstraintAlgorithm;
46
class ReferenceVariableStochasticDynamics;
47
class ReferenceVariableVerletDynamics;
48
class ReferenceVerletDynamics;
49

50
51
namespace OpenMM {

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 * This kernel is invoked at the start of each force evaluation to clear the forces.
 */
class ReferenceInitializeForcesKernel : public InitializeForcesKernel {
public:
    ReferenceInitializeForcesKernel(std::string name, const Platform& platform) : InitializeForcesKernel(name, platform) {
    }
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     */
    void initialize(const System& system);
    /**
     * Execute the kernel.
     * 
     * @param context    the context in which to execute this kernel
     */
70
    void execute(ContextImpl& context);
71
72
};

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
 * This kernel is invoked to get or set the current time.
 */
class ReferenceUpdateTimeKernel : public UpdateTimeKernel {
public:
    ReferenceUpdateTimeKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : UpdateTimeKernel(name, platform), data(data) {
    }
    /**
     * Initialize the kernel.
     *
     * @param system     the System this kernel will be applied to
     */
    void initialize(const System& system);
    /**
     * Get the current time (in picoseconds).
     *
     * @param context    the context in which to execute this kernel
     */
91
    double getTime(const ContextImpl& context) const;
92
93
94
95
96
    /**
     * Set the current time (in picoseconds).
     *
     * @param context    the context in which to execute this kernel
     */
97
    void setTime(ContextImpl& context, double time);
98
99
100
101
private:
    ReferencePlatform::PlatformData& data;
};

102
/**
103
 * This kernel is invoked by HarmonicBondForce to calculate the forces acting on the system and the energy of the system.
104
 */
105
class ReferenceCalcHarmonicBondForceKernel : public CalcHarmonicBondForceKernel {
106
public:
107
    ReferenceCalcHarmonicBondForceKernel(std::string name, const Platform& platform) : CalcHarmonicBondForceKernel(name, platform) {
108
    }
109
    ~ReferenceCalcHarmonicBondForceKernel();
110
    /**
111
     * Initialize the kernel.
112
     * 
113
     * @param system     the System this kernel will be applied to
114
115
116
117
118
119
120
121
     * @param force      the HarmonicBondForce this kernel will be used for
     */
    void initialize(const System& system, const HarmonicBondForce& force);
    /**
     * Execute the kernel to calculate the forces.
     * 
     * @param context    the context in which to execute this kernel
     */
122
    void executeForces(ContextImpl& context);
123
124
125
126
127
128
    /**
     * Execute the kernel to calculate the energy.
     * 
     * @param context    the context in which to execute this kernel
     * @return the potential energy due to the HarmonicBondForce
     */
129
    double executeEnergy(ContextImpl& context);
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
private:
    int numBonds;
    int **bondIndexArray;
    RealOpenMM **bondParamArray;
};

/**
 * This kernel is invoked by HarmonicAngleForce to calculate the forces acting on the system and the energy of the system.
 */
class ReferenceCalcHarmonicAngleForceKernel : public CalcHarmonicAngleForceKernel {
public:
    ReferenceCalcHarmonicAngleForceKernel(std::string name, const Platform& platform) : CalcHarmonicAngleForceKernel(name, platform) {
    }
    ~ReferenceCalcHarmonicAngleForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the HarmonicAngleForce this kernel will be used for
     */
    void initialize(const System& system, const HarmonicAngleForce& force);
    /**
     * Execute the kernel to calculate the forces.
     * 
     * @param context    the context in which to execute this kernel
     */
156
    void executeForces(ContextImpl& context);
157
158
159
160
161
162
    /**
     * Execute the kernel to calculate the energy.
     * 
     * @param context    the context in which to execute this kernel
     * @return the potential energy due to the HarmonicAngleForce
     */
163
    double executeEnergy(ContextImpl& context);
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
private:
    int numAngles;
    int **angleIndexArray;
    RealOpenMM **angleParamArray;
};

/**
 * This kernel is invoked by PeriodicTorsionForce to calculate the forces acting on the system and the energy of the system.
 */
class ReferenceCalcPeriodicTorsionForceKernel : public CalcPeriodicTorsionForceKernel {
public:
    ReferenceCalcPeriodicTorsionForceKernel(std::string name, const Platform& platform) : CalcPeriodicTorsionForceKernel(name, platform) {
    }
    ~ReferenceCalcPeriodicTorsionForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the PeriodicTorsionForce this kernel will be used for
     */
    void initialize(const System& system, const PeriodicTorsionForce& force);
    /**
     * Execute the kernel to calculate the forces.
     * 
     * @param context    the context in which to execute this kernel
     */
190
    void executeForces(ContextImpl& context);
191
192
193
194
195
196
    /**
     * Execute the kernel to calculate the energy.
     * 
     * @param context    the context in which to execute this kernel
     * @return the potential energy due to the PeriodicTorsionForce
     */
197
    double executeEnergy(ContextImpl& context);
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
private:
    int numTorsions;
    int **torsionIndexArray;
    RealOpenMM **torsionParamArray;
};

/**
 * This kernel is invoked by RBTorsionForce to calculate the forces acting on the system and the energy of the system.
 */
class ReferenceCalcRBTorsionForceKernel : public CalcRBTorsionForceKernel {
public:
    ReferenceCalcRBTorsionForceKernel(std::string name, const Platform& platform) : CalcRBTorsionForceKernel(name, platform) {
    }
    ~ReferenceCalcRBTorsionForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the RBTorsionForce this kernel will be used for
     */
    void initialize(const System& system, const RBTorsionForce& force);
    /**
     * Execute the kernel to calculate the forces.
     * 
     * @param context    the context in which to execute this kernel
     */
224
    void executeForces(ContextImpl& context);
225
226
227
228
229
230
    /**
     * Execute the kernel to calculate the energy.
     * 
     * @param context    the context in which to execute this kernel
     * @return the potential energy due to the RBTorsionForce
     */
231
    double executeEnergy(ContextImpl& context);
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
private:
    int numTorsions;
    int **torsionIndexArray;
    RealOpenMM **torsionParamArray;
};

/**
 * This kernel is invoked by NonbondedForce to calculate the forces acting on the system.
 */
class ReferenceCalcNonbondedForceKernel : public CalcNonbondedForceKernel {
public:
    ReferenceCalcNonbondedForceKernel(std::string name, const Platform& platform) : CalcNonbondedForceKernel(name, platform) {
    }
    ~ReferenceCalcNonbondedForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system     the System this kernel will be applied to
     * @param force      the NonbondedForce this kernel will be used for
251
     */
252
    void initialize(const System& system, const NonbondedForce& force);
253
    /**
254
     * Execute the kernel to calculate the forces.
255
     * 
256
     * @param context    the context in which to execute this kernel
257
     */
258
    void executeForces(ContextImpl& context);
259
    /**
260
     * Execute the kernel to calculate the energy.
261
     * 
262
     * @param context    the context in which to execute this kernel
263
     * @return the potential energy due to the NonbondedForce
264
     */
265
    double executeEnergy(ContextImpl& context);
266
private:
Peter Eastman's avatar
Peter Eastman committed
267
    int numParticles, num14;
268
    int **exclusionArray, **bonded14IndexArray;
Peter Eastman's avatar
Peter Eastman committed
269
    RealOpenMM **particleParamArray, **bonded14ParamArray;
270
    RealOpenMM nonbondedCutoff, periodicBoxSize[3], rfDielectric, ewaldAlpha;
271
    int kmax[3];
272
273
274
    std::vector<std::set<int> > exclusions;
    NonbondedMethod nonbondedMethod;
    NeighborList* neighborList;
275
276
277
};

/**
278
 * This kernel is invoked by GBSAOBCForce to calculate the forces acting on the system.
279
 */
280
class ReferenceCalcGBSAOBCForceKernel : public CalcGBSAOBCForceKernel {
281
public:
282
    ReferenceCalcGBSAOBCForceKernel(std::string name, const Platform& platform) : CalcGBSAOBCForceKernel(name, platform) {
283
    }
284
    ~ReferenceCalcGBSAOBCForceKernel();
285
    /**
286
     * Initialize the kernel.
287
     * 
288
     * @param system     the System this kernel will be applied to
289
     * @param force      the GBSAOBCForce this kernel will be used for
290
     */
291
    void initialize(const System& system, const GBSAOBCForce& force);
292
    /**
293
     * Execute the kernel to calculate the forces.
294
     * 
295
     * @param context    the context in which to execute this kernel
296
     */
297
    void executeForces(ContextImpl& context);
298
    /**
299
     * Execute the kernel to calculate the energy.
300
     * 
301
     * @param context    the context in which to execute this kernel
302
     * @return the potential energy due to the GBSAOBCForce
303
     */
304
    double executeEnergy(ContextImpl& context);
305
306
307
private:
    CpuObc* obc;
    std::vector<RealOpenMM> charges;
308
309
};

Mark Friedrichs's avatar
Mark Friedrichs committed
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/**
 * This kernel is invoked by GBVIForce to calculate the forces acting on the system.
 */
class ReferenceCalcGBVIForceKernel : public CalcGBVIForceKernel {
public:
    ReferenceCalcGBVIForceKernel(std::string name, const Platform& platform) : CalcGBVIForceKernel(name, platform) {
    }
    ~ReferenceCalcGBVIForceKernel();
    /**
     * Initialize the kernel.
     * 
     * @param system       the System this kernel will be applied to
     * @param force        the GBVIForce this kernel will be used for
     * @param scaled radii the scaled radii (Eq. 5 of Labute paper)
     */
    void initialize(const System& system, const GBVIForce& force, const std::vector<double> & scaledRadii);
    /**
     * Execute the kernel to calculate the forces.
     * 
     * @param context    the context in which to execute this kernel
     */
331
    void executeForces(ContextImpl& context);
Mark Friedrichs's avatar
Mark Friedrichs committed
332
333
334
335
336
337
    /**
     * Execute the kernel to calculate the energy.
     * 
     * @param context    the context in which to execute this kernel
     * @return the potential energy due to the GBVIForce
     */
338
    double executeEnergy(ContextImpl& context);
Mark Friedrichs's avatar
Mark Friedrichs committed
339
340
341
342
343
private:
    CpuGBVI * gbvi;
    std::vector<RealOpenMM> charges;
};

344
345
346
347
348
/**
 * This kernel is invoked by VerletIntegrator to take one time step.
 */
class ReferenceIntegrateVerletStepKernel : public IntegrateVerletStepKernel {
public:
349
350
    ReferenceIntegrateVerletStepKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : IntegrateVerletStepKernel(name, platform),
        data(data), dynamics(0), constraints(0), masses(0), constraintDistances(0), constraintIndices(0) {
351
    }
352
    ~ReferenceIntegrateVerletStepKernel();
353
    /**
354
     * Initialize the kernel.
355
     * 
356
357
     * @param system     the System this kernel will be applied to
     * @param integrator the VerletIntegrator this kernel will be used for
358
     */
359
    void initialize(const System& system, const VerletIntegrator& integrator);
360
361
362
    /**
     * Execute the kernel.
     * 
363
364
     * @param context    the context in which to execute this kernel
     * @param integrator the VerletIntegrator this kernel is being used for
365
     */
366
    void execute(ContextImpl& context, const VerletIntegrator& integrator);
367
private:
368
    ReferencePlatform::PlatformData& data;
369
    ReferenceVerletDynamics* dynamics;
370
    ReferenceConstraintAlgorithm* constraints;
371
    RealOpenMM* masses;
372
    RealOpenMM* constraintDistances;
373
374
375
    int** constraintIndices;
    int numConstraints;
    double prevStepSize;
376
377
378
379
380
381
382
};

/**
 * This kernel is invoked by LangevinIntegrator to take one time step.
 */
class ReferenceIntegrateLangevinStepKernel : public IntegrateLangevinStepKernel {
public:
383
384
    ReferenceIntegrateLangevinStepKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : IntegrateLangevinStepKernel(name, platform),
        data(data), dynamics(0), constraints(0), masses(0), constraintDistances(0), constraintIndices(0) {
385
    }
386
    ~ReferenceIntegrateLangevinStepKernel();
387
    /**
Peter Eastman's avatar
Peter Eastman committed
388
     * Initialize the kernel, setting up the particle masses.
389
     * 
390
391
     * @param system     the System this kernel will be applied to
     * @param integrator the LangevinIntegrator this kernel will be used for
392
     */
393
    void initialize(const System& system, const LangevinIntegrator& integrator);
394
395
396
    /**
     * Execute the kernel.
     * 
397
398
     * @param context    the context in which to execute this kernel
     * @param integrator the LangevinIntegrator this kernel is being used for
399
     */
400
    void execute(ContextImpl& context, const LangevinIntegrator& integrator);
401
private:
402
    ReferencePlatform::PlatformData& data;
403
    ReferenceStochasticDynamics* dynamics;
404
    ReferenceConstraintAlgorithm* constraints;
405
    RealOpenMM* masses;
406
    RealOpenMM* constraintDistances;
407
408
409
    int** constraintIndices;
    int numConstraints;
    double prevTemp, prevFriction, prevStepSize;
410
411
412
413
414
415
416
};

/**
 * This kernel is invoked by BrownianIntegrator to take one time step.
 */
class ReferenceIntegrateBrownianStepKernel : public IntegrateBrownianStepKernel {
public:
417
418
    ReferenceIntegrateBrownianStepKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : IntegrateBrownianStepKernel(name, platform),
        data(data), dynamics(0), constraints(0), masses(0), constraintDistances(0), constraintIndices(0) {
419
    }
420
    ~ReferenceIntegrateBrownianStepKernel();
421
    /**
422
     * Initialize the kernel.
423
     * 
424
425
     * @param system     the System this kernel will be applied to
     * @param integrator the BrownianIntegrator this kernel will be used for
426
     */
427
    void initialize(const System& system, const BrownianIntegrator& integrator);
428
429
430
    /**
     * Execute the kernel.
     * 
431
432
     * @param context    the context in which to execute this kernel
     * @param integrator the BrownianIntegrator this kernel is being used for
433
     */
434
    void execute(ContextImpl& context, const BrownianIntegrator& integrator);
435
private:
436
    ReferencePlatform::PlatformData& data;
437
    ReferenceBrownianDynamics* dynamics;
438
    ReferenceConstraintAlgorithm* constraints;
439
    RealOpenMM* masses;
440
    RealOpenMM* constraintDistances;
441
442
443
    int** constraintIndices;
    int numConstraints;
    double prevTemp, prevFriction, prevStepSize;
444
445
};

446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
/**
 * This kernel is invoked by VariableLangevinIntegrator to take one time step.
 */
class ReferenceIntegrateVariableLangevinStepKernel : public IntegrateVariableLangevinStepKernel {
public:
    ReferenceIntegrateVariableLangevinStepKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : IntegrateVariableLangevinStepKernel(name, platform),
        data(data), dynamics(0), constraints(0), masses(0), constraintDistances(0), constraintIndices(0) {
    }
    ~ReferenceIntegrateVariableLangevinStepKernel();
    /**
     * Initialize the kernel.
     *
     * @param system     the System this kernel will be applied to
     * @param integrator the LangevinIntegrator this kernel will be used for
     */
    void initialize(const System& system, const VariableLangevinIntegrator& integrator);
    /**
     * Execute the kernel.
     *
     * @param context    the context in which to execute this kernel
     * @param integrator the LangevinIntegrator this kernel is being used for
     * @param maxTime    the maximum time beyond which the simulation should not be advanced
     */
469
    void execute(ContextImpl& context, const VariableLangevinIntegrator& integrator, double maxTime);
470
471
472
473
474
475
476
477
478
479
480
private:
    ReferencePlatform::PlatformData& data;
    ReferenceVariableStochasticDynamics* dynamics;
    ReferenceConstraintAlgorithm* constraints;
    RealOpenMM* masses;
    RealOpenMM* constraintDistances;
    int** constraintIndices;
    int numConstraints;
    double prevTemp, prevFriction, prevErrorTol;
};

481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
/**
 * This kernel is invoked by VariableVerletIntegrator to take one time step.
 */
class ReferenceIntegrateVariableVerletStepKernel : public IntegrateVariableVerletStepKernel {
public:
    ReferenceIntegrateVariableVerletStepKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : IntegrateVariableVerletStepKernel(name, platform),
        data(data), dynamics(0), constraints(0), masses(0), constraintDistances(0), constraintIndices(0) {
    }
    ~ReferenceIntegrateVariableVerletStepKernel();
    /**
     * Initialize the kernel.
     *
     * @param system     the System this kernel will be applied to
     * @param integrator the VerletIntegrator this kernel will be used for
     */
    void initialize(const System& system, const VariableVerletIntegrator& integrator);
    /**
     * Execute the kernel.
     *
     * @param context    the context in which to execute this kernel
     * @param integrator the VerletIntegrator this kernel is being used for
502
     * @param maxTime    the maximum time beyond which the simulation should not be advanced
503
     */
504
    void execute(ContextImpl& context, const VariableVerletIntegrator& integrator, double maxTime);
505
506
507
508
509
510
511
512
private:
    ReferencePlatform::PlatformData& data;
    ReferenceVariableVerletDynamics* dynamics;
    ReferenceConstraintAlgorithm* constraints;
    RealOpenMM* masses;
    RealOpenMM* constraintDistances;
    int** constraintIndices;
    int numConstraints;
513
    double prevErrorTol;
514
515
};

516
/**
Peter Eastman's avatar
Peter Eastman committed
517
 * This kernel is invoked by AndersenThermostat at the start of each time step to adjust the particle velocities.
518
519
520
 */
class ReferenceApplyAndersenThermostatKernel : public ApplyAndersenThermostatKernel {
public:
521
    ReferenceApplyAndersenThermostatKernel(std::string name, const Platform& platform) : ApplyAndersenThermostatKernel(name, platform), thermostat(0) {
522
    }
523
    ~ReferenceApplyAndersenThermostatKernel();
524
    /**
525
     * Initialize the kernel.
526
     * 
527
528
     * @param system     the System this kernel will be applied to
     * @param thermostat the AndersenThermostat this kernel will be used for
529
     */
530
    void initialize(const System& system, const AndersenThermostat& thermostat);
531
532
533
    /**
     * Execute the kernel.
     * 
534
     * @param context    the context in which to execute this kernel
535
     */
536
    void execute(ContextImpl& context);
537
538
539
private:
    ReferenceAndersenThermostat* thermostat;
    RealOpenMM* masses;
540
541
542
543
544
545
546
};

/**
 * This kernel is invoked to calculate the kinetic energy of the system.
 */
class ReferenceCalcKineticEnergyKernel : public CalcKineticEnergyKernel {
public:
547
    ReferenceCalcKineticEnergyKernel(std::string name, const Platform& platform) : CalcKineticEnergyKernel(name, platform) {
548
549
    }
    /**
550
     * Initialize the kernel.
551
     * 
552
     * @param system     the System this kernel will be applied to
553
     */
554
    void initialize(const System& system);
555
556
557
    /**
     * Execute the kernel.
     * 
558
     * @param context    the context in which to execute this kernel
559
     */
560
    double execute(ContextImpl& context);
561
562
private:
    std::vector<double> masses;
563
564
};

565
566
567
568
569
/**
 * This kernel is invoked to remove center of mass motion from the system.
 */
class ReferenceRemoveCMMotionKernel : public RemoveCMMotionKernel {
public:
570
    ReferenceRemoveCMMotionKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : RemoveCMMotionKernel(name, platform), data(data) {
571
572
    }
    /**
Peter Eastman's avatar
Peter Eastman committed
573
     * Initialize the kernel, setting up the particle masses.
574
     * 
575
576
     * @param system     the System this kernel will be applied to
     * @param force      the CMMotionRemover this kernel will be used for
577
     */
578
    void initialize(const System& system, const CMMotionRemover& force);
579
580
581
    /**
     * Execute the kernel.
     * 
582
     * @param context    the context in which to execute this kernel
583
     */
584
    void execute(ContextImpl& context);
585
private:
586
    ReferencePlatform::PlatformData& data;
587
    std::vector<double> masses;
588
    int frequency;
589
590
};

591
592
593
} // namespace OpenMM

#endif /*OPENMM_REFERENCEKERNELS_H_*/