56 #include "Vector/vector_dist.hpp" 58 #include "Draw/DrawParticles.hpp" 218 const double dp = 0.0085;
224 const double coeff_sound = 20.0;
227 const double gamma_ = 7.0;
230 const double H = 0.0147224318643;
232 const double FourH2 = 4.0 * H*H;
235 const double Eta2 = 0.01 * H*H;
238 const double visco = 0.1;
244 const double MassFluid = 0.000614125;
247 const double MassBound = 0.000614125;
251 const double t_end = 1.5;
253 const double t_end = 0.001;
257 const double gravity = 9.81;
260 const double rho_zero = 1000.0;
266 const double CFLnumber = 0.2;
269 const double DtMin = 0.00001;
272 const double RhoMin = 700.0;
275 const double RhoMax = 1300.0;
278 double max_fluid_height = 0.0;
283 const size_t type = 0;
286 const size_t nn_num = 1;
292 const int rho_prev = 3;
295 const int Pressure = 4;
304 const int velocity = 7;
307 const int velocity_prev = 8;
314 typedef vector_dist<3,double,aggregate<int, int,double, double, double, double, double[3], double[3], double[3]> >
particles;
325 template<
typename Decomposition,
typename vector>
inline void addComputation(
Decomposition & dec, vector & vd,
size_t v,
size_t p)
327 if (vd.template getProp<type>(p) == FLUID )
328 {dec.addComputationCost(v,4);}
330 {dec.addComputationCost(v,3);}
333 template<
typename Decomposition>
inline void applyModel(
Decomposition & dec,
size_t v)
335 dec.setSubSubDomainComputationCost(v, dec.getSubSubDomainComputationCost(v) * dec.getSubSubDomainComputationCost(v));
338 float distributionTol()
347 template<
typename Decomposition,
typename vector>
inline void addComputation(
Decomposition & dec, vector & vd,
size_t v,
size_t p)
349 dec.addComputationCost(v,vd.template getProp<nn_num>(p) + 4);
352 template<
typename Decomposition>
inline void applyModel(
Decomposition & dec,
size_t v)
356 float distributionTol()
370 double rho_a = vd.template getProp<rho>(a);
371 double rho_frac = rho_a / rho_zero;
373 vd.template getProp<Pressure>(a) = B*( rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac - 1.0);
379 const double a2 = 1.0/M_PI/H/H/H;
381 inline double Wab(
double r)
386 {
return (1.0 - 3.0/2.0*r*r + 3.0/4.0*r*r*r)*a2;}
388 {
return (1.0/4.0*(2.0 - r*r)*(2.0 - r*r)*(2.0 - r*r))*a2;}
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;
404 double qq2 = qq * qq;
405 double fac1 = (c1*qq + d1*qq2)/r;
406 double b1 = (qq < 1.0)?1.0f:0.0f;
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;
412 double factor = (b1*fac1 + b2*fac2);
414 DW.
get(0) = factor * dx.
get(0);
415 DW.
get(1) = factor * dx.
get(1);
416 DW.
get(2) = factor * dx.
get(2);
419 inline double Tensile(
double r,
double rhoa,
double rhob,
double prs1,
double prs2)
427 double wqq2=wqq1*wqq1;
429 wab=a2_4*(wqq2*wqq1);
436 wab=a2*(1.0f-1.5f*wqq2+0.75f*wqq3);
440 double fab=wab*W_dap;
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);
445 return (fab*(tensilp1+tensilp2));
452 const double dot_rr2 = dot/(rr2+Eta2);
453 visc=std::max(dot_rr2,visc);
457 const float amubar=H*dot_rr2;
458 const float robar=(rhoa+rhob)*0.5f;
459 const float pi_visc=(-visco*cbar*amubar/robar);
468 template<
typename VerletList>
inline void calc_forces(
particles & vd,
VerletList & NN,
double & max_visc)
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;
494 while (itg2.isNext())
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;
516 while (part.isNext())
525 size_t typea = vd.
getProp<type>(a);
528 double massa = (vd.
getProp<type>(a) == FLUID)?MassFluid:MassBound;
531 double rhoa = vd.
getProp<rho>(a);
534 double Pa = vd.
getProp<Pressure>(a);
540 auto Np = NN.template getNNIterator<NO_CHECK>(a);
545 while (Np.isNext() ==
true)
556 float r2 = norm2(dr);
559 if (r2 < FourH2 && r2 > 1e-18)
563 unsigned int typeb = vd.
getProp<type>(b);
565 double massb = (typeb == FLUID)?MassFluid:MassBound;
567 double Pb = vd.
getProp<Pressure>(b);
568 double rhob = vd.
getProp<rho>(b);
577 double factor = - ((Pa + Pb) / (rhoa * rhob) + Tensile(r,rhoa,rhob,Pa,Pb) + Pi(dr,r2,v_rel,rhoa,rhob,massb,visc));
580 factor = (typea == BOUNDARY && typeb == BOUNDARY)?0.0f:factor;
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);
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);
590 double scal = (v_rel.get(0)*DW.
get(0)+v_rel.get(1)*DW.
get(1)+v_rel.get(2)*DW.
get(2));
593 scal = (typea == BOUNDARY && typeb == BOUNDARY)?0.0f:scal;
595 vd.
getProp<drho>(a) += massb*scal;
596 vd.
getProp<drho>(b) += massa*scal;
613 vd.template ghost_put<add_,drho,force>();
618 void max_acceleration_and_velocity(
particles & vd,
double & max_acc,
double & max_vel)
623 while (part.isNext())
628 double acc2 = norm2(acc);
631 double vel2 = norm2(vel);
641 max_acc = sqrt(max_acc);
642 max_vel = sqrt(max_vel);
650 double calc_deltaT(
particles & vd,
double ViscDtMax)
654 max_acceleration_and_velocity(vd,Maxacc,Maxvel);
657 const double dt_f = (Maxacc)?sqrt(H/Maxacc):std::numeric_limits<int>::max();
660 const double dt_cv = H/(std::max(cbar,Maxvel*10.) + H*ViscDtMax);
663 double dt=double(CFLnumber)*std::min(dt_f,dt_cv);
676 void verlet_int(
particles & vd,
double dt,
double & max_disp)
685 double dt205 = dt*dt*0.5;
693 while (part.isNext())
699 if (vd.template getProp<type>(a) == BOUNDARY)
702 double rhop = vd.template getProp<rho>(a);
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;
711 vd.template getProp<rho_prev>(a) = rhop;
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;
727 double d2 = dx*dx + dy*dy + dz*dz;
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);
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);
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)
747 to_remove.add(a.getKey());
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;
764 max_disp = sqrt(max_disp);
773 void euler_int(
particles & vd,
double dt,
double & max_disp)
782 double dt205 = dt*dt*0.5;
788 while (part.isNext())
794 if (vd.template getProp<type>(a) == BOUNDARY)
797 double rhop = vd.template getProp<rho>(a);
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;
806 vd.template getProp<rho_prev>(a) = rhop;
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;
821 double d2 = dx*dx + dy*dy + dz*dz;
823 max_disp = (max_disp > d2)?max_disp:d2;
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);
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);
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)
840 to_remove.add(a.getKey());
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;
855 max_disp = sqrt(max_disp);
861 int main(
int argc,
char* argv[])
864 openfpm_init(&argc,&argv);
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};
871 W_dap = 1.0/Wab(H/1.5);
874 size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
878 double skin = 0.25 * 2*H;
879 double r_gskin = 2*H + skin;
895 particles vd(0,domain,bc,g,BIND_DEC_TO_GHOST);
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});
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);
913 while (fluid_it.isNext())
924 vd.template getLastProp<type>() = FLUID;
933 vd.template getLastProp<Pressure>() = rho_zero * gravity * (max_fluid_height - fluid_it.get().get(2));
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;
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;
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});
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});
958 holes.add(recipient2);
959 holes.add(obstacle1);
962 while (bound_box.isNext())
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;
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;
986 while (obstacle_box.isNext())
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);
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;
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;
1017 auto & v_cl = create_vcluster();
1020 std::cout <<
"SUM: " << tot_part << std::endl;
1029 vd.
ghost_get<type,rho,Pressure,velocity>();
1039 double tot_disp = 0.0;
1049 if (2*tot_disp >= skin)
1066 std::cout <<
"REBALANCED " << std::endl;
1073 vd.
ghost_get<type,rho,Pressure,velocity>();
1082 std::cout <<
"RECONSTRUCT Verlet " << std::endl;
1089 vd.
ghost_get<type,rho,Pressure,velocity>(SKIP_LABELLING);
1094 double max_visc = 0.0;
1097 calc_forces(vd,NN,max_visc);
1104 double dt = calc_deltaT(vd,max_visc);
1111 verlet_int(vd,dt,max_disp);
1114 euler_int(vd,dt,max_disp);
1118 tot_disp += max_disp;
1127 vd.
write_frame(
"Geometry",write,VTK_WRITER | FORMAT_BINARY);
1129 vd.
ghost_get<type,rho,Pressure,velocity>(SKIP_LABELLING);
1133 std::cout <<
"TIME: " << t <<
" write " << it_time.
getwct() <<
" " << v_cl.
getProcessUnitID() <<
" TOT disp: " << tot_disp <<
" " << cnt << std::endl;
1138 std::cout <<
"TIME: " << t <<
" " << it_time.
getwct() <<
" " << v_cl.
getProcessUnitID() <<
" TOT disp: " << tot_disp <<
" " << cnt << std::endl;
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
Class for Verlet list implementation.
Second model for dynamic load balancing.
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.
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.
void remove(openfpm::vector< size_t > &keys, size_t start=0)
Remove a set of elements from the distributed vector.
Implementation of VCluster class.
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.
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.
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
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.
__device__ __host__ T getHigh(int i) const
get the high interval of the box
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
Class for cpu time benchmarking.