OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
main.cu
1 #include "Decomposition/Distribution/BoxDistribution.hpp"
2 #include "Grid/grid_dist_id.hpp"
3 #include "data_type/aggregate.hpp"
4 #include "timer.hpp"
5 
64 #ifdef __NVCC__
65 
66 constexpr int U = 0;
67 constexpr int V = 1;
68 
69 constexpr int U_next = 2;
70 constexpr int V_next = 3;
71 
72 constexpr int x = 0;
73 constexpr int y = 1;
74 constexpr int z = 2;
75 
77 
78 typedef sgrid_dist_id_gpu<3,float,aggregate<float,float,float,float>,CudaMemory, Dec> SparseGridType;
79 
80 void init(SparseGridType & grid, Box<3,float> & domain, size_t (& div)[3])
81 {
83 
84  double spacing_x = grid.spacing(0);
85  double spacing_y = grid.spacing(1);
86  double spacing_z = grid.spacing(2);
87 
88  typedef typename GetAddBlockType<SparseGridType>::type InsertBlockT;
89 
90  // Get the processor domain in continuos
91 
92  for (int i = 0 ; i < div[0] ; i++)
93  {
94  for (int j = 0 ; j < div[1] ; j++)
95  {
96  for (int k = 0 ; k < div[2] ; k++)
97  {
98  Point<3,double> p({0.5+i*1.0,0.5+j*1.0,0.5+k*1.0});
99  Sphere<3,double> sph(p,0.3);
100 
101  Box<3,size_t> bx;
102 
103  for (int s = 0 ; s < 3 ; s++)
104  {
105  bx.setLow(s,(size_t)((sph.center(s) - 0.31)/grid.spacing(s)));
106  bx.setHigh(s,(size_t)((sph.center(s) + 0.31)/grid.spacing(s)));
107  }
108 
109  grid.addPoints([spacing_x,spacing_y,spacing_z,sph] __device__ (int i, int j, int k)
110  {
111  Point<3,double> pc({i*spacing_x,j*spacing_y,k*spacing_z});
112 
113  // Check if the point is in the domain
114  if (sph.isInside(pc) )
115  {return true;}
116  return false;
117  },
118  [] __device__ (InsertBlockT & data, int i, int j, int k)
119  {
120  data.template get<U>() = 1.0;
121  data.template get<V>() = 0.0;
122  }
123  );
124 
125  grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
126  grid.removeUnusedBuffers();
127  }
128  }
129  }
130 
131  for (int i = 0 ; i < div[0] ; i++)
132  {
133  for (int j = 0 ; j < div[1] ; j++)
134  {
135  Point<3,double> u({0.0,0.0,1.0});
136  Point<3,double> c({0.5+i,0.5+j,0.0});
137 
138  Box<3,size_t> bx;
139 
140  bx.setLow(0,(0.4+i)/spacing_x);
141  bx.setHigh(0,(0.6+i)/spacing_x);
142 
143  bx.setLow(1,(0.4+j)/spacing_y);
144  bx.setHigh(1,(0.6+j)/spacing_y);
145 
146  bx.setLow(2,0);
147  bx.setHigh(2,(size_t)grid.size(2));
148 
149  grid.addPoints(bx.getKP1(),bx.getKP2(),[spacing_x,spacing_y,spacing_z,u,c] __device__ (int i, int j, int k)
150  {
151  Point<3,double> pc({i*spacing_x,j*spacing_y,k*spacing_z});
152  Point<3,double> pcs({i*spacing_x,j*spacing_y,k*spacing_z});
153  Point<3,double> vp;
154 
155  // shift
156  pc -= c;
157 
158  // calculate the distance from the diagonal
159  vp.get(0) = pc.get(1)*u.get(2) - pc.get(2)*u.get(1);
160  vp.get(1) = pc.get(2)*u.get(0) - pc.get(0)*u.get(2);
161  vp.get(2) = pc.get(0)*u.get(1) - pc.get(1)*u.get(0);
162 
163  double distance = vp.norm();
164 
165  // Check if the point is in the domain
166  if (distance < 0.1 )
167  {return true;}
168 
169  return false;
170  },
171  [] __device__ (InsertBlockT & data, int i, int j, int k)
172  {
173  data.template get<U>() = 1.0;
174  data.template get<V>() = 0.0;
175  }
176  );
177 
178  grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
179  grid.removeUnusedBuffers();
180  }
181  }
182 
183  for (int i = 0 ; i < div[0] ; i++)
184  {
185  for (int k = 0 ; k < div[2] ; k++)
186  {
187  Point<3,double> u({0.0,1.0,0.0});
188  Point<3,double> c({0.5+i,0.0,0.5+k});
189 
190  Box<3,size_t> bx;
191 
192  bx.setLow(0,(0.4+i)/spacing_x);
193  bx.setHigh(0,(0.6+i)/spacing_x);
194 
195  bx.setLow(2,(0.4+k)/spacing_z);
196  bx.setHigh(2,(0.6+k)/spacing_z);
197 
198  bx.setLow(1,0);
199  bx.setHigh(1,(size_t)grid.size(1));
200 
201  grid.addPoints(bx.getKP1(),bx.getKP2(),[spacing_x,spacing_y,spacing_z,u,c] __device__ (int i, int j, int k)
202  {
203  Point<3,double> pc({i*spacing_x,j*spacing_y,k*spacing_z});
204  Point<3,double> pcs({i*spacing_x,j*spacing_y,k*spacing_z});
205  Point<3,double> vp;
206 
207  // shift
208  pc -= c;
209 
210  // calculate the distance from the diagonal
211  vp.get(0) = pc.get(1)*u.get(2) - pc.get(2)*u.get(1);
212  vp.get(1) = pc.get(2)*u.get(0) - pc.get(0)*u.get(2);
213  vp.get(2) = pc.get(0)*u.get(1) - pc.get(1)*u.get(0);
214 
215  double distance = vp.norm();
216 
217  // Check if the point is in the domain
218  if (distance < 0.1 )
219  {return true;}
220 
221  return false;
222  },
223  [] __device__ (InsertBlockT & data, int i, int j, int k)
224  {
225  data.template get<U>() = 1.0;
226  data.template get<V>() = 0.0;
227  }
228  );
229 
230  grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
231  grid.removeUnusedBuffers();
232  }
233  }
234 
235  for (int j = 0 ; j < div[1] ; j++)
236  {
237  for (int k = 0 ; k < div[2] ; k++)
238  {
239  Point<3,double> u({1.0,0.0,0.0});
240  Point<3,double> c({0.0,0.5+j,0.5+k});
241 
242  Box<3,size_t> bx;
243 
244  bx.setLow(1,(0.4+j)/spacing_y);
245  bx.setHigh(1,(0.6+j)/spacing_y);
246 
247  bx.setLow(2,(0.4+k)/spacing_z);
248  bx.setHigh(2,(0.6+k)/spacing_z);
249 
250  bx.setLow(0,0);
251  bx.setHigh(0,(size_t)grid.size(0));
252 
253  grid.addPoints(bx.getKP1(),bx.getKP2(),[spacing_x,spacing_y,spacing_z,u,c] __device__ (int i, int j, int k)
254  {
255  Point<3,double> pc({i*spacing_x,j*spacing_y,k*spacing_z});
256  Point<3,double> pcs({i*spacing_x,j*spacing_y,k*spacing_z});
257  Point<3,double> vp;
258 
259  // shift
260  pc -= c;
261 
262  // calculate the distance from the diagonal
263  vp.get(0) = pc.get(1)*u.get(2) - pc.get(2)*u.get(1);
264  vp.get(1) = pc.get(2)*u.get(0) - pc.get(0)*u.get(2);
265  vp.get(2) = pc.get(0)*u.get(1) - pc.get(1)*u.get(0);
266 
267  double distance = vp.norm();
268 
269  // Check if the point is in the domain
270  if (distance < 0.1 )
271  {return true;}
272 
273  return false;
274  },
275  [] __device__ (InsertBlockT & data, int i, int j, int k)
276  {
277  data.template get<U>() = 1.0;
278  data.template get<V>() = 0.0;
279  }
280  );
281 
282  grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
283  grid.removeUnusedBuffers();
284  }
285  }
286 
288 
289  long int x_start = grid.size(0)*0.4f/domain.getHigh(0);
290  long int y_start = grid.size(1)*0.4f/domain.getHigh(1);
291  long int z_start = grid.size(1)*0.4f/domain.getHigh(2);
292 
293  long int x_stop = grid.size(0)*0.6f/domain.getHigh(0);
294  long int y_stop = grid.size(1)*0.6f/domain.getHigh(1);
295  long int z_stop = grid.size(1)*0.6f/domain.getHigh(2);
296 
298 
299  grid_key_dx<3> start({x_start,y_start,z_start});
300  grid_key_dx<3> stop ({x_stop,y_stop,z_stop});
301 
302  grid.addPoints(start,stop,[] __device__ (int i, int j, int k)
303  {
304  return true;
305  },
306  [] __device__ (InsertBlockT & data, int i, int j, int k)
307  {
308  data.template get<U>() = 0.5;
309  data.template get<V>() = 0.24;
310  }
311  );
312 
313  grid.template flush<smin_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
314 
316 }
317 
318 
319 int main(int argc, char* argv[])
320 {
321  openfpm_init(&argc,&argv);
322 
323  // First we check which type of decomposition BoxDistritubion prodice
324  auto & v_cl = create_vcluster();
325 
326  openfpm::vector<int> facts;
327  getPrimeFactors(v_cl.size(),facts);
328 
329  size_t div[3];
330 
331  for (int i = 0 ; i < 3 ; i++)
332  {div[i] = 1;}
333 
334  for (int i = 0 ; i < facts.size() ; i++)
335  {div[i % 3] *= facts.get(i);}
336 
337  grid_sm<3,void> gdist(div);
338 
339  // domain
340  Box<3,float> domain({0.0,0.0,0.0},{div[0]*1.0f,div[1]*1.0f,div[2]*1.0f});
341 
342  // grid size
343  size_t sz[3] = {64*div[0],64*div[1],64*div[2]};
344 
345  // Define periodicity of the grid
346  periodicity<3> bc = {PERIODIC,PERIODIC,PERIODIC};
347 
348  // Ghost in grid unit
349  Ghost<3,long int> g(1);
350 
351  // deltaT
352  float deltaT = 0.25;
353 
354  // Diffusion constant for specie U
355  float du = 2*1e-5;
356 
357  // Diffusion constant for specie V
358  float dv = 1*1e-5;
359 
360  // Number of timesteps
361 #ifdef TEST_RUN
362  size_t timeSteps = 300;
363 #else
364  size_t timeSteps = 15000;
365 #endif
366 
367  // K and F (Physical constant in the equation)
368  float K = 0.053;
369  float F = 0.014;
370 
371  SparseGridType grid(sz,domain,g,bc,0,gdist);
372 
373  // spacing of the grid on x and y
374  float spacing[3] = {grid.spacing(0),grid.spacing(1),grid.spacing(2)};
375 
376  init(grid,domain,div);
377 
378  grid.deviceToHost<U,V,U_next,V_next>();
379  grid.write("final");
380 
381  openfpm_finalize();
382  return 0;
383 
384  // sync the ghost
385  grid.template ghost_get<U,V>(RUN_ON_DEVICE);
386 
387  // because we assume that spacing[x] == spacing[y] we use formula 2
388  // and we calculate the prefactor of Eq 2
389  float uFactor = deltaT * du/(spacing[x]*spacing[x]);
390  float vFactor = deltaT * dv/(spacing[x]*spacing[x]);
391 
392  timer tot_sim;
393  tot_sim.start();
394 
395  for (size_t i = 0; i < timeSteps ; ++i)
396  {
397  if (v_cl.rank() == 0)
398  {std::cout << "STEP: " << i << std::endl;}
399 /* if (i % 300 == 0)
400  {
401  std::cout << "STEP: " << i << std::endl;
402  grid.write_frame("out",i,VTK_WRITER);
403  }*/
404 
406 
407  typedef typename GetCpBlockType<decltype(grid),0,1>::type CpBlockType;
408 
410 
411  auto func = [uFactor,vFactor,deltaT,F,K] __device__ (float & u_out, float & v_out,
412  CpBlockType & u, CpBlockType & v,
413  int i, int j, int k){
414 
415  float uc = u(i,j,k);
416  float vc = v(i,j,k);
417 
418  u_out = uc + uFactor *(u(i-1,j,k) + u(i+1,j,k) +
419  u(i,j-1,k) + u(i,j+1,k) +
420  u(i,j,k-1) + u(i,j,k+1) - 6.0f*uc) - deltaT * uc*vc*vc
421  - deltaT * F * (uc - 1.0f);
422 
423 
424  v_out = vc + vFactor *(v(i-1,j,k) + v(i+1,j,k) +
425  v(i,j+1,k) + v(i,j-1,k) +
426  v(i,j,k-1) + v(i,j,k+1) - 6.0f*vc) + deltaT * uc*vc*vc
427  - deltaT * (F+K) * vc;
428  };
429 
431 
433 
434  if (i % 2 == 0)
435  {
436  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);
437 
438  // After copy we synchronize again the ghost part U and V
439 
440  grid.ghost_get<U_next,V_next>(RUN_ON_DEVICE | SKIP_LABELLING);
441  }
442  else
443  {
444  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);
445 
446  // After copy we synchronize again the ghost part U and V
447  grid.ghost_get<U,V>(RUN_ON_DEVICE | SKIP_LABELLING);
448  }
449 
451 
452  // Every 500 time step we output the configuration for
453  // visualization
454 // if (i % 500 == 0)
455 // {
456 // grid.save("output_" + std::to_string(count));
457 // count++;
458 // }
459  }
460 
461  tot_sim.stop();
462  std::cout << "Total simulation: " << tot_sim.getwct() << std::endl;
463 
464  grid.deviceToHost<U,V,U_next,V_next>();
465  grid.write("final");
466 
468 
480 
482  openfpm_finalize();
483 
485 
494 }
495 
496 #else
497 
498 int main(int argc, char* argv[])
499 {
500  return 0;
501 }
502 
503 #endif
504 
grid_key_dx is the key to access any element in the grid
Definition: grid_key.hpp:18
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:27
size_t size()
Stub size.
Definition: map_vector.hpp:211
double getwct()
Return the elapsed real time.
Definition: timer.hpp:130
Definition: Ghost.hpp:39
__device__ __host__ T norm()
norm of the vector
Definition: Point.hpp:231
__device__ __host__ void setHigh(int i, T val)
set the high interval of the box
Definition: Box.hpp:544
This class decompose a space into sub-sub-domains and distribute them across processors.
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition: Point.hpp:172
__device__ __host__ void setLow(int i, T val)
set the low interval of the box
Definition: Box.hpp:533
KeyT const ValueT ValueT OffsetIteratorT OffsetIteratorT int
[in] The number of segments that comprise the sorting data
void start()
Start the timer.
Definition: timer.hpp:90
get the type of the block
Declaration grid_sm.
Definition: grid_sm.hpp:147
This class implement the Sphere concept in an N-dimensional space.
Definition: Sphere.hpp:23
OutputIteratorT OffsetT ReductionOpT OuputT init
< [in] The initial value of the reduction
__device__ __host__ T getHigh(int i) const
get the high interval of the box
Definition: Box.hpp:567
Boundary conditions.
Definition: common.hpp:21
Class for cpu time benchmarking.
Definition: timer.hpp:27
void stop()
Stop the timer.
Definition: timer.hpp:119
[v_transform metafunction]