OpenFPM  5.2.0
Project that contain the implementation of distributed structures
main.cpp
1 
8 #include "Vector/vector_dist.hpp"
9 #include "Plot/GoogleChart.hpp"
10 #include "Plot/util.hpp"
11 #include "timer.hpp"
12 
33 
35 constexpr int velocity = 0;
36 constexpr int force = 1;
37 
39 
57 
59 template<typename CellList> void calc_forces(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, CellList & NN, double sigma12, double sigma6, double r_cut2)
60 {
61 
63 
77 
79  vd.updateCellList(NN);
80 
82 
98 
100  // Get an iterator over particles
101  auto it2 = vd.getDomainIterator();
102 
103  // For each particle p ...
104  while (it2.isNext())
105  {
106  // ... get the particle p
107  auto p = it2.get();
108 
109  // Get the position xp of the particle
110  Point<3,double> xp = vd.getPos(p);
111 
112  // Reset the force counter
113  vd.template getProp<force>(p)[0] = 0.0;
114  vd.template getProp<force>(p)[1] = 0.0;
115  vd.template getProp<force>(p)[2] = 0.0;
116 
117  // Get an iterator over the neighborhood particles of p
118  auto Np = NN.getNNIteratorBox(NN.getCell(vd.getPos(p)));
119 
120  // For each neighborhood particle ...
121  while (Np.isNext())
122  {
123  // ... q
124  auto q = Np.get();
125 
126  // if (p == q) skip this particle
127  if (q == p.getKey()) {++Np; continue;};
128 
129  // Get the position of p
130  Point<3,double> xq = vd.getPos(q);
131 
132  // Get the distance between p and q
133  Point<3,double> r = xp - xq;
134 
135  // take the norm of this vector
136  double rn = norm2(r);
137 
138  if (rn > r_cut2)
139  {++Np; continue;};
140 
141  // Calculate the force, using pow is slower
142  Point<3,double> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) - sigma6 / (rn*rn*rn*rn)) * r;
143 
144  // we sum the force produced by q on p
145  vd.template getProp<force>(p)[0] += f.get(0);
146  vd.template getProp<force>(p)[1] += f.get(1);
147  vd.template getProp<force>(p)[2] += f.get(2);
148 
149  // Next neighborhood
150  ++Np;
151  }
152 
153  // Next particle
154  ++it2;
155  }
156 
158 
160 
161 }
162 
164 
177 
179 template<typename CellList> double calc_energy(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, CellList & NN, double sigma12, double sigma6, double r_cut2)
180 {
181  double rc = r_cut2;
182  double shift = 2.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
183 
185 
198 
200  double E = 0.0;
201 // vd.updateCellList(NN);
202 
204 
220 
222  // Get the iterator
223  auto it2 = vd.getDomainIterator();
224 
225  // For each particle ...
226  while (it2.isNext())
227  {
228  // ... p
229  auto p = it2.get();
230 
231  // Get the position of the particle p
232  Point<3,double> xp = vd.getPos(p);
233 
234  // Get an iterator over the neighborhood of the particle p
235  auto Np = NN.getNNIteratorBox(NN.getCell(vd.getPos(p)));
236 
237  // For each neighborhood of the particle p
238  while (Np.isNext())
239  {
240  // Neighborhood particle q
241  auto q = Np.get();
242 
243  // if p == q skip this particle
244  if (q == p.getKey()) {++Np; continue;};
245 
246  // Get position of the particle q
247  Point<3,double> xq = vd.getPos(q);
248 
249  // take the normalized direction
250  double rn = norm2(xp - xq);
251 
252  if (rn > r_cut2)
253  {++Np;continue;}
254 
255  // potential energy (using pow is slower)
256  E += 2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
257 
258  // Next neighborhood
259  ++Np;
260  }
261 
262  // Kinetic energy of the particle given by its actual speed
263  E += (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
264  vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
265  vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
266 
267  // Next Particle
268  ++it2;
269  }
270 
272 
274 
275  // Calculated energy
276  return E;
277 }
278 
280 
281 int main(int argc, char* argv[])
282 {
300 
302  openfpm_init(&argc,&argv);
303 
304  auto & v_cl = create_vcluster();
305  double sigma = 0.1;
306  double r_cut = 3.0*sigma;
307 
308  // we will use it do place particles on a 10x10x10 Grid like
309  size_t sz[3] = {50,50,50};
310 
311  // domain
312  Box<3,double> box({0.0,0.0,0.0},{1.0,1.0,1.0});
313 
314  // Boundary conditions
315  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
316 
317  // ghost, big enough to contain the interaction radius
318  Ghost<3,double> ghost(r_cut);
319 
320  double dt = 0.0005;
321  double sigma12 = pow(sigma,12);
322  double sigma6 = pow(sigma,6);
323 
326 
328 
341 
344 
346 
361 
363  // We create the grid iterator
364  if (v_cl.rank() == 0) {
365 
366  auto it = vd.getGridIterator(sz);
367 
368  while (it.isNext())
369  {
370  // Create a new particle
371  vd.add();
372 
373  // key contain (i,j,k) index of the grid
374  auto key = it.get();
375 
376  // The index of the grid can be accessed with key.get(0) == i, key.get(1) == j ...
377  // We use getLastPos to set the position of the last particle added
378  vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
379  vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
380  vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
381 
382  // We use getLastProp to set the property value of the last particle we added
383  vd.template getLastProp<velocity>()[0] = 0.0;
384  vd.template getLastProp<velocity>()[1] = 0.0;
385  vd.template getLastProp<velocity>()[2] = 0.0;
386 
387  vd.template getLastProp<force>()[0] = 0.0;
388  vd.template getLastProp<force>()[1] = 0.0;
389  vd.template getLastProp<force>()[2] = 0.0;
390 
391  ++it;
392  }
393 
394  std::cerr << "size local 1 " << vd.size_local() << std::endl;
395  }
396  vd.addComputationCosts();
397  vd.getDecomposition().decompose();
398  vd.map();
399  vd.ghost_get<>();
400 
401  std::cerr << "size local 2 " << vd.size_local() << std::endl;
403 
443  timer tsim;
444  tsim.start();
445 
447 
448  // Get the Cell list structure
449  auto NN = vd.getCellList<CELL_MEMBAL<3,double>>(r_cut);
450 
451  // The standard
452  // auto NN = vd.getCellList(r_cut);
453 
454  // calculate forces
455  calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
456  unsigned long int f = 0;
457 
458  // MD time stepping
459  for (size_t i = 0; i < 10000 ; i++)
460  {
461  // Get the iterator
462  auto it3 = vd.getDomainIterator();
463 
464  // integrate velicity and space based on the calculated forces (Step1)
465  while (it3.isNext())
466  {
467  auto p = it3.get();
468 
469  // here we calculate v(tn + 0.5)
470  vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
471  vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
472  vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
473 
474  // here we calculate x(tn + 1)
475  vd.getPos(p)[0] += vd.template getProp<velocity>(p)[0]*dt;
476  vd.getPos(p)[1] += vd.template getProp<velocity>(p)[1]*dt;
477  vd.getPos(p)[2] += vd.template getProp<velocity>(p)[2]*dt;
478 
479  ++it3;
480  }
481 
482  // Because we moved the particles in space we have to map them and re-sync the ghost
483  vd.map();
484  vd.template ghost_get<>();
485 
486  // calculate forces or a(tn + 1) Step 2
487  calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
488 
489  // Integrate the velocity Step 3
490  auto it4 = vd.getDomainIterator();
491 
492  while (it4.isNext())
493  {
494  auto p = it4.get();
495 
496  // here we calculate v(tn + 1)
497  vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
498  vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
499  vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
500 
501  ++it4;
502  }
503 
504  // After every iteration collect some statistic about the configuration
505  if (i % 100 == 0)
506  {
507  // We write the particle position for visualization (Without ghost)
508  vd.deleteGhost();
509  vd.write_frame("particles_",f);
510 
511  // we resync the ghost
512  vd.ghost_get<>();
513 
514  // We calculate the energy
515  double energy = calc_energy(vd,NN,sigma12,sigma6,r_cut*r_cut);
516  auto & vcl = create_vcluster();
517  vcl.sum(energy);
518  vcl.execute();
519 
520  // we save the energy calculated at time step i c contain the time-step y contain the energy
521  x.add(i);
522  y.add({energy});
523 
524  // We also print on terminal the value of the energy
525  // only one processor (master) write on terminal
526  if (vcl.getProcessUnitID() == 0)
527  std::cout << "Energy: " << energy << std::endl;
528 
529  f++;
530  }
531  }
532 
534 
535  tsim.stop();
536  std::cout << "Time: " << tsim.getwct() << std::endl;
537 
553 
555  // Google charts options, it store the options to draw the X Y graph
556  GCoptions options;
557 
558  // Title of the graph
559  options.title = std::string("Energy with time");
560 
561  // Y axis name
562  options.yAxis = std::string("Energy");
563 
564  // X axis name
565  options.xAxis = std::string("iteration");
566 
567  // width of the line
568  options.lineWidth = 1.0;
569 
570  // Resolution in x
571  options.width = 1280;
572 
573  // Resolution in y
574  options.heigh = 720;
575 
576  // Add zoom capability
577  options.more = GC_ZOOM;
578 
579  // Object that draw the X Y graph
580  GoogleChart cg;
581 
582  // Add the graph
583  // The graph that it produce is in svg format that can be opened on browser
584  cg.AddLinesGraph(x,y,options);
585 
586  // Write into html format
587  cg.write("gc_plot2_out.html");
588 
590 
602 
604  openfpm_finalize();
605 
607 
629 }
630 
631 
632 
633 
timer::stop
void stop()
Stop the timer.
Definition: timer.hpp:119
GCoptions::yAxis
std::string yAxis
Y axis name.
Definition: GoogleChart.hpp:30
GCoptions
Google chart options.
Definition: GoogleChart.hpp:25
GCoptions::xAxis
std::string xAxis
X axis name.
Definition: GoogleChart.hpp:32
GCoptions::width
size_t width
width of the graph in pixels
Definition: GoogleChart.hpp:46
GoogleChart
Small class to produce graph with Google chart in HTML.
Definition: GoogleChart.hpp:215
timer::getwct
double getwct()
Return the elapsed real time.
Definition: timer.hpp:130
timer
Class for cpu time benchmarking.
Definition: timer.hpp:27
aggregate
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:220
GoogleChart::AddLinesGraph
void AddLinesGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y, const GCoptions &opt)
Add a simple lines graph.
Definition: GoogleChart.hpp:886
GCoptions::lineWidth
size_t lineWidth
Width of the line.
Definition: GoogleChart.hpp:56
openfpm::vector
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:203
CellList
Class for FAST cell list implementation.
Definition: CellList.hpp:557
GCoptions::more
std::string more
more
Definition: GoogleChart.hpp:67
Box
This class represent an N-dimensional box.
Definition: Box.hpp:59
shift
Definition: CellDecomposer.hpp:27
GCoptions::heigh
size_t heigh
height of the graph in pixels
Definition: GoogleChart.hpp:49
vector_dist
Distributed vector.
Definition: vector_dist.hpp:170
timer::start
void start()
Start the timer.
Definition: timer.hpp:90
Point
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:27
GCoptions::title
std::string title
Title of the chart.
Definition: GoogleChart.hpp:28
Ghost
Definition: Ghost.hpp:39
GoogleChart::write
void write(std::string file)
It write the graphs on file in html format using Google charts.
Definition: GoogleChart.hpp:959