OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
main.cu
1#define SCAN_WITH_CUB
2
75#ifdef __NVCC__
76
77#include "Vector/vector_dist.hpp"
78#include "Plot/GoogleChart.hpp"
79#include "Plot/util.hpp"
80#include "timer.hpp"
81
82#ifdef TEST_RUN
83size_t nstep = 100;
84#else
85size_t nstep = 1000;
86#endif
87
88typedef float real_number;
89
91
92constexpr int velocity = 0;
93constexpr int force = 1;
94constexpr int energy = 2;
95
97
98template<typename vector_dist_type,typename NN_type>
99__global__ void calc_force_gpu(vector_dist_type vd, NN_type NN, real_number sigma12, real_number sigma6, real_number r_cut2)
100{
101 auto p = GET_PARTICLE(vd);
102
103 // Get the position xp of the particle
104 Point<3,real_number> xp = vd.getPos(p);
105
106 // Reset the force counter
107 vd.template getProp<force>(p)[0] = 0.0;
108 vd.template getProp<force>(p)[1] = 0.0;
109 vd.template getProp<force>(p)[2] = 0.0;
110
111
112
113 // Get an iterator over the neighborhood particles of p
114 auto Np = NN.getNNIterator(NN.getCell(vd.getPos(p)));
115
116 // For each neighborhood particle ...
117 while (Np.isNext())
118 {
119 // ... q
120 auto q = Np.get();
121
122 // if (p == q) skip this particle
123 if (q == p) {++Np; continue;};
124
125 // Get the position of p
126 Point<3,real_number> xq = vd.getPos(q);
127
128 // Get the distance between p and q
129 Point<3,real_number> r = xp - xq;
130
131 // take the norm of this vector
132 real_number rn = norm2(r);
133
134 if (rn > r_cut2)
135 {++Np; continue;};
136
137 // Calculate the force, using pow is slower
138 Point<3,real_number> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) - sigma6 / (rn*rn*rn*rn)) * r;
139
140 // we sum the force produced by q on p
141 vd.template getProp<force>(p)[0] += f.get(0);
142 vd.template getProp<force>(p)[1] += f.get(1);
143 vd.template getProp<force>(p)[2] += f.get(2);
144
145 // Next neighborhood
146 ++Np;
147 }
148}
149
151
152template<typename vector_dist_type>
153__global__ void update_velocity_position(vector_dist_type vd, real_number dt)
154{
155 auto p = GET_PARTICLE(vd);
156
157 // here we calculate v(tn + 0.5)
158 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
159 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
160 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
161
162 // here we calculate x(tn + 1)
163 vd.getPos(p)[0] += vd.template getProp<velocity>(p)[0]*dt;
164 vd.getPos(p)[1] += vd.template getProp<velocity>(p)[1]*dt;
165 vd.getPos(p)[2] += vd.template getProp<velocity>(p)[2]*dt;
166}
167
168template<typename vector_dist_type>
169__global__ void update_velocity(vector_dist_type vd, real_number dt)
170{
171 auto p = GET_PARTICLE(vd);
172
173 // here we calculate v(tn + 1)
174 vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
175 vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
176 vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
177}
178
180
182
183template<typename vector_dist_type,typename NN_type>
184__global__ void particle_energy(vector_dist_type vd, NN_type NN, real_number sigma12, real_number sigma6, real_number shift, real_number r_cut2)
185{
186 auto p = GET_PARTICLE(vd);
187
188 // Get the position of the particle p
189 Point<3,real_number> xp = vd.getPos(p);
190
191 // Get an iterator over the neighborhood of the particle p
192 auto Np = NN.getNNIterator(NN.getCell(vd.getPos(p)));
193
194 real_number E = 0;
195
196 // For each neighborhood of the particle p
197 while (Np.isNext())
198 {
199 // Neighborhood particle q
200 auto q = Np.get();
201
202 // if p == q skip this particle
203 if (q == p) {++Np; continue;};
204
205 // Get position of the particle q
206 Point<3,real_number> xq = vd.getPos(q);
207
208 // take the normalized direction
209 real_number rn = norm2(xp - xq);
210
211 if (rn > r_cut2)
212 {++Np;continue;}
213
214 // potential energy (using pow is slower)
215 E += 2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
216
217 // Next neighborhood
218 ++Np;
219 }
220
221 // Kinetic energy of the particle given by its actual speed
222 vd.template getProp<energy>(p) = E + (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
223 vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
224 vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
225}
226
228
230
231template<typename CellList> void calc_forces(vector_dist_gpu<3,real_number, aggregate<real_number[3],real_number[3],real_number> > & vd, CellList & NN, real_number sigma12, real_number sigma6, real_number r_cut2)
232{
233 vd.updateCellList(NN);
234
235 // Get an iterator over particles
236 auto it2 = vd.getDomainIteratorGPU();
237
238 CUDA_LAUNCH(calc_force_gpu,it2,vd.toKernel(),NN.toKernel(),sigma12,sigma6,r_cut2);
239}
240
242
243template<typename CellList> real_number calc_energy(vector_dist_gpu<3,real_number, aggregate<real_number[3],real_number[3],real_number> > & vd, CellList & NN, real_number sigma12, real_number sigma6, real_number r_cut2)
244{
245 real_number rc = r_cut2;
246 real_number shift = 2.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
247
248 vd.updateCellList(NN);
249
250 auto it2 = vd.getDomainIteratorGPU();
251
252 CUDA_LAUNCH(particle_energy,it2,vd.toKernel(),NN.toKernel(),sigma12,sigma6,shift,r_cut2);
253
255
256 // Calculated energy
257 return reduce_local<energy,_add_>(vd);
258
260}
261
262int main(int argc, char* argv[])
263{
264 openfpm_init(&argc,&argv);
265
266 real_number sigma = 0.01;
267 real_number r_cut = 3.0*sigma;
268
269 // we will use it do place particles on a 10x10x10 Grid like
270 size_t sz[3] = {100,100,100};
271
272 // domain
273 Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
274
275 // Boundary conditions
276 size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
277
278 // ghost, big enough to contain the interaction radius
279 Ghost<3,float> ghost(r_cut);
280
281 real_number dt = 0.00005;
282 real_number sigma12 = pow(sigma,12);
283 real_number sigma6 = pow(sigma,6);
284
287
289
290 // We create the grid iterator
291 auto it = vd.getGridIterator(sz);
292
293 while (it.isNext())
294 {
295 // Create a new particle
296 vd.add();
297
298 // key contain (i,j,k) index of the grid
299 auto key = it.get();
300
301 // The index of the grid can be accessed with key.get(0) == i, key.get(1) == j ...
302 // We use getLastPos to set the position of the last particle added
303 vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
304 vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
305 vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
306
307 // We use getLastProp to set the property value of the last particle we added
308 vd.template getLastProp<velocity>()[0] = 0.0;
309 vd.template getLastProp<velocity>()[1] = 0.0;
310 vd.template getLastProp<velocity>()[2] = 0.0;
311
312 vd.template getLastProp<force>()[0] = 0.0;
313 vd.template getLastProp<force>()[1] = 0.0;
314 vd.template getLastProp<force>()[2] = 0.0;
315
316 ++it;
317 }
318
319 vd.hostToDevicePos();
320 vd.hostToDeviceProp<velocity,force>();
321
322 vd.map(RUN_ON_DEVICE);
323 vd.ghost_get<>(RUN_ON_DEVICE);
324
325 timer tsim;
326 tsim.start();
327
329
330 // Get the Cell list structure
331 auto NN = vd.getCellListGPU(r_cut);
332
333 // The standard
334 // auto NN = vd.getCellList(r_cut);
335
336 // calculate forces
337 calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
338 unsigned long int f = 0;
339
340 // MD time stepping
341 for (size_t i = 0; i < nstep ; i++)
342 {
343 // Get the iterator
344 auto it3 = vd.getDomainIteratorGPU();
345
346 CUDA_LAUNCH(update_velocity_position,it3,vd.toKernel(),dt);
347
349
350 // Because we moved the particles in space we have to map them and re-sync the ghost
351 vd.map(RUN_ON_DEVICE);
352 vd.template ghost_get<>(RUN_ON_DEVICE);
353
355
356 // calculate forces or a(tn + 1) Step 2
357 calc_forces(vd,NN,sigma12,sigma6,r_cut*r_cut);
358
359
360 // Integrate the velocity Step 3
361 auto it4 = vd.getDomainIteratorGPU();
362
363 CUDA_LAUNCH(update_velocity,it4,vd.toKernel(),dt);
364
365 // After every iteration collect some statistic about the configuration
366 if (i % 100 == 0)
367 {
369
370 vd.deviceToHostPos();
371 vd.deviceToHostProp<0,1,2>();
372
373 // We write the particle position for visualization (Without ghost)
374 vd.deleteGhost();
375 vd.write_frame("particles_",f);
376
378
379 // we resync the ghost
380 vd.ghost_get<>(RUN_ON_DEVICE);
381
382 // We calculate the energy
383 real_number energy = calc_energy(vd,NN,sigma12,sigma6,r_cut*r_cut);
384 auto & vcl = create_vcluster();
385 vcl.sum(energy);
386 vcl.execute();
387
388 // we save the energy calculated at time step i c contain the time-step y contain the energy
389 x.add(i);
390 y.add({energy});
391
392 // We also print on terminal the value of the energy
393 // only one processor (master) write on terminal
394 if (vcl.getProcessUnitID() == 0)
395 std::cout << "Energy: " << energy << std::endl;
396
397 f++;
398 }
399 }
400
402
403 tsim.stop();
404 std::cout << "Time: " << tsim.getwct() << std::endl;
405
406 // Google charts options, it store the options to draw the X Y graph
407 GCoptions options;
408
409 // Title of the graph
410 options.title = std::string("Energy with time");
411
412 // Y axis name
413 options.yAxis = std::string("Energy");
414
415 // X axis name
416 options.xAxis = std::string("iteration");
417
418 // width of the line
419 options.lineWidth = 1.0;
420
421 // Resolution in x
422 options.width = 1280;
423
424 // Resolution in y
425 options.heigh = 720;
426
427 // Add zoom capability
428 options.more = GC_ZOOM;
429
430 // Object that draw the X Y graph
431 GoogleChart cg;
432
433 // Add the graph
434 // The graph that it produce is in svg format that can be opened on browser
435 cg.AddLinesGraph(x,y,options);
436
437 // Write into html format
438 cg.write("gc_plot2_out.html");
439
440 openfpm_finalize();
441}
442
443#else
444
445int main(int argc, char* argv[])
446{
447 return 0;
448}
449
450#endif
451
452
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
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition Point.hpp:172
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...