OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
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 double 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 
753  }
754 
755  vd.template getProp<velocity_prev>(a)[0] = velX;
756  vd.template getProp<velocity_prev>(a)[1] = velY;
757  vd.template getProp<velocity_prev>(a)[2] = velZ;
758  vd.template getProp<rho_prev>(a) = rhop;
759 
760  ++part;
761  }
762 
765  Vcluster & v_cl = create_vcluster();
766  v_cl.max(max_disp);
767  v_cl.execute();
768 
769  max_disp = sqrt(max_disp);
770 
773  // increment the iteration counter
774  cnt++;
775 }
776 
778 void euler_int(particles & vd, double dt, double & max_disp)
780 {
781  // list of the particle to remove
782  to_remove.clear();
783 
784  // particle iterator
785  auto part = vd.getDomainIterator();
786 
787  double dt205 = dt*dt*0.5;
788  double dt2 = dt*2.0;
789 
790  max_disp = 0;
791 
792  // For each particle ...
793  while (part.isNext())
794  {
795  // ... a
796  auto a = part.get();
797 
798  // if the particle is boundary
799  if (vd.template getProp<type>(a) == BOUNDARY)
800  {
801  // Update rho
802  double rhop = vd.template getProp<rho>(a);
803 
804  // Update only the density
805  vd.template getProp<velocity>(a)[0] = 0.0;
806  vd.template getProp<velocity>(a)[1] = 0.0;
807  vd.template getProp<velocity>(a)[2] = 0.0;
808  double rhonew = vd.template getProp<rho>(a) + dt*vd.template getProp<drho>(a);
809  vd.template getProp<rho>(a) = (rhonew < rho_zero)?rho_zero:rhonew;
810 
811  vd.template getProp<rho_prev>(a) = rhop;
812 
813  ++part;
814  continue;
815  }
816 
817  //-Calculate displacement and update position / Calcula desplazamiento y actualiza posicion.
818  double dx = vd.template getProp<velocity>(a)[0]*dt + vd.template getProp<force>(a)[0]*dt205;
819  double dy = vd.template getProp<velocity>(a)[1]*dt + vd.template getProp<force>(a)[1]*dt205;
820  double dz = vd.template getProp<velocity>(a)[2]*dt + vd.template getProp<force>(a)[2]*dt205;
821 
822  vd.getPos(a)[0] += dx;
823  vd.getPos(a)[1] += dy;
824  vd.getPos(a)[2] += dz;
825 
826  double d2 = dx*dx + dy*dy + dz*dz;
827 
828  max_disp = (max_disp > d2)?max_disp:d2;
829 
830  double velX = vd.template getProp<velocity>(a)[0];
831  double velY = vd.template getProp<velocity>(a)[1];
832  double velZ = vd.template getProp<velocity>(a)[2];
833  double rhop = vd.template getProp<rho>(a);
834 
835  vd.template getProp<velocity>(a)[0] = vd.template getProp<velocity>(a)[0] + vd.template getProp<force>(a)[0]*dt;
836  vd.template getProp<velocity>(a)[1] = vd.template getProp<velocity>(a)[1] + vd.template getProp<force>(a)[1]*dt;
837  vd.template getProp<velocity>(a)[2] = vd.template getProp<velocity>(a)[2] + vd.template getProp<force>(a)[2]*dt;
838  vd.template getProp<rho>(a) = vd.template getProp<rho>(a) + dt*vd.template getProp<drho>(a);
839 
840  // Check if the particle go out of range in space and in density
841  if (vd.getPos(a)[0] < 0.000263878 || vd.getPos(a)[1] < 0.000263878 || vd.getPos(a)[2] < 0.000263878 ||
842  vd.getPos(a)[0] > 0.000263878+1.59947 || vd.getPos(a)[1] > 0.000263878+0.672972 || vd.getPos(a)[2] > 0.000263878+0.903944 ||
843  vd.template getProp<rho>(a) < RhoMin || vd.template getProp<rho>(a) > RhoMax)
844  {
845  to_remove.add(a.getKey());
846  }
847 
848  vd.template getProp<velocity_prev>(a)[0] = velX;
849  vd.template getProp<velocity_prev>(a)[1] = velY;
850  vd.template getProp<velocity_prev>(a)[2] = velZ;
851  vd.template getProp<rho_prev>(a) = rhop;
852 
853  ++part;
854  }
855 
856  Vcluster & v_cl = create_vcluster();
857  v_cl.max(max_disp);
858  v_cl.execute();
859 
860  max_disp = sqrt(max_disp);
861 
862  // increment the iteration counter
863  cnt++;
864 }
865 
866 int main(int argc, char* argv[])
867 {
868  // initialize the library
869  openfpm_init(&argc,&argv);
870 
871  // Here we define our domain a 2D box with internals from 0 to 1.0 for x and y
872  Box<3,double> domain({-0.05,-0.05,-0.05},{1.7010,0.7065,0.5025});
873  size_t sz[3] = {207,90,66};
874 
875  // Fill W_dap
876  W_dap = 1.0/Wab(H/1.5);
877 
878  // Here we define the boundary conditions of our problem
879  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
880 
883  double skin = 0.25 * 2*H;
884  double r_gskin = 2*H + skin;
885 
886  // extended boundary around the domain, and the processor domain
887  // by the support of the cubic kernel
888  Ghost<3,double> g(r_gskin);
889 
892  // Eliminating the lower part of the ghost
893  // We are using CRS scheme
894  g.setLow(0,0.0);
895  g.setLow(1,0.0);
896  g.setLow(2,0.0);
897 
900  particles vd(0,domain,bc,g,BIND_DEC_TO_GHOST);
901 
904  // You can ignore all these dp/2.0 is a trick to reach the same initialization
905  // of Dual-SPH that use a different criteria to draw particles
906  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});
907 
908  // return an iterator to the fluid particles to add to vd
909  auto fluid_it = DrawParticles::DrawBox(vd,sz,domain,fluid_box);
910 
911  // here we fill some of the constants needed by the simulation
912  max_fluid_height = fluid_it.getBoxMargins().getHigh(2);
913  h_swl = fluid_it.getBoxMargins().getHigh(2) - fluid_it.getBoxMargins().getLow(2);
914  B = (coeff_sound)*(coeff_sound)*gravity*h_swl*rho_zero / gamma_;
915  cbar = coeff_sound * sqrt(gravity * h_swl);
916 
917  // for each particle inside the fluid box ...
918  while (fluid_it.isNext())
919  {
920  // ... add a particle ...
921  vd.add();
922 
923  // ... and set it position ...
924  vd.getLastPos()[0] = fluid_it.get().get(0);
925  vd.getLastPos()[1] = fluid_it.get().get(1);
926  vd.getLastPos()[2] = fluid_it.get().get(2);
927 
928  // and its type.
929  vd.template getLastProp<type>() = FLUID;
930 
931  // We also initialize the density of the particle and the hydro-static pressure given by
932  //
933  // rho_zero*g*h = P
934  //
935  // rho_p = (P/B + 1)^(1/Gamma) * rho_zero
936  //
937 
938  vd.template getLastProp<Pressure>() = rho_zero * gravity * (max_fluid_height - fluid_it.get().get(2));
939 
940  vd.template getLastProp<rho>() = pow(vd.template getLastProp<Pressure>() / B + 1, 1.0/gamma_) * rho_zero;
941  vd.template getLastProp<rho_prev>() = vd.template getLastProp<rho>();
942  vd.template getLastProp<velocity>()[0] = 0.0;
943  vd.template getLastProp<velocity>()[1] = 0.0;
944  vd.template getLastProp<velocity>()[2] = 0.0;
945 
946  vd.template getLastProp<velocity_prev>()[0] = 0.0;
947  vd.template getLastProp<velocity_prev>()[1] = 0.0;
948  vd.template getLastProp<velocity_prev>()[2] = 0.0;
949 
950  // next fluid particle
951  ++fluid_it;
952  }
953 
954  // Recipient
955  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});
956  Box<3,double> recipient2({dp,dp,dp},{1.6-dp/2.0,0.67-dp/2.0,0.4+dp/2.0});
957 
958  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});
959  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});
960  Box<3,double> obstacle3({0.9+dp,0.24,0.0},{1.02,0.36,0.45});
961 
963  holes.add(recipient2);
964  holes.add(obstacle1);
965  auto bound_box = DrawParticles::DrawSkin(vd,sz,domain,holes,recipient1);
966 
967  while (bound_box.isNext())
968  {
969  vd.add();
970 
971  vd.getLastPos()[0] = bound_box.get().get(0);
972  vd.getLastPos()[1] = bound_box.get().get(1);
973  vd.getLastPos()[2] = bound_box.get().get(2);
974 
975  vd.template getLastProp<type>() = BOUNDARY;
976  vd.template getLastProp<rho>() = rho_zero;
977  vd.template getLastProp<rho_prev>() = rho_zero;
978  vd.template getLastProp<velocity>()[0] = 0.0;
979  vd.template getLastProp<velocity>()[1] = 0.0;
980  vd.template getLastProp<velocity>()[2] = 0.0;
981 
982  vd.template getLastProp<velocity_prev>()[0] = 0.0;
983  vd.template getLastProp<velocity_prev>()[1] = 0.0;
984  vd.template getLastProp<velocity_prev>()[2] = 0.0;
985 
986  ++bound_box;
987  }
988 
989  auto obstacle_box = DrawParticles::DrawSkin(vd,sz,domain,obstacle2,obstacle1);
990 
991  while (obstacle_box.isNext())
992  {
993  vd.add();
994 
995  vd.getLastPos()[0] = obstacle_box.get().get(0);
996  vd.getLastPos()[1] = obstacle_box.get().get(1);
997  vd.getLastPos()[2] = obstacle_box.get().get(2);
998 
999  vd.template getLastProp<type>() = BOUNDARY;
1000  vd.template getLastProp<rho>() = rho_zero;
1001  vd.template getLastProp<rho_prev>() = rho_zero;
1002  vd.template getLastProp<velocity>()[0] = 0.0;
1003  vd.template getLastProp<velocity>()[1] = 0.0;
1004  vd.template getLastProp<velocity>()[2] = 0.0;
1005 
1006  vd.template getLastProp<velocity_prev>()[0] = 0.0;
1007  vd.template getLastProp<velocity_prev>()[1] = 0.0;
1008  vd.template getLastProp<velocity_prev>()[2] = 0.0;
1009 
1010  ++obstacle_box;
1011  }
1012 
1013  vd.map();
1014 
1016  //
1017  //
1018  //
1019 
1020  size_t tot_part = vd.size_local();
1021 
1022  auto & v_cl = create_vcluster();
1023  v_cl.sum(tot_part);
1024  v_cl.execute();
1025  std::cout << "SUM: " << tot_part << std::endl;
1026 
1027  // Now that we fill the vector with particles
1028  ModelCustom md;
1029 
1030  vd.addComputationCosts(md);
1031  vd.getDecomposition().decompose();
1032  vd.map();
1033 
1034  vd.ghost_get<type,rho,Pressure,velocity>();
1035 
1037  auto NN = vd.getVerletCrs(r_gskin);
1040  size_t write = 0;
1041  size_t it = 0;
1042  size_t it_reb = 0;
1043  double t = 0.0;
1044  double tot_disp = 0.0;
1045  double max_disp;
1046  while (t <= t_end)
1047  {
1048  Vcluster & v_cl = create_vcluster();
1049  timer it_time;
1050 
1053  it_reb++;
1054  if (2*tot_disp >= skin)
1055  {
1056  vd.remove(to_remove);
1057 
1058  vd.map();
1059 
1060  if (it_reb > 200)
1061  {
1062  ModelCustom2 md;
1063  vd.addComputationCosts(md);
1064  vd.getDecomposition().redecompose(200);
1065 
1066  vd.map();
1067 
1068  it_reb = 0;
1069 
1070  if (v_cl.getProcessUnitID() == 0)
1071  std::cout << "REBALANCED " << std::endl;
1072 
1073  }
1074 
1075  // Calculate pressure from the density
1076  EqState(vd);
1077 
1078  vd.ghost_get<type,rho,Pressure,velocity>();
1079 
1081  vd.updateVerlet(NN,r_gskin,VL_CRS_SYMMETRIC);
1084  tot_disp = 0.0;
1085 
1086  if (v_cl.getProcessUnitID() == 0)
1087  std::cout << "RECONSTRUCT Verlet " << std::endl;
1088  }
1089  else
1090  {
1091  // Calculate pressure from the density
1092  EqState(vd);
1093 
1094  vd.ghost_get<type,rho,Pressure,velocity>(SKIP_LABELLING);
1095  }
1096 
1099  double max_visc = 0.0;
1100 
1101  // Calc forces
1102  calc_forces(vd,NN,max_visc);
1103 
1104  // Get the maximum viscosity term across processors
1105  v_cl.max(max_visc);
1106  v_cl.execute();
1107 
1108  // Calculate delta t integration
1109  double dt = calc_deltaT(vd,max_visc);
1110 
1113  // VerletStep or euler step
1114  it++;
1115  if (it < 40)
1116  verlet_int(vd,dt,max_disp);
1117  else
1118  {
1119  euler_int(vd,dt,max_disp);
1120  it = 0;
1121  }
1122 
1123  tot_disp += max_disp;
1124 
1127  t += dt;
1128 
1129  if (write < t*100)
1130  {
1131  vd.deleteGhost();
1132  vd.write_frame("Geometry",write,VTK_WRITER | FORMAT_BINARY);
1133  vd.getDecomposition().write("dec" + std::to_string(write));
1134  vd.ghost_get<type,rho,Pressure,velocity>(SKIP_LABELLING);
1135  write++;
1136 
1137  if (v_cl.getProcessUnitID() == 0)
1138  std::cout << "TIME: " << t << " write " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " TOT disp: " << tot_disp << " " << cnt << std::endl;
1139  }
1140  else
1141  {
1142  if (v_cl.getProcessUnitID() == 0)
1143  std::cout << "TIME: " << t << " " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " TOT disp: " << tot_disp << " " << cnt << std::endl;
1144  }
1145  }
1146 
1147  openfpm_finalize();
1148 }
1149 
void sum(T &num)
Sum the numbers across all processors and get the result.
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
T getLow(int i) const
get the i-coordinate of the low bound interval of the box
Definition: Box.hpp:479
openfpm::vector_key_iterator_seq< typename vrl::Mem_type_type::loc_index > getParticleIteratorCRS(vrl &NN)
Get a special particle iterator able to iterate across particles using symmetric crossing scheme...
size_t getProcessUnitID()
Get the process unit id.
static PointIteratorSkin< dim, T, Decomposition > DrawSkin(vector_dist< dim, T, aggr, layout, layout_base, Decomposition > &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)
void execute()
Execute all the requests.
Class for Verlet list implementation.
bool write_frame(std::string out, size_t iteration, int opt=VTK_WRITER)
Output particle position and properties.
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.
T getHigh(int i) const
get the high interval of the box
Definition: Box.hpp:490
Decomposition & getDecomposition()
Get the decomposition.
VerletL getVerletCrs(St r_cut)
for each particle get the symmetric verlet list
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:22
vector_dist_iterator getGhostIterator() const
Get the iterator across the position of the ghost particles.
void max(T &num)
Get the maximum number across all processors (or reduction with infinity norm)
void deleteGhost()
Delete the particles on the ghost.
double getwct()
Return the elapsed real time.
Definition: timer.hpp:108
Definition: Ghost.hpp:39
Implementation of VCluster class.
Definition: VCluster.hpp:36
This class define the domain decomposition interface.
void remove(openfpm::vector< size_t > &keys, size_t start=0)
Remove a set of elements from the distributed vector.
size_t size_local() const
return the local size of the vector
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
const T & get(size_t i) const
Get coordinate.
Definition: Point.hpp:142
void addComputationCosts(const self &vd, Model md=Model())
Add the computation cost on the decomposition coming from the particles.
void map(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor...
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:56
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
Distributed vector.
vect_dist_key_dx get()
Get the actual key.
auto getLastPos() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element.
Model for Dynamic load balancing.
Definition: main.cpp:221
Class for cpu time benchmarking.
Definition: timer.hpp:25
static PointIterator< dim, T, Decomposition > DrawBox(vector_dist< dim, T, aggr, layout, layout_base, Decomposition > &vd, size_t(&sz)[dim], Box< dim, T > &domain, Box< dim, T > &sub)
Draw particles in a box.