OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
main_cpu_best.cpp
1#include "Vector/vector_dist.hpp"
2#include "Decomposition/CartDecomposition.hpp"
3#include "data_type/aggregate.hpp"
4#include "Plot/GoogleChart.hpp"
5#include "Plot/util.hpp"
6#include "timer.hpp"
7
8#ifdef TEST_RUN
9size_t nstep = 100;
10#else
11size_t nstep = 1000;
12#endif
13
14typedef float real_number;
15
16constexpr int velocity = 0;
17constexpr int force = 1;
18
19
20template<typename VerletList>
21void calc_forces(vector_dist<3,real_number, aggregate<real_number[3],real_number[3]> > & vd, VerletList & NN, real_number sigma12, real_number sigma6, real_number r_cut)
22{
23 // Reset force on the ghost
24
25 auto itg = vd.getDomainAndGhostIterator();
26
27 while (itg.isNext())
28 {
29 auto p = itg.get();
30
31 // Reset force
32 vd.getProp<force>(p)[0] = 0.0;
33 vd.getProp<force>(p)[1] = 0.0;
34 vd.getProp<force>(p)[2] = 0.0;
35
36 ++itg;
37 }
38
40
41 // Get an iterator over particles
42 auto it2 = vd.getParticleIteratorCRS(NN);
43
45
46 // For each particle p ...
47 while (it2.isNext())
48 {
49 // ... get the particle p
50 auto p = it2.get();
51
52 // Get the position xp of the particle
53 Point<3,real_number> xp = vd.getPos(p);
54
55 // Get an iterator over the neighborhood particles of p
56 // Note that in case of symmetric
57 auto Np = NN.template getNNIterator<NO_CHECK>(p);
58
59 // For each neighborhood particle ...
60 while (Np.isNext())
61 {
62 // ... q
63 auto q = Np.get();
64
65 // if (p == q) skip this particle
66 if (q == p) {++Np; continue;};
67
68 // Get the position of q
69 Point<3,real_number> xq = vd.getPos(q);
70
71 // Get the distance between p and q
72 Point<3,real_number> r = xp - xq;
73
74 // take the norm of this vector
75 real_number rn = norm2(r);
76
77 if (rn > r_cut * r_cut) {++Np;continue;}
78
79 // Calculate the force, using pow is slower
80 Point<3,real_number> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) - sigma6 / (rn*rn*rn*rn)) * r;
81
82 // we sum the force produced by q on p
83 vd.template getProp<force>(p)[0] += f.get(0);
84 vd.template getProp<force>(p)[1] += f.get(1);
85 vd.template getProp<force>(p)[2] += f.get(2);
86
88
89 // we sum the force produced by p on q
90 vd.template getProp<force>(q)[0] -= f.get(0);
91 vd.template getProp<force>(q)[1] -= f.get(1);
92 vd.template getProp<force>(q)[2] -= f.get(2);
93
95
96 // Next neighborhood
97 ++Np;
98 }
99
100 // Next particle
101 ++it2;
102 }
103
104 // Sum the contribution to the real particles
105 vd.ghost_put<add_,force>();
106}
107
108
109template<typename VerletList>
110real_number calc_energy(vector_dist<3,real_number, aggregate<real_number[3],real_number[3]> > & vd, VerletList & NN, real_number sigma12, real_number sigma6, real_number r_cut)
111{
112 real_number E = 0.0;
113
114 real_number rc = r_cut*r_cut;
115 real_number shift = 4.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
116
117 // Get an iterator over particles
118 auto it2 = vd.getParticleIteratorCRS(NN);
119
120 // For each particle ...
121 while (it2.isNext())
122 {
123 // ... p
124 auto p = it2.get();
125
126 // Get the position of the particle p
127 Point<3,real_number> xp = vd.getPos(p);
128
129 // Get an iterator over the neighborhood particles of p
130 auto Np = NN.template getNNIterator<NO_CHECK>(p);
131
132 real_number Ep = E;
133
134 // For each neighborhood of the particle p
135 while (Np.isNext())
136 {
137 // Neighborhood particle q
138 auto q = Np.get();
139
140 // if p == q skip this particle
141 if (q == p) {++Np; continue;};
142
143 // Get position of the particle q
144 Point<3,real_number> xq = vd.getPos(q);
145
146 // take the normalized direction
147 real_number rn = norm2(xp - xq);
148
149 if (rn >= r_cut*r_cut) {++Np;continue;}
150
151 // potential energy (using pow is slower)
152 E += 4.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
153
154 // Next neighborhood
155 ++Np;
156 }
157
158 // To note that the crossing scheme go across the domain particles +
159 // some ghost particles. This mean that we have to filter out the ghost
160 // particles otherwise we count real_number energies
161 //
162 if (p < vd.size_local())
163 {
164 // Kinetic energy of the particle given by its actual speed
165 E += (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
166 vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
167 vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
168 }
169
170 // Next Particle
171 ++it2;
172 }
173
174 // Calculated energy
175 return E;
176}
177
178int main(int argc, char* argv[])
179{
180 real_number dt = 0.00005;
181 real_number sigma = 0.01;
182 real_number r_cut = 3.0*sigma;
183 real_number r_gskin = 1.3*r_cut;
184 real_number sigma12 = pow(sigma,12);
185 real_number sigma6 = pow(sigma,6);
186
189
190 openfpm_init(&argc,&argv);
191 Vcluster<> & v_cl = create_vcluster();
192
193 // we will use it do place particles on a 10x10x10 Grid like
194 size_t sz[3] = {100,100,100};
195
196 // domain
197 Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
198
199 // Boundary conditions
200 size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
201
202 // ghost, big enough to contain the interaction radius
203 Ghost<3,float> ghost(r_gskin);
204 ghost.setLow(0,0.0);
205 ghost.setLow(1,0.0);
206 ghost.setLow(2,0.0);
207
208 vector_dist<3,real_number, aggregate<real_number[3],real_number[3]> > vd(0,box,bc,ghost,BIND_DEC_TO_GHOST);
209
210 size_t k = 0;
211 size_t start = vd.accum();
212
213 auto it = vd.getGridIterator(sz);
214
215 while (it.isNext())
216 {
217 vd.add();
218
219 auto key = it.get();
220
221 vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
222 vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
223 vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
224
225 vd.template getLastProp<velocity>()[0] = 0.0;
226 vd.template getLastProp<velocity>()[1] = 0.0;
227 vd.template getLastProp<velocity>()[2] = 0.0;
228
229 vd.template getLastProp<force>()[0] = 0.0;
230 vd.template getLastProp<force>()[1] = 0.0;
231 vd.template getLastProp<force>()[2] = 0.0;
232
233 k++;
234 ++it;
235 }
236
237 vd.map();
238 vd.ghost_get<>();
239
240 timer tsim;
241 tsim.start();
242
243 // Get the Cell list structure
244 auto NN = vd.getVerletCrs(r_gskin);;
245
246 // calculate forces
247 calc_forces(vd,NN,sigma12,sigma6,r_cut);
248 unsigned long int f = 0;
249
250 int cnt = 0;
251 real_number max_disp = 0.0;
252
253 // MD time stepping
254 for (size_t i = 0; i < nstep ; i++)
255 {
256 // Get the iterator
257 auto it3 = vd.getDomainIterator();
258
259 real_number max_displ = 0.0;
260
261 // integrate velicity and space based on the calculated forces (Step1)
262 while (it3.isNext())
263 {
264 auto p = it3.get();
265
266 // here we calculate v(tn + 0.5)
267 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
268 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
269 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
270
271 Point<3,real_number> disp({vd.template getProp<velocity>(p)[0]*dt,vd.template getProp<velocity>(p)[1]*dt,vd.template getProp<velocity>(p)[2]*dt});
272
273 // here we calculate x(tn + 1)
274 vd.getPos(p)[0] += disp.get(0);
275 vd.getPos(p)[1] += disp.get(1);
276 vd.getPos(p)[2] += disp.get(2);
277
278 if (disp.norm() > max_displ)
279 max_displ = disp.norm();
280
281 ++it3;
282 }
283
284 if (max_disp < max_displ)
285 max_disp = max_displ;
286
287 // Because we moved the particles in space we have to map them and re-sync the ghost
288 if (cnt % 10 == 0)
289 {
290 vd.map();
291 vd.template ghost_get<>();
292 // Get the Cell list structure
293 vd.updateVerlet(NN,r_gskin,VL_CRS_SYMMETRIC);
294 }
295 else
296 {
297 vd.template ghost_get<>(SKIP_LABELLING);
298 }
299
300 cnt++;
301
302 // calculate forces or a(tn + 1) Step 2
303 calc_forces(vd,NN,sigma12,sigma6,r_cut);
304
305 // Integrate the velocity Step 3
306 auto it4 = vd.getDomainIterator();
307
308 while (it4.isNext())
309 {
310 auto p = it4.get();
311
312 // here we calculate v(tn + 1)
313 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
314 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
315 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
316
317 ++it4;
318 }
319
320 // After every iteration collect some statistic about the confoguration
321 if (i % 100 == 0)
322 {
323 // We write the particle position for visualization (Without ghost)
324 vd.deleteGhost();
325 vd.write("particles_",f);
326
327 // we resync the ghost
328 vd.ghost_get<>();
329
330
331 // We calculate the energy
332 real_number energy = calc_energy(vd,NN,sigma12,sigma6,r_cut);
333 auto & vcl = create_vcluster();
334 vcl.sum(energy);
335 vcl.max(max_disp);
336 vcl.execute();
337
338 // we save the energy calculated at time step i c contain the time-step y contain the energy
339 x.add(i);
340 y.add({energy});
341
342 // We also print on terminal the value of the energy
343 // only one processor (master) write on terminal
344 if (vcl.getProcessUnitID() == 0)
345 std::cout << "Energy: " << energy << " " << max_disp << " " << std::endl;
346
347 max_disp = 0.0;
348
349 f++;
350 }
351 }
352
353 tsim.stop();
354 std::cout << "Time: " << tsim.getwct() << std::endl;
355
356 // Google charts options, it store the options to draw the X Y graph
357 GCoptions options;
358
359 // Title of the graph
360 options.title = std::string("Energy with time");
361
362 // Y axis name
363 options.yAxis = std::string("Energy");
364
365 // X axis name
366 options.xAxis = std::string("iteration");
367
368 // width of the line
369 options.lineWidth = 1.0;
370
371 // Object that draw the X Y graph
372 GoogleChart cg;
373
374 // Add the graph
375 // The graph that it produce is in svg format that can be opened on browser
376 cg.AddLinesGraph(x,y,options);
377
378 // Write into html format
379 cg.write("gc_plot2_out.html");
380
381 openfpm_finalize();
382}
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.
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.
This structure define the operation add to use with copy general.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...