OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
Gray Scott in 3D using sparse grids on GPU

Solving a gray scott-system in 3D using Sparse grids on gpu

This example show how to solve a Gray-Scott system in 3D using sparse grids on gpu

In figure is the final solution of the problem

More or less this example is the adaptation of the dense example in 3D

See also
Gray Scott in 3D

Initializetion

On gpu we can add points using the function addPoints this function take 2 lamda functions the first take 3 arguments (in 3D) i,j,k these are the global coordinates for a point. We can return either true either false. In case of true the point is created in case of false the point is not inserted. The second lamda is instead used to initialize the point inserted. The arguments of the second lambda are the data argument we use to initialize the point and the global coordinates i,j,k

After we add the points we have to flush the added points. This us achieved using the function flush the template parameters indicate how we have to act on the points. Consider infact we are adding points already exist ... do we have to add it using the max or the min. FLUSH_ON_DEVICE say instead that the operation is performed using the GPU

typedef typename GetAddBlockType<SparseGridType>::type InsertBlockT;
grid.addPoints([] __device__ (int i, int j, int k)
{
return true;
},
[] __device__ (InsertBlockT & data, int i, int j, int k)
{
data.template get<U>() = 1.0;
data.template get<V>() = 0.0;
}
);
grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);

The function can also called with a specified range

grid_key_dx<3> start({x_start,y_start,z_start});
grid_key_dx<3> stop ({x_stop,y_stop,z_stop});
grid.addPoints(start,stop,[] __device__ (int i, int j, int k)
{
return true;
},
[] __device__ (InsertBlockT & data, int i, int j, int k)
{
data.template get<U>() = 0.5;
data.template get<V>() = 0.24;
}
);
grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
grid_key_dx is the key to access any element in the grid
Definition grid_key.hpp:19

Update

to calculate the right-hand-side we use the function conv2 this function can be used to do a convolution that involve two properties

The function accept a lambda function where the first 2 arguments are the output of the same type of the two property choosen.

The arguments 3 and 4 contain the properties of two selected properties. while i,j,k are the coordinates we have to calculate the convolution. The call conv2 also accept template parameters the first two indicate the source porperties, the other two are the destination properties. While the last is the extension of the stencil. In this case we use 1.

The lambda function is defined as

auto func = [uFactor,vFactor,deltaT,F,K] __device__ (float & u_out, float & v_out,
CpBlockType & u, CpBlockType & v,
int i, int j, int k){
float uc = u(i,j,k);
float vc = v(i,j,k);
u_out = uc + uFactor *(u(i-1,j,k) + u(i+1,j,k) +
u(i,j-1,k) + u(i,j+1,k) +
u(i,j,k-1) + u(i,j,k+1) - 6.0*uc) - deltaT * uc*vc*vc
- deltaT * F * (uc - 1.0);
v_out = vc + vFactor *(v(i-1,j,k) + v(i+1,j,k) +
v(i,j+1,k) + v(i,j-1,k) +
v(i,j,k-1) + v(i,j,k+1) - 6.0*vc) + deltaT * uc*vc*vc
- deltaT * (F+K) * vc;
};
[v_transform metafunction]

and used in the body loop

if (i % 2 == 0)
{
grid.conv2<U,V,U_next,V_next,1>({0,0,0},{(long int)sz[0]-1,(long int)sz[1]-1,(long int)sz[2]-1},func);
// After copy we synchronize again the ghost part U and V
grid.ghost_get<U_next,V_next>(RUN_ON_DEVICE | SKIP_LABELLING);
}
else
{
grid.conv2<U_next,V_next,U,V,1>({0,0,0},{(long int)sz[0]-1,(long int)sz[1]-1,(long int)sz[2]-1},func);
// After copy we synchronize again the ghost part U and V
grid.ghost_get<U,V>(RUN_ON_DEVICE | SKIP_LABELLING);
}
KeyT const ValueT ValueT OffsetIteratorT OffsetIteratorT int
[in] The number of segments that comprise the sorting data

Solving a gray scott-system in 3D using Sparse grids on gpu

This example show how to solve a Gray-Scott system in 3D using sparse grids on gpu

In figure is the final solution of the problem

More or less this example is the adaptation of the dense example in 3D

See also
Gray Scott in 3D

Initializetion

On gpu we can add points using the function addPoints this function take 2 lamda functions the first take 3 arguments (in 3D) i,j,k these are the global coordinates for a point. We can return either true either false. In case of true the point is created in case of false the point is not inserted. The second lamda is instead used to initialize the point inserted. The arguments of the second lambda are the data argument we use to initialize the point and the global coordinates i,j,k

After we add the points we have to flush the added points. This us achieved using the function flush the template parameters indicate how we have to act on the points. Consider infact we are adding points already exist ... do we have to add it using the max or the min. FLUSH_ON_DEVICE say instead that the operation is performed using the GPU

typedef typename GetAddBlockType<SparseGridType>::type InsertBlockT;
grid.addPoints([] __device__ (int i, int j, int k)
{
return true;
},
[] __device__ (InsertBlockT & data, int i, int j, int k)
{
data.template get<U>() = 1.0;
data.template get<V>() = 0.0;
}
);
grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);

The function can also called with a specified range

grid_key_dx<3> start({x_start,y_start,z_start});
grid_key_dx<3> stop ({x_stop,y_stop,z_stop});
grid.addPoints(start,stop,[] __device__ (int i, int j, int k)
{
return true;
},
[] __device__ (InsertBlockT & data, int i, int j, int k)
{
data.template get<U>() = 0.5;
data.template get<V>() = 0.24;
}
);
grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);

Update

to calculate the right-hand-side we use the function conv2 this function can be used to do a convolution that involve two properties

The function accept a lambda function where the first 2 arguments are the output of the same type of the two property choosen.

The arguments 3 and 4 contain the properties of two selected properties. while i,j,k are the coordinates we have to calculate the convolution. The call conv2 also accept template parameters the first two indicate the source porperties, the other two are the destination properties. While the last is the extension of the stencil. In this case we use 1.

The lambda function is defined as

auto func = [uFactor,vFactor,deltaT,F,K] __device__ (float & u_out, float & v_out,
CpBlockType & u, CpBlockType & v,
int i, int j, int k){
float uc = u(i,j,k);
float vc = v(i,j,k);
u_out = uc + uFactor *(u(i-1,j,k) + u(i+1,j,k) +
u(i,j-1,k) + u(i,j+1,k) +
u(i,j,k-1) + u(i,j,k+1) - 6.0*uc) - deltaT * uc*vc*vc
- deltaT * F * (uc - 1.0);
v_out = vc + vFactor *(v(i-1,j,k) + v(i+1,j,k) +
v(i,j+1,k) + v(i,j-1,k) +
v(i,j,k-1) + v(i,j,k+1) - 6.0*vc) + deltaT * uc*vc*vc
- deltaT * (F+K) * vc;
};

and used in the body loop

if (i % 2 == 0)
{
grid.conv2<U,V,U_next,V_next,1>({0,0,0},{(long int)sz[0]-1,(long int)sz[1]-1,(long int)sz[2]-1},func);
// After copy we synchronize again the ghost part U and V
grid.ghost_get<U_next,V_next>(RUN_ON_DEVICE | SKIP_LABELLING);
}
else
{
grid.conv2<U_next,V_next,U,V,1>({0,0,0},{(long int)sz[0]-1,(long int)sz[1]-1,(long int)sz[2]-1},func);
// After copy we synchronize again the ghost part U and V
grid.ghost_get<U,V>(RUN_ON_DEVICE | SKIP_LABELLING);
}

Solving a gray scott-system in 3D using Sparse grids on gpu

This example show how to solve a Gray-Scott system in 3D using sparse grids on gpu

In figure is the final solution of the problem

More or less this example is the adaptation of the dense example in 3D

See also
Gray Scott in 3D

Initializetion

On gpu we can add points using the function addPoints this function take 2 lamda functions the first take 3 arguments (in 3D) i,j,k these are the global coordinates for a point. We can return either true either false. In case of true the point is created in case of false the point is not inserted. The second lamda is instead used to initialize the point inserted. The arguments of the second lambda are the data argument we use to initialize the point and the global coordinates i,j,k

After we add the points we have to flush the added points. This us achieved using the function flush the template parameters indicate how we have to act on the points. Consider infact we are adding points already exist ... do we have to add it using the max or the min. FLUSH_ON_DEVICE say instead that the operation is performed using the GPU

typedef typename GetAddBlockType<SparseGridType>::type InsertBlockT;
grid.addPoints([] __device__ (int i, int j, int k)
{
return true;
},
[] __device__ (InsertBlockT & data, int i, int j, int k)
{
data.template get<U>() = 1.0;
data.template get<V>() = 0.0;
}
);
grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);

The function can also called with a specified range

grid_key_dx<3> start({x_start,y_start,z_start});
grid_key_dx<3> stop ({x_stop,y_stop,z_stop});
grid.addPoints(start,stop,[] __device__ (int i, int j, int k)
{
return true;
},
[] __device__ (InsertBlockT & data, int i, int j, int k)
{
data.template get<U>() = 0.5;
data.template get<V>() = 0.24;
}
);
grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);

Update

to calculate the right-hand-side we use the function conv2 this function can be used to do a convolution that involve two properties

The function accept a lambda function where the first 2 arguments are the output of the same type of the two property choosen.

The arguments 3 and 4 contain the properties of two selected properties. while i,j,k are the coordinates we have to calculate the convolution. The call conv2 also accept template parameters the first two indicate the source porperties, the other two are the destination properties. While the last is the extension of the stencil. In this case we use 1.

The lambda function is defined as

auto func = [uFactor,vFactor,deltaT,F,K] __device__ (float & u_out, float & v_out,
CpBlockType & u, CpBlockType & v,
int i, int j, int k){
float uc = u(i,j,k);
float vc = v(i,j,k);
u_out = uc + uFactor *(u(i-1,j,k) + u(i+1,j,k) +
u(i,j-1,k) + u(i,j+1,k) +
u(i,j,k-1) + u(i,j,k+1) - 6.0*uc) - deltaT * uc*vc*vc
- deltaT * F * (uc - 1.0);
v_out = vc + vFactor *(v(i-1,j,k) + v(i+1,j,k) +
v(i,j+1,k) + v(i,j-1,k) +
v(i,j,k-1) + v(i,j,k+1) - 6.0*vc) + deltaT * uc*vc*vc
- deltaT * (F+K) * vc;
};

and used in the body loop

if (i % 2 == 0)
{
grid.conv2<U,V,U_next,V_next,1>({0,0,0},{(long int)sz[0]-1,(long int)sz[1]-1,(long int)sz[2]-1},func);
// After copy we synchronize again the ghost part U and V
grid.ghost_get<U_next,V_next>(RUN_ON_DEVICE | SKIP_LABELLING);
}
else
{
grid.conv2<U_next,V_next,U,V,1>({0,0,0},{(long int)sz[0]-1,(long int)sz[1]-1,(long int)sz[2]-1},func);
// After copy we synchronize again the ghost part U and V
grid.ghost_get<U,V>(RUN_ON_DEVICE | SKIP_LABELLING);
}