OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
main.cu
1 #include "Grid/grid_dist_id.hpp"
2 #include "data_type/aggregate.hpp"
3 #include "timer.hpp"
4 
35 #ifdef __NVCC__
36 
37 constexpr int U = 0;
38 constexpr int V = 1;
39 constexpr int U_next = 2;
40 constexpr int V_next = 3;
41 
42 typedef sgrid_dist_id_gpu<3,double,aggregate<double,double,double,double> > sgrid_type;
43 
44 void init(sgrid_type & grid, Box<3,double> & domain)
45 {
46  auto it = grid.getGridIterator();
47  Point<3,double> p1;
48  Point<3,double> p2;
49  Point<3,double> p3;
50 
51  // Shere1
52  for (int i = 0 ; i < 3 ; i++)
53  {p1.get(i) = 2.0;}
54 
55  // Shere2
56  for (int i = 0 ; i < 3 ; i++)
57  {p2.get(i) = 1.0;}
58 
59  // Shere3
60  for (int i = 0 ; i < 3 ; i++)
61  {p3.get(i) = 0.5;}
62 
63  Sphere<3,double> sph1(p1,0.3);
64  Sphere<3,double> sph2(p2,0.3);
65  Sphere<3,double> sph3(p3,0.3);
66 
67  Point<3,double> u({1.0,1.0,1.0});
68  Box<3,double> channel_box(p3,p1);
69 
70  double spacing_x = grid.spacing(0);
71  double spacing_y = grid.spacing(1);
72  double spacing_z = grid.spacing(2);
73 
74  typedef typename GetAddBlockType<sgrid_type>::type InsertBlockT;
75 
76  grid.addPoints([spacing_x,spacing_y,spacing_z,u,sph1,sph2,sph3,channel_box] __device__ (int i, int j, int k)
77  {
78  Point<3,double> pc({i*spacing_x,j*spacing_y,k*spacing_z});
79  Point<3,double> vp;
80 
81  // calculate the distance from the diagonal
82  vp.get(0) = pc.get(1)*u.get(2) - pc.get(2)*u.get(1);
83  vp.get(1) = pc.get(2)*u.get(0) - pc.get(0)*u.get(2);
84  vp.get(2) = pc.get(0)*u.get(1) - pc.get(1)*u.get(0);
85 
86  double distance = vp.norm() / sqrt(3.0f);
87 
88  // Check if the point is in the domain
89  if (sph1.isInside(pc) || sph2.isInside(pc) || sph3.isInside(pc) || (distance < 0.1 && channel_box.isInside(pc)) )
90  {return true;}
91 
92  return false;
93  },
94  [] __device__ (InsertBlockT & data, int i, int j, int k)
95  {
96  data.template get<U>() = 1.0;
97  data.template get<V>() = 0.0;
98  }
99  );
100 
101 
102  grid.template flush<smax_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
103 
104  long int x_start = grid.size(0)*1.95f/domain.getHigh(0);
105  long int y_start = grid.size(1)*1.95f/domain.getHigh(1);
106  long int z_start = grid.size(1)*1.95f/domain.getHigh(2);
107 
108  long int x_stop = grid.size(0)*2.05f/domain.getHigh(0);
109  long int y_stop = grid.size(1)*2.05f/domain.getHigh(1);
110  long int z_stop = grid.size(1)*2.05f/domain.getHigh(2);
111 
112  grid_key_dx<3> start({x_start,y_start,z_start});
113  grid_key_dx<3> stop ({x_stop,y_stop,z_stop});
114 
115  grid.addPoints(start,stop,[] __device__ (int i, int j, int k)
116  {
117  return true;
118  },
119  [] __device__ (InsertBlockT & data, int i, int j, int k)
120  {
121  data.template get<U>() = 0.5;
122  data.template get<V>() = 0.24;
123  }
124  );
125 
126  grid.template flush<smin_<U>,smax_<V>>(flush_type::FLUSH_ON_DEVICE);
127 }
128 
129 
130 int main(int argc, char* argv[])
131 {
132  openfpm_init(&argc,&argv);
133 
134  // domain
135  Box<3,double> domain({0.0,0.0,0.0},{2.5,2.5,2.5});
136 
137  // grid size
138  size_t sz[3] = {256,256,256};
139 
140  // Define periodicity of the grid
141  periodicity<3> bc = {PERIODIC,PERIODIC,PERIODIC};
142 
143  // Ghost in grid unit
144  Ghost<3,long int> g(1);
145 
146  // deltaT
147  double deltaT = 0.1;
148 
149  // Diffusion constant for specie U
150  double du = 2*1e-5;
151 
152  // Diffusion constant for specie V
153  double dv = 1*1e-5;
154 
155 #ifdef TEST_RUN
156  // Number of timesteps
157  size_t timeSteps = 300;
158 #else
159  // Number of timesteps
160  size_t timeSteps = 150000;
161 #endif
162 
163  // K and F (Physical constant in the equation)
164  double K = 0.053;
165  double F = 0.014;
166 
167  sgrid_type grid(sz,domain,g,bc);
168 
169  grid.template setBackgroundValue<0>(-0.5);
170  grid.template setBackgroundValue<1>(-0.5);
171  grid.template setBackgroundValue<2>(-0.5);
172  grid.template setBackgroundValue<3>(-0.5);
173 
174  // spacing of the grid on x and y
175  double spacing[3] = {grid.spacing(0),grid.spacing(1),grid.spacing(2)};
176 
177  init(grid,domain);
178 
179  // sync the ghost
180  grid.template ghost_get<U,V>(RUN_ON_DEVICE);
181 
182  // because we assume that spacing[x] == spacing[y] we use formula 2
183  // and we calculate the prefactor of Eq 2
184  double uFactor = deltaT * du/(spacing[0]*spacing[0]);
185  double vFactor = deltaT * dv/(spacing[0]*spacing[0]);
186 
187  grid.template deviceToHost<U,V>();
188  grid.write("Init_condition");
189 
190  timer tot_sim;
191  tot_sim.start();
192 
193  for (size_t i = 0; i < timeSteps; ++i)
194  {
196 
197  typedef typename GetCpBlockType<decltype(grid),0,1>::type CpBlockType;
198 
199  auto func = [uFactor,vFactor,deltaT,F,K] __device__ (double & u_out, double & v_out,
200  CpBlockType & u, CpBlockType & v,
201  int i, int j, int k){
202 
203  double uc = u(i,j,k);
204  double vc = v(i,j,k);
205 
206  double u_px = u(i+1,j,k);
207  double u_mx = u(i-1,j,k);
208 
209  double u_py = u(i,j+1,k);
210  double u_my = u(i,j-1,k);
211 
212  double u_pz = u(i,j,k+1);
213  double u_mz = u(i,j,k-1);
214 
215  double v_px = v(i+1,j,k);
216  double v_mx = v(i-1,j,k);
217 
218  double v_py = v(i,j+1,k);
219  double v_my = v(i,j-1,k);
220 
221  double v_pz = v(i,j,k+1);
222  double v_mz = v(i,j,k-1);
223 
224  // U fix
225 
226  if (u_mx < -0.1 && u_px < -0.1)
227  {
228  u_mx = uc;
229  u_px = uc;
230  }
231 
232  if (u_mx < -0.1)
233  {u_mx = u_px;}
234 
235  if (u_px < -0.1)
236  {u_px = u_mx;}
237 
238  if (u_my < -0.1 && u_py < -0.1)
239  {
240  u_my = uc;
241  u_py = uc;
242  }
243 
244  if (u_my < -0.1)
245  {u_my = u_py;}
246 
247  if (u_py < -0.1)
248  {u_py = u_my;}
249 
250  if (u_mz < -0.1 && u_pz < -0.1)
251  {
252  u_mz = uc;
253  u_pz = uc;
254  }
255 
256  if (u_mz < -0.1)
257  {u_mz = u_pz;}
258 
259  if (u_pz < -0.1)
260  {u_pz = u_mz;}
261 
262  // V fix
263 
264  if (v_mx < -0.1 && v_px < -0.1)
265  {
266  v_mx = uc;
267  v_px = uc;
268  }
269 
270  if (v_mx < -0.1)
271  {v_mx = v_px;}
272 
273  if (v_px < -0.1)
274  {v_px = v_mx;}
275 
276  if (v_my < -0.1 && v_py < -0.1)
277  {
278  v_my = uc;
279  v_py = uc;
280  }
281 
282  if (v_my < -0.1)
283  {v_my = v_py;}
284 
285  if (v_py < -0.1)
286  {v_py = v_my;}
287 
288  if (v_mz < -0.1 && v_pz < -0.1)
289  {
290  v_mz = uc;
291  v_pz = uc;
292  }
293 
294  if (v_mz < -0.1)
295  {v_mz = v_pz;}
296 
297  if (v_pz < -0.1)
298  {v_pz = v_mz;}
299 
300  u_out = uc + uFactor *(u_mx + u_px +
301  u_my + u_py +
302  u_mz + u_pz - 6.0*uc) - deltaT * uc*vc*vc
303  - deltaT * F * (uc - 1.0);
304 
305 
306  v_out = vc + vFactor *(v_mx + v_px +
307  v_py + v_my +
308  v_mz + v_pz - 6.0*vc) + deltaT * uc*vc*vc
309  - deltaT * (F+K) * vc;
310 
311  };
312 
313 
314  if (i % 2 == 0)
315  {
316  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);
317 
318  // After copy we synchronize again the ghost part U and V
319 
320  grid.ghost_get<U_next,V_next>(RUN_ON_DEVICE | SKIP_LABELLING);
321  }
322  else
323  {
324  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);
325 
326  // After copy we synchronize again the ghost part U and V
327  grid.ghost_get<U,V>(RUN_ON_DEVICE | SKIP_LABELLING);
328  }
329 
331 
332  // After copy we synchronize again the ghost part U and V
333 
334  // Every 500 time step we output the configuration for
335  // visualization
336 /* if (i % 500 == 0)
337  {
338  grid.save("output_" + std::to_string(count));
339  count++;
340  }*/
341 
342  std::cout << "STEP: " << i << std::endl;
343 /* if (i % 300 == 0)
344  {
345  grid.template deviceToHost<U,V>();
346  grid.write_frame("out",i);
347  }*/
348  }
349 
350  tot_sim.stop();
351  std::cout << "Total simulation: " << tot_sim.getwct() << std::endl;
352 
353  grid.template deviceToHost<U,V>();
354  grid.write("Final");
355 
357 
369 
371  openfpm_finalize();
372 
374 
383 }
384 
385 #else
386 
387 int main(int argc, char* argv[])
388 {
389  return 0;
390 }
391 
392 #endif
393 
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
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
This is a distributed grid.
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition: Point.hpp:172
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
This class represent an N-dimensional box.
Definition: Box.hpp:60
get the type of the block
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]