OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
main.cpp
1
8#include "Vector/vector_dist.hpp"
9#include "Plot/GoogleChart.hpp"
10#include "Plot/util.hpp"
11#include "timer.hpp"
12
34
35constexpr int velocity = 0;
36constexpr int force = 1;
37
39
58
59template<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
78
79 vd.updateCellList(NN);
80
82
99
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.template getNNIterator<NO_CHECK>(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
178
179template<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
199
200 double E = 0.0;
201// vd.updateCellList(NN);
202
204
221
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.template getNNIterator<NO_CHECK>(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
281int main(int argc, char* argv[])
282{
301
302 openfpm_init(&argc,&argv);
303
304 double sigma = 0.1;
305 double r_cut = 3.0*sigma;
306
307 // we will use it do place particles on a 10x10x10 Grid like
308 size_t sz[3] = {10,10,10};
309
310 // domain
311 Box<3,double> box({0.0,0.0,0.0},{1.0,1.0,1.0});
312
313 // Boundary conditions
314 size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
315
316 // ghost, big enough to contain the interaction radius
317 Ghost<3,double> ghost(r_cut);
318
319 double dt = 0.0005;
320 double sigma12 = pow(sigma,12);
321 double sigma6 = pow(sigma,6);
322
325
327
341
343
345
361
362 // We create the grid iterator
363 auto it = vd.getGridIterator(sz);
364
365 while (it.isNext())
366 {
367 // Create a new particle
368 vd.add();
369
370 // key contain (i,j,k) index of the grid
371 auto key = it.get();
372
373 // The index of the grid can be accessed with key.get(0) == i, key.get(1) == j ...
374 // We use getLastPos to set the position of the last particle added
375 vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
376 vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
377 vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
378
379 // We use getLastProp to set the property value of the last particle we added
380 vd.template getLastProp<velocity>()[0] = 0.0;
381 vd.template getLastProp<velocity>()[1] = 0.0;
382 vd.template getLastProp<velocity>()[2] = 0.0;
383
384 vd.template getLastProp<force>()[0] = 0.0;
385 vd.template getLastProp<force>()[1] = 0.0;
386 vd.template getLastProp<force>()[2] = 0.0;
387
388 ++it;
389 }
390
391 vd.map();
392 vd.ghost_get<>();
393
395
435 timer tsim;
436 tsim.start();
437
439
440 // Get the Cell list structure
441 auto NN = vd.getCellList<CELL_MEMBAL(3,double)>(r_cut);
442
443 // The standard
444 // auto NN = vd.getCellList(r_cut);
445
446 // calculate forces
447 calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
448 unsigned long int f = 0;
449
450 // MD time stepping
451 for (size_t i = 0; i < 10000 ; i++)
452 {
453 // Get the iterator
454 auto it3 = vd.getDomainIterator();
455
456 // integrate velicity and space based on the calculated forces (Step1)
457 while (it3.isNext())
458 {
459 auto p = it3.get();
460
461 // here we calculate v(tn + 0.5)
462 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
463 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
464 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
465
466 // here we calculate x(tn + 1)
467 vd.getPos(p)[0] += vd.template getProp<velocity>(p)[0]*dt;
468 vd.getPos(p)[1] += vd.template getProp<velocity>(p)[1]*dt;
469 vd.getPos(p)[2] += vd.template getProp<velocity>(p)[2]*dt;
470
471 ++it3;
472 }
473
474 // Because we moved the particles in space we have to map them and re-sync the ghost
475 vd.map();
476 vd.template ghost_get<>();
477
478 // calculate forces or a(tn + 1) Step 2
479 calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
480
481 // Integrate the velocity Step 3
482 auto it4 = vd.getDomainIterator();
483
484 while (it4.isNext())
485 {
486 auto p = it4.get();
487
488 // here we calculate v(tn + 1)
489 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
490 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
491 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
492
493 ++it4;
494 }
495
496 // After every iteration collect some statistic about the configuration
497 if (i % 100 == 0)
498 {
499 // We write the particle position for visualization (Without ghost)
500 vd.deleteGhost();
501 vd.write_frame("particles_",f);
502
503 // we resync the ghost
504 vd.ghost_get<>();
505
506 // We calculate the energy
507 double energy = calc_energy(vd,NN,sigma12,sigma6,r_cut*r_cut);
508 auto & vcl = create_vcluster();
509 vcl.sum(energy);
510 vcl.execute();
511
512 // we save the energy calculated at time step i c contain the time-step y contain the energy
513 x.add(i);
514 y.add({energy});
515
516 // We also print on terminal the value of the energy
517 // only one processor (master) write on terminal
518 if (vcl.getProcessUnitID() == 0)
519 std::cout << "Energy: " << energy << std::endl;
520
521 f++;
522 }
523 }
524
526
527 tsim.stop();
528 std::cout << "Time: " << tsim.getwct() << std::endl;
529
546
547 // Google charts options, it store the options to draw the X Y graph
548 GCoptions options;
549
550 // Title of the graph
551 options.title = std::string("Energy with time");
552
553 // Y axis name
554 options.yAxis = std::string("Energy");
555
556 // X axis name
557 options.xAxis = std::string("iteration");
558
559 // width of the line
560 options.lineWidth = 1.0;
561
562 // Resolution in x
563 options.width = 1280;
564
565 // Resolution in y
566 options.heigh = 720;
567
568 // Add zoom capability
569 options.more = GC_ZOOM;
570
571 // Object that draw the X Y graph
572 GoogleChart cg;
573
574 // Add the graph
575 // The graph that it produce is in svg format that can be opened on browser
576 cg.AddLinesGraph(x,y,options);
577
578 // Write into html format
579 cg.write("gc_plot2_out.html");
580
582
595
596 openfpm_finalize();
597
599
621}
622
623
624
625
This class represent an N-dimensional box.
Definition Box.hpp:61
Class for FAST cell list implementation.
Definition CellList.hpp:357
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.
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.
Google chart options.
size_t width
width of the graph in pixels
size_t heigh
height of the graph in pixels
std::string xAxis
X axis name.
size_t lineWidth
Width of the line.
std::string more
more
std::string title
Title of the chart.
std::string yAxis
Y axis name.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...