OpenFPM  5.2.0
Project that contain the implementation of distributed structures
main.cu
1 
73 #ifdef __NVCC__
74 
75 #include "Vector/vector_dist.hpp"
76 #include "Plot/GoogleChart.hpp"
77 #include "Plot/util.hpp"
78 #include "timer.hpp"
79 
80 #ifdef TEST_RUN
81 size_t nstep = 100;
82 #else
83 size_t nstep = 1000;
84 #endif
85 
86 typedef float real_number;
87 
89 
90 constexpr int velocity = 0;
91 constexpr int force = 1;
92 constexpr int energy = 2;
93 
95 
96 template<typename vector_dist_type,typename NN_type>
97 __global__ void calc_force_gpu(vector_dist_type vd, NN_type NN, real_number sigma12, real_number sigma6, real_number r_cut2)
98 {
99  auto p = GET_PARTICLE(vd);
100 
101  // Get the position xp of the particle
102  Point<3,real_number> xp = vd.getPos(p);
103 
104  // Reset the force counter
105  vd.template getProp<force>(p)[0] = 0.0;
106  vd.template getProp<force>(p)[1] = 0.0;
107  vd.template getProp<force>(p)[2] = 0.0;
108 
109 
110 
111  // Get an iterator over the neighborhood particles of p
112  auto Np = NN.getNNIteratorBox(NN.getCell(vd.getPos(p)));
113 
114  // For each neighborhood particle ...
115  while (Np.isNext())
116  {
117  // ... q
118  auto q = Np.get();
119 
120  // if (p == q) skip this particle
121  if (q == p) {++Np; continue;};
122 
123  // Get the position of p
124  Point<3,real_number> xq = vd.getPos(q);
125 
126  // Get the distance between p and q
127  Point<3,real_number> r = xp - xq;
128 
129  // take the norm of this vector
130  real_number rn = norm2(r);
131 
132  if (rn > r_cut2)
133  {++Np; continue;};
134 
135  // Calculate the force, using pow is slower
136  Point<3,real_number> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) - sigma6 / (rn*rn*rn*rn)) * r;
137 
138  // we sum the force produced by q on p
139  vd.template getProp<force>(p)[0] += f.get(0);
140  vd.template getProp<force>(p)[1] += f.get(1);
141  vd.template getProp<force>(p)[2] += f.get(2);
142 
143  // Next neighborhood
144  ++Np;
145  }
146 }
147 
149 
150 template<typename vector_dist_type>
151 __global__ void update_velocity_position(vector_dist_type vd, real_number dt)
152 {
153  auto p = GET_PARTICLE(vd);
154 
155  // here we calculate v(tn + 0.5)
156  vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
157  vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
158  vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
159 
160  // here we calculate x(tn + 1)
161  vd.getPos(p)[0] += vd.template getProp<velocity>(p)[0]*dt;
162  vd.getPos(p)[1] += vd.template getProp<velocity>(p)[1]*dt;
163  vd.getPos(p)[2] += vd.template getProp<velocity>(p)[2]*dt;
164 }
165 
166 template<typename vector_dist_type>
167 __global__ void update_velocity(vector_dist_type vd, real_number dt)
168 {
169  auto p = GET_PARTICLE(vd);
170 
171  // here we calculate v(tn + 1)
172  vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
173  vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
174  vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
175 }
176 
178 
180 
181 template<typename vector_dist_type,typename NN_type>
182 __global__ void particle_energy(vector_dist_type vd, NN_type NN, real_number sigma12, real_number sigma6, real_number shift, real_number r_cut2)
183 {
184  auto p = GET_PARTICLE(vd);
185 
186  // Get the position of the particle p
187  Point<3,real_number> xp = vd.getPos(p);
188 
189  // Get an iterator over the neighborhood of the particle p
190  auto Np = NN.getNNIteratorBox(NN.getCell(vd.getPos(p)));
191 
192  real_number E = 0;
193 
194  // For each neighborhood of the particle p
195  while (Np.isNext())
196  {
197  // Neighborhood particle q
198  auto q = Np.get();
199 
200  // if p == q skip this particle
201  if (q == p) {++Np; continue;};
202 
203  // Get position of the particle q
204  Point<3,real_number> xq = vd.getPos(q);
205 
206  // take the normalized direction
207  real_number rn = norm2(xp - xq);
208 
209  if (rn > r_cut2)
210  {++Np;continue;}
211 
212  // potential energy (using pow is slower)
213  E += 2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
214 
215  // Next neighborhood
216  ++Np;
217  }
218 
219  // Kinetic energy of the particle given by its actual speed
220  vd.template getProp<energy>(p) = E + (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
221  vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
222  vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
223 }
224 
226 
228 
229 template<typename CellList> void calc_forces(vector_dist_gpu<3,real_number, aggregate<real_number[3],real_number[3],real_number> > & vd, CellList & NN, real_number sigma12, real_number sigma6, real_number r_cut2)
230 {
231  vd.updateCellListGPU(NN);
232 
233  // Get an iterator over particles
234  auto it2 = vd.getDomainIteratorGPU();
235 
236  CUDA_LAUNCH(calc_force_gpu,it2,vd.toKernel(),NN.toKernel(),sigma12,sigma6,r_cut2);
237 }
238 
240 
241 template<typename CellList> real_number calc_energy(vector_dist_gpu<3,real_number, aggregate<real_number[3],real_number[3],real_number> > & vd, CellList & NN, real_number sigma12, real_number sigma6, real_number r_cut2)
242 {
243  real_number rc = r_cut2;
244  real_number shift = 2.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
245 
246  vd.updateCellListGPU(NN);
247 
248  auto it2 = vd.getDomainIteratorGPU();
249 
250  CUDA_LAUNCH(particle_energy,it2,vd.toKernel(),NN.toKernel(),sigma12,sigma6,shift,r_cut2);
251 
253 
254  // Calculated energy
255  return reduce_local<energy,_add_>(vd);
256 
258 }
259 
260 int main(int argc, char* argv[])
261 {
262  openfpm_init(&argc,&argv);
263 
264  real_number sigma = 0.01;
265  real_number r_cut = 3.0*sigma;
266 
267  // we will use it do place particles on a 10x10x10 Grid like
268  size_t sz[3] = {100,100,100};
269 
270  // domain
271  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
272 
273  // Boundary conditions
274  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
275 
276  // ghost, big enough to contain the interaction radius
277  Ghost<3,float> ghost(r_cut);
278 
279  real_number dt = 0.00005;
280  real_number sigma12 = pow(sigma,12);
281  real_number sigma6 = pow(sigma,6);
282 
285 
287 
288  // We create the grid iterator
289  auto it = vd.getGridIterator(sz);
290 
291  while (it.isNext())
292  {
293  // Create a new particle
294  vd.add();
295 
296  // key contain (i,j,k) index of the grid
297  auto key = it.get();
298 
299  // The index of the grid can be accessed with key.get(0) == i, key.get(1) == j ...
300  // We use getLastPos to set the position of the last particle added
301  vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
302  vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
303  vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
304 
305  // We use getLastProp to set the property value of the last particle we added
306  vd.template getLastProp<velocity>()[0] = 0.0;
307  vd.template getLastProp<velocity>()[1] = 0.0;
308  vd.template getLastProp<velocity>()[2] = 0.0;
309 
310  vd.template getLastProp<force>()[0] = 0.0;
311  vd.template getLastProp<force>()[1] = 0.0;
312  vd.template getLastProp<force>()[2] = 0.0;
313 
314  ++it;
315  }
316 
317  vd.hostToDevicePos();
318  vd.hostToDeviceProp<velocity,force>();
319 
320  vd.map(RUN_ON_DEVICE);
321  vd.ghost_get<>(RUN_ON_DEVICE);
322 
323  timer tsim;
324  tsim.start();
325 
327 
328  // Get the Cell list structure
329  auto NN = vd.getCellListGPU(r_cut, CL_NON_SYMMETRIC, 2);
330 
331  // The standard
332  // auto NN = vd.getCellList(r_cut);
333 
334  // calculate forces
335  calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
336  unsigned long int f = 0;
337 
338  // MD time stepping
339  for (size_t i = 0; i < nstep ; i++)
340  {
341  // Get the iterator
342  auto it3 = vd.getDomainIteratorGPU();
343 
344  CUDA_LAUNCH(update_velocity_position,it3,vd.toKernel(),dt);
345 
347 
348  // Because we moved the particles in space we have to map them and re-sync the ghost
349  vd.map(RUN_ON_DEVICE);
350  vd.template ghost_get<>(RUN_ON_DEVICE);
351 
353 
354  // calculate forces or a(tn + 1) Step 2
355  calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
356 
357 
358  // Integrate the velocity Step 3
359  auto it4 = vd.getDomainIteratorGPU();
360 
361  CUDA_LAUNCH(update_velocity,it4,vd.toKernel(),dt);
362 
363  // After every iteration collect some statistic about the configuration
364  if (i % 100 == 0)
365  {
367 
368  vd.deviceToHostPos();
369  vd.deviceToHostProp<0,1,2>();
370 
371  // We write the particle position for visualization (Without ghost)
372  vd.deleteGhost();
373  vd.write_frame("particles_",f);
374 
376 
377  // we resync the ghost
378  vd.ghost_get<>(RUN_ON_DEVICE);
379 
380  // We calculate the energy
381  real_number energy = calc_energy(vd,NN,sigma12,sigma6,r_cut*r_cut);
382  auto & vcl = create_vcluster();
383  vcl.sum(energy);
384  vcl.execute();
385 
386  // we save the energy calculated at time step i c contain the time-step y contain the energy
387  x.add(i);
388  y.add({energy});
389 
390  // We also print on terminal the value of the energy
391  // only one processor (master) write on terminal
392  if (vcl.getProcessUnitID() == 0)
393  std::cout << "Energy: " << energy << std::endl;
394 
395  f++;
396  }
397  }
398 
400 
401  tsim.stop();
402  std::cout << "Time: " << tsim.getwct() << std::endl;
403 
404  // Google charts options, it store the options to draw the X Y graph
405  GCoptions options;
406 
407  // Title of the graph
408  options.title = std::string("Energy with time");
409 
410  // Y axis name
411  options.yAxis = std::string("Energy");
412 
413  // X axis name
414  options.xAxis = std::string("iteration");
415 
416  // width of the line
417  options.lineWidth = 1.0;
418 
419  // Resolution in x
420  options.width = 1280;
421 
422  // Resolution in y
423  options.heigh = 720;
424 
425  // Add zoom capability
426  options.more = GC_ZOOM;
427 
428  // Object that draw the X Y graph
429  GoogleChart cg;
430 
431  // Add the graph
432  // The graph that it produce is in svg format that can be opened on browser
433  cg.AddLinesGraph(x,y,options);
434 
435  // Write into html format
436  cg.write("gc_plot2_out.html");
437 
438  openfpm_finalize();
439 }
440 
441 #else
442 
443 int main(int argc, char* argv[])
444 {
445  return 0;
446 }
447 
448 #endif
449 
450 
Class for FAST cell list implementation.
Definition: CellList.hpp:558
Definition: Ghost.hpp:40
Small class to produce graph with Google chart in HTML.
void write(std::string file)
It write the graphs on file in html format using Google charts.
void AddLinesGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y, const GCoptions &opt)
Add a simple lines graph.
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:28
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:204
Class for cpu time benchmarking.
Definition: timer.hpp:28
void stop()
Stop the timer.
Definition: timer.hpp:119
void start()
Start the timer.
Definition: timer.hpp:90
double getwct()
Return the elapsed real time.
Definition: timer.hpp:130
Distributed vector.
bool write_frame(std::string out, size_t iteration, int opt=VTK_WRITER)
Output particle position and properties.
void deviceToHostPos()
Move the memory from the device to host memory.
grid_dist_id_iterator_dec< Decomposition > getGridIterator(const size_t(&sz)[dim])
auto getPos(vect_dist_key_dx vec_key) -> decltype(vPos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
void ghost_get(size_t opt=WITH_POSITION)
It synchronize the properties and position of the ghost particles.
void hostToDevicePos()
Move the memory from the device to host memory.
void map(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor.
void deviceToHostProp()
Move the memory from the device to host memory.
void add()
Add local particle.
void hostToDeviceProp()
Move the memory from the device to host memory.
void deleteGhost()
Delete the particles on the ghost.
auto getLastPos() -> decltype(vPos.template get< 0 >(0))
Get the position of the last element.
Google chart options.
Definition: GoogleChart.hpp:26
size_t width
width of the graph in pixels
Definition: GoogleChart.hpp:46
size_t heigh
height of the graph in pixels
Definition: GoogleChart.hpp:49
std::string xAxis
X axis name.
Definition: GoogleChart.hpp:32
size_t lineWidth
Width of the line.
Definition: GoogleChart.hpp:56
std::string more
more
Definition: GoogleChart.hpp:67
std::string title
Title of the chart.
Definition: GoogleChart.hpp:28
std::string yAxis
Y axis name.
Definition: GoogleChart.hpp:30
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:221