OpenFPM  5.2.0
Project that contain the implementation of distributed structures
main2.cpp
1 
59 //#define SE_CLASS1
60 //#define STOP_ON_ERROR
61 
63 #include "Vector/vector_dist.hpp"
64 #include "Operators/Vector/vector_dist_operators.hpp"
65 #include "Vector/vector_dist_subset.hpp"
66 #include "OdeIntegrators/OdeIntegrators.hpp"
67 #include "Draw/DrawParticles.hpp"
68 
69 #include <math.h>
71 
116 // A constant to indicate boundary particles
117 #define BOUNDARY 0
118 
119 // A constant to indicate fluid particles
120 #define FLUID 1
121 
122 // initial spacing between particles dp in the formulas
123 const double dp = 0.0085;
124 // Maximum height of the fluid water
125 // is going to be calculated and filled later on
126 double h_swl = 0.0;
127 
128 // c_s in the formulas (constant used to calculate the sound speed)
129 const double coeff_sound = 20.0;
130 
131 // gamma in the formulas
132 const double gamma_ = 7.0;
133 
134 // sqrt(3.0*dp*dp) support of the kernel
135 const double H = 0.0147224318643;
136 
137 // Eta in the formulas
138 const double Eta2 = 0.01 * H*H;
139 
140 // alpha in the formula
141 const double visco = 0.1;
142 
143 // cbar in the formula (calculated later)
144 double cbar = 0.0;
145 
146 // Mass of the fluid particles
147 const double MassFluid = 0.000614125;
148 
149 // Mass of the boundary particles
150 const double MassBound = 0.000614125;
151 
152 // End simulation time
153 #ifdef TEST_RUN
154 const double t_end = 0.001;
155 #else
156 const double t_end = 1.5;
157 #endif
158 
159 // Gravity acceleration
160 const double gravity = 9.81;
161 
162 // Reference densitu 1000Kg/m^3
163 const double RhoZero = 1000.0;
164 
165 // Filled later require h_swl, it is b in the formulas
166 double B = 0.0;
167 
168 // Constant used to define time integration
169 const double CFLnumber = 0.2;
170 
171 // Minimum T
172 const double DtMin = 0.00001;
173 
174 // Minimum Rho allowed
175 const double RhoMin = 700.0;
176 
177 // Maximum Rho allowed
178 const double RhoMax = 1300.0;
179 
180 // Filled in initialization
181 double max_fluid_height = 0.0;
182 
183 // Properties
184 
185 // FLUID or BOUNDARY
186 const size_t TYPE = 0;
187 
188 // Density
189 const int RHO = 1;
190 
191 // Density at step n-1
192 const int RHO_PREV = 2;
193 
194 // Density temporal variable
195 // needed for template expression
196 const int RHO_TMP = 8;
197 
198 // Pressure
199 const int PRESSURE = 3;
200 
201 // Delta rho calculated in the force calculation
202 const int DRHO = 4;
203 
204 // calculated force
205 const int FORCE = 5;
206 
207 // velocity
208 const int VELOCITY = 6;
209 
210 // velocity at previous step
211 const int VELOCITY_PREV = 7;
212 
213 // velocity temporal variable
214 // needed for template expression
215 const int VELOCITY_TMP = 9;
216 
221 // Type of the vector containing particles
223 // | | | | | | | | | |
224 // | | | | | | | | | |
225 // type density density Pressure delta force velocity velocity density velocity
226 // at n-1 density at n - 1
228 // typedef vector_dist_ws<3,double,property_type> vector_dist_type;
230 
231 // global variable dt to be accessible in RHSFunctor
232 double dt;
233 
234 // global iteration variable to be accessible in RHSFunctor
235 size_t iteration;
236 
241 struct ModelCustom
242 {
243  template<typename Decomposition, typename vector> inline void addComputation(Decomposition & dec,
244  vector & vectorDist,
245  size_t v,
246  size_t p)
247  {
248  if (vectorDist.template getProp<TYPE>(p) == FLUID)
249  dec.addComputationCost(v,4);
250  else
251  dec.addComputationCost(v,3);
252  }
253 
254  template<typename Decomposition> inline void applyModel(Decomposition & dec, size_t v)
255  {
256  dec.setSubSubDomainComputationCost(v, dec.getSubSubDomainComputationCost(v) * dec.getSubSubDomainComputationCost(v));
257  }
258 
259  double distributionTol()
260  {
261  return 1.01;
262  }
263 };
264 
282 inline void EqState(vector_dist_type & vectorDist)
283 {
284  auto it = vectorDist.getDomainIterator();
285 
286  while (it.isNext())
287  {
288  auto a = it.get();
289 
290  double rho_a = vectorDist.template getProp<RHO>(a);
291  double rho_frac = rho_a / RhoZero;
292 
293  vectorDist.template getProp<PRESSURE>(a) = B*( rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac - 1.0);
294 
295  ++it;
296  }
297 }
298 
317 const double a2 = 1.0/M_PI/H/H/H;
318 
319 inline double Wab(double r)
320 {
321  r /= H;
322 
323  if (r < 1.0)
324  return (1.0 - 3.0/2.0*r*r + 3.0/4.0*r*r*r)*a2;
325  else if (r < 2.0)
326  return (1.0/4.0*(2.0 - r)*(2.0 - r)*(2.0 - r))*a2;
327  else
328  return 0.0;
329 }
330 
348 const double c1 = -3.0/M_PI/H/H/H/H;
349 const double d1 = 9.0/4.0/M_PI/H/H/H/H;
350 const double c2 = -3.0/4.0/M_PI/H/H/H/H;
351 const double a2_4 = 0.25*a2;
352 // Filled later
353 double W_dap = 0.0;
354 
355 inline void DWab(Point<3,double> & dx, Point<3,double> & DW, double r, bool print)
356 {
357  const double qq=r/H;
358 
359  double qq2 = qq * qq;
360  double fac1 = (c1*qq + d1*qq2)/r;
361  double b1 = (qq < 1.0)?1.0f:0.0f;
362 
363  double wqq = (2.0 - qq);
364  double fac2 = c2 * wqq * wqq / r;
365  double b2 = (qq >= 1.0 && qq < 2.0)?1.0f:0.0f;
366 
367  double factor = (b1*fac1 + b2*fac2);
368 
369  DW.get(0) = factor * dx.get(0);
370  DW.get(1) = factor * dx.get(1);
371  DW.get(2) = factor * dx.get(2);
372 }
373 
394 // Tensile correction
395 inline double Tensile(double r, double rhoa, double rhob, double prs1, double prs2)
396 {
397  const double qq=r/H;
398  //-Cubic Spline kernel
399  double wab;
400  if(r>H)
401  {
402  double wqq1=2.0f-qq;
403  double wqq2=wqq1*wqq1;
404 
405  wab=a2_4*(wqq2*wqq1);
406  }
407  else
408  {
409  double wqq2=qq*qq;
410  double wqq3=wqq2*qq;
411 
412  wab=a2*(1.0f-1.5f*wqq2+0.75f*wqq3);
413  }
414 
415  //-Tensile correction.
416  double fab=wab*W_dap;
417  fab*=fab; fab*=fab; //fab=fab^4
418  const double tensilp1=(prs1/(rhoa*rhoa))*(prs1>0? 0.01: -0.2);
419  const double tensilp2=(prs2/(rhob*rhob))*(prs2>0? 0.01: -0.2);
420 
421  return (fab*(tensilp1+tensilp2));
422 }
423 
442 inline double Pi(const Point<3,double> & dr, double rr2, Point<3,double> & dv, double rhoa, double rhob, double massb, double & visc)
443 {
444  const double dot = dr.get(0)*dv.get(0) + dr.get(1)*dv.get(1) + dr.get(2)*dv.get(2);
445  const double dot_rr2 = dot/(rr2+Eta2);
446  visc=std::max(dot_rr2,visc);
447 
448  if(dot < 0)
449  {
450  const float amubar=H*dot_rr2;
451  const float robar=(rhoa+rhob)*0.5f;
452  const float pi_visc=(-visco*cbar*amubar/robar);
453 
454  return pi_visc;
455  }
456  else
457  return 0.0;
458 }
459 
477 template<typename CellList> inline void calc_forces(vector_dist_type & vectorDist, CellList & cellList, double & max_visc)
478 {
479  auto part = vectorDist.getDomainIterator();
480 
481  // Update the cell-list
482  vectorDist.updateCellList(cellList);
483 
484  // For each particle ...
485  while (part.isNext())
486  {
487  // ... a
488  auto a = part.get();
489 
490  // Get the position xp of the particle
491  Point<3,double> xa = vectorDist.getPos(a);
492 
493  // Take the mass of the particle dependently if it is FLUID or BOUNDARY
494  double massa = (vectorDist.getProp<TYPE>(a) == FLUID)?MassFluid:MassBound;
495 
496  // Get the density of the of the particle a
497  double rhoa = vectorDist.getProp<RHO>(a);
498 
499  // Get the pressure of the particle a
500  double Pa = vectorDist.getProp<PRESSURE>(a);
501 
502  // Get the Velocity of the particle a
503  Point<3,double> va = vectorDist.getProp<VELOCITY>(a);
504 
505  // Reset the force counter (- gravity on zeta direction)
506  vectorDist.template getProp<FORCE>(a)[0] = 0.0;
507  vectorDist.template getProp<FORCE>(a)[1] = 0.0;
508  vectorDist.template getProp<FORCE>(a)[2] = -gravity;
509  vectorDist.template getProp<DRHO>(a) = 0.0;
510 
511  // We threat FLUID particle differently from BOUNDARY PARTICLES ...
512  if (vectorDist.getProp<TYPE>(a) != FLUID)
513  {
514  // If it is a boundary particle calculate the delta rho based on equation 2
515  // This require to run across the neighborhoods particles of a
516  auto Np = cellList.getNNIteratorBox(cellList.getCell(vectorDist.getPos(a)));
517 
518  // For each neighborhood particle
519  while (Np.isNext() == true)
520  {
521  // ... q
522  auto b = Np.get();
523 
524  // Get the position xp of the particle
525  Point<3,double> xb = vectorDist.getPos(b);
526 
527  // if (p == q) skip this particle
528  if (a.getKey() == b) {++Np; continue;};
529 
530  // get the mass of the particle
531  double massb = (vectorDist.getProp<TYPE>(b) == FLUID)?MassFluid:MassBound;
532 
533  // Get the velocity of the particle b
534  Point<3,double> vb = vectorDist.getProp<VELOCITY>(b);
535 
536  // Get the pressure and density of particle b
537  double Pb = vectorDist.getProp<PRESSURE>(b);
538  double rhob = vectorDist.getProp<RHO>(b);
539 
540  // Get the distance between p and q
541  Point<3,double> dr = xa - xb;
542  // take the norm of this vector
543  double r2 = norm2(dr);
544 
545  // If the particles interact ...
546  if (r2 < 4.0*H*H)
547  {
548  // ... calculate delta rho
549  double r = sqrt(r2);
550 
551  Point<3,double> dv = va - vb;
552 
553  Point<3,double> DW;
554  DWab(dr,DW,r,false);
555 
556  const double dot = dr.get(0)*dv.get(0) + dr.get(1)*dv.get(1) + dr.get(2)*dv.get(2);
557  const double dot_rr2 = dot/(r2+Eta2);
558  max_visc=std::max(dot_rr2,max_visc);
559 
560  vectorDist.getProp<DRHO>(a) += massb*(dv.get(0)*DW.get(0)+dv.get(1)*DW.get(1)+dv.get(2)*DW.get(2));
561  }
562 
563  ++Np;
564  }
565  }
566  else
567  {
568  // If it is a fluid particle calculate based on equation 1 and 2
569 
570  // Get an iterator over the neighborhood particles of p
571  auto Np = cellList.getNNIteratorBox(cellList.getCell(vectorDist.getPos(a)));
572 
573  // For each neighborhood particle
574  while (Np.isNext() == true)
575  {
576  // ... q
577  auto b = Np.get();
578 
579  // Get the position xp of the particle
580  Point<3,double> xb = vectorDist.getPos(b);
581 
582  // if (p == q) skip this particle
583  if (a.getKey() == b) {++Np; continue;};
584 
585  double massb = (vectorDist.getProp<TYPE>(b) == FLUID)?MassFluid:MassBound;
586  Point<3,double> vb = vectorDist.getProp<VELOCITY>(b);
587  double Pb = vectorDist.getProp<PRESSURE>(b);
588  double rhob = vectorDist.getProp<RHO>(b);
589 
590  // Get the distance between p and q
591  Point<3,double> dr = xa - xb;
592  // take the norm of this vector
593  double r2 = norm2(dr);
594 
595  // if they interact
596  if (r2 < 4.0*H*H)
597  {
598  double r = sqrt(r2);
599 
600  Point<3,double> v_rel = va - vb;
601 
602  Point<3,double> DW;
603  DWab(dr,DW,r,false);
604 
605  double factor = - massb*((vectorDist.getProp<PRESSURE>(a) + vectorDist.getProp<PRESSURE>(b)) / (rhoa * rhob) + Tensile(r,rhoa,rhob,Pa,Pb) + Pi(dr,r2,v_rel,rhoa,rhob,massb,max_visc));
606 
607  vectorDist.getProp<FORCE>(a)[0] += factor * DW.get(0);
608  vectorDist.getProp<FORCE>(a)[1] += factor * DW.get(1);
609  vectorDist.getProp<FORCE>(a)[2] += factor * DW.get(2);
610 
611  vectorDist.getProp<DRHO>(a) += massb*(v_rel.get(0)*DW.get(0)+v_rel.get(1)*DW.get(1)+v_rel.get(2)*DW.get(2));
612  }
613 
614  ++Np;
615  }
616  }
617 
618  ++part;
619  }
620 }
621 
640 void max_acceleration_and_velocity(vector_dist_type & vectorDist, double & max_acc, double & max_vel)
641 {
642  // Calculate the maximum acceleration
643  auto part = vectorDist.getDomainIterator();
644 
645  while (part.isNext())
646  {
647  auto a = part.get();
648 
649  Point<3,double> acc(vectorDist.getProp<FORCE>(a));
650  double acc2 = norm2(acc);
651 
652  Point<3,double> vel(vectorDist.getProp<VELOCITY>(a));
653  double vel2 = norm2(vel);
654 
655  if (vel2 >= max_vel)
656  max_vel = vel2;
657 
658  if (acc2 >= max_acc)
659  max_acc = acc2;
660 
661  ++part;
662  }
663  max_acc = sqrt(max_acc);
664  max_vel = sqrt(max_vel);
665 
666  Vcluster<> & v_cl = create_vcluster();
667  v_cl.max(max_acc);
668  v_cl.max(max_vel);
669  v_cl.execute();
670 }
671 
697 double calc_deltaT(vector_dist_type & vectorDist, double ViscDtMax)
698 {
699  double Maxacc = 0.0;
700  double Maxvel = 0.0;
701  max_acceleration_and_velocity(vectorDist,Maxacc,Maxvel);
702 
703  //-dt1 depends on force per unit mass.
704  const double dt_f = (Maxacc)?sqrt(H/Maxacc):std::numeric_limits<int>::max();
705 
706  //-dt2 combines the Courant and the viscous time-step controls.
707  const double dt_cv = H/(std::max(cbar,Maxvel*10.) + H*ViscDtMax);
708 
709  //-dt new value of time step.
710  double dt=double(CFLnumber)*std::min(dt_f,dt_cv);
711  if(dt<double(DtMin))
712  dt=double(DtMin);
713 
714  return dt;
715 }
716 
740 template<typename vector_dist_type, typename CellList_type>
741 struct RHSFunctor
742 {
743  CellList_type &cellList;
744  vector_dist_type &vectorDist;
745 
746  //Constructor
747  RHSFunctor(vector_dist_type &vectorDist, CellList_type &cellList) :
748  cellList(cellList),
749  vectorDist(vectorDist)
750  {}
751 
752  void operator()( state_type_7d_ofp &X , state_type_7d_ofp &dxdt , const double t)
753  {
754  double dt05 = dt*0.5;
755  double dt2 = dt*2.0;
756 
757  auto posExpression = getV<POS_PROP>(vectorDist);
758  auto forceExpression = getV<FORCE>(vectorDist);
759  auto drhoExpression = getV<DRHO>(vectorDist);
760  auto typeExpression = getV<TYPE>(vectorDist);
761 
762  auto rhoExpression = getV<RHO>(vectorDist);
763  auto rho_prevExpression = getV<RHO_PREV>(vectorDist);
764 
765  auto velocityExpression = getV<VELOCITY>(vectorDist);
766  auto velocity_prevExpression = getV<VELOCITY_PREV>(vectorDist);
767 
768  if (iteration < 40) {
769  X.data.get<0>() = rho_prevExpression;
770 
771  X.data.get<4>() = velocity_prevExpression[0];
772  X.data.get<5>() = velocity_prevExpression[1];
773  X.data.get<6>() = velocity_prevExpression[2];
774 
775  dxdt.data.get<0>() = 2*drhoExpression;
776 
777  dxdt.data.get<1>() = velocityExpression[0] + forceExpression[0]*dt05 * typeExpression;
778  dxdt.data.get<2>() = velocityExpression[1] + forceExpression[1]*dt05 * typeExpression;
779  dxdt.data.get<3>() = velocityExpression[2] + forceExpression[2]*dt05 * typeExpression;
780 
781  dxdt.data.get<4>() = forceExpression[0]*2 * typeExpression;
782  dxdt.data.get<5>() = forceExpression[1]*2 * typeExpression;
783  dxdt.data.get<6>() = forceExpression[2]*2 * typeExpression;
784  }
785 
786  else
787  {
788  dxdt.data.get<0>() = drhoExpression;
789 
790  dxdt.data.get<1>() = velocityExpression[0] + forceExpression[0]*dt05 * typeExpression;
791  dxdt.data.get<2>() = velocityExpression[1] + forceExpression[1]*dt05 * typeExpression;
792  dxdt.data.get<3>() = velocityExpression[2] + forceExpression[2]*dt05 * typeExpression;
793 
794  dxdt.data.get<4>() = forceExpression[0] * typeExpression;
795  dxdt.data.get<5>() = forceExpression[1] * typeExpression;
796  dxdt.data.get<6>() = forceExpression[2] * typeExpression;
797  }
798  }
799 };
801 
835 openfpm::vector<size_t> to_remove;
836 
837 void checkPosPrpLimits(vector_dist_type & vectorDist)
838 {
839  // list of the particle to remove
840  to_remove.clear();
841 
842  // particle iterator
843  auto part = vectorDist.getDomainIterator();
844 
845  // For each particle ...
846  while (part.isNext())
847  {
848  // ... a
849  auto a = part.get();
850 
851  // if the particle is boundary
852  if (vectorDist.template getProp<TYPE>(a) == BOUNDARY)
853  {
854  double rho = vectorDist.template getProp<RHO>(a);
855 
856  if (rho < RhoZero)
857  vectorDist.template getProp<RHO>(a) = RhoZero;
858 
859  ++part;
860  continue;
861  }
862 
863  // Check if the particle go out of range in space and in density
864  if (vectorDist.getPos(a)[0] < 0.000263878 || vectorDist.getPos(a)[1] < 0.000263878 || vectorDist.getPos(a)[2] < 0.000263878 ||
865  vectorDist.getPos(a)[0] > 0.000263878+1.59947 || vectorDist.getPos(a)[1] > 0.000263878+0.672972 || vectorDist.getPos(a)[2] > 0.000263878+0.903944 ||
866  vectorDist.template getProp<RHO>(a) < RhoMin || vectorDist.template getProp<RHO>(a) > RhoMax)
867  {
868  to_remove.add(a.getKey());
869  }
870 
871  ++part;
872  }
873 
874  // remove the particles
875  vectorDist.remove(to_remove,0);
876 }
877 
905 template<typename Vector, typename CellList>
906 inline void sensor_pressure(Vector & vectorDist,
907  CellList & cellList,
910 {
911  Vcluster<> & v_cl = create_vcluster();
912 
913  press_t.add();
914 
915  for (size_t i = 0 ; i < probes.size() ; i++)
916  {
917  float press_tmp = 0.0f;
918  float tot_ker = 0.0;
919 
920  // if the probe is inside the processor domain
921  if (vectorDist.getDecomposition().isLocal(probes.get(i)) == true)
922  {
923  // Get the position of the probe i
924  Point<3,double> xp = probes.get(i);
925 
926  // get the iterator over the neighbohood particles of the probes position
927  auto itg = cellList.getNNIteratorBox(cellList.getCell(probes.get(i)));
928  while (itg.isNext())
929  {
930  auto q = itg.get();
931 
932  // Only the fluid particles are importants
933  if (vectorDist.template getProp<TYPE>(q) != FLUID)
934  {
935  ++itg;
936  continue;
937  }
938 
939  // Get the position of the neighborhood particle q
940  Point<3,double> xq = vectorDist.getPos(q);
941 
942  // Calculate the contribution of the particle to the pressure
943  // of the probe
944  double r = sqrt(norm2(xp - xq));
945 
946  double ker = Wab(r) * (MassFluid / RhoZero);
947 
948  // Also keep track of the calculation of the summed
949  // kernel
950  tot_ker += ker;
951 
952  // Add the total pressure contribution
953  press_tmp += vectorDist.template getProp<PRESSURE>(q) * ker;
954 
955  // next neighborhood particle
956  ++itg;
957  }
958 
959  // We calculate the pressure normalizing the
960  // sum over all kernels
961  if (tot_ker == 0.0)
962  press_tmp = 0.0;
963  else
964  press_tmp = 1.0 / tot_ker * press_tmp;
965 
966  }
967 
968  // This is not necessary in principle, but if you
969  // want to make all processor aware of the history of the calculated
970  // pressure we have to execute this
971  v_cl.sum(press_tmp);
972  v_cl.execute();
973 
974  // We add the calculated pressure into the history
975  press_t.last().add(press_tmp);
976  }
977 }
978 
981 int main(int argc, char* argv[])
982 {
999 
1000  // initialize the library
1001  openfpm_init(&argc,&argv);
1002 
1003  // It contain for each time-step the value detected by the probes
1006 
1007  probes.add({0.8779,0.3,0.02});
1008  probes.add({0.754,0.31,0.02});
1009 
1010  // Here we define our domain a 2D box with internals from 0 to 1.0 for x and y
1011  Box<3,double> domain({-0.05,-0.05,-0.05},{1.7010,0.7065,0.5025});
1012  size_t sz[3] = {207,90,66};
1013 
1014  // Fill W_dap
1015  W_dap = 1.0/Wab(H/1.5);
1016 
1017  // Here we define the boundary conditions of our problem
1018  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
1019 
1020  // extended boundary around the domain, and the processor domain
1021  Ghost<3,double> g(2*H);
1022 
1024 
1061 
1062  vector_dist_type vectorDist(0,domain,bc,g,DEC_GRAN(512));
1063 
1065 
1101 
1102  // You can ignore all these dp/2.0 is a trick to reach the same initialization
1103  // of Dual-SPH that use a different criteria to draw particles
1104  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});
1105 
1106  // return an iterator to the fluid particles to add to vectorDist
1107  auto fluid_it = DrawParticles::DrawBox(vectorDist,sz,domain,fluid_box);
1108 
1109  // here we fill some of the constants needed by the simulation
1110  max_fluid_height = fluid_it.getBoxMargins().getHigh(2);
1111  h_swl = fluid_it.getBoxMargins().getHigh(2) - fluid_it.getBoxMargins().getLow(2);
1112  B = (coeff_sound)*(coeff_sound)*gravity*h_swl*RhoZero / gamma_;
1113  cbar = coeff_sound * sqrt(gravity * h_swl);
1114 
1115  // for each particle inside the fluid box ...
1116  while (fluid_it.isNext())
1117  {
1118  // ... add a particle ...
1119  vectorDist.add();
1120 
1121  // ... and set it position ...
1122  vectorDist.getLastPos()[0] = fluid_it.get().get(0);
1123  vectorDist.getLastPos()[1] = fluid_it.get().get(1);
1124  vectorDist.getLastPos()[2] = fluid_it.get().get(2);
1125 
1126  // and its type.
1127  vectorDist.template getLastProp<TYPE>() = FLUID;
1128 
1129  // We also initialize the density of the particle and the hydro-static pressure given by
1130  //
1131  // RhoZero*g*h = P
1132  //
1133  // rho_p = (P/B + 1)^(1/Gamma) * RhoZero
1134  //
1135 
1136  vectorDist.template getLastProp<PRESSURE>() = RhoZero * gravity * (max_fluid_height - fluid_it.get().get(2));
1137 
1138  vectorDist.template getLastProp<RHO>() = pow(vectorDist.template getLastProp<PRESSURE>() / B + 1, 1.0/gamma_) * RhoZero;
1139  vectorDist.template getLastProp<RHO_PREV>() = vectorDist.template getLastProp<RHO>();
1140  vectorDist.template getLastProp<VELOCITY>()[0] = 0.0;
1141  vectorDist.template getLastProp<VELOCITY>()[1] = 0.0;
1142  vectorDist.template getLastProp<VELOCITY>()[2] = 0.0;
1143 
1144  vectorDist.template getLastProp<VELOCITY_PREV>()[0] = 0.0;
1145  vectorDist.template getLastProp<VELOCITY_PREV>()[1] = 0.0;
1146  vectorDist.template getLastProp<VELOCITY_PREV>()[2] = 0.0;
1147 
1148  // next fluid particle
1149  ++fluid_it;
1150  }
1151 
1153 
1178 
1179  // Recipient
1180  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});
1181  Box<3,double> recipient2({dp,dp,dp},{1.6-dp/2.0,0.67-dp/2.0,0.4+dp/2.0});
1182 
1183  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});
1184  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});
1185  Box<3,double> obstacle3({0.9+dp,0.24,0.0},{1.02,0.36,0.45});
1186 
1188  holes.add(recipient2);
1189  holes.add(obstacle1);
1190  auto bound_box = DrawParticles::DrawSkin(vectorDist,sz,domain,holes,recipient1);
1191 
1192  while (bound_box.isNext())
1193  {
1194  vectorDist.add();
1195 
1196  vectorDist.getLastPos()[0] = bound_box.get().get(0);
1197  vectorDist.getLastPos()[1] = bound_box.get().get(1);
1198  vectorDist.getLastPos()[2] = bound_box.get().get(2);
1199 
1200  vectorDist.template getLastProp<TYPE>() = BOUNDARY;
1201  vectorDist.template getLastProp<RHO>() = RhoZero;
1202  vectorDist.template getLastProp<RHO_PREV>() = RhoZero;
1203  vectorDist.template getLastProp<VELOCITY>()[0] = 0.0;
1204  vectorDist.template getLastProp<VELOCITY>()[1] = 0.0;
1205  vectorDist.template getLastProp<VELOCITY>()[2] = 0.0;
1206 
1207  vectorDist.template getLastProp<VELOCITY_PREV>()[0] = 0.0;
1208  vectorDist.template getLastProp<VELOCITY_PREV>()[1] = 0.0;
1209  vectorDist.template getLastProp<VELOCITY_PREV>()[2] = 0.0;
1210 
1211  ++bound_box;
1212  }
1213 
1215 
1233 
1234  auto obstacle_box = DrawParticles::DrawSkin(vectorDist,sz,domain,obstacle2,obstacle1);
1235 
1236  while (obstacle_box.isNext())
1237  {
1238  vectorDist.add();
1239 
1240  vectorDist.getLastPos()[0] = obstacle_box.get().get(0);
1241  vectorDist.getLastPos()[1] = obstacle_box.get().get(1);
1242  vectorDist.getLastPos()[2] = obstacle_box.get().get(2);
1243 
1244  vectorDist.template getLastProp<TYPE>() = BOUNDARY;
1245  vectorDist.template getLastProp<RHO>() = RhoZero;
1246  vectorDist.template getLastProp<RHO_PREV>() = RhoZero;
1247  vectorDist.template getLastProp<VELOCITY>()[0] = 0.0;
1248  vectorDist.template getLastProp<VELOCITY>()[1] = 0.0;
1249  vectorDist.template getLastProp<VELOCITY>()[2] = 0.0;
1250 
1251  vectorDist.template getLastProp<VELOCITY_PREV>()[0] = 0.0;
1252  vectorDist.template getLastProp<VELOCITY_PREV>()[1] = 0.0;
1253  vectorDist.template getLastProp<VELOCITY_PREV>()[2] = 0.0;
1254 
1255  ++obstacle_box;
1256  }
1257 
1258  vectorDist.map();
1259 
1261 
1344 
1345  // Now that we fill the vector with particles
1346  ModelCustom md;
1347 
1348  vectorDist.addComputationCosts(md);
1349  vectorDist.getDecomposition().decompose();
1350  vectorDist.map();
1351 
1353 
1354  vectorDist.ghost_get<TYPE,RHO,PRESSURE,VELOCITY>();
1355 
1356  auto cellList = vectorDist.getCellList(2*H);
1357 
1358  // Evolve
1359 
1375 
1376  //Now we create a odeint stepper object (explicit Euler). Since we are in 7d, we are going to use "state_type_7d_ofp". Which is a structure or state_type compatible with odeint. We further pass all the parameters including "boost::numeric::odeint::vector_space_algebra_ofp",which tell odeint to use openfpm algebra.
1377  // The template parameters are: state_type_7d_ofp (state type of X), double (type of the value inside the state), state_type_7d_ofp (state type of DxDt), double (type of the time), boost::numeric::odeint::vector_space_algebra_ofp (our algebra)
1378  boost::numeric::odeint::euler<state_type_7d_ofp, double, state_type_7d_ofp, double, boost::numeric::odeint::vector_space_algebra_ofp> eulerOdeint;
1379 
1380  // RHS functor for odeint
1381  RHSFunctor<decltype(vectorDist), decltype(cellList)> rhsFunctor(vectorDist, cellList);
1382 
1383  //Furhter, odeint needs data in a state type "state_type_7d_ofp", we create one and fill in the initial condition.
1385 
1386  auto posExpression = getV<POS_PROP>(vectorDist);
1387  auto forceExpression = getV<FORCE>(vectorDist);
1388  auto drhoExpression = getV<DRHO>(vectorDist);
1389  auto typeExpression = getV<TYPE>(vectorDist);
1390 
1391  auto rhoExpression = getV<RHO>(vectorDist);
1392  auto rho_tmpExpression = getV<RHO_TMP>(vectorDist);
1393  auto rho_prevExpression = getV<RHO_PREV>(vectorDist);
1394 
1395  auto velocityExpression = getV<VELOCITY>(vectorDist);
1396  auto velocity_tmpExpression = getV<VELOCITY_TMP>(vectorDist);
1397  auto velocity_prevExpression = getV<VELOCITY_PREV>(vectorDist);
1398 
1399  //Since we created a 7d state_type we initialize three fields in the object data using the method get.
1400  X.data.get<0>() = rhoExpression;
1401  X.data.get<1>() = posExpression[0];
1402  X.data.get<2>() = posExpression[1];
1403  X.data.get<3>() = posExpression[2];
1404  X.data.get<4>() = velocityExpression[0];
1405  X.data.get<5>() = velocityExpression[1];
1406  X.data.get<6>() = velocityExpression[2];
1407 
1408  // global variable
1409  iteration = 0;
1410 
1411  size_t write = 0;
1412  size_t it_reb = 0;
1413  double t = 0.0;
1414  while (t <= t_end)
1415  {
1416  Vcluster<> & v_cl = create_vcluster();
1417  timer it_time;
1418 
1420  it_reb++;
1421  if (it_reb == 200)
1422  {
1423  vectorDist.map();
1424 
1425  it_reb = 0;
1426  ModelCustom md;
1427  vectorDist.addComputationCosts(md);
1428  vectorDist.getDecomposition().decompose();
1429 
1430  if (v_cl.getProcessUnitID() == 0)
1431  std::cout << "REBALANCED " << std::endl;
1432  }
1433 
1434  vectorDist.map();
1435 
1436  // Calculate pressure from the density
1437  EqState(vectorDist);
1438 
1439  double max_visc = 0.0;
1440 
1441  vectorDist.ghost_get<TYPE,RHO,PRESSURE,VELOCITY>();
1442 
1443  // update subset data structures
1444  // vectorDistSubsetFluid.update();
1445  // vectorDistSubsetBoundary.update();
1446 
1447  // Calc forces
1448  calc_forces(vectorDist,cellList,max_visc);
1449 
1450  // Get the maximum viscosity term across processors
1451  v_cl.max(max_visc);
1452  v_cl.execute();
1453 
1454  // Calculate delta t integration
1455  // global variable
1456  dt = calc_deltaT(vectorDist,max_visc);
1457 
1458  // global iteration variable
1459  iteration++;
1460 
1461  rho_tmpExpression = rhoExpression;
1462  velocity_tmpExpression[0] = velocityExpression[0];
1463  velocity_tmpExpression[1] = velocityExpression[1];
1464  velocity_tmpExpression[2] = velocityExpression[2];
1465 
1466  // Reinitialize Odeint state vector as the particle
1467  // distribution could have changed after map()
1468  if (iteration < 40) {
1469  X.data.get<0>() = rho_prevExpression;
1470 
1471  X.data.get<4>() = velocity_prevExpression[0];
1472  X.data.get<5>() = velocity_prevExpression[1];
1473  X.data.get<6>() = velocity_prevExpression[2];
1474  } else {
1475  X.data.get<0>() = rhoExpression;
1476  X.data.get<4>() = velocityExpression[0];
1477  X.data.get<5>() = velocityExpression[1];
1478  X.data.get<6>() = velocityExpression[2];
1479  }
1480 
1481  X.data.get<1>() = posExpression[0];
1482  X.data.get<2>() = posExpression[1];
1483  X.data.get<3>() = posExpression[2];
1484 
1485  eulerOdeint.do_step(rhsFunctor, X, t, dt);
1486 
1487  rhoExpression=X.data.get<0>();
1488  posExpression[0] = X.data.get<1>();
1489  posExpression[1] = X.data.get<2>();
1490  posExpression[2] = X.data.get<3>();
1491  velocityExpression[0] = X.data.get<4>();
1492  velocityExpression[1] = X.data.get<5>();
1493  velocityExpression[2] = X.data.get<6>();
1494 
1495  rho_prevExpression = rho_tmpExpression;
1496  velocity_prevExpression[0] = velocity_tmpExpression[0];
1497  velocity_prevExpression[1] = velocity_tmpExpression[1];
1498  velocity_prevExpression[2] = velocity_tmpExpression[2];
1499 
1500  if (iteration == 40)
1501  // Once in 40 iterations
1502  // euler time stepping is done in RHSFunctor
1503  iteration = 0;
1504 
1505  checkPosPrpLimits(vectorDist);
1506 
1507  t += dt;
1508 
1509  if (write < t*100)
1510  {
1511  // sensor_pressure calculation require ghost and update cell-list
1512  vectorDist.map();
1513  vectorDist.ghost_get<TYPE,RHO,PRESSURE,VELOCITY>();
1514  vectorDist.updateCellList(cellList);
1515 
1516  // Reinitialize Odeint state vector as the particle
1517  // distribution could have changed after map()
1518  if (iteration < 40) {
1519  X.data.get<0>() = rho_prevExpression;
1520 
1521  X.data.get<4>() = velocity_prevExpression[0];
1522  X.data.get<5>() = velocity_prevExpression[1];
1523  X.data.get<6>() = velocity_prevExpression[2];
1524  } else {
1525  X.data.get<0>() = rhoExpression;
1526  X.data.get<4>() = velocityExpression[0];
1527  X.data.get<5>() = velocityExpression[1];
1528  X.data.get<6>() = velocityExpression[2];
1529  }
1530 
1531  X.data.get<1>() = posExpression[0];
1532  X.data.get<2>() = posExpression[1];
1533  X.data.get<3>() = posExpression[2];
1534 
1535  // calculate the pressure at the sensor points
1536  sensor_pressure(vectorDist,cellList,press_t,probes);
1537 
1538  vectorDist.write_frame("Geometry",write);
1539  write++;
1540 
1541  if (v_cl.getProcessUnitID() == 0)
1542  {std::cout << "TIME: " << t << " write " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " " << iteration << " Max visc: " << max_visc << std::endl;}
1543  }
1544  else
1545  {
1546  if (v_cl.getProcessUnitID() == 0)
1547  {std::cout << "TIME: " << t << " " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " " << iteration << " Max visc: " << max_visc << std::endl;}
1548  }
1549  }
1550 
1552 
1567 
1568  openfpm_finalize();
1569 
1571 
1580 }
This class represent an N-dimensional box.
Definition: Box.hpp:60
__device__ __host__ T getLow(int i) const
get the i-coordinate of the low bound interval of the box
Definition: Box.hpp:555
__device__ __host__ T getHigh(int i) const
get the high interval of the box
Definition: Box.hpp:566
Class for FAST cell list implementation.
Definition: CellList.hpp:558
This class define the domain decomposition interface.
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)
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.
Definition: Ghost.hpp:40
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
void execute()
Execute all the requests.
void sum(T &num)
Sum the numbers across all processors and get the result.
size_t getProcessUnitID()
Get the process unit id.
void max(T &num)
Get the maximum number across all processors (or reduction with infinity norm)
Implementation of VCluster class.
Definition: VCluster.hpp:59
Sparse Matrix implementation stub object when OpenFPM is compiled with no linear algebra support.
Definition: Vector.hpp:40
Class for cpu time benchmarking.
Definition: timer.hpp:28
double getwct()
Return the elapsed real time.
Definition: timer.hpp:130
Distributed vector.
auto getProp(vect_dist_key_dx vec_key) -> decltype(vPrp.template get< id >(vec_key.getKey()))
Get the property of an element.
void updateCellList(CellL &cellList, bool no_se3=false)
Update a cell list using the stored particles.
auto getPos(vect_dist_key_dx vec_key) -> decltype(vPos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
void remove(std::set< size_t > &keys)
Remove a set of elements from the distributed vector.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
Model for Dynamic load balancing.
Definition: main.cpp:232
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:221
A 7d Odeint and Openfpm compatible structure.