"plugins/amoeba/vscode:/vscode.git/clone" did not exist on "29654b8000371484c3311cfb6d8bf719de3b65c1"
verlet.cl 4.2 KB
Newer Older
1
2
3
4
/**
 * Perform the first step of verlet integration.
 */

5
6
7
8
__kernel void integrateVerletPart1(int numAtoms, __global const mixed2* restrict dt, __global const real4* restrict posq, __global const real4* restrict posqCorrection, __global mixed4* restrict velm, __global const real4* restrict force, __global mixed4* restrict posDelta) {
    mixed2 stepSize = dt[0];
    mixed dtPos = stepSize.y;
    mixed dtVel = 0.5f*(stepSize.x+stepSize.y);
9
10
    int index = get_global_id(0);
    while (index < numAtoms) {
11
        mixed4 velocity = velm[index];
12
        if (velocity.w != 0.0) {
13
14
15
16
17
18
19
20
21
22
#ifdef USE_MIXED_PRECISION
            real4 pos1 = posq[index];
            real4 pos2 = posqCorrection[index];
            mixed4 pos = (mixed4) (pos1.x+(mixed)pos2.x, pos1.y+(mixed)pos2.y, pos1.z+(mixed)pos2.z, pos1.w);
#else
            real4 pos = posq[index];
#endif
            velocity.x += force[index].x*dtVel*velocity.w;
            velocity.y += force[index].y*dtVel*velocity.w;
            velocity.z += force[index].z*dtVel*velocity.w;
23
24
25
26
            pos.xyz = velocity.xyz*dtPos;
            posDelta[index] = pos;
            velm[index] = velocity;
        }
27
28
29
30
31
32
33
34
        index += get_global_size(0);
    }
}

/**
 * Perform the second step of verlet integration.
 */

35
36
__kernel void integrateVerletPart2(int numAtoms, __global mixed2* restrict dt, __global real4* restrict posq, __global real4* restrict posqCorrection, __global mixed4* restrict velm, __global const mixed4* restrict posDelta) {
    mixed2 stepSize = dt[0];
37
#ifdef SUPPORTS_DOUBLE_PRECISION
38
39
    double oneOverDt = 1.0/stepSize.y;
#else
Peter Eastman's avatar
Bug fix  
Peter Eastman committed
40
    float oneOverDt = 1.0f/stepSize.y;
41
#endif
Peter Eastman's avatar
Bug fix  
Peter Eastman committed
42
43
    if (get_global_id(0) == 0)
        dt[0].x = stepSize.y;
44
    barrier(CLK_LOCAL_MEM_FENCE);
45
46
    int index = get_global_id(0);
    while (index < numAtoms) {
47
        mixed4 velocity = velm[index];
48
        if (velocity.w != 0.0) {
49
50
51
52
53
54
55
56
#ifdef USE_MIXED_PRECISION
            real4 pos1 = posq[index];
            real4 pos2 = posqCorrection[index];
            mixed4 pos = (mixed4) (pos1.x+(mixed)pos2.x, pos1.y+(mixed)pos2.y, pos1.z+(mixed)pos2.z, pos1.w);
#else
            real4 pos = posq[index];
#endif
            mixed4 delta = posDelta[index];
57
            pos.xyz += delta.xyz;
58
#ifdef SUPPORTS_DOUBLE_PRECISION
59
            velocity.xyz = convert_mixed4(convert_double4(delta)*oneOverDt).xyz;
60
#else
61
            velocity.xyz = delta.xyz*oneOverDt;
62
#endif
63
64
65
66
#ifdef USE_MIXED_PRECISION
            posq[index] = convert_real4(pos);
            posqCorrection[index] = (real4) (pos.x-(real) pos.x, pos.y-(real) pos.y, pos.z-(real) pos.z, 0);
#else
67
            posq[index] = pos;
68
#endif
69
70
            velm[index] = velocity;
        }
71
72
73
        index += get_global_size(0);
    }
}
74
75
76
77
78

/**
 * Select the step size to use for the next step.
 */

79
__kernel void selectVerletStepSize(int numAtoms, mixed maxStepSize, mixed errorTol, __global mixed2* restrict dt, __global const mixed4* restrict velm, __global const real4* restrict force, __local mixed* restrict error) {
80
81
    // Calculate the error.

82
    mixed err = 0;
83
    int index = get_local_id(0);
84
    while (index < numAtoms) {
85
86
        real4 f = force[index];
        mixed invMass = velm[index].w;
Peter Eastman's avatar
Bug fix  
Peter Eastman committed
87
        err += (f.x*f.x + f.y*f.y + f.z*f.z)*invMass;
88
89
90
91
92
93
94
        index += get_global_size(0);
    }
    error[get_local_id(0)] = err;
    barrier(CLK_LOCAL_MEM_FENCE);

    // Sum the errors from all threads.

95
    for (unsigned int offset = 1; offset < get_local_size(0); offset *= 2) {
96
97
98
99
100
        if (get_local_id(0)+offset < get_local_size(0) && (get_local_id(0)&(2*offset-1)) == 0)
            error[get_local_id(0)] += error[get_local_id(0)+offset];
        barrier(CLK_LOCAL_MEM_FENCE);
    }
    if (get_local_id(0) == 0) {
101
102
        mixed totalError = sqrt(error[0]/(numAtoms*3));
        mixed newStepSize = sqrt(errorTol/totalError);
103
        mixed oldStepSize = dt[0].y;
104
105
106
107
108
109
110
111
112
        if (oldStepSize > 0.0f)
            newStepSize = min(newStepSize, oldStepSize*2.0f); // For safety, limit how quickly dt can increase.
        if (newStepSize > oldStepSize && newStepSize < 1.1f*oldStepSize)
            newStepSize = oldStepSize; // Keeping dt constant between steps improves the behavior of the integrator.
        if (newStepSize > maxStepSize)
            newStepSize = maxStepSize;
        dt[0].y = newStepSize;
    }
}