Fish schooling
Wrote a kernel for fish schooling. The opencl kernel is below.
[sourcecode language=”cpp”]
__kernel
void
fishy_simulation ( __global float4* pos,
__global float4* dirvec,
float speed,
float deltaTime,
float inner_radius,
float outer_radius,
int num_fishes,
__local float4* localPos,
__local float4* localdir,
__global float4* newPosition,
__global float4* newDirection,
__global float4* dbgArray
)
{
float wa = 1.0f;
float wo = 1.0f;
unsigned int tid = get_local_id(0);
unsigned int gid = get_global_id(0);
unsigned int localSize = get_local_size(0);
unsigned int numTiles = num_fishes/localSize;
float4 myPos = pos[gid];
float4 mydir = dirvec[gid];
float4 vec = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
float4 temp1 = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
float4 temp2 = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
int inc = 0;
int ouc = 0;
for(int i = 0; i < numTiles; ++i)
{
// load one tile into local memory
int idx = i * localSize + tid;
localPos[tid] = pos[idx];
localdir[tid] = dirvec[idx];
// Synchronize to make sure data is available for processing
barrier(CLK_LOCAL_MEM_FENCE);
//calculate the change in position due to each fish
for(int j = 0; j < localSize; ++j)
{
float4 t = localPos[j] - myPos;
temp1 = t;
float len = sqrt ( t.x * t.x + t.y * t.y + t.z * t.z );
if ( len != 0.0f )
{
if ( len <= inner_radius )
{
t.x = -(temp1.x/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
t.y = -(temp1.y/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
t.z = -(temp1.z/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
vec += t;
inc++;
}
if ( len > inner_radius && len <= outer_radius )
{
t.x = (temp1.x/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
t.y = (temp1.y/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
t.z = (temp1.z/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
temp2 = localdir[j];
temp1.x = (temp2.x/( sqrt (temp2.x *temp2.x + temp2.y * temp2.y + temp2.z * temp2.z ) ));
temp1.y = (temp2.y/( sqrt (temp2.x *temp2.x + temp2.y * temp2.y + temp2.z * temp2.z ) ));
temp1.z = (temp2.z/( sqrt (temp2.x *temp2.x + temp2.y * temp2.y + temp2.z * temp2.z ) ));
t = wa * t;
temp1 = wo * temp1;
vec = vec + t + temp1;
ouc++;
}
}
}
// Synchronize to make sure data is available for processing
//barrier(CLK_LOCAL_MEM_FENCE);
}
float len = sqrt ( vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
if ( len == 0.0f )
{
vec = mydir;
}
temp1 = vec;
vec.x = (temp1.x/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
vec.y = (temp1.y/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
vec.z = (temp1.z/( sqrt (temp1.x *temp1.x + temp1.y * temp1.y + temp1.z * temp1.z ) ));
newPosition[gid] = myPos + speed * vec * deltaTime;
newDirection[gid] = vec;
if ( newPosition[gid].x > 45 || newPosition[gid].x < -45 )
{
newDirection[gid].x = -newDirection[gid].x;
}
if ( newPosition[gid].y > 45 || newPosition[gid].y < -45 )
{
newDirection[gid].y = -newDirection[gid].y;
}
if ( newPosition[gid].z > 45 || newPosition[gid].z < -45 )
{
newDirection[gid].z = -newDirection[gid].z;
}
dbgArray[0] = pos[0];
dbgArray[1] = newPosition[0];
dbgArray[2] = inc;
dbgArray[3] = ouc;
if ( gid == 0)
{
dbgArray[4] = vec;
}
}
[/sourcecode]