OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
main_vl.cpp
1
2#include "Vector/vector_dist.hpp"
3#include "Decomposition/CartDecomposition.hpp"
4#include "data_type/aggregate.hpp"
5#include "Plot/GoogleChart.hpp"
6#include "Plot/util.hpp"
7#include "timer.hpp"
8
29
30constexpr int velocity = 0;
31constexpr int force = 1;
32
34
62
64
65void calc_forces(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, VerletList<3, double, Mem_fast<>, shift<3, double> > & NN, double sigma12, double sigma6, double r_cut)
66{
68
69 // Get an iterator over particles
70 auto it2 = vd.getDomainIterator();
71
72 // For each particle p ...
73 while (it2.isNext())
74 {
75 // ... get the particle p
76 auto p = it2.get();
77
78 // Get the position xp of the particle
79 Point<3,double> xp = vd.getPos(p);
80
81 // Reset the forice counter
82 vd.template getProp<force>(p)[0] = 0.0;
83 vd.template getProp<force>(p)[1] = 0.0;
84 vd.template getProp<force>(p)[2] = 0.0;
85
87
88 // Get an iterator over the neighborhood particles of p
89 auto Np = NN.template getNNIterator<NO_CHECK>(p.getKey());
90
92
93 // For each neighborhood particle ...
94 while (Np.isNext())
95 {
96 // ... q
97 auto q = Np.get();
98
99 // if (p == q) skip this particle
100 if (q == p.getKey()) {++Np; continue;};
101
102 // Get the position of p
103 Point<3,double> xq = vd.getPos(q);
104
105 // Get the distance between p and q
106 Point<3,double> r = xp - xq;
107
108 // take the norm of this vector
109 double rn = norm2(r);
110
111 if (rn > r_cut * r_cut) {++Np;continue;}
112
113 // Calculate the force, using pow is slower
114 Point<3,double> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) - sigma6 / (rn*rn*rn*rn)) * r;
115
116 // we sum the force produced by q on p
117 vd.template getProp<force>(p)[0] += f.get(0);
118 vd.template getProp<force>(p)[1] += f.get(1);
119 vd.template getProp<force>(p)[2] += f.get(2);
120
121 // Next neighborhood
122 ++Np;
123 }
124
125 // Next particle
126 ++it2;
127 }
128}
129
131
152
153double calc_energy(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, VerletList<3, double, Mem_fast<>, shift<3, double> > & NN, double sigma12, double sigma6, double r_cut)
154{
155 double E = 0.0;
156
157 double rc = r_cut*r_cut;
158 double shift = 2.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
159
160 // Get the iterator
161 auto it2 = vd.getDomainIterator();
162
163 // For each particle ...
164 while (it2.isNext())
165 {
166 // ... p
167 auto p = it2.get();
168
169 // Get the position of the particle p
170 Point<3,double> xp = vd.getPos(p);
171
172 // Get an iterator over the neighborhood of the particle p
173 auto Np = NN.template getNNIterator<NO_CHECK>(p.getKey());
174
175 // For each neighborhood of the particle p
176 while (Np.isNext())
177 {
178 // Neighborhood particle q
179 auto q = Np.get();
180
181 // if p == q skip this particle
182 if (q == p.getKey()) {++Np; continue;};
183
184 // Get position of the particle q
185 Point<3,double> xq = vd.getPos(q);
186
187 // take the normalized direction
188 double rn = norm2(xp - xq);
189
190 if (rn >= r_cut*r_cut)
191 {++Np;continue;}
192
193 // potential energy (using pow is slower)
194 E += 2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
195
196 // Next neighborhood
197 ++Np;
198 }
199
200 // Kinetic energy of the particle given by its actual speed
201 E += (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
202 vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
203 vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
204
205 // Next Particle
206 ++it2;
207 }
208
209 // Calculated energy
210 return E;
211}
212
214
215int main(int argc, char* argv[])
216{
263
264 double dt = 0.00025;
265 double sigma = 0.1;
266 double r_cut = 3.0*sigma;
267 double r_gskin = 1.3*r_cut;
268 double sigma12 = pow(sigma,12);
269 double sigma6 = pow(sigma,6);
270
273
274 openfpm_init(&argc,&argv);
275 Vcluster<> & v_cl = create_vcluster();
276
277 // we will use it do place particles on a 10x10x10 Grid like
278 size_t sz[3] = {10,10,10};
279
280 // domain
281 Box<3,double> box({0.0,0.0,0.0},{1.0,1.0,1.0});
282
283 // Boundary conditions
284 size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
285
286 // ghost, big enough to contain the interaction radius
287 Ghost<3,double> ghost(r_gskin);
288
290
291 auto it = vd.getGridIterator(sz);
292
293 while (it.isNext())
294 {
295 vd.add();
296
297 auto key = it.get();
298
299 vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
300 vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
301 vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
302
303 vd.template getLastProp<velocity>()[0] = 0.0;
304 vd.template getLastProp<velocity>()[1] = 0.0;
305 vd.template getLastProp<velocity>()[2] = 0.0;
306
307 vd.template getLastProp<force>()[0] = 0.0;
308 vd.template getLastProp<force>()[1] = 0.0;
309 vd.template getLastProp<force>()[2] = 0.0;
310
311 ++it;
312 }
313
314 timer tsim;
315 tsim.start();
316
318
319 // Get the Cell list structure
320 auto NN = vd.getVerlet(r_gskin);
321
323
324 // calculate forces
325 calc_forces(vd,NN,sigma12,sigma6,r_cut);
326 unsigned long int f = 0;
327
328 int cnt = 0;
329 double max_disp = 0.0;
330
331 // MD time stepping
332 for (size_t i = 0; i < 10000 ; i++)
333 {
334 // Get the iterator
335 auto it3 = vd.getDomainIterator();
336
337 double max_displ = 0.0;
338
339 // integrate velicity and space based on the calculated forces (Step1)
340 while (it3.isNext())
341 {
342 auto p = it3.get();
343
344 // here we calculate v(tn + 0.5)
345 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
346 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
347 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
348
349 Point<3,double> disp({vd.template getProp<velocity>(p)[0]*dt,vd.template getProp<velocity>(p)[1]*dt,vd.template getProp<velocity>(p)[2]*dt});
350
351 // here we calculate x(tn + 1)
352 vd.getPos(p)[0] += disp.get(0);
353 vd.getPos(p)[1] += disp.get(1);
354 vd.getPos(p)[2] += disp.get(2);
355
356 if (disp.norm() > max_displ)
357 max_displ = disp.norm();
358
359 ++it3;
360 }
361
362 if (max_disp < max_displ)
363 max_disp = max_displ;
364
366
367 // Because we moved the particles in space we have to map them and re-sync the ghost
368 if (cnt % 10 == 0)
369 {
370 vd.map();
371 vd.template ghost_get<>();
372 // Get the Cell list structure
373 vd.updateVerlet(NN,r_gskin);
374 }
375 else
376 {
377 vd.template ghost_get<>(SKIP_LABELLING);
378 }
379
381
382 cnt++;
383
384 // calculate forces or a(tn + 1) Step 2
385 calc_forces(vd,NN,sigma12,sigma6,r_cut);
386
387 // Integrate the velocity Step 3
388 auto it4 = vd.getDomainIterator();
389
390 while (it4.isNext())
391 {
392 auto p = it4.get();
393
394 // here we calculate v(tn + 1)
395 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
396 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
397 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
398
399 ++it4;
400 }
401
402 // After every iteration collect some statistic about the confoguration
403 if (i % 100 == 0)
404 {
405 // We write the particle position for visualization (Without ghost)
406 vd.deleteGhost();
407 vd.write_frame("particles_",f);
408
409 // we resync the ghost
410 vd.ghost_get<>(SKIP_LABELLING);
411
412 // We calculate the energy
413 double energy = calc_energy(vd,NN,sigma12,sigma6,r_cut);
414 auto & vcl = create_vcluster();
415 vcl.sum(energy);
416 vcl.max(max_disp);
417 vcl.execute();
418
419 // we save the energy calculated at time step i c contain the time-step y contain the energy
420 x.add(i);
421 y.add({energy});
422
423 // We also print on terminal the value of the energy
424 // only one processor (master) write on terminal
425 if (vcl.getProcessUnitID() == 0)
426 std::cout << "Energy: " << energy << " " << max_disp << " " << std::endl;
427
428 max_disp = 0.0;
429
430 f++;
431 }
432 }
433
434 tsim.stop();
435 std::cout << "Time: " << tsim.getwct() << std::endl;
436
438
439 // Google charts options, it store the options to draw the X Y graph
440 GCoptions options;
441
442 // Title of the graph
443 options.title = std::string("Energy with time");
444
445 // Y axis name
446 options.yAxis = std::string("Energy");
447
448 // X axis name
449 options.xAxis = std::string("iteration");
450
451 // width of the line
452 options.lineWidth = 1.0;
453
454 // Object that draw the X Y graph
455 GoogleChart cg;
456
457 // Add the graph
458 // The graph that it produce is in svg format that can be opened on browser
459 cg.AddLinesGraph(x,y,options);
460
461 // Write into html format
462 cg.write("gc_plot2_out.html");
463
465
478
479 openfpm_finalize();
480
482}
This class represent an N-dimensional box.
Definition Box.hpp:61
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.
It is a class that work like a vector of vector.
Definition MemFast.hpp:89
This class implement the point shape in an N-dimensional space.
Definition Point.hpp:28
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition Point.hpp:172
Implementation of VCluster class.
Definition VCluster.hpp:59
Class for Verlet list implementation.
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.
std::string xAxis
X axis name.
size_t lineWidth
Width of the line.
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...