kCalculateCDLJObcGbsaForces1.h 29.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/* -------------------------------------------------------------------------- *
 *                                   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) 2009 Stanford University and the Authors.           *
 * Authors: Scott Le Grand, 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
29
30
31
32
 * -------------------------------------------------------------------------- */

/**
 * This file contains the kernel for evalauating nonbonded forces and the first stage of GBSA.
 * It is included several times in kCalculateCDLJObcGbsaForces1.cu with different #defines to generate
 * different versions of the kernels.
 */

Scott Le Grand's avatar
Scott Le Grand committed
33
34
35
__global__ 
#if (__CUDA_ARCH__ >= 200)
__launch_bounds__(GF1XX_NONBOND_THREADS_PER_BLOCK, 1)
36
#elif (__CUDA_ARCH__ >= 120)
Scott Le Grand's avatar
Scott Le Grand committed
37
38
39
40
__launch_bounds__(GT2XX_NONBOND_THREADS_PER_BLOCK, 1)
#else
__launch_bounds__(G8X_NONBOND_THREADS_PER_BLOCK, 1)
#endif
41
void METHOD_NAME(kCalculateCDLJObcGbsa, Forces1_kernel)(unsigned int* workUnit )
42
{
43
    extern __shared__ volatile Atom sA[];
44
45
    unsigned int totalWarps   = cSim.nonbond_blocks*cSim.nonbond_threads_per_block/GRID;
    unsigned int warp         = (blockIdx.x*blockDim.x+threadIdx.x)/GRID;
46
    unsigned int numWorkUnits = cSim.pInteractionCount[0];
47
48
    unsigned int pos          = warp*numWorkUnits/totalWarps;
    unsigned int end          = (warp+1)*numWorkUnits/totalWarps;
49
50
    float CDLJObcGbsa_energy;
    float energy = 0.0f;
51
#ifdef USE_CUTOFF
52
    volatile float* tempBuffer = (volatile float*) &sA[cSim.nonbond_threads_per_block];
53
54
#endif

55
    unsigned int lasty        = -0xFFFFFFFF;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    while (pos < end)
    {

        // Extract cell coordinates from appropriate work unit
        unsigned int x                      = workUnit[pos];
        unsigned int y                      = ((x >> 2) & 0x7fff) << GRIDBITS;
        bool bExclusionFlag                 = (x & 0x1);
        x                                   = (x >> 17) << GRIDBITS;
        unsigned int tgx                    = threadIdx.x & (GRID - 1);
        unsigned int i                      = x + tgx;
        float4 apos                         = cSim.pPosq[i];
        float2 a                            = cSim.pAttr[i];
        float br                            = cSim.pBornRadii[i];
        unsigned int tbx                    = threadIdx.x - tgx;
70
        unsigned int tj                     = tgx;
71
        volatile Atom* psA                  = &sA[tbx];
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
        float4 af;
        af.x                        = 0.0f;
        af.y                        = 0.0f;
        af.z                        = 0.0f;
        af.w                        = 0.0f;
        if (x == y) // Handle diagonals uniquely at 50% efficiency
        {
            // Read fixed atom data into registers and GRF
            sA[threadIdx.x].x           = apos.x;
            sA[threadIdx.x].y           = apos.y;
            sA[threadIdx.x].z           = apos.z;
            sA[threadIdx.x].q           = apos.w;
            float q2                    = cSim.preFactor * apos.w;
            apos.w                     *= cSim.epsfac;
            sA[threadIdx.x].sig         = a.x;
            sA[threadIdx.x].eps         = a.y;
            sA[threadIdx.x].br          = br;
            if (!bExclusionFlag)
            {
                for (unsigned int j = 0; j < GRID; j++)
                {
                    float dx                = psA[j].x - apos.x;
                    float dy                = psA[j].y - apos.y;
                    float dz                = psA[j].z - apos.z;
#ifdef USE_PERIODIC
97
98
99
                    dx                     -= floorf(dx*cSim.invPeriodicBoxSizeX+0.5f)*cSim.periodicBoxSizeX;
                    dy                     -= floorf(dy*cSim.invPeriodicBoxSizeY+0.5f)*cSim.periodicBoxSizeY;
                    dz                     -= floorf(dz*cSim.invPeriodicBoxSizeZ+0.5f)*cSim.periodicBoxSizeZ;
100
101
102
103
#endif
                    float r2                = dx * dx + dy * dy + dz * dz;

                    // CDLJ part
104
                    float invR              = 1.0f / sqrtf(r2);
105
106
107
108
109
110
                    float sig               = a.x + psA[j].sig;
                    float sig2              = invR * sig;
                    sig2                   *= sig2;
                    float sig6              = sig2 * sig2 * sig2;
                    float eps               = a.y * psA[j].eps;
                    float dEdR              = eps * (12.0f * sig6 - 6.0f) * sig6;
111
                    CDLJObcGbsa_energy      = eps * (sig6 - 1.0f) * sig6;
112
113
#ifdef USE_CUTOFF
                    dEdR                   += apos.w * psA[j].q * (invR - 2.0f * cSim.reactionFieldK * r2);
114
                    CDLJObcGbsa_energy     += apos.w * psA[j].q * (invR + cSim.reactionFieldK * r2 - cSim.reactionFieldC);
115
#else
116
                    float factorX           = apos.w * psA[j].q * invR;
117

118
119
                    dEdR                   += factorX;
                    CDLJObcGbsa_energy     += factorX;
120
121
122
123
124
125
#endif
                    dEdR                   *= invR * invR;

                    // ObcGbsaForce1 part
                    float alpha2_ij         = br * psA[j].br;
                    float D_ij              = r2 / (4.0f * alpha2_ij);
126
                    float expTerm           = expf(-D_ij);
127
                    float denominator2      = r2 + alpha2_ij * expTerm;
128
                    float denominator       = sqrtf(denominator2);
129
130
131
                    float Gpol              = (q2 * psA[j].q) / (denominator * denominator2);
                    float dGpol_dalpha2_ij  = -0.5f * Gpol * expTerm * (1.0f + D_ij);
                    dEdR                   += Gpol * (1.0f - 0.25f * expTerm);
132
                    CDLJObcGbsa_energy     += (q2 * psA[j].q) / denominator;
133

134
#ifdef USE_CUTOFF
135
136
137
138
                    if ( i >= cSim.atoms || (x+j) >= cSim.atoms || r2 > cSim.nonbondedCutoffSqr)
#else
                    if ( i >= cSim.atoms || (x+j) >= cSim.atoms)
#endif
139
                    {
140
141
142
                        dEdR                = 0.0f;
                        dGpol_dalpha2_ij    = 0.0f;
                        CDLJObcGbsa_energy  = 0.0f;
143
                    }
144
                    energy                 += 0.5f*CDLJObcGbsa_energy;
145
146
147
148
149
150
151
                    // Add Forces
                    dx                     *= dEdR;
                    dy                     *= dEdR;
                    dz                     *= dEdR;
                    af.x                   -= dx;
                    af.y                   -= dy;
                    af.z                   -= dz;
152
                    af.w                   += dGpol_dalpha2_ij * psA[j].br;
153

154
                }
155
156
157

            } else {

158
                unsigned int xi   = x>>GRIDBITS;
159
                unsigned int cell = xi+xi*cSim.paddedNumberOfAtoms/GRID-xi*(xi+1)/2;
160
                unsigned int excl = cSim.pExclusion[cSim.pExclusionIndex[cell]+tgx];
161
162
163
164
165
166
                for (unsigned int j = 0; j < GRID; j++)
                {
                    float dx                = psA[j].x - apos.x;
                    float dy                = psA[j].y - apos.y;
                    float dz                = psA[j].z - apos.z;
#ifdef USE_PERIODIC
167
168
169
                    dx                     -= floorf(dx*cSim.invPeriodicBoxSizeX+0.5f)*cSim.periodicBoxSizeX;
                    dy                     -= floorf(dy*cSim.invPeriodicBoxSizeY+0.5f)*cSim.periodicBoxSizeY;
                    dz                     -= floorf(dz*cSim.invPeriodicBoxSizeZ+0.5f)*cSim.periodicBoxSizeZ;
170
#endif
171
                    float r2                = dx * dx + dy * dy + dz * dz;
172
173

                    // CDLJ part
174
                    float invR              = 1.0f / sqrtf(r2);
175
176
177
178
179
180
                    float sig               = a.x + psA[j].sig;
                    float sig2              = invR * sig;
                    sig2                   *= sig2;
                    float sig6              = sig2 * sig2 * sig2;
                    float eps               = a.y * psA[j].eps;
                    float dEdR              = eps * (12.0f * sig6 - 6.0f) * sig6;
181
                    CDLJObcGbsa_energy      = eps * (sig6 - 1.0f) * sig6;
182
183
#ifdef USE_CUTOFF
                    dEdR                   += apos.w * psA[j].q * (invR - 2.0f * cSim.reactionFieldK * r2);
184
                    CDLJObcGbsa_energy     += apos.w * psA[j].q * (invR + cSim.reactionFieldK * r2 - cSim.reactionFieldC);
185
#else
186
                    float factorX           = apos.w * psA[j].q * invR;
187

188
189
                    dEdR                   += factorX;
                    CDLJObcGbsa_energy     += factorX;
190
191
192
193
#endif
                    dEdR                   *= invR * invR;
                    if (!(excl & 0x1))
                    {
194
                        dEdR                = 0.0f;
195
		                  CDLJObcGbsa_energy  = 0.0f;
196
197
198
199
200
                    }

                    // ObcGbsaForce1 part
                    float alpha2_ij         = br * psA[j].br;
                    float D_ij              = r2 / (4.0f * alpha2_ij);
201
                    float expTerm           = expf(-D_ij);
202
                    float denominator2      = r2 + alpha2_ij * expTerm;
203
                    float denominator       = sqrtf(denominator2);
204
205
206
                    float Gpol              = (q2 * psA[j].q) / (denominator * denominator2);
                    float dGpol_dalpha2_ij  = -0.5f * Gpol * expTerm * (1.0f + D_ij);
                    dEdR                   += Gpol * (1.0f - 0.25f * expTerm);
207
                    CDLJObcGbsa_energy     += (q2 * psA[j].q) / denominator;
208
#if defined USE_CUTOFF
209
                    if (i >= cSim.atoms || x+j >= cSim.atoms || r2 > cSim.nonbondedCutoffSqr)
210
211
#else
                    if (i >= cSim.atoms || x+j >= cSim.atoms )
212
#endif
213
                    {
214
215
216
                        dEdR                = 0.0f;
                        dGpol_dalpha2_ij    = 0.0f;
		                  CDLJObcGbsa_energy  = 0.0f;
217
                    }
218
219
                    energy                 += 0.5f*CDLJObcGbsa_energy;

220
221
222
223
224
225
226
                    // Add Forces
                    dx                     *= dEdR;
                    dy                     *= dEdR;
                    dz                     *= dEdR;
                    af.x                   -= dx;
                    af.y                   -= dy;
                    af.z                   -= dz;
227
                    af.w                   += dGpol_dalpha2_ij * psA[j].br;
228
229
230
231
232
233
                    excl                  >>= 1;
                }
            }

            // Write results
#ifdef USE_OUTPUT_BUFFER_PER_WARP
234
            unsigned int offset         = x + tgx + warp*cSim.stride;
Peter Eastman's avatar
Peter Eastman committed
235
236
237
#else
            unsigned int offset         = x + tgx + (x >> GRIDBITS) * cSim.stride;
#endif
238
            float4 of                   = cSim.pForce4[offset];
239
240
241
242
            of.x                       += af.x;
            of.y                       += af.y;
            of.z                       += af.z;
            of.w                       += af.w;
243
            cSim.pForce4[offset]        = of;
Peter Eastman's avatar
Peter Eastman committed
244
            cSim.pBornForce[offset]     = of.w;
245
246

        } else {
247
248
249
            // Read fixed atom data into registers and GRF
            if (lasty != y)
            {
250
                unsigned int j              = y + tgx;
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
                float4 temp                 = cSim.pPosq[j];
                float2 temp1                = cSim.pAttr[j];
                sA[threadIdx.x].br          = cSim.pBornRadii[j];
                sA[threadIdx.x].x           = temp.x;
                sA[threadIdx.x].y           = temp.y;
                sA[threadIdx.x].z           = temp.z;
                sA[threadIdx.x].q           = temp.w;
                sA[threadIdx.x].sig         = temp1.x;
                sA[threadIdx.x].eps         = temp1.y;
            }
            sA[threadIdx.x].fx          = 0.0f;
            sA[threadIdx.x].fy          = 0.0f;
            sA[threadIdx.x].fz          = 0.0f;
            sA[threadIdx.x].fb          = 0.0f;
            float q2                    = apos.w * cSim.preFactor;
            apos.w                     *= cSim.epsfac;
            if (!bExclusionFlag)
            {
269
270
271
#ifdef USE_CUTOFF
                unsigned int flags = cSim.pInteractionFlag[pos];
                if (flags == 0)
272
                {
273
274
275
276
277
278
279
                    // No interactions in this block.
                }
                else if (flags == 0xFFFFFFFF)
#endif
                {
                    // Compute all interactions within this block.

280
                    for (unsigned int j = 0; j < GRID; j++)
281
282
283
284
                    {
                        float dx                = psA[tj].x - apos.x;
                        float dy                = psA[tj].y - apos.y;
                        float dz                = psA[tj].z - apos.z;
285
#ifdef USE_PERIODIC
286
287
288
                        dx                     -= floorf(dx*cSim.invPeriodicBoxSizeX+0.5f)*cSim.periodicBoxSizeX;
                        dy                     -= floorf(dy*cSim.invPeriodicBoxSizeY+0.5f)*cSim.periodicBoxSizeY;
                        dz                     -= floorf(dz*cSim.invPeriodicBoxSizeZ+0.5f)*cSim.periodicBoxSizeZ;
289
#endif
290
                        float r2                = dx * dx + dy * dy + dz * dz;
291

292
                        // CDLJ part
293
                        float invR              = 1.0f / sqrtf(r2);
294
295
296
297
298
299
                        float sig               = a.x + psA[tj].sig;
                        float sig2              = invR * sig;
                        sig2                   *= sig2;
                        float sig6              = sig2 * sig2 * sig2;
                        float eps               = a.y * psA[tj].eps;
                        float dEdR              = eps * (12.0f * sig6 - 6.0f) * sig6;
300
                        CDLJObcGbsa_energy      = eps * (sig6 - 1.0f) * sig6;
301
#ifdef USE_CUTOFF
302
                        dEdR                   += apos.w * psA[tj].q * (invR - 2.0f * cSim.reactionFieldK * r2);
303
                        CDLJObcGbsa_energy     += apos.w * psA[tj].q * (invR + cSim.reactionFieldK * r2 - cSim.reactionFieldC);
304
#else
305
                        float factorX           = apos.w * psA[tj].q * invR;
306

307
308
                        dEdR                   += factorX;
                        CDLJObcGbsa_energy     += factorX;
309
#endif
310
                        dEdR                   *= invR * invR;
311

312
313
314
                        // ObcGbsaForce1 part
                        float alpha2_ij         = br * psA[tj].br;
                        float D_ij              = r2 / (4.0f * alpha2_ij);
315
                        float expTerm           = expf(-D_ij);
316
                        float denominator2      = r2 + alpha2_ij * expTerm;
317
                        float denominator       = sqrtf(denominator2);
318
319
320
                        float Gpol              = (q2 * psA[tj].q) / (denominator * denominator2);
                        float dGpol_dalpha2_ij  = -0.5f * Gpol * expTerm * (1.0f + D_ij);
                        dEdR                   += Gpol * (1.0f - 0.25f * expTerm);
321
                        CDLJObcGbsa_energy     += (q2 * psA[tj].q) / denominator;
322
#ifdef USE_CUTOFF
323
324
325
326
                        if ( i >= cSim.atoms || (y+tj) >= cSim.atoms || r2 > cSim.nonbondedCutoffSqr)
#else
                        if ( i >= cSim.atoms || (y+tj) >= cSim.atoms)
#endif
327
                        {
328
329
330
                            dEdR               = 0.0f;
                            dGpol_dalpha2_ij   = 0.0f;
       			             CDLJObcGbsa_energy = 0.0f;
331
                        }
332
333
                        energy                += CDLJObcGbsa_energy;

334
335
336
337
338
339
340
                        // Add forces
                        dx                     *= dEdR;
                        dy                     *= dEdR;
                        dz                     *= dEdR;
                        af.x                   -= dx;
                        af.y                   -= dy;
                        af.z                   -= dz;
341
                        af.w                   += dGpol_dalpha2_ij * psA[tj].br;
342
343
344
                        psA[tj].fx             += dx;
                        psA[tj].fy             += dy;
                        psA[tj].fz             += dz;
345
                        psA[tj].fb             += dGpol_dalpha2_ij * br;
346

347
                        tj                      = (tj + 1) & (GRID - 1);
348
349


350
                    }
351
352
353
354
355
356
                }
#ifdef USE_CUTOFF
                else
                {
                    // Compute only a subset of the interactions in this block.

357
                    for (unsigned int j = 0; j < GRID; j++)
358
359
360
361
362
363
364
                    {
                        if ((flags&(1<<j)) != 0)
                        {
                            float dx                = psA[j].x - apos.x;
                            float dy                = psA[j].y - apos.y;
                            float dz                = psA[j].z - apos.z;
#ifdef USE_PERIODIC
365
366
367
                            dx -= floorf(dx*cSim.invPeriodicBoxSizeX+0.5f)*cSim.periodicBoxSizeX;
                            dy -= floorf(dy*cSim.invPeriodicBoxSizeY+0.5f)*cSim.periodicBoxSizeY;
                            dz -= floorf(dz*cSim.invPeriodicBoxSizeZ+0.5f)*cSim.periodicBoxSizeZ;
368
#endif
369
                            float r2                = dx * dx + dy * dy + dz * dz;
370

371
                            // CDLJ part
372
                            float invR              = 1.0f / sqrtf(r2);
373
374
375
376
377
378
                            float sig               = a.x + psA[j].sig;
                            float sig2              = invR * sig;
                            sig2                   *= sig2;
                            float sig6              = sig2 * sig2 * sig2;
                            float eps               = a.y * psA[j].eps;
                            float dEdR              = eps * (12.0f * sig6 - 6.0f) * sig6;
379
                            CDLJObcGbsa_energy      = eps * (sig6 - 1.0f) * sig6;
380
381
#ifdef USE_CUTOFF
                            dEdR                   += apos.w * psA[j].q * (invR - 2.0f * cSim.reactionFieldK * r2);
382
                            CDLJObcGbsa_energy     += apos.w * psA[j].q * (invR + cSim.reactionFieldK * r2 - cSim.reactionFieldC);
383
#else
384
                            float factorX           = apos.w * psA[j].q * invR;
385

386
387
                            dEdR                   += factorX;
                            CDLJObcGbsa_energy     += factorX;
388
389
390
391
392
393
#endif
                            dEdR                   *= invR * invR;

                            // ObcGbsaForce1 part
                            float alpha2_ij         = br * psA[j].br;
                            float D_ij              = r2 / (4.0f * alpha2_ij);
394
                            float expTerm           = expf(-D_ij);
395
                            float denominator2      = r2 + alpha2_ij * expTerm;
396
                            float denominator       = sqrtf(denominator2);
397
398
399
                            float Gpol              = (q2 * psA[j].q) / (denominator * denominator2);
                            float dGpol_dalpha2_ij  = -0.5f * Gpol * expTerm * (1.0f + D_ij);
                            dEdR                   += Gpol * (1.0f - 0.25f * expTerm);
400
                            CDLJObcGbsa_energy     += (q2 * psA[j].q) / denominator;
401
402

#ifdef USE_CUTOFF
403
404
405
                            if ( i >= cSim.atoms || (y+j) >= cSim.atoms || r2 > cSim.nonbondedCutoffSqr)
#else
                            if ( i >= cSim.atoms || (y+j) >= cSim.atoms)
406
#endif
407
                            {
408
409
410
                                dEdR                = 0.0f;
                                dGpol_dalpha2_ij    = 0.0f;
				                    CDLJObcGbsa_energy  = 0.0f;
411
                            }
412
413
                            energy                 += CDLJObcGbsa_energy;
                             
414
415
416
417
418
419
420
                            // Add forces
                            dx                     *= dEdR;
                            dy                     *= dEdR;
                            dz                     *= dEdR;
                            af.x                   -= dx;
                            af.y                   -= dy;
                            af.z                   -= dz;
421
422
                            af.w                   += dGpol_dalpha2_ij * psA[j].br;

423
424
425
426
427
428
429
430
431
432
433
                            tempBuffer[threadIdx.x] = dx;
                            if (tgx % 2 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+1];
                            if (tgx % 4 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+2];
                            if (tgx % 8 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+4];
                            if (tgx % 16 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+8];
                            if (tgx == 0)
                                psA[j].fx += tempBuffer[threadIdx.x] + tempBuffer[threadIdx.x+16];
434

435
436
437
438
439
440
441
442
443
444
445
                            tempBuffer[threadIdx.x] = dy;
                            if (tgx % 2 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+1];
                            if (tgx % 4 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+2];
                            if (tgx % 8 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+4];
                            if (tgx % 16 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+8];
                            if (tgx == 0)
                                psA[j].fy += tempBuffer[threadIdx.x] + tempBuffer[threadIdx.x+16];
446

447
448
449
450
451
452
453
454
455
456
457
                            tempBuffer[threadIdx.x] = dz;
                            if (tgx % 2 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+1];
                            if (tgx % 4 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+2];
                            if (tgx % 8 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+4];
                            if (tgx % 16 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+8];
                            if (tgx == 0)
                                psA[j].fz += tempBuffer[threadIdx.x] + tempBuffer[threadIdx.x+16];
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472

                            // Sum the Born forces.

                            tempBuffer[threadIdx.x] = dGpol_dalpha2_ij * br;
                            if (tgx % 2 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+1];
                            if (tgx % 4 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+2];
                            if (tgx % 8 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+4];
                            if (tgx % 16 == 0)
                                tempBuffer[threadIdx.x] += tempBuffer[threadIdx.x+8];
                            if (tgx == 0)
                                psA[j].fb += tempBuffer[threadIdx.x] + tempBuffer[threadIdx.x+16];

473
474
                        }
                    }
475
                }
476
#endif
477
            } else {
478
479
                unsigned int xi   = x>>GRIDBITS;
                unsigned int yi   = y>>GRIDBITS;
480
                unsigned int cell = xi+yi*cSim.paddedNumberOfAtoms/GRID-yi*(yi+1)/2;
481
482
                unsigned int excl = cSim.pExclusion[cSim.pExclusionIndex[cell]+tgx];
                excl              = (excl >> tgx) | (excl << (GRID - tgx));
483
                for (unsigned int j = 0; j < GRID; j++)
484
485
486
487
488
                {
                    float dx                = psA[tj].x - apos.x;
                    float dy                = psA[tj].y - apos.y;
                    float dz                = psA[tj].z - apos.z;
#ifdef USE_PERIODIC
489
490
491
                    dx                     -= floorf(dx*cSim.invPeriodicBoxSizeX+0.5f)*cSim.periodicBoxSizeX;
                    dy                     -= floorf(dy*cSim.invPeriodicBoxSizeY+0.5f)*cSim.periodicBoxSizeY;
                    dz                     -= floorf(dz*cSim.invPeriodicBoxSizeZ+0.5f)*cSim.periodicBoxSizeZ;
492
493
494
495
#endif
                    float r2                = dx * dx + dy * dy + dz * dz;

                    // CDLJ part
496
                    float invR              = 1.0f / sqrtf(r2);
497
498
499
500
501
502
                    float sig               = a.x + psA[tj].sig;
                    float sig2              = invR * sig;
                    sig2                   *= sig2;
                    float sig6              = sig2 * sig2 * sig2;
                    float eps               = a.y * psA[tj].eps;
                    float dEdR              = eps * (12.0f * sig6 - 6.0f) * sig6;
503
		              CDLJObcGbsa_energy      = eps * (sig6 - 1.0f) * sig6;
504
505
#ifdef USE_CUTOFF
                    dEdR                   += apos.w * psA[tj].q * (invR - 2.0f * cSim.reactionFieldK * r2);
506
                    CDLJObcGbsa_energy     += apos.w * psA[tj].q * (invR + cSim.reactionFieldK * r2 - cSim.reactionFieldC);
507
#else
508
509
510
                    float factorX           = apos.w * psA[tj].q * invR;
                    dEdR                   += factorX;
                    CDLJObcGbsa_energy     += factorX;
511
512
513
514
#endif
                    dEdR                   *= invR * invR;
                    if (!(excl & 0x1))
                    {
515
516
                        dEdR                = 0.0f;
			               CDLJObcGbsa_energy  = 0.0f;
517
518
519
520
521
                    }

                    // ObcGbsaForce1 part
                    float alpha2_ij         = br * psA[tj].br;
                    float D_ij              = r2 / (4.0f * alpha2_ij);
522
                    float expTerm           = expf(-D_ij);
523
                    float denominator2      = r2 + alpha2_ij * expTerm;
524
                    float denominator       = sqrtf(denominator2);
525
526
527
                    float Gpol              = (q2 * psA[tj].q) / (denominator * denominator2);
                    float dGpol_dalpha2_ij  = -0.5f * Gpol * expTerm * (1.0f + D_ij);
                    dEdR                   += Gpol * (1.0f - 0.25f * expTerm);
528
		              CDLJObcGbsa_energy     += (q2 * psA[tj].q) / denominator;
529
530

#ifdef USE_CUTOFF
531
                    if (i >= cSim.atoms || y+tj >= cSim.atoms || r2 > cSim.nonbondedCutoffSqr)
532
533
534
#else
                    if (i >= cSim.atoms || y+tj >= cSim.atoms )
#endif
535
                    {
536
537
538
                        dEdR               = 0.0f;
                        dGpol_dalpha2_ij   = 0.0f;
			               CDLJObcGbsa_energy = 0.0f;
539
                    }
540
541
                    energy                += CDLJObcGbsa_energy;
                     
542
543
544
545
546
547
548
                    // Add forces
                    dx                     *= dEdR;
                    dy                     *= dEdR;
                    dz                     *= dEdR;
                    af.x                   -= dx;
                    af.y                   -= dy;
                    af.z                   -= dz;
549
                    af.w                   += dGpol_dalpha2_ij * psA[tj].br;
550
551
552
                    psA[tj].fx             += dx;
                    psA[tj].fy             += dy;
                    psA[tj].fz             += dz;
553
                    psA[tj].fb             += dGpol_dalpha2_ij * br;
554
                    excl                  >>= 1;
555

556
557
558
559
560
561
                    tj                      = (tj + 1) & (GRID - 1);
                }
            }

            // Write results
#ifdef USE_OUTPUT_BUFFER_PER_WARP
562
            unsigned int offset         = x + tgx + warp*cSim.stride;
Peter Eastman's avatar
Peter Eastman committed
563
564
565
#else
            unsigned int offset         = x + tgx + (y >> GRIDBITS) * cSim.stride;
#endif
566
            float4 of                   = cSim.pForce4[offset];
567
568
569
570
            of.x                       += af.x;
            of.y                       += af.y;
            of.z                       += af.z;
            of.w                       += af.w;
571
            cSim.pForce4[offset]       = of;
572
            cSim.pBornForce[offset]     = of.w;
Peter Eastman's avatar
Peter Eastman committed
573
#ifdef USE_OUTPUT_BUFFER_PER_WARP
574
            offset                      = y + tgx + warp*cSim.stride;
Peter Eastman's avatar
Peter Eastman committed
575
576
577
#else
            offset                      = y + tgx + (x >> GRIDBITS) * cSim.stride;
#endif
578
            of                          = cSim.pForce4[offset];
579
580
581
582
            of.x                       += sA[threadIdx.x].fx;
            of.y                       += sA[threadIdx.x].fy;
            of.z                       += sA[threadIdx.x].fz;
            of.w                       += sA[threadIdx.x].fb;
583
            cSim.pForce4[offset]       = of;
584
            cSim.pBornForce[offset]     = of.w;
585
586
587
588
            lasty = y;
        }
        pos++;
    }
589
    cSim.pEnergy[blockIdx.x*blockDim.x+threadIdx.x] += energy;
590
}