OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
main.cpp
1 
53 //#define SE_CLASS1
54 //#define STOP_ON_ERROR
55 
56 #include "Vector/vector_dist.hpp"
57 #include <math.h>
58 #include "Draw/DrawParticles.hpp"
59 
211 // A constant to indicate boundary particles
212 #define BOUNDARY 1
213 
214 // A constant to indicate fluid particles
215 #define FLUID 0
216 
217 // initial spacing between particles dp in the formulas
218 const double dp = 0.0085;
219 // Maximum height of the fluid water
220 // is going to be calculated and filled later on
221 double h_swl = 0.0;
222 
223 // c_s in the formulas (constant used to calculate the sound speed)
224 const double coeff_sound = 20.0;
225 
226 // gamma in the formulas
227 const double gamma_ = 7.0;
228 
229 // sqrt(3.0*dp*dp) support of the kernel
230 const double H = 0.0147224318643;
231 
232 const double FourH2 = 4.0 * H*H;
233 
234 // Eta in the formulas
235 const double Eta2 = 0.01 * H*H;
236 
237 // alpha in the formula
238 const double visco = 0.1;
239 
240 // cbar in the formula (calculated later)
241 double cbar = 0.0;
242 
243 // Mass of the fluid particles
244 const double MassFluid = 0.000614125;
245 
246 // Mass of the boundary particles
247 const double MassBound = 0.000614125;
248 
249 // End simulation time
250 #ifndef TEST_RUN
251 const double t_end = 1.5;
252 #else
253 const double t_end = 0.001;
254 #endif
255 
256 // Gravity acceleration
257 const double gravity = 9.81;
258 
259 // Reference densitu 1000Kg/m^3
260 const double rho_zero = 1000.0;
261 
262 // Filled later require h_swl, it is b in the formulas
263 double B = 0.0;
264 
265 // Constant used to define time integration
266 const double CFLnumber = 0.2;
267 
268 // Minimum T
269 const double DtMin = 0.00001;
270 
271 // Minimum Rho allowed
272 const double RhoMin = 700.0;
273 
274 // Maximum Rho allowed
275 const double RhoMax = 1300.0;
276 
277 // Filled in initialization
278 double max_fluid_height = 0.0;
279 
280 // Properties
281 
282 // FLUID or BOUNDARY
283 const size_t type = 0;
284 
285 // FLUID or BOUNDARY
286 const size_t nn_num = 1;
287 
288 // Density
289 const int rho = 2;
290 
291 // Density at step n-1
292 const int rho_prev = 3;
293 
294 // Pressure
295 const int Pressure = 4;
296 
297 // Delta rho calculated in the force calculation
298 const int drho = 5;
299 
300 // calculated force
301 const int force = 6;
302 
303 // velocity
304 const int velocity = 7;
305 
306 // velocity at previous step
307 const int velocity_prev = 8;
308 
313 // Type of the vector containing particles
315 // | | | | | | | | |
316 // | | | | | | | | |
317 // type | density density Pressure delta force velocity velocity
318 // | at n-1 density at n - 1
319 // |
320 // Number of neighborhood
321 
323 struct ModelCustom
324 {
325  template<typename Decomposition, typename vector> inline void addComputation(Decomposition & dec, vector & vd, size_t v, size_t p)
326  {
327  if (vd.template getProp<type>(p) == FLUID )
328  {dec.addComputationCost(v,4);}
329  else
330  {dec.addComputationCost(v,3);}
331  }
332 
333  template<typename Decomposition> inline void applyModel(Decomposition & dec, size_t v)
334  {
335  dec.setSubSubDomainComputationCost(v, dec.getSubSubDomainComputationCost(v) * dec.getSubSubDomainComputationCost(v));
336  }
337 
338  float distributionTol()
339  {
340  return 1.01;
341  }
342 };
343 
346 {
347  template<typename Decomposition, typename vector> inline void addComputation(Decomposition & dec, vector & vd, size_t v, size_t p)
348  {
349  dec.addComputationCost(v,vd.template getProp<nn_num>(p) + 4);
350  }
351 
352  template<typename Decomposition> inline void applyModel(Decomposition & dec, size_t v)
353  {
354  }
355 
356  float distributionTol()
357  {
358  return 1.01;
359  }
360 };
361 
362 inline void EqState(particles & vd)
363 {
364  auto it = vd.getDomainIterator();
365 
366  while (it.isNext())
367  {
368  auto a = it.get();
369 
370  double rho_a = vd.template getProp<rho>(a);
371  double rho_frac = rho_a / rho_zero;
372 
373  vd.template getProp<Pressure>(a) = B*( rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac - 1.0);
374 
375  ++it;
376  }
377 }
378 
379 const double a2 = 1.0/M_PI/H/H/H;
380 
381 inline double Wab(double r)
382 {
383  r /= H;
384 
385  if (r < 1.0)
386  {return (1.0 - 3.0/2.0*r*r + 3.0/4.0*r*r*r)*a2;}
387  else if (r < 2.0)
388  {return (1.0/4.0*(2.0 - r*r)*(2.0 - r*r)*(2.0 - r*r))*a2;}
389  else
390  {return 0.0;}
391 }
392 
393 const double c1 = -3.0/M_PI/H/H/H/H;
394 const double d1 = 9.0/4.0/M_PI/H/H/H/H;
395 const double c2 = -3.0/4.0/M_PI/H/H/H/H;
396 const double a2_4 = 0.25*a2;
397 // Filled later
398 double W_dap = 0.0;
399 
400 inline void DWab(Point<3,double> & dx, Point<3,double> & DW, double r)
401 {
402  const double qq=r/H;
403 
404  double qq2 = qq * qq;
405  double fac1 = (c1*qq + d1*qq2)/r;
406  double b1 = (qq < 1.0)?1.0f:0.0f;
407 
408  double wqq = (2.0 - qq);
409  double fac2 = c2 * wqq * wqq / r;
410  double b2 = (qq >= 1.0 && qq < 2.0)?1.0f:0.0f;
411 
412  double factor = (b1*fac1 + b2*fac2);
413 
414  DW.get(0) = factor * dx.get(0);
415  DW.get(1) = factor * dx.get(1);
416  DW.get(2) = factor * dx.get(2);
417 }
418 
419 inline double Tensile(double r, double rhoa, double rhob, double prs1, double prs2)
420 {
421  const double qq=r/H;
422  //-Cubic Spline kernel
423  double wab;
424  if(r>H)
425  {
426  double wqq1=2.0f-qq;
427  double wqq2=wqq1*wqq1;
428 
429  wab=a2_4*(wqq2*wqq1);
430  }
431  else
432  {
433  double wqq2=qq*qq;
434  double wqq3=wqq2*qq;
435 
436  wab=a2*(1.0f-1.5f*wqq2+0.75f*wqq3);
437  }
438 
439  //-Tensile correction.
440  double fab=wab*W_dap;
441  fab*=fab; fab*=fab; //fab=fab^4
442  const double tensilp1=(prs1/(rhoa*rhoa))*(prs1>0? 0.01: -0.2);
443  const double tensilp2=(prs2/(rhob*rhob))*(prs2>0? 0.01: -0.2);
444 
445  return (fab*(tensilp1+tensilp2));
446 }
447 
448 
449 inline double Pi(const Point<3,double> & dr, double rr2, Point<3,double> & dv, double rhoa, double rhob, double massb, double & visc)
450 {
451  const double dot = dr.get(0)*dv.get(0) + dr.get(1)*dv.get(1) + dr.get(2)*dv.get(2);
452  const double dot_rr2 = dot/(rr2+Eta2);
453  visc=std::max(dot_rr2,visc);
454 
455  if(dot < 0)
456  {
457  const float amubar=H*dot_rr2;
458  const float robar=(rhoa+rhob)*0.5f;
459  const float pi_visc=(-visco*cbar*amubar/robar);
460 
461  return pi_visc;
462  }
463  else
464  return 0.0;
465 }
466 
467 
468 template<typename VerletList> inline void calc_forces(particles & vd, VerletList & NN, double & max_visc)
469 {
472  // Reset the ghost
473  auto itg = vd.getDomainIterator();
474  while (itg.isNext())
475  {
476  auto p = itg.get();
477  // Reset force
478 
479  // Reset the force counter (- gravity on zeta direction)
480  vd.template getProp<force>(p)[0] = 0.0;
481  vd.template getProp<force>(p)[1] = 0.0;
482  vd.template getProp<force>(p)[2] = -gravity;
483  vd.template getProp<drho>(p) = 0.0;
484 
485 
486  ++itg;
487  }
488 
493  auto itg2 = vd.getGhostIterator();
494  while (itg2.isNext())
495  {
496  auto p = itg2.get();
497  // Reset force
498 
499  // Reset the force counter (- gravity on zeta direction)
500  vd.template getProp<force>(p)[0] = 0.0;
501  vd.template getProp<force>(p)[1] = 0.0;
502  vd.template getProp<force>(p)[2] = 0.0;
503  vd.template getProp<drho>(p) = 0.0;
504 
505  ++itg2;
506  }
507 
510  // Get an iterator over particles
511  auto part = vd.getParticleIteratorCRS(NN);
512 
513  double visc = 0;
514 
515  // For each particle ...
516  while (part.isNext())
517  {
518  // ... a
519  auto a = part.get();
520 
521  // Get the position xp of the particle
522  Point<3,double> xa = vd.getPos(a);
523 
524  // Type of the particle
525  size_t typea = vd.getProp<type>(a);
526 
527  // Take the mass of the particle dependently if it is FLUID or BOUNDARY
528  double massa = (vd.getProp<type>(a) == FLUID)?MassFluid:MassBound;
529 
530  // Get the density of the of the particle a
531  double rhoa = vd.getProp<rho>(a);
532 
533  // Get the pressure of the particle a
534  double Pa = vd.getProp<Pressure>(a);
535 
536  // Get the Velocity of the particle a
537  Point<3,double> va = vd.getProp<velocity>(a);
538 
539  // Get an iterator over the neighborhood particles of p
540  auto Np = NN.template getNNIterator<NO_CHECK>(a);
541 
542  size_t nn = 0;
543 
544  // For each neighborhood particle
545  while (Np.isNext() == true)
546  {
547  // ... q
548  auto b = Np.get();
549 
550  // Get the position xp of the particle
551  Point<3,double> xb = vd.getPos(b);
552 
553  // Get the distance between p and q
554  Point<3,double> dr = xa - xb;
555  // take the norm of this vector
556  float r2 = norm2(dr);
557 
558  // if they interact
559  if (r2 < FourH2 && r2 > 1e-18)
560  {
561  double r = sqrt(r2);
562 
563  unsigned int typeb = vd.getProp<type>(b);
564 
565  double massb = (typeb == FLUID)?MassFluid:MassBound;
566  Point<3,double> vb = vd.getProp<velocity>(b);
567  double Pb = vd.getProp<Pressure>(b);
568  double rhob = vd.getProp<rho>(b);
569 
570  Point<3,double> v_rel = va - vb;
571 
572  Point<3,double> DW;
573  DWab(dr,DW,r);
574 
576 
577  double factor = - ((Pa + Pb) / (rhoa * rhob) + Tensile(r,rhoa,rhob,Pa,Pb) + Pi(dr,r2,v_rel,rhoa,rhob,massb,visc));
578 
579  // Bound - Bound does not produce any change
580  factor = (typea == BOUNDARY && typeb == BOUNDARY)?0.0f:factor;
581 
582  vd.getProp<force>(a)[0] += massb * factor * DW.get(0);
583  vd.getProp<force>(a)[1] += massb * factor * DW.get(1);
584  vd.getProp<force>(a)[2] += massb * factor * DW.get(2);
585 
586  vd.getProp<force>(b)[0] -= massa * factor * DW.get(0);
587  vd.getProp<force>(b)[1] -= massa * factor * DW.get(1);
588  vd.getProp<force>(b)[2] -= massa * factor * DW.get(2);
589 
590  double scal = (v_rel.get(0)*DW.get(0)+v_rel.get(1)*DW.get(1)+v_rel.get(2)*DW.get(2));
591 
592  // Bound - Bound does not produce any change
593  scal = (typea == BOUNDARY && typeb == BOUNDARY)?0.0f:scal;
594 
595  vd.getProp<drho>(a) += massb*scal;
596  vd.getProp<drho>(b) += massa*scal;
597 
599  }
600 
601  nn++;
602  ++Np;
603  }
604 
605  // Number of particles here
606  vd.getProp<nn_num>(a) = nn;
607 
608  ++part;
609  }
610 
612 
613  vd.template ghost_put<add_,drho,force>();
614 
616 }
617 
618 void max_acceleration_and_velocity(particles & vd, double & max_acc, double & max_vel)
619 {
620  // Calculate the maximum acceleration
621  auto part = vd.getDomainIterator();
622 
623  while (part.isNext())
624  {
625  auto a = part.get();
626 
627  Point<3,double> acc(vd.getProp<force>(a));
628  double acc2 = norm2(acc);
629 
630  Point<3,double> vel(vd.getProp<velocity>(a));
631  double vel2 = norm2(vel);
632 
633  if (vel2 >= max_vel)
634  max_vel = vel2;
635 
636  if (acc2 >= max_acc)
637  max_acc = acc2;
638 
639  ++part;
640  }
641  max_acc = sqrt(max_acc);
642  max_vel = sqrt(max_vel);
643 
644  Vcluster<> & v_cl = create_vcluster();
645  v_cl.max(max_acc);
646  v_cl.max(max_vel);
647  v_cl.execute();
648 }
649 
650 double calc_deltaT(particles & vd, double ViscDtMax)
651 {
652  double Maxacc = 0.0;
653  double Maxvel = 0.0;
654  max_acceleration_and_velocity(vd,Maxacc,Maxvel);
655 
656  //-dt1 depends on force per unit mass.
657  const double dt_f = (Maxacc)?sqrt(H/Maxacc):std::numeric_limits<int>::max();
658 
659  //-dt2 combines the Courant and the viscous time-step controls.
660  const double dt_cv = H/(std::max(cbar,Maxvel*10.) + H*ViscDtMax);
661 
662  //-dt new value of time step.
663  double dt=double(CFLnumber)*std::min(dt_f,dt_cv);
664  if(dt<double(DtMin))
665  {dt=double(DtMin);}
666 
667  return dt;
668 }
669 
670 
671 openfpm::vector<size_t> to_remove;
672 
673 size_t cnt = 0;
674 
676 void verlet_int(particles & vd, double dt, double & max_disp)
678 {
679  // list of the particle to remove
680  to_remove.clear();
681 
682  // particle iterator
683  auto part = vd.getDomainIterator();
684 
685  double dt205 = dt*dt*0.5;
686  double dt2 = dt*2.0;
687 
689  max_disp = 0;
692  // For each particle ...
693  while (part.isNext())
694  {
695  // ... a
696  auto a = part.get();
697 
698  // if the particle is boundary
699  if (vd.template getProp<type>(a) == BOUNDARY)
700  {
701  // Update rho
702  double rhop = vd.template getProp<rho>(a);
703 
704  // Update only the density
705  vd.template getProp<velocity>(a)[0] = 0.0;
706  vd.template getProp<velocity>(a)[1] = 0.0;
707  vd.template getProp<velocity>(a)[2] = 0.0;
708  double rhonew = vd.template getProp<rho_prev>(a) + dt2*vd.template getProp<drho>(a);
709  vd.template getProp<rho>(a) = (rhonew < rho_zero)?rho_zero:rhonew;
710 
711  vd.template getProp<rho_prev>(a) = rhop;
712 
713  ++part;
714  continue;
715  }
716 
717  //-Calculate displacement and update position / Calcula desplazamiento y actualiza posicion.
718  double dx = vd.template getProp<velocity>(a)[0]*dt + vd.template getProp<force>(a)[0]*dt205;
719  double dy = vd.template getProp<velocity>(a)[1]*dt + vd.template getProp<force>(a)[1]*dt205;
720  double dz = vd.template getProp<velocity>(a)[2]*dt + vd.template getProp<force>(a)[2]*dt205;
721 
722  vd.getPos(a)[0] += dx;
723  vd.getPos(a)[1] += dy;
724  vd.getPos(a)[2] += dz;
725 
727  double d2 = dx*dx + dy*dy + dz*dz;
728 
729  max_disp = (max_disp > d2)?max_disp:d2;
732  double velX = vd.template getProp<velocity>(a)[0];
733  double velY = vd.template getProp<velocity>(a)[1];
734  double velZ = vd.template getProp<velocity>(a)[2];
735  double rhop = vd.template getProp<rho>(a);
736 
737  vd.template getProp<velocity>(a)[0] = vd.template getProp<velocity_prev>(a)[0] + vd.template getProp<force>(a)[0]*dt2;
738  vd.template getProp<velocity>(a)[1] = vd.template getProp<velocity_prev>(a)[1] + vd.template getProp<force>(a)[1]*dt2;
739  vd.template getProp<velocity>(a)[2] = vd.template getProp<velocity_prev>(a)[2] + vd.template getProp<force>(a)[2]*dt2;
740  vd.template getProp<rho>(a) = vd.template getProp<rho_prev>(a) + dt2*vd.template getProp<drho>(a);
741 
742  // Check if the particle go out of range in space and in density
743  if (vd.getPos(a)[0] < 0.000263878 || vd.getPos(a)[1] < 0.000263878 || vd.getPos(a)[2] < 0.000263878 ||
744  vd.getPos(a)[0] > 0.000263878+1.59947 || vd.getPos(a)[1] > 0.000263878+0.672972 || vd.getPos(a)[2] > 0.000263878+0.903944 ||
745  vd.template getProp<rho>(a) < RhoMin || vd.template getProp<rho>(a) > RhoMax)
746  {
747  to_remove.add(a.getKey());
748  }
749 
750  vd.template getProp<velocity_prev>(a)[0] = velX;
751  vd.template getProp<velocity_prev>(a)[1] = velY;
752  vd.template getProp<velocity_prev>(a)[2] = velZ;
753  vd.template getProp<rho_prev>(a) = rhop;
754 
755  ++part;
756  }
757 
760  Vcluster<> & v_cl = create_vcluster();
761  v_cl.max(max_disp);
762  v_cl.execute();
763 
764  max_disp = sqrt(max_disp);
765 
768  // increment the iteration counter
769  cnt++;
770 }
771 
773 void euler_int(particles & vd, double dt, double & max_disp)
775 {
776  // list of the particle to remove
777  to_remove.clear();
778 
779  // particle iterator
780  auto part = vd.getDomainIterator();
781 
782  double dt205 = dt*dt*0.5;
783  double dt2 = dt*2.0;
784 
785  max_disp = 0;
786 
787  // For each particle ...
788  while (part.isNext())
789  {
790  // ... a
791  auto a = part.get();
792 
793  // if the particle is boundary
794  if (vd.template getProp<type>(a) == BOUNDARY)
795  {
796  // Update rho
797  double rhop = vd.template getProp<rho>(a);
798 
799  // Update only the density
800  vd.template getProp<velocity>(a)[0] = 0.0;
801  vd.template getProp<velocity>(a)[1] = 0.0;
802  vd.template getProp<velocity>(a)[2] = 0.0;
803  double rhonew = vd.template getProp<rho>(a) + dt*vd.template getProp<drho>(a);
804  vd.template getProp<rho>(a) = (rhonew < rho_zero)?rho_zero:rhonew;
805 
806  vd.template getProp<rho_prev>(a) = rhop;
807 
808  ++part;
809  continue;
810  }
811 
812  //-Calculate displacement and update position / Calcula desplazamiento y actualiza posicion.
813  double dx = vd.template getProp<velocity>(a)[0]*dt + vd.template getProp<force>(a)[0]*dt205;
814  double dy = vd.template getProp<velocity>(a)[1]*dt + vd.template getProp<force>(a)[1]*dt205;
815  double dz = vd.template getProp<velocity>(a)[2]*dt + vd.template getProp<force>(a)[2]*dt205;
816 
817  vd.getPos(a)[0] += dx;
818  vd.getPos(a)[1] += dy;
819  vd.getPos(a)[2] += dz;
820 
821  double d2 = dx*dx + dy*dy + dz*dz;
822 
823  max_disp = (max_disp > d2)?max_disp:d2;
824 
825  double velX = vd.template getProp<velocity>(a)[0];
826  double velY = vd.template getProp<velocity>(a)[1];
827  double velZ = vd.template getProp<velocity>(a)[2];
828  double rhop = vd.template getProp<rho>(a);
829 
830  vd.template getProp<velocity>(a)[0] = vd.template getProp<velocity>(a)[0] + vd.template getProp<force>(a)[0]*dt;
831  vd.template getProp<velocity>(a)[1] = vd.template getProp<velocity>(a)[1] + vd.template getProp<force>(a)[1]*dt;
832  vd.template getProp<velocity>(a)[2] = vd.template getProp<velocity>(a)[2] + vd.template getProp<force>(a)[2]*dt;
833  vd.template getProp<rho>(a) = vd.template getProp<rho>(a) + dt*vd.template getProp<drho>(a);
834 
835  // Check if the particle go out of range in space and in density
836  if (vd.getPos(a)[0] < 0.000263878 || vd.getPos(a)[1] < 0.000263878 || vd.getPos(a)[2] < 0.000263878 ||
837  vd.getPos(a)[0] > 0.000263878+1.59947 || vd.getPos(a)[1] > 0.000263878+0.672972 || vd.getPos(a)[2] > 0.000263878+0.903944 ||
838  vd.template getProp<rho>(a) < RhoMin || vd.template getProp<rho>(a) > RhoMax)
839  {
840  to_remove.add(a.getKey());
841  }
842 
843  vd.template getProp<velocity_prev>(a)[0] = velX;
844  vd.template getProp<velocity_prev>(a)[1] = velY;
845  vd.template getProp<velocity_prev>(a)[2] = velZ;
846  vd.template getProp<rho_prev>(a) = rhop;
847 
848  ++part;
849  }
850 
851  Vcluster<> & v_cl = create_vcluster();
852  v_cl.max(max_disp);
853  v_cl.execute();
854 
855  max_disp = sqrt(max_disp);
856 
857  // increment the iteration counter
858  cnt++;
859 }
860 
861 int main(int argc, char* argv[])
862 {
863  // initialize the library
864  openfpm_init(&argc,&argv);
865 
866  // Here we define our domain a 2D box with internals from 0 to 1.0 for x and y
867  Box<3,double> domain({-0.05,-0.05,-0.05},{1.7010,0.7065,0.5025});
868  size_t sz[3] = {207,90,66};
869 
870  // Fill W_dap
871  W_dap = 1.0/Wab(H/1.5);
872 
873  // Here we define the boundary conditions of our problem
874  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
875 
878  double skin = 0.25 * 2*H;
879  double r_gskin = 2*H + skin;
880 
881  // extended boundary around the domain, and the processor domain
882  // by the support of the cubic kernel
883  Ghost<3,double> g(r_gskin);
884 
887  // Eliminating the lower part of the ghost
888  // We are using CRS scheme
889  g.setLow(0,0.0);
890  g.setLow(1,0.0);
891  g.setLow(2,0.0);
892 
895  particles vd(0,domain,bc,g,BIND_DEC_TO_GHOST);
896 
899  // You can ignore all these dp/2.0 is a trick to reach the same initialization
900  // of Dual-SPH that use a different criteria to draw particles
901  Box<3,double> fluid_box({dp/2.0,dp/2.0,dp/2.0},{0.4+dp/2.0,0.67-dp/2.0,0.3+dp/2.0});
902 
903  // return an iterator to the fluid particles to add to vd
904  auto fluid_it = DrawParticles::DrawBox(vd,sz,domain,fluid_box);
905 
906  // here we fill some of the constants needed by the simulation
907  max_fluid_height = fluid_it.getBoxMargins().getHigh(2);
908  h_swl = fluid_it.getBoxMargins().getHigh(2) - fluid_it.getBoxMargins().getLow(2);
909  B = (coeff_sound)*(coeff_sound)*gravity*h_swl*rho_zero / gamma_;
910  cbar = coeff_sound * sqrt(gravity * h_swl);
911 
912  // for each particle inside the fluid box ...
913  while (fluid_it.isNext())
914  {
915  // ... add a particle ...
916  vd.add();
917 
918  // ... and set it position ...
919  vd.getLastPos()[0] = fluid_it.get().get(0);
920  vd.getLastPos()[1] = fluid_it.get().get(1);
921  vd.getLastPos()[2] = fluid_it.get().get(2);
922 
923  // and its type.
924  vd.template getLastProp<type>() = FLUID;
925 
926  // We also initialize the density of the particle and the hydro-static pressure given by
927  //
928  // rho_zero*g*h = P
929  //
930  // rho_p = (P/B + 1)^(1/Gamma) * rho_zero
931  //
932 
933  vd.template getLastProp<Pressure>() = rho_zero * gravity * (max_fluid_height - fluid_it.get().get(2));
934 
935  vd.template getLastProp<rho>() = pow(vd.template getLastProp<Pressure>() / B + 1, 1.0/gamma_) * rho_zero;
936  vd.template getLastProp<rho_prev>() = vd.template getLastProp<rho>();
937  vd.template getLastProp<velocity>()[0] = 0.0;
938  vd.template getLastProp<velocity>()[1] = 0.0;
939  vd.template getLastProp<velocity>()[2] = 0.0;
940 
941  vd.template getLastProp<velocity_prev>()[0] = 0.0;
942  vd.template getLastProp<velocity_prev>()[1] = 0.0;
943  vd.template getLastProp<velocity_prev>()[2] = 0.0;
944 
945  // next fluid particle
946  ++fluid_it;
947  }
948 
949  // Recipient
950  Box<3,double> recipient1({0.0,0.0,0.0},{1.6+dp/2.0,0.67+dp/2.0,0.4+dp/2.0});
951  Box<3,double> recipient2({dp,dp,dp},{1.6-dp/2.0,0.67-dp/2.0,0.4+dp/2.0});
952 
953  Box<3,double> obstacle1({0.9,0.24-dp/2.0,0.0},{1.02+dp/2.0,0.36,0.45+dp/2.0});
954  Box<3,double> obstacle2({0.9+dp,0.24+dp/2.0,0.0},{1.02-dp/2.0,0.36-dp,0.45-dp/2.0});
955  Box<3,double> obstacle3({0.9+dp,0.24,0.0},{1.02,0.36,0.45});
956 
958  holes.add(recipient2);
959  holes.add(obstacle1);
960  auto bound_box = DrawParticles::DrawSkin(vd,sz,domain,holes,recipient1);
961 
962  while (bound_box.isNext())
963  {
964  vd.add();
965 
966  vd.getLastPos()[0] = bound_box.get().get(0);
967  vd.getLastPos()[1] = bound_box.get().get(1);
968  vd.getLastPos()[2] = bound_box.get().get(2);
969 
970  vd.template getLastProp<type>() = BOUNDARY;
971  vd.template getLastProp<rho>() = rho_zero;
972  vd.template getLastProp<rho_prev>() = rho_zero;
973  vd.template getLastProp<velocity>()[0] = 0.0;
974  vd.template getLastProp<velocity>()[1] = 0.0;
975  vd.template getLastProp<velocity>()[2] = 0.0;
976 
977  vd.template getLastProp<velocity_prev>()[0] = 0.0;
978  vd.template getLastProp<velocity_prev>()[1] = 0.0;
979  vd.template getLastProp<velocity_prev>()[2] = 0.0;
980 
981  ++bound_box;
982  }
983 
984  auto obstacle_box = DrawParticles::DrawSkin(vd,sz,domain,obstacle2,obstacle1);
985 
986  while (obstacle_box.isNext())
987  {
988  vd.add();
989 
990  vd.getLastPos()[0] = obstacle_box.get().get(0);
991  vd.getLastPos()[1] = obstacle_box.get().get(1);
992  vd.getLastPos()[2] = obstacle_box.get().get(2);
993 
994  vd.template getLastProp<type>() = BOUNDARY;
995  vd.template getLastProp<rho>() = rho_zero;
996  vd.template getLastProp<rho_prev>() = rho_zero;
997  vd.template getLastProp<velocity>()[0] = 0.0;
998  vd.template getLastProp<velocity>()[1] = 0.0;
999  vd.template getLastProp<velocity>()[2] = 0.0;
1000 
1001  vd.template getLastProp<velocity_prev>()[0] = 0.0;
1002  vd.template getLastProp<velocity_prev>()[1] = 0.0;
1003  vd.template getLastProp<velocity_prev>()[2] = 0.0;
1004 
1005  ++obstacle_box;
1006  }
1007 
1008  vd.map();
1009 
1011  //
1012  //
1013  //
1014 
1015  size_t tot_part = vd.size_local();
1016 
1017  auto & v_cl = create_vcluster();
1018  v_cl.sum(tot_part);
1019  v_cl.execute();
1020  std::cout << "SUM: " << tot_part << std::endl;
1021 
1022  // Now that we fill the vector with particles
1023  ModelCustom md;
1024 
1025  vd.addComputationCosts(md);
1026  vd.getDecomposition().decompose();
1027  vd.map();
1028 
1029  vd.ghost_get<type,rho,Pressure,velocity>();
1030 
1032  auto NN = vd.getVerletCrs(r_gskin);
1035  size_t write = 0;
1036  size_t it = 0;
1037  size_t it_reb = 0;
1038  double t = 0.0;
1039  double tot_disp = 0.0;
1040  double max_disp;
1041  while (t <= t_end)
1042  {
1043  Vcluster<> & v_cl = create_vcluster();
1044  timer it_time;
1045 
1048  it_reb++;
1049  if (2*tot_disp >= skin)
1050  {
1051  vd.remove(to_remove);
1052 
1053  vd.map();
1054 
1055  if (it_reb > 200)
1056  {
1057  ModelCustom2 md;
1058  vd.addComputationCosts(md);
1059  vd.getDecomposition().redecompose(200);
1060 
1061  vd.map();
1062 
1063  it_reb = 0;
1064 
1065  if (v_cl.getProcessUnitID() == 0)
1066  std::cout << "REBALANCED " << std::endl;
1067 
1068  }
1069 
1070  // Calculate pressure from the density
1071  EqState(vd);
1072 
1073  vd.ghost_get<type,rho,Pressure,velocity>();
1074 
1076  vd.updateVerlet(NN,r_gskin,VL_CRS_SYMMETRIC);
1079  tot_disp = 0.0;
1080 
1081  if (v_cl.getProcessUnitID() == 0)
1082  std::cout << "RECONSTRUCT Verlet " << std::endl;
1083  }
1084  else
1085  {
1086  // Calculate pressure from the density
1087  EqState(vd);
1088 
1089  vd.ghost_get<type,rho,Pressure,velocity>(SKIP_LABELLING);
1090  }
1091 
1094  double max_visc = 0.0;
1095 
1096  // Calc forces
1097  calc_forces(vd,NN,max_visc);
1098 
1099  // Get the maximum viscosity term across processors
1100  v_cl.max(max_visc);
1101  v_cl.execute();
1102 
1103  // Calculate delta t integration
1104  double dt = calc_deltaT(vd,max_visc);
1105 
1108  // VerletStep or euler step
1109  it++;
1110  if (it < 40)
1111  verlet_int(vd,dt,max_disp);
1112  else
1113  {
1114  euler_int(vd,dt,max_disp);
1115  it = 0;
1116  }
1117 
1118  tot_disp += max_disp;
1119 
1122  t += dt;
1123 
1124  if (write < t*100)
1125  {
1126  vd.deleteGhost();
1127  vd.write_frame("Geometry",write,VTK_WRITER | FORMAT_BINARY);
1128  vd.getDecomposition().write("dec" + std::to_string(write));
1129  vd.ghost_get<type,rho,Pressure,velocity>(SKIP_LABELLING);
1130  write++;
1131 
1132  if (v_cl.getProcessUnitID() == 0)
1133  std::cout << "TIME: " << t << " write " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " TOT disp: " << tot_disp << " " << cnt << std::endl;
1134  }
1135  else
1136  {
1137  if (v_cl.getProcessUnitID() == 0)
1138  std::cout << "TIME: " << t << " " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " TOT disp: " << tot_disp << " " << cnt << std::endl;
1139  }
1140  }
1141 
1142  openfpm_finalize();
1143 }
1144 
void updateVerlet(VerletList< dim, St, Mem_type, shift< dim, St > > &ver, St r_cut, size_t opt=VL_NON_SYMMETRIC)
for each particle get the verlet list
Decomposition & getDecomposition()
Get the decomposition.
bool write_frame(std::string out, size_t iteration, int opt=VTK_WRITER)
Output particle position and properties.
size_t getProcessUnitID()
Get the process unit id.
__device__ __host__ T getLow(int i) const
get the i-coordinate of the low bound interval of the box
Definition: Box.hpp:556
Class for Verlet list implementation.
Second model for dynamic load balancing.
Definition: main.cpp:345
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
static PointIteratorSkin< dim, T, typename vd_type::Decomposition_type > DrawSkin(vd_type &vd, size_t(&sz)[dim], Box< dim, T > &domain, Box< dim, T > &sub_A, Box< dim, T > &sub_B)
Draw particles in a box B excluding the area of a second box A (B - A)
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:27
vector_dist_iterator getGhostIterator() const
Get the iterator across the position of the ghost particles.
void addComputationCosts(const self &vd, Model md=Model())
Add the computation cost on the decomposition coming from the particles.
double getwct()
Return the elapsed real time.
Definition: timer.hpp:130
void remove(openfpm::vector< size_t > &keys, size_t start=0)
Remove a set of elements from the distributed vector.
Definition: Ghost.hpp:39
Implementation of VCluster class.
Definition: VCluster.hpp:58
openfpm::vector_key_iterator_seq< typename vrl::Mem_type_type::local_index_type > getParticleIteratorCRS(vrl &NN)
Get a special particle iterator able to iterate across particles using symmetric crossing scheme.
void execute()
Execute all the requests.
This class define the domain decomposition interface.
void deleteGhost()
Delete the particles on the ghost.
auto getLastPos() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element.
void map(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor.
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition: Point.hpp:172
size_t size_local() const
return the local size of the vector
void ghost_get(size_t opt=WITH_POSITION)
It synchronize the properties and position of the ghost particles.
void add()
Add local particle.
This class represent an N-dimensional box.
Definition: Box.hpp:60
void sum(T &num)
Sum the numbers across all processors and get the result.
static PointIterator< dim, T, typename vd_type::Decomposition_type > DrawBox(vd_type &vd, size_t(&sz)[dim], Box< dim, T > &domain, Box< dim, T > &sub)
Draw particles in a box.
VerletL getVerletCrs(St r_cut)
for each particle get the symmetric verlet list
Distributed vector.
void max(T &num)
Get the maximum number across all processors (or reduction with infinity norm)
vect_dist_key_dx get()
Get the actual key.
Model for Dynamic load balancing.
Definition: main.cpp:221
__device__ __host__ T getHigh(int i) const
get the high interval of the box
Definition: Box.hpp:567
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
Class for cpu time benchmarking.
Definition: timer.hpp:27