customHbondForce.cl 7.96 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
35
36
37
38
39
40
41
42
43
44
45
46
/**
 * Compute the difference between two vectors, setting the fourth component to the squared magnitude.
 */
float4 delta(float4 vec1, float4 vec2) {
    float4 result = (float4) (vec1.x-vec2.x, vec1.y-vec2.y, vec1.z-vec2.z, 0.0f);
    result.w = result.x*result.x + result.y*result.y + result.z*result.z;
    return result;
}

/**
 * Compute the difference between two vectors, taking periodic boundary conditions into account
 * and setting the fourth component to the squared magnitude.
 */
float4 deltaPeriodic(float4 vec1, float4 vec2) {
    float4 result = (float4) (vec1.x-vec2.x, vec1.y-vec2.y, vec1.z-vec2.z, 0.0f);
#ifdef USE_PERIODIC
    result.x -= floor(result.x/PERIODIC_BOX_SIZE_X+0.5f)*PERIODIC_BOX_SIZE_X;
    result.y -= floor(result.y/PERIODIC_BOX_SIZE_Y+0.5f)*PERIODIC_BOX_SIZE_Y;
    result.z -= floor(result.z/PERIODIC_BOX_SIZE_Z+0.5f)*PERIODIC_BOX_SIZE_Z;
#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.
 */
float computeAngle(float4 vec1, float4 vec2) {
    float dot = vec1.x*vec2.x + vec1.y*vec2.y + vec1.z*vec2.z;
    float cosine = dot/sqrt(vec1.w*vec2.w);
    float angle;
    if (cosine > 0.99f || cosine < -0.99f) {
        // We're close to the singularity in acos(), so take the cross product and use asin() instead.

        float4 cross_prod = cross(vec1, vec2);
        float scale = vec1.w*vec2.w;
        angle = asin(sqrt(dot(cross_prod, cross_prod)/scale));
        if (cosine < 0.0f)
            angle = M_PI-angle;
    }
    else
       angle = acos(cosine);
    return angle;
}

/**
47
 * Compute the cross product of two vectors, setting the fourth component to the squared magnitude.
48
 */
49
50
51
52
53
float4 computeCross(float4 vec1, float4 vec2) {
    float4 result = cross(vec1, vec2);
    result.w = result.x*result.x + result.y*result.y + result.z*result.z;
    return result;
}
54

55
56
57
58
59
/**
 * Compute forces on donors.
 */
__kernel void computeDonorForces(__global float4* forceBuffers, __global float* energyBuffer, __global float4* posq, /*__global unsigned int* exclusions,
        __global unsigned int* exclusionIndices, */__global int4* donorAtoms, __global int4* acceptorAtoms, __global int4* donorBufferIndices, __local float4* posBuffer
60
61
62
63
        PARAMETER_ARGUMENTS) {
    float energy = 0.0f;
    float4 f1 = 0;
    float4 f2 = 0;
64
65
    float4 f3 = 0;
    for (int donorStart = 0; donorStart < NUM_DONORS; donorStart += get_global_size(0)) {
66
67
        // Load information about the donor this thread will compute forces on.

68
69
70
71
72
73
74
75
76
77
78
        int donorIndex = donorStart+get_global_id(0);
        int4 atoms;
        float4 d1, d2, d3;
        if (donorIndex < NUM_DONORS) {
            atoms = donorAtoms[donorIndex];
            d1 = posq[atoms.x];
            d2 = posq[atoms.y];
            d3 = posq[atoms.z];
        }
        else
            atoms = (int4) (-1, -1, -1, -1);
79
80
81
82
        for (int acceptorStart = 0; acceptorStart < NUM_ACCEPTORS; acceptorStart += get_local_size(0)) {
            // Load the next block of acceptors into local memory.

            int blockSize = min((int) get_local_size(0), NUM_ACCEPTORS-acceptorStart);
83
84
85
86
87
            if (get_local_id(0) < blockSize) {
                int4 atoms2 = acceptorAtoms[acceptorStart+get_local_id(0)];
                posBuffer[3*get_local_id(0)] = posq[atoms2.x];
                posBuffer[3*get_local_id(0)+1] = posq[atoms2.y];
                posBuffer[3*get_local_id(0)+2] = posq[atoms2.z];
88
89
            }
            barrier(CLK_LOCAL_MEM_FENCE);
90
91
92
93
94
95
96
97
            if (donorIndex < NUM_DONORS) {
                for (int index = 0; index < blockSize; index++) {
                    // Compute the interaction between a donor and an acceptor.

                    float4 a1 = posBuffer[3*index];
                    float4 a2 = posBuffer[3*index+1];
                    float4 a3 = posBuffer[3*index+2];
                    float4 deltaD1A1 = deltaPeriodic(d1, a1);
98
#ifdef USE_CUTOFF
99
                    if (deltaD1A1.w < CUTOFF_SQUARED) {
100
#endif
101
102
103
                        COMPUTE_DONOR_FORCE
#ifdef USE_CUTOFF
                    }
104
#endif
105
106
107
                }
            }
        }
108

109
        // Write results
110

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
        int4 bufferIndices = donorBufferIndices[donorIndex];
        if (atoms.x > -1) {
            unsigned int offset = atoms.x+bufferIndices.x*PADDED_NUM_ATOMS;
            float4 force = forceBuffers[offset];
            force.xyz += f1.xyz;
            forceBuffers[offset] = force;
        }
        if (atoms.y > -1) {
            unsigned int offset = atoms.y+bufferIndices.y*PADDED_NUM_ATOMS;
            float4 force = forceBuffers[offset];
            force.xyz += f2.xyz;
            forceBuffers[offset] = force;
        }
        if (atoms.z > -1) {
            unsigned int offset = atoms.z+bufferIndices.z*PADDED_NUM_ATOMS;
            float4 force = forceBuffers[offset];
            force.xyz += f3.xyz;
            forceBuffers[offset] = force;
        }
    }
    energyBuffer[get_global_id(0)] += energy;
}
/**
 * Compute forces on acceptors.
 */
__kernel void computeAcceptorForces(__global float4* forceBuffers, __global float* energyBuffer, __global float4* posq, /*__global unsigned int* exclusions,
        __global unsigned int* exclusionIndices, */__global int4* donorAtoms, __global int4* acceptorAtoms, __global int4* acceptorBufferIndices, __local float4* posBuffer
        PARAMETER_ARGUMENTS) {
    float4 f1 = 0;
    float4 f2 = 0;
    float4 f3 = 0;
    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);
        int4 atoms;
        float4 a1, a2, a3;
        if (acceptorIndex < NUM_ACCEPTORS) {
            atoms = acceptorAtoms[acceptorIndex];
            a1 = posq[atoms.x];
            a2 = posq[atoms.y];
            a3 = posq[atoms.z];
        }
        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.

            int blockSize = min((int) get_local_size(0), NUM_DONORS-donorStart);
            if (get_local_id(0) < blockSize) {
                int4 atoms2 = donorAtoms[donorStart+get_local_id(0)];
                posBuffer[3*get_local_id(0)] = posq[atoms2.x];
                posBuffer[3*get_local_id(0)+1] = posq[atoms2.y];
                posBuffer[3*get_local_id(0)+2] = posq[atoms2.z];
            }
            barrier(CLK_LOCAL_MEM_FENCE);
            if (acceptorIndex < NUM_ACCEPTORS) {
                for (int index = 0; index < blockSize; index++) {
                    // Compute the interaction between a donor and an acceptor.

                    float4 d1 = posBuffer[3*index];
                    float4 d2 = posBuffer[3*index+1];
                    float4 d3 = posBuffer[3*index+2];
                    float4 deltaD1A1 = deltaPeriodic(d1, a1);
#ifdef USE_CUTOFF
                    if (deltaD1A1.w < CUTOFF_SQUARED) {
177
#endif
178
                        COMPUTE_ACCEPTOR_FORCE
179
#ifdef USE_CUTOFF
180
                    }
181
#endif
182
                }
183
184
185
186
187
            }
        }

        // Write results

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
        int4 bufferIndices = acceptorBufferIndices[acceptorIndex];
        if (atoms.x > -1) {
            unsigned int offset = atoms.x+bufferIndices.x*PADDED_NUM_ATOMS;
            float4 force = forceBuffers[offset];
            force.xyz += f1.xyz;
            forceBuffers[offset] = force;
        }
        if (atoms.y > -1) {
            unsigned int offset = atoms.y+bufferIndices.y*PADDED_NUM_ATOMS;
            float4 force = forceBuffers[offset];
            force.xyz += f2.xyz;
            forceBuffers[offset] = force;
        }
        if (atoms.z > -1) {
            unsigned int offset = atoms.z+bufferIndices.z*PADDED_NUM_ATOMS;
            float4 force = forceBuffers[offset];
            force.xyz += f3.xyz;
            forceBuffers[offset] = force;
        }
207
208
    }
}