OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
main.cpp
1 #include "Grid/grid_dist_id.hpp"
2 #include "data_type/aggregate.hpp"
3 #include "timer.hpp"
4 
10 constexpr int U = 0;
11 constexpr int V = 1;
12 constexpr int phi = 2;
13 constexpr int normal = 3;
14 constexpr int tgrad_u = 4;
15 constexpr int tgrad_v = 5;
16 constexpr int U_next = 6;
17 constexpr int V_next = 7;
18 
19 constexpr int x = 0;
20 constexpr int y = 1;
21 constexpr int z = 2;
22 
24 
25 void init(sgrid_type & grid, Box<3,double> & domain)
26 {
28 
29  auto it = grid.getGridIterator();
30  Point<3,double> p1({0.5,0.5,0.5});
31 
32  double sx = grid.spacing(0);
33 
34  Sphere<3,double> sph1(p1,0.3);
35  Sphere<3,double> sph2(p1,0.3 - sx*10);
36  Sphere<3,double> sph_zero(p1,0.3 - sx*5);
37 
38  while (it.isNext())
39  {
40  // Get the local grid key
41  auto key = it.get_dist();
42  auto keyg = it.get();
43 
44  Point<3,double> pc;
45  Point<3,double> vp;
46 
47  for (int i = 0 ; i < 3 ; i++)
48  {pc.get(i) = keyg.get(i) * it.getSpacing(i);}
49 
50  // Check if the point is in the first sphere
51  if (sph1.isInside(pc) == true && sph2.isInside(pc) == false)
52  {
53  Point<3,double> pn = pc - p1;
54  pn /= pn.norm();
55  double theta = acos(pn * Point<3,double>({0.0,0.0,1.0}));
56  Point<3,double> pn_ = pn;
57  pn_[2] = 0.0;
58  pn_ /= pn_.norm();
59  double aphi = acos(pn_ * Point<3,double>({1.0,0.0,0.0}));
60 
61  // Create a perturbation in the solid angle
62  if (theta > 0.6 && theta < 0.8 && aphi > 0.0 && aphi < 0.2)
63  {
64  grid.template insert<U>(key) = 0.5;
65  grid.template insert<V>(key) = 0.25;
66  }
67  else
68  {
69  grid.template insert<U>(key) = 1.0;
70  grid.template insert<V>(key) = 0.0;
71  }
72  grid.template insert<phi>(key) = sph_zero.distance(pc);
73  grid.template insert<normal>(key)[0] = pn[0];
74  grid.template insert<normal>(key)[1] = pn[1];
75  grid.template insert<normal>(key)[2] = pn[2];
76 
77  // Old values U and V
78  grid.template insert<U_next>(key) = 0.0;
79  grid.template insert<V_next>(key) = 0.0;
80  }
81 
82  ++it;
83  }
84 
86 }
87 
88 template<unsigned int U_src,unsigned int V_src,unsigned int U_dst, unsigned int V_dst>
89 void extend(sgrid_type & grid)
90 {
91  double delta = 1e-10;
92  double max = 0.0;
93  auto it = grid.getDomainIterator();
94 
95  while (it.isNext())
96  {
97  // center point
98  auto Cp = it.get();
99 
100  // plus,minus X,Y,Z
101  auto mx = Cp.move(0,-1);
102  auto px = Cp.move(0,+1);
103  auto my = Cp.move(1,-1);
104  auto py = Cp.move(1,1);
105  auto mz = Cp.move(2,-1);
106  auto pz = Cp.move(2,1);
107 
108  double s = grid.get<phi>(Cp) / sqrt(fabs(grid.get<phi>(Cp)) + delta);
109 
110  double Uext = 0.0;
111  double Vext = 0.0;
112 
113  double dir = s*grid.get<normal>(Cp)[x];
114 
115  if (dir > 0)
116  {
117  Uext += dir * (grid.get<U_src>(Cp) - grid.get<U_src>(mx));
118  Vext += dir * (grid.get<V_src>(Cp) - grid.get<V_src>(mx));
119  }
120  else if (dir < 0)
121  {
122  Uext += dir * (grid.get<U_src>(px) - grid.get<U_src>(Cp));
123  Vext += dir * (grid.get<V_src>(px) - grid.get<V_src>(Cp));
124  }
125 
126 
127  dir = s*grid.get<normal>(Cp)[y];
128  if (dir > 0)
129  {
130  Uext += dir * (grid.get<U_src>(Cp) - grid.get<U_src>(my));
131  Vext += dir * (grid.get<V_src>(Cp) - grid.get<V_src>(my));
132  }
133  else if (dir < 0)
134  {
135  Uext += dir * (grid.get<U_src>(py) - grid.get<U_src>(Cp));
136  Vext += dir * (grid.get<V_src>(py) - grid.get<V_src>(Cp));
137  }
138 
139  dir = s*grid.get<normal>(Cp)[z];
140  if (dir > 0)
141  {
142  Uext += dir * (grid.get<U_src>(Cp) - grid.get<U_src>(mz));
143  Vext += dir * (grid.get<V_src>(Cp) - grid.get<V_src>(mz));
144  }
145  else if (dir < 0)
146  {
147  Uext += dir * (grid.get<U_src>(pz) - grid.get<U_src>(Cp));
148  Vext += dir * (grid.get<V_src>(pz) - grid.get<V_src>(Cp));
149  }
150 
151  if (Uext >= max)
152  {
153  max = Uext;
154  }
155 
156  grid.insert<U_dst>(Cp) = grid.get<U_src>(Cp) - 1.0*Uext;
157  grid.insert<V_dst>(Cp) = grid.get<V_src>(Cp) - 1.0*Vext;
158 
159  // Next point in the grid
160  ++it;
161  }
162 
163  std::cout << "UEX max: " << max << std::endl;
164 }
165 
166 int main(int argc, char* argv[])
167 {
168  openfpm_init(&argc,&argv);
169 
170  // domain
171  Box<3,double> domain({0.0,0.0,0.0},{2.5,2.5,2.5});
172 
173  // grid size
174  size_t sz[3] = {512,512,512};
175 
176  // Define periodicity of the grid
177  periodicity<3> bc = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
178 
179  // Ghost in grid unit
180  Ghost<3,long int> g(1);
181 
182  // deltaT
183  double deltaT = 0.3;
184 
185  // Diffusion constant for specie U
186  double du = 1*1e-5;
187 
188  // Diffusion constant for specie V
189  double dv = 0.5*1e-5;
190 
191 #ifdef TEST_RUN
192  // Number of timesteps
193  size_t timeSteps = 200;
194 #else
195  // Number of timesteps
196  size_t timeSteps = 150000;
197 #endif
198 
199  // K and F (Physical constant in the equation)
200  double K = 0.053;
201  double F = 0.014;
202 
203  sgrid_type grid(sz,domain,g,bc);
204 
205 
206  // spacing of the grid on x and y
207  double spacing[3] = {grid.spacing(0),grid.spacing(1),grid.spacing(2)};
208 
209  init(grid,domain);
210 
211  // sync the ghost
212  size_t count = 0;
213  grid.template ghost_get<U,V>();
214 
215  // because we assume that spacing[x] == spacing[y] we use formula 2
216  // and we calculate the prefactor of Eq 2
217  double uFactor = deltaT * du;
218  double vFactor = deltaT * dv;
219 
220  auto & v_cl = create_vcluster();
221 
222  timer tot_sim;
223  tot_sim.start();
224 
225  for (size_t i = 0; i < timeSteps ; ++i)
226  {
227  {
228  auto it = grid.getDomainIterator();
229 
230  while (it.isNext())
231  {
232  // center point
233  auto Cp = it.get();
234 
235  // plus,minus X,Y,Z
236  auto mx = Cp.move(0,-1);
237  auto px = Cp.move(0,+1);
238  auto my = Cp.move(1,-1);
239  auto py = Cp.move(1,1);
240  auto mz = Cp.move(2,-1);
241  auto pz = Cp.move(2,1);
242 
243  grid.insert<tgrad_u>(Cp)[0] = 0.0;
244  grid.insert<tgrad_u>(Cp)[1] = 0.0;
245  grid.insert<tgrad_u>(Cp)[2] = 0.0;
246  grid.insert<tgrad_v>(Cp)[0] = 0.0;
247  grid.insert<tgrad_v>(Cp)[1] = 0.0;
248  grid.insert<tgrad_v>(Cp)[2] = 0.0;
249 
251 
252  if (grid.existPoint(mz) == true && grid.existPoint(pz) == true &&
253  grid.existPoint(my) == true && grid.existPoint(py) == true &&
254  grid.existPoint(mx) == true && grid.existPoint(px) == true )
255  {
256  Point<3,double> gradU;
257  gradU[x] = (grid.get<U>(Cp) - grid.get<U>(mx)) / grid.spacing(0);
258  gradU[y] = (grid.get<U>(Cp) - grid.get<U>(my)) / grid.spacing(1);
259  gradU[z] = (grid.get<U>(Cp) - grid.get<U>(mz)) / grid.spacing(2);
260 
261  Point<3,double> gradV;
262  gradV[x] = (grid.get<V>(Cp) - grid.get<V>(mx)) / grid.spacing(0);
263  gradV[y] = (grid.get<V>(Cp) - grid.get<V>(my)) / grid.spacing(1);
264  gradV[z] = (grid.get<V>(Cp) - grid.get<V>(mz)) / grid.spacing(2);
265 
266  Point<3,double> PgradU;
267  Point<3,double> PgradV;
268 
269  PgradU.zero();
270  PgradV.zero();
271 
272  for (int i = 0 ; i < 3 ; i++)
273  {
274  for (int j = 0 ; j < 3 ; j++)
275  {
276  grid.insert<tgrad_u>(Cp)[i] += (((i == j)?1.0:0.0) - grid.get<normal>(Cp)[i]*grid.get<normal>(Cp)[j])*gradU[j];
277  grid.insert<tgrad_v>(Cp)[i] += (((i == j)?1.0:0.0) - grid.get<normal>(Cp)[i]*grid.get<normal>(Cp)[j])*gradV[j];
278  }
279  }
280  }
281  ++it;
282  }
283  }
284 
285 // Old.write_frame("Init_condition",i);
286 
287  {
288  auto it = grid.getDomainIterator();
289 
290  while (it.isNext())
291  {
292  // center point
293  auto Cp = it.get();
294 
295  // plus,minus X,Y,Z
296  auto mx = Cp.move(0,-1);
297  auto px = Cp.move(0,+1);
298  auto my = Cp.move(1,-1);
299  auto py = Cp.move(1,1);
300  auto mz = Cp.move(2,-1);
301  auto pz = Cp.move(2,1);
302 
304 
305  // Mirror z
306 
307  if (grid.existPoint(mz) == true && grid.existPoint(pz) == true &&
308  grid.existPoint(my) == true && grid.existPoint(py) == true &&
309  grid.existPoint(mx) == true && grid.existPoint(px) == true )
310  {
311  double lapU = 0;
312  double lapV = 0;
313 
314  //Div
315  lapU += (grid.get<tgrad_u>(px)[0] - grid.get<tgrad_u>(Cp)[0]) / grid.spacing(0);
316  lapV += (grid.get<tgrad_v>(px)[0] - grid.get<tgrad_v>(Cp)[0]) / grid.spacing(0);
317  lapU += (grid.get<tgrad_u>(py)[1] - grid.get<tgrad_u>(Cp)[1]) / grid.spacing(1);
318  lapV += (grid.get<tgrad_v>(py)[1] - grid.get<tgrad_v>(Cp)[1]) / grid.spacing(1);
319  lapU += (grid.get<tgrad_u>(pz)[2] - grid.get<tgrad_u>(Cp)[2]) / grid.spacing(2);
320  lapV += (grid.get<tgrad_v>(pz)[2] - grid.get<tgrad_v>(Cp)[2]) / grid.spacing(2);
321 
322  // update based on Eq 2
323  grid.insert<U_next>(Cp) = grid.get<U>(Cp) + uFactor * lapU +
324  - deltaT * grid.get<U>(Cp) * grid.get<V>(Cp) * grid.get<V>(Cp) +
325  - deltaT * F * (grid.get<U>(Cp) - 1.0);
326 
327 
328  // update based on Eq 2
329  grid.insert<V_next>(Cp) = grid.get<V>(Cp) + vFactor * lapV +
330  deltaT * grid.get<U>(Cp) * grid.get<V>(Cp) * grid.get<V>(Cp) +
331  - deltaT * (F+K) * grid.get<V>(Cp);
332  }
333 
334  // Next point in the grid
335  ++it;
336  }
337  }
338 
339 // New.write_frame("update",i);
340 
341  // Extend
342 
343  if (i % 5 == 0)
344  {
345  for (int j = 0 ; j < 2 ; j++)
346  {
347  if (j % 2 == 0)
348  {extend<U_next,V_next,U,V>(grid);}
349  else
350  {extend<U,V,U_next,V_next>(grid);}
351 
352  // Here we copy New into the old grid in preparation of the new step
353  // It would be better to alternate, but using this we can show the usage
354  // of the function copy. To note that copy work only on two grid of the same
355  // decomposition. If you want to copy also the decomposition, or force to be
356  // exactly the same, use Old = New
357  //New.copy_sparse(Old);
358  }
359  }
360 
361 /* auto it = grid.getDomainIterator();
362 
363  while (it.isNext())
364  {
365  // center point
366  auto Cp = it.get();
367 
368  // update based on Eq 2
369  grid.insert<U>(Cp) = grid.get<U_next>(Cp);
370  grid.insert<V>(Cp) = grid.get<V_next>(Cp);
371 
372  ++it;
373  }*/
374 
376 
377  // After copy we synchronize again the ghost part U and V
378  grid.ghost_get<U,V>();
379 
380  // Every 500 time step we output the configuration for
381  // visualization
382  if (i % 500 == 0)
383  {
384  grid.save("output_" + std::to_string(count));
385  count++;
386  }
387 
388  if (v_cl.rank() == 0)
389  {std::cout << "STEP: " << i << " " << std::endl;}
390  if (i % 100 == 0)
391  {
392  grid.write_frame("out",i);
393  }
394  }
395 
396  tot_sim.stop();
397  std::cout << "Total simulation: " << tot_sim.getwct() << std::endl;
398 
400 
412 
414  openfpm_finalize();
415 
417 
426 }
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
void start()
Start the timer.
Definition: timer.hpp:90
This class represent an N-dimensional box.
Definition: Box.hpp:60
__device__ __host__ void zero()
Set to zero the point coordinate.
Definition: Point.hpp:284
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
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]