OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
main_cpu.cpp
1 #include "Vector/vector_dist.hpp"
2 #include "Plot/GoogleChart.hpp"
3 #include "Plot/util.hpp"
4 #include "timer.hpp"
5 
6 #ifdef TEST_RUN
7 size_t nstep = 100;
8 #else
9 size_t nstep = 1000;
10 #endif
11 
12 typedef float real_number;
13 
14 constexpr int velocity = 0;
15 constexpr int force = 1;
16 
17 
18 template<typename CellList> void calc_forces(vector_dist<3,real_number, aggregate<real_number[3],real_number[3]> > & vd, CellList & NN, real_number sigma12, real_number sigma6, real_number r_cut2)
19 {
20  vd.updateCellList(NN);
21 
22  // Get an iterator over particles
23  auto it2 = vd.getDomainIterator();
24 
25  // For each particle p ...
26  while (it2.isNext())
27  {
28  // ... get the particle p
29  auto p = it2.get();
30 
31  // Get the position xp of the particle
32  Point<3,real_number> xp = vd.getPos(p);
33 
34  // Reset the force counter
35  vd.template getProp<force>(p)[0] = 0.0;
36  vd.template getProp<force>(p)[1] = 0.0;
37  vd.template getProp<force>(p)[2] = 0.0;
38 
39  // Get an iterator over the neighborhood particles of p
40  auto Np = NN.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(p)));
41 
42  // For each neighborhood particle ...
43  while (Np.isNext())
44  {
45  // ... q
46  auto q = Np.get();
47 
48  // if (p == q) skip this particle
49  if (q == p.getKey()) {++Np; continue;};
50 
51  // Get the position of p
52  Point<3,real_number> xq = vd.getPos(q);
53 
54  // Get the distance between p and q
55  Point<3,real_number> r = xp - xq;
56 
57  // take the norm of this vector
58  real_number rn = norm2(r);
59 
60  if (rn > r_cut2)
61  {++Np; continue;};
62 
63  // Calculate the force, using pow is slower
64  Point<3,real_number> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) - sigma6 / (rn*rn*rn*rn)) * r;
65 
66  // we sum the force produced by q on p
67  vd.template getProp<force>(p)[0] += f.get(0);
68  vd.template getProp<force>(p)[1] += f.get(1);
69  vd.template getProp<force>(p)[2] += f.get(2);
70 
71  // Next neighborhood
72  ++Np;
73  }
74 
75  // Next particle
76  ++it2;
77  }
78 }
79 
80 template<typename CellList> real_number calc_energy(vector_dist<3,real_number, aggregate<real_number[3],real_number[3]> > & vd, CellList & NN, real_number sigma12, real_number sigma6, real_number r_cut2)
81 {
82  real_number rc = r_cut2;
83  real_number shift = 2.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
84 
85  real_number E = 0.0;
86 
87  // Get the iterator
88  auto it2 = vd.getDomainIterator();
89 
90  // For each particle ...
91  while (it2.isNext())
92  {
93  // ... p
94  auto p = it2.get();
95 
96  // Get the position of the particle p
97  Point<3,real_number> xp = vd.getPos(p);
98 
99  // Get an iterator over the neighborhood of the particle p
100  auto Np = NN.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(p)));
101 
102  // For each neighborhood of the particle p
103  while (Np.isNext())
104  {
105  // Neighborhood particle q
106  auto q = Np.get();
107 
108  // if p == q skip this particle
109  if (q == p.getKey()) {++Np; continue;};
110 
111  // Get position of the particle q
112  Point<3,real_number> xq = vd.getPos(q);
113 
114  // take the normalized direction
115  real_number rn = norm2(xp - xq);
116 
117  if (rn > r_cut2)
118  {++Np;continue;}
119 
120  // potential energy (using pow is slower)
121  E += 2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
122 
123  // Next neighborhood
124  ++Np;
125  }
126 
127  // Kinetic energy of the particle given by its actual speed
128  E += (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
129  vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
130  vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
131 
132  // Next Particle
133  ++it2;
134  }
135 
136  return E;
137 }
138 
140 
141 int main(int argc, char* argv[])
142 {
143  openfpm_init(&argc,&argv);
144 
145  real_number sigma = 0.01;
146  real_number r_cut = 3.0*sigma;
147 
148  // we will use it do place particles on a 10x10x10 Grid like
149  size_t sz[3] = {100,100,100};
150 
151  // domain
152  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
153 
154  // Boundary conditions
155  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
156 
157  // ghost, big enough to contain the interaction radius
158  Ghost<3,float> ghost(r_cut);
159 
160  real_number dt = 0.00005;
161  real_number sigma12 = pow(sigma,12);
162  real_number sigma6 = pow(sigma,6);
163 
166 
168 
169  // We create the grid iterator
170  auto it = vd.getGridIterator(sz);
171 
172  while (it.isNext())
173  {
174  // Create a new particle
175  vd.add();
176 
177  // key contain (i,j,k) index of the grid
178  auto key = it.get();
179 
180  // The index of the grid can be accessed with key.get(0) == i, key.get(1) == j ...
181  // We use getLastPos to set the position of the last particle added
182  vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
183  vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
184  vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
185 
186  // We use getLastProp to set the property value of the last particle we added
187  vd.template getLastProp<velocity>()[0] = 0.0;
188  vd.template getLastProp<velocity>()[1] = 0.0;
189  vd.template getLastProp<velocity>()[2] = 0.0;
190 
191  vd.template getLastProp<force>()[0] = 0.0;
192  vd.template getLastProp<force>()[1] = 0.0;
193  vd.template getLastProp<force>()[2] = 0.0;
194 
195  ++it;
196  }
197 
198  vd.map();
199  vd.ghost_get<>();
200 
201  timer tsim;
202  tsim.start();
203 
205 
206  // Get the Cell list structure
207  auto NN = vd.getCellList(r_cut);
208 
209  // The standard
210  // auto NN = vd.getCellList(r_cut);
211 
212  // calculate forces
213  calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
214  unsigned long int f = 0;
215 
216  // MD time stepping
217  for (size_t i = 0; i < nstep ; i++)
218  {
219  timer t_s;
220  t_s.start();
221 
222  // Get the iterator
223  auto it3 = vd.getDomainIterator();
224 
225  // integrate velicity and space based on the calculated forces (Step1)
226  while (it3.isNext())
227  {
228  auto p = it3.get();
229 
230  // here we calculate v(tn + 0.5)
231  vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
232  vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
233  vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
234 
235  // here we calculate x(tn + 1)
236  vd.getPos(p)[0] += vd.template getProp<velocity>(p)[0]*dt;
237  vd.getPos(p)[1] += vd.template getProp<velocity>(p)[1]*dt;
238  vd.getPos(p)[2] += vd.template getProp<velocity>(p)[2]*dt;
239 
240  ++it3;
241  }
242 
243  // Because we moved the particles in space we have to map them and re-sync the ghost
244  vd.map();
245  vd.template ghost_get<>();
246 
247  // calculate forces or a(tn + 1) Step 2
248  calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
249 
250 
251  // Integrate the velocity Step 3
252  auto it4 = vd.getDomainIterator();
253 
254  while (it4.isNext())
255  {
256  auto p = it4.get();
257 
258  // here we calculate v(tn + 1)
259  vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
260  vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
261  vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
262 
263  ++it4;
264  }
265 
266  // After every iteration collect some statistic about the configuration
267  if (i % 500 == 0)
268  {
269  // We write the particle position for visualization (Without ghost)
270  vd.deleteGhost();
271  vd.write("particles_",f);
272 
273  // we resync the ghost
274  vd.ghost_get<>();
275 
276  // We calculate the energy
277  real_number energy = calc_energy(vd,NN,sigma12,sigma6,r_cut*r_cut);
278  auto & vcl = create_vcluster();
279  vcl.sum(energy);
280  vcl.execute();
281 
282  // we save the energy calculated at time step i c contain the time-step y contain the energy
283  x.add(i);
284  y.add({energy});
285 
286  // We also print on terminal the value of the energy
287  // only one processor (master) write on terminal
288  if (vcl.getProcessUnitID() == 0)
289  std::cout << "Energy: " << energy << std::endl;
290 
291  f++;
292  }
293 
294  t_s.stop();
295 
296  if (i % 100 == 0)
297  {
298  // resort the particle for better cache efficency
299  vd.reorder(5,reorder_opt::LINEAR);
300  }
301  }
302 
303  tsim.stop();
304  std::cout << "Time: " << tsim.getwct() << std::endl;
305 
306  // Google charts options, it store the options to draw the X Y graph
307  GCoptions options;
308 
309  // Title of the graph
310  options.title = std::string("Energy with time");
311 
312  // Y axis name
313  options.yAxis = std::string("Energy");
314 
315  // X axis name
316  options.xAxis = std::string("iteration");
317 
318  // width of the line
319  options.lineWidth = 1.0;
320 
321  // Resolution in x
322  options.width = 1280;
323 
324  // Resolution in y
325  options.heigh = 720;
326 
327  // Add zoom capability
328  options.more = GC_ZOOM;
329 
330  // Object that draw the X Y graph
331  GoogleChart cg;
332 
333  // Add the graph
334  // The graph that it produce is in svg format that can be opened on browser
335  cg.AddLinesGraph(x,y,options);
336 
337  // Write into html format
338  cg.write("gc_plot2_out.html");
339 
340  openfpm_finalize();
341 }
342 
343 
344 
345 
size_t heigh
height of the graph in pixels
Definition: GoogleChart.hpp:49
void AddLinesGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y, const GCoptions &opt)
Add a simple lines graph.
std::string title
Title of the chart.
Definition: GoogleChart.hpp:28
std::string more
more
Definition: GoogleChart.hpp:67
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
std::string yAxis
Y axis name.
Definition: GoogleChart.hpp:30
Small class to produce graph with Google chart in HTML.
void start()
Start the timer.
Definition: timer.hpp:90
size_t lineWidth
Width of the line.
Definition: GoogleChart.hpp:56
void write(std::string file)
It write the graphs on file in html format using Google charts.
size_t width
width of the graph in pixels
Definition: GoogleChart.hpp:46
Distributed vector.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:214
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:202
Class for FAST cell list implementation.
Definition: CellList.hpp:356
std::string xAxis
X axis name.
Definition: GoogleChart.hpp:32
Google chart options.
Definition: GoogleChart.hpp:25
Class for cpu time benchmarking.
Definition: timer.hpp:27
void stop()
Stop the timer.
Definition: timer.hpp:119