customHbondForce.cl 9.53 KB
Newer Older
1
/**
Peter Eastman's avatar
Peter Eastman committed
2
 * Compute the difference between two vectors, optionally taking periodic boundary conditions into account
3
4
 * and setting the fourth component to the squared magnitude.
 */
Peter Eastman's avatar
Peter Eastman committed
5
real4 delta(real4 vec1, real4 vec2, real4 periodicBoxSize, real4 invPeriodicBoxSize, real4 periodicBoxVecX, real4 periodicBoxVecY, real4 periodicBoxVecZ) {
6
    real4 result = (real4) (vec1.x-vec2.x, vec1.y-vec2.y, vec1.z-vec2.z, 0);
7
#ifdef USE_PERIODIC
8
    APPLY_PERIODIC_TO_DELTA(result)
9
10
11
12
13
14
15
16
#endif
    result.w = result.x*result.x + result.y*result.y + result.z*result.z;
    return result;
}

/**
 * Compute the angle between two vectors.  The w component of each vector should contain the squared magnitude.
 */
17
18
19
20
real computeAngle(real4 vec1, real4 vec2) {
    real dotProduct = vec1.x*vec2.x + vec1.y*vec2.y + vec1.z*vec2.z;
    real cosine = dotProduct*RSQRT(vec1.w*vec2.w);
    real angle;
21
22
23
    if (cosine > 0.99f || cosine < -0.99f) {
        // We're close to the singularity in acos(), so take the cross product and use asin() instead.

24
25
        real4 crossProduct = cross(vec1, vec2);
        real scale = vec1.w*vec2.w;
26
        angle = asin(SQRT(dot(crossProduct, crossProduct)/scale));
27
        if (cosine < 0.0f)
28
            angle = PI-angle;
29
30
31
32
33
34
35
    }
    else
       angle = acos(cosine);
    return angle;
}

/**
36
 * Compute the cross product of two vectors, setting the fourth component to the squared magnitude.
37
 */
38
39
real4 computeCross(real4 vec1, real4 vec2) {
    real4 result = cross(vec1, vec2);
40
41
42
    result.w = result.x*result.x + result.y*result.y + result.z*result.z;
    return result;
}
43

44
45
46
/**
 * Compute forces on donors.
 */
47
__kernel void computeDonorForces(__global real4* restrict forceBuffers, __global mixed* restrict energyBuffer, __global const real4* restrict posq, __global const int4* restrict exclusions,
48
49
        __global const int4* restrict donorAtoms, __global const int4* restrict acceptorAtoms, __global const int4* restrict donorBufferIndices, __local real4* posBuffer, real4 periodicBoxSize, real4 invPeriodicBoxSize,
        real4 periodicBoxVecX, real4 periodicBoxVecY, real4 periodicBoxVecZ
50
        PARAMETER_ARGUMENTS) {
51
    mixed energy = 0;
52
53
54
    real4 f1 = (real4) 0;
    real4 f2 = (real4) 0;
    real4 f3 = (real4) 0;
55
    for (int donorStart = 0; donorStart < NUM_DONORS; donorStart += get_global_size(0)) {
56
57
        // Load information about the donor this thread will compute forces on.

58
        int donorIndex = donorStart+get_global_id(0);
59
        int4 atoms, exclusionIndices;
60
        real4 d1, d2, d3;
61
62
        if (donorIndex < NUM_DONORS) {
            atoms = donorAtoms[donorIndex];
63
64
65
            d1 = (atoms.x > -1 ? posq[atoms.x] : (real4) 0);
            d2 = (atoms.y > -1 ? posq[atoms.y] : (real4) 0);
            d3 = (atoms.z > -1 ? posq[atoms.z] : (real4) 0);
66
67
68
#ifdef USE_EXCLUSIONS
            exclusionIndices = exclusions[donorIndex];
#endif
69
70
71
        }
        else
            atoms = (int4) (-1, -1, -1, -1);
72
73
74
        for (int acceptorStart = 0; acceptorStart < NUM_ACCEPTORS; acceptorStart += get_local_size(0)) {
            // Load the next block of acceptors into local memory.

Peter Eastman's avatar
Peter Eastman committed
75
            barrier(CLK_LOCAL_MEM_FENCE);
76
            int blockSize = min((int) get_local_size(0), NUM_ACCEPTORS-acceptorStart);
77
            if (get_local_id(0) < blockSize) {
78
                int4 atoms2 = acceptorAtoms[acceptorStart+get_local_id(0)];
79
80
81
                posBuffer[3*get_local_id(0)] = (atoms2.x > -1 ? posq[atoms2.x] : (real4) 0);
                posBuffer[3*get_local_id(0)+1] = (atoms2.y > -1 ? posq[atoms2.y] : (real4) 0);
                posBuffer[3*get_local_id(0)+2] = (atoms2.z > -1 ? posq[atoms2.z] : (real4) 0);
82
83
            }
            barrier(CLK_LOCAL_MEM_FENCE);
84
85
            if (donorIndex < NUM_DONORS) {
                for (int index = 0; index < blockSize; index++) {
86
                    int acceptorIndex = acceptorStart+index;
87
#ifdef USE_EXCLUSIONS
88
89
90
                    if (acceptorIndex == exclusionIndices.x || acceptorIndex == exclusionIndices.y || acceptorIndex == exclusionIndices.z || acceptorIndex == exclusionIndices.w)
                        continue;
#endif
91
92
                    // Compute the interaction between a donor and an acceptor.

93
94
95
                    real4 a1 = posBuffer[3*index];
                    real4 a2 = posBuffer[3*index+1];
                    real4 a3 = posBuffer[3*index+2];
Peter Eastman's avatar
Peter Eastman committed
96
                    real4 deltaD1A1 = delta(d1, a1, periodicBoxSize, invPeriodicBoxSize, periodicBoxVecX, periodicBoxVecY, periodicBoxVecZ);
97
#ifdef USE_CUTOFF
98
                    if (deltaD1A1.w < CUTOFF_SQUARED) {
99
#endif
100
101
102
                        COMPUTE_DONOR_FORCE
#ifdef USE_CUTOFF
                    }
103
#endif
104
105
106
                }
            }
        }
107

108
        // Write results
109

110
111
112
113
        if (donorIndex < NUM_DONORS) {
            int4 bufferIndices = donorBufferIndices[donorIndex];
            if (atoms.x > -1) {
                unsigned int offset = atoms.x+bufferIndices.x*PADDED_NUM_ATOMS;
114
                real4 force = forceBuffers[offset];
115
116
117
118
119
                force.xyz += f1.xyz;
                forceBuffers[offset] = force;
            }
            if (atoms.y > -1) {
                unsigned int offset = atoms.y+bufferIndices.y*PADDED_NUM_ATOMS;
120
                real4 force = forceBuffers[offset];
121
122
123
124
125
                force.xyz += f2.xyz;
                forceBuffers[offset] = force;
            }
            if (atoms.z > -1) {
                unsigned int offset = atoms.z+bufferIndices.z*PADDED_NUM_ATOMS;
126
                real4 force = forceBuffers[offset];
127
128
129
                force.xyz += f3.xyz;
                forceBuffers[offset] = force;
            }
130
131
132
133
134
135
136
        }
    }
    energyBuffer[get_global_id(0)] += energy;
}
/**
 * Compute forces on acceptors.
 */
137
__kernel void computeAcceptorForces(__global real4* restrict forceBuffers, __global mixed* restrict energyBuffer, __global const real4* restrict posq, __global const int4* restrict exclusions,
138
139
        __global const int4* restrict donorAtoms, __global const int4* restrict acceptorAtoms, __global const int4* restrict acceptorBufferIndices, __local real4* restrict posBuffer, real4 periodicBoxSize, real4 invPeriodicBoxSize,
        real4 periodicBoxVecX, real4 periodicBoxVecY, real4 periodicBoxVecZ
140
        PARAMETER_ARGUMENTS) {
141
142
143
    real4 f1 = (real4) 0;
    real4 f2 = (real4) 0;
    real4 f3 = (real4) 0;
144
145
146
147
    for (int acceptorStart = 0; acceptorStart < NUM_ACCEPTORS; acceptorStart += get_global_size(0)) {
        // Load information about the acceptor this thread will compute forces on.

        int acceptorIndex = acceptorStart+get_global_id(0);
148
        int4 atoms, exclusionIndices;
149
        real4 a1, a2, a3;
150
151
        if (acceptorIndex < NUM_ACCEPTORS) {
            atoms = acceptorAtoms[acceptorIndex];
152
153
154
            a1 = (atoms.x > -1 ? posq[atoms.x] : (real4) 0);
            a2 = (atoms.y > -1 ? posq[atoms.y] : (real4) 0);
            a3 = (atoms.z > -1 ? posq[atoms.z] : (real4) 0);
155
156
157
#ifdef USE_EXCLUSIONS
            exclusionIndices = exclusions[acceptorIndex];
#endif
158
159
160
161
162
163
        }
        else
            atoms = (int4) (-1, -1, -1, -1);
        for (int donorStart = 0; donorStart < NUM_DONORS; donorStart += get_local_size(0)) {
            // Load the next block of donors into local memory.

Peter Eastman's avatar
Peter Eastman committed
164
            barrier(CLK_LOCAL_MEM_FENCE);
165
            int blockSize = min((int) get_local_size(0), NUM_DONORS-donorStart);
166
            if (get_local_id(0) < blockSize) {
167
                int4 atoms2 = donorAtoms[donorStart+get_local_id(0)];
168
169
170
                posBuffer[3*get_local_id(0)] = (atoms2.x > -1 ? posq[atoms2.x] : (real4) 0);
                posBuffer[3*get_local_id(0)+1] = (atoms2.y > -1 ? posq[atoms2.y] : (real4) 0);
                posBuffer[3*get_local_id(0)+2] = (atoms2.z > -1 ? posq[atoms2.z] : (real4) 0);
171
172
173
174
            }
            barrier(CLK_LOCAL_MEM_FENCE);
            if (acceptorIndex < NUM_ACCEPTORS) {
                for (int index = 0; index < blockSize; index++) {
175
                    int donorIndex = donorStart+index;
176
#ifdef USE_EXCLUSIONS
177
178
179
                    if (donorIndex == exclusionIndices.x || donorIndex == exclusionIndices.y || donorIndex == exclusionIndices.z || donorIndex == exclusionIndices.w)
                        continue;
#endif
180
181
                    // Compute the interaction between a donor and an acceptor.

182
183
184
                    real4 d1 = posBuffer[3*index];
                    real4 d2 = posBuffer[3*index+1];
                    real4 d3 = posBuffer[3*index+2];
Peter Eastman's avatar
Peter Eastman committed
185
                    real4 deltaD1A1 = delta(d1, a1, periodicBoxSize, invPeriodicBoxSize, periodicBoxVecX, periodicBoxVecY, periodicBoxVecZ);
186
187
#ifdef USE_CUTOFF
                    if (deltaD1A1.w < CUTOFF_SQUARED) {
188
#endif
189
                        COMPUTE_ACCEPTOR_FORCE
190
#ifdef USE_CUTOFF
191
                    }
192
#endif
193
                }
194
195
196
197
198
            }
        }

        // Write results

199
200
201
202
        if (acceptorIndex < NUM_ACCEPTORS) {
            int4 bufferIndices = acceptorBufferIndices[acceptorIndex];
            if (atoms.x > -1) {
                unsigned int offset = atoms.x+bufferIndices.x*PADDED_NUM_ATOMS;
203
                real4 force = forceBuffers[offset];
204
205
206
207
208
                force.xyz += f1.xyz;
                forceBuffers[offset] = force;
            }
            if (atoms.y > -1) {
                unsigned int offset = atoms.y+bufferIndices.y*PADDED_NUM_ATOMS;
209
                real4 force = forceBuffers[offset];
210
211
212
213
214
                force.xyz += f2.xyz;
                forceBuffers[offset] = force;
            }
            if (atoms.z > -1) {
                unsigned int offset = atoms.z+bufferIndices.z*PADDED_NUM_ATOMS;
215
                real4 force = forceBuffers[offset];
216
217
218
                force.xyz += f3.xyz;
                forceBuffers[offset] = force;
            }
219
        }
220
221
    }
}