From 528ec2063faf7fe233ad56b8b9f5532a21637188 Mon Sep 17 00:00:00 2001 From: Pietro Incardona <incardon@mpi-cbg.de> Date: Fri, 27 Jan 2017 22:22:05 +0100 Subject: [PATCH] examples SPH update --- example/Vector/0_simple/main.cpp | 1 + .../4_multiphase_celllist_verlet/main.cpp | 4 +- example/Vector/7_SPH_dlb/main.cpp | 778 ++++++++++++------ openfpm_numerics | 2 +- openfpm_pdata.doc | 2 +- src/Decomposition/CartDecomposition.hpp | 7 +- .../Distribution/ParMetisDistribution.hpp | 29 +- src/Graph/CartesianGraphFactory.hpp | 23 +- src/Graph/ids.hpp | 17 + src/Makefile.am | 2 +- src/Vector/vector_dist.hpp | 20 +- src/Vector/vector_dist_MP_unit_tests.hpp | 16 +- src/Vector/vector_dist_comm.hpp | 23 +- .../vector_dist_multiphase_functions.hpp | 30 +- src/Vector/vector_dist_unit_test.hpp | 2 +- 15 files changed, 667 insertions(+), 289 deletions(-) diff --git a/example/Vector/0_simple/main.cpp b/example/Vector/0_simple/main.cpp index a2c9b7b2..b17023e1 100644 --- a/example/Vector/0_simple/main.cpp +++ b/example/Vector/0_simple/main.cpp @@ -11,6 +11,7 @@ * \subpage Vector_5_md_vl_sym * \subpage Vector_5_md_vl_sym_crs * \subpage Vector_6_complex_usage + * \subpage Vector_7_sph_dlb * */ diff --git a/example/Vector/4_multiphase_celllist_verlet/main.cpp b/example/Vector/4_multiphase_celllist_verlet/main.cpp index e426b889..65b92e93 100644 --- a/example/Vector/4_multiphase_celllist_verlet/main.cpp +++ b/example/Vector/4_multiphase_celllist_verlet/main.cpp @@ -317,7 +317,7 @@ int main(int argc, char* argv[]) CL_phase1 = phases.get(1).getCellListSym(r_cut); // This function create a Verlet-list between phases 0 and 1 - NN_ver01 = createVerletSym(phases.get(0),CL_phase1,r_cut); + NN_ver01 = createVerletSym(phases.get(0),phases.get(1),CL_phase1,r_cut); // Get an iterator over the real and ghost particles it = phases.get(0).getDomainAndGhostIterator(); @@ -419,7 +419,7 @@ int main(int argc, char* argv[]) CL_all = createCellListSymM<2>(phases,r_cut); // Type of the multiphase Verlet-list - typedef decltype(createVerletSymM<2>(phases.get(0),CL_all,r_cut)) verlet_type; + typedef decltype(createVerletSymM<2>(phases.get(0),phases,CL_all,r_cut)) verlet_type; // for each phase we create one Verlet-list that contain the neighborhood // from all the phases diff --git a/example/Vector/7_SPH_dlb/main.cpp b/example/Vector/7_SPH_dlb/main.cpp index 9a6dfc1b..2c6f10ce 100644 --- a/example/Vector/7_SPH_dlb/main.cpp +++ b/example/Vector/7_SPH_dlb/main.cpp @@ -1,5 +1,5 @@ /*! - * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balacing + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balacing * * * [TOC] @@ -8,11 +8,15 @@ * # SPH with Dynamic load Balancing # {#SPH_dlb} * * - * This example show the classical SPH Dam break simulation with Dynamic load balancing + * This example show the classical SPH Dam break simulation with Load Balancing and Dynamic load balancing. With + * Load balancing and Dynamic load balancing we indicate the possibility of the system to re-adapt the domain + * decomposition to keep all the processor load and reduce idle time. * * ## inclusion ## {#e0_v_inclusion} * * In order to use distributed vectors in our code we have to include the file Vector/vector_dist.hpp + * we also include DrawParticles that has nice utilities to draw particles in parallel accordingly + * to simple shapes * * \snippet Vector/7_SPH_dlb/main.cpp inclusion * @@ -21,56 +25,211 @@ //! \cond [inclusion] \endcond #include "Vector/vector_dist.hpp" #include <math.h> +#include "Draw/DrawParticles.hpp" //! \cond [inclusion] \endcond -#include "Draw/DrawParticles.hpp" +/*! + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balacing + * + * ## Parameters {#e7_sph_parameters} + * + * The SPH formulation used in this example code follow these equations + * + * \f$\frac{dv_a}{dt} = - \sum_{b = NN(a) } m_b \left(\frac{P_a + P_b}{\rho_a \rho_b} + \Pi_{ab} \right) \nabla_{a} W_{ab} + g \tag{1} \f$ + * + * \f$\frac{d\rho_a}{dt} = \sum_{b = NN(a) } m_b v_{ab} \cdot \nabla_{a} W_{ab} \tag{2} \f$ + * + * \f$ P_a = b \left[ \left( \frac{\rho_a}{\rho_{0}} \right)^{\gamma} - 1 \right] \tag{3} \f$ + * + * with + * + * \f$ \Pi_{ab} = \begin{cases} - \frac {\alpha \bar{c_{ab}} \mu_{ab} }{\bar{\rho_{ab}} } & v_{ab} \cdot r_{ab} > 0 \\ 0 & v_{ab} \cdot r_{ab} < 0 \end{cases} \tag{4}\f$ + * + * and the constants defined as + * + * \f$ b = \frac{c_{s}^{2} \rho_0}{\gamma} \tag{5} \f$ + * + * \f$ c_s = \sqrt{g \cdot h_{swl}} \tag{6} \f$ + * + * While the particle kernel support is given by + * + * \f$ H = \sqrt{3 \cdot dp} \tag{7} \f$ + * + * Explain the equations is out of the context of this tutorial. An introduction + * can be found in the original Monghagan SPH paper. In this example we use the version + * used by Dual-SPH (http://www.dual.sphysics.org/). A summary of the equation and constants can be founded in + * their User Manual and the XML user Manual. + * In the following we define all the constants required by the simulation + * + * \snippet Vector/7_SPH_dlb/main.cpp sim parameters + * + */ + +/*! \cond [sim parameters] \endcond */ +// A constant to indicate boundary particles #define BOUNDARY 0 -#define FLUID 1 -double lower_z = 2.0; +// A constant to indicate fluid particles +#define FLUID 1 +// initial spacing between particles dp in the formulas const double dp = 0.0085; +// Maximum height of the fluid water +// is coing to be calculated and filled later on double h_swl = 0.0; + +// in the formulas indicated with c_s (constant used to calculate the sound speed) const double coeff_sound = 20.0; + +// gamma in the formulas const double gamma_ = 7.0; -// sqrt(3.0*dp*dp) + +// sqrt(3.0*dp*dp) support of the kernel const double H = 0.0147224318643; + +// Eta in the formulas const double Eta2 = 0.01 * H*H; + + const double visco = 0.1; double cbar = 0.0; + +// Mass of the fluid particles const double MassFluid = 0.000614125; + +// Mass of the boundary particles const double MassBound = 0.000614125; -const double t_end = 1.0; + +// End simulation time +const double t_end = 1.5; + +// Gravity acceleration const double gravity = 9.81; + +// Reference densitu 1000Kg/m^3 const double rho_zero = 1000.0; + +// Filled later require h_swl, it is b in the formulas double B = 0.0; + +// Constant used to define time integration const double CFLnumber = 0.2; + +// Minimum T const double DtMin = 0.00001; +// Minimum Rho allowed +const double RhoMin = 700.0; + +// Maximum Rho allowed +const double RhoMax = 1300.0; + // Filled in initialization double max_fluid_height = 0.0; +// Properties + +// FLUID or BOUNDARY const size_t type = 0; + +// Density const int rho = 1; + +// Density at step n-1 const int rho_prev = 2; + +// Pressure const int Pressure = 3; + +// Delta rho calculated in the force calculation const int drho = 4; + +// calculated force const int force = 5; + +// velocity const int velocity = 6; + +// velocity at previous step const int velocity_prev = 7; -typedef vector_dist<3,double,aggregate<size_t,double,double,double,double,double[3],double[3],double[3]>> particles; +// Type of the vector containing particles +typedef vector_dist<3,double,aggregate<size_t,double, double, double, double, double[3], double[3], double[3]>> particles; +// | | | | | | | | +// | | | | | | | | +// type density density Pressure delta force velocity velocity +// at n-1 density at n - 1 -inline void EqState(particles & vd) + +/*! \cond [sim parameters] \endcond */ + +/*! \brief Linear model + * + * The linear model count each particle as weight one + * + */ +struct ModelCustom +{ + size_t factor = 1; + + template<typename Decomposition, typename vector> inline void addComputation(Decomposition & dec, const vector & vd, size_t v, size_t p) + { + if (vd.template getProp<type>(p) == FLUID) + { + dec.addComputationCost(v,3); + } + else + { + dec.addComputationCost(v,2); + } + + } + + template<typename Decomposition> inline void applyModel(Decomposition & dec, size_t v) + { + dec.setSubSubDomainComputationCost(v, dec.getSubSubDomainComputationCost(v) * dec.getSubSubDomainComputationCost(v)); + } +}; + +/*! \brief Linear model + * + * The linear model count each particle as weight one + * + */ +struct ModelCustom1 { -// double min = 100000000.0; -// double max = 0.0; -// double accum = 0.0; -// size_t n = 0; + size_t factor = 1; + + template<typename Decomposition, typename vector> inline void addComputation(Decomposition & dec, const vector & vd, size_t v, size_t p) + { + + dec.addComputationCost(v,100); + } -// Vcluster & v_cl = create_vcluster(); + template<typename Decomposition> inline void applyModel(Decomposition & dec, size_t v) + { + } +}; + +/*! + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balacing + * + * ## Equation of state and SPH Kernels {#e7_sph_equation_state} + * + * This function implement the formula 3 in the set of equations. It calculate the + * pressure of each particle based on the local density of each particle. + * + * \snippet Vector/7_SPH_dlb/main.cpp eq_state_and_ker + * + */ + +/*! \cond [eq_state_and_ker] \endcond */ + + +inline void EqState(particles & vd) +{ auto it = vd.getDomainIterator(); while (it.isNext()) @@ -82,40 +241,27 @@ inline void EqState(particles & vd) vd.template getProp<Pressure>(a) = B*( rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac*rho_frac - 1.0); - /// DEBUG - -/* if (vd.template getProp<Pressure>(a) < min) - min = vd.template getProp<Pressure>(a); - - if (vd.template getProp<Pressure>(a) > max) - max = vd.template getProp<Pressure>(a); - - if (vd.template getProp<Pressure>(a) > 2849.0) - std::cout << "Particle: " << Point<3,double>(vd.getPos(a)).toString() << std::endl; - - accum += vd.template getProp<Pressure>(a); - n++;*/ - ++it; } +} -/* v_cl.max(max); - v_cl.min(min); - v_cl.sum(accum); - v_cl.sum(n); +/*! \cond [eq_state_and_ker] \endcond */ - v_cl.execute(); +/*! + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * This function define the Cubic kernel or \f$ W_{ab} \f$ in the set of equations. The cubic kernel is + * defined as + * + * \f$ \begin{cases} 1.0 - \frac{3}{2} q^2 + \frac{3}{4} q^3 & 0 < q < 1 \\ (2 - q)^3 & 1 < q < 2 \\ 0 & q > 2 \end{cases} \f$ + * + * \snippet Vector/7_SPH_dlb/main.cpp kernel_sph + * + */ - std::cout << "Max: " << max << " min: " << min << " accum: " << accum/n << " " << B << " n: " << n << std::endl;*/ -} +/*! \cond [kernel_sph] \endcond */ -const double c1 = -3.0/M_PI/H/H/H/H; -const double d1 = 9.0/4.0/M_PI/H/H/H/H; -const double c2 = -3.0/4.0/M_PI/H/H/H/H; const double a2 = 1.0/M_PI/H/H/H; -const double a2_4 = 0.25*a2; -// Filled later -double W_dap = 0.0; inline double Wab(double r) { @@ -129,6 +275,29 @@ inline double Wab(double r) return 0.0; } +/*! \cond [kernel_sph] \endcond */ + +/*! + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * This function define the derivative of the Cubic kernel function \f$ W_{ab} \f$ in the set of equations. + * + * \f$ \nabla W_{ab} = \beta (x,y,z) \f$ + * + * \f$ \beta = \begin{cases} (c_1 q + d_1 q^2) & 0 < q < 1 \\ c_2 (2 - q)^2 & 1 < q < 2 \end{cases} \f$ + * + * \snippet Vector/7_SPH_dlb/main.cpp kernel_sph_der + * + */ + +/*! \cond [kernel_sph_der] \endcond */ + +const double c1 = -3.0/M_PI/H/H/H/H; +const double d1 = 9.0/4.0/M_PI/H/H/H/H; +const double c2 = -3.0/4.0/M_PI/H/H/H/H; +const double a2_4 = 0.25*a2; +// Filled later +double W_dap = 0.0; inline void DWab(Point<3,double> & dx, Point<3,double> & DW, double r, bool print) { @@ -160,8 +329,26 @@ inline void DWab(Point<3,double> & dx, Point<3,double> & DW, double r, bool prin } } +/*! \cond [kernel_sph_der] \endcond */ + +/*! + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * This function define the Tensile term. An explanation of the Tensile term is out of the + * context of this tutorial, but in brief is an additional repulsive term that avoid the particles + * to get enough near. Can be considered at small scale like a repulsive force that avoid + * particles to get too close like the Lennard-Jhonned potential at atomistic level. A good + * reference is the Monaghan paper "SPH without a Tensile Instability" + * + * \snippet Vector/7_SPH_dlb/main.cpp tensile_term + * + * + */ + +/*! \cond [tensile_term] \endcond */ + // Tensile correction -inline double Tensile(double r, double rhoa, double rhob, double prs1, double prs2, bool print) +inline double Tensile(double r, double rhoa, double rhob, double prs1, double prs2) { const double qq=r/H; //-Cubic Spline kernel @@ -187,13 +374,26 @@ inline double Tensile(double r, double rhoa, double rhob, double prs1, double pr const double tensilp1=(prs1/(rhoa*rhoa))*(prs1>0? 0.01: -0.2); const double tensilp2=(prs2/(rhob*rhob))*(prs2>0? 0.01: -0.2); -// if (print == true) -// std::cout << "fab " << fab << " tensilp1: " << tensilp1 << " tensilp2: " << tensilp2 << std::endl; - return (fab*(tensilp1+tensilp2)); } -inline double Pi(const Point<3,double> & dr, double rr2, Point<3,double> & dv, double rhoa, double rhob, double massb, double & visc, bool print) +/*! \cond [tensile_term] \endcond */ + + +/*! + * + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * This function is the implementation of the viscous term \f$ \Pi_{ab} \f$ + * + * \snippet Vector/7_SPH_dlb/main.cpp viscous_term + * + * + */ + +/*! \cond [viscous_term] \endcond */ + +inline double Pi(const Point<3,double> & dr, double rr2, Point<3,double> & dv, double rhoa, double rhob, double massb, double & visc) { const double dot = dr.get(0)*dv.get(0) + dr.get(1)*dv.get(1) + dr.get(2)*dv.get(2); const double dot_rr2 = dot/(rr2+Eta2); @@ -205,169 +405,189 @@ inline double Pi(const Point<3,double> & dr, double rr2, Point<3,double> & dv, d const float robar=(rhoa+rhob)*0.5f; const float pi_visc=(-visco*cbar*amubar/robar); - if (print == true) - std::cout << " visco: " << visco << " " << cbar << " " << amubar << " " << robar << " "; - return pi_visc; } else return 0.0; } +/*! \cond [viscous_term] \endcond */ + +/*! + * + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * ## Force calculation {#e7_force_calc} + * + * Calculate forces. It calculate equation 1 and 2 in the set of formulas + * + * \snippet Vector/7_SPH_dlb/main.cpp calc_forces + * + * + */ + +/*! \cond [calc_forces] \endcond */ + template<typename CellList> inline double calc_forces(particles & vd, CellList & NN, double & max_visc) { auto part = vd.getDomainIterator(); - - Point<3,double> ForceMax({ 0.0, 0.0, 0.0}); - Point<3,double> ForceMin({10000000.0,1000000.0,1000000,0}); - double visc = 0; -// std::cout << "c1: " << c1 << " c2: " << c2 << " d1: " << d1 << std::endl; + // Update the cell-list vd.updateCellList(NN); + // For each particle ... while (part.isNext()) { + // ... a auto a = part.get(); // Get the position xp of the particle Point<3,double> xa = vd.getPos(a); - if (vd.getProp<type>(a) != FLUID) - { - ++part; - continue; - } - + // Take the mass of the particle dependently if it is FLUID or BOUNDARY double massa = (vd.getProp<type>(a) == FLUID)?MassFluid:MassBound; + + // Get the density of the of the particle a double rhoa = vd.getProp<rho>(a); + + // Get the pressure of the particle a double Pa = vd.getProp<Pressure>(a); + + // Get the Velocity of the particle a Point<3,double> va = vd.getProp<velocity>(a); - // Reset the force counter + // Reset the force counter (- gravity on zeta direction) vd.template getProp<force>(a)[0] = 0.0; vd.template getProp<force>(a)[1] = 0.0; vd.template getProp<force>(a)[2] = -gravity; vd.template getProp<drho>(a) = 0.0; - size_t cnt = 0; + // We threat FLUID particle differently from BOUNDARY PARTICLES ... + if (vd.getProp<type>(a) != FLUID) + { + // If it is a boundary particle calculate the delta rho based on equation 2 + // This require to run across the neighborhoods particles of a + auto Np = NN.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(a))); -// std::cout << "---------------------" << std::endl; -// std::cout << vd.getPos(a)[0] << " " << vd.getPos(a)[1] << " " << vd.getPos(a)[2] << std::endl; + // For each neighborhood particle + while (Np.isNext() == true) + { + // ... q + auto b = Np.get(); - // Get an iterator over the neighborhood particles of p - auto Np = NN.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(a))); + // Get the position xp of the particle + Point<3,double> xb = vd.getPos(b); - while (Np.isNext() == true) - { - // ... q - auto b = Np.get(); + // if (p == q) skip this particle + if (a.getKey() == b) {++Np; continue;}; - // Get the position xp of the particle - Point<3,double> xb = vd.getPos(b); + // get the mass of the particle + double massb = (vd.getProp<type>(b) == FLUID)?MassFluid:MassBound; - // if (p == q) skip this particle - if (a.getKey() == b) {++Np; continue;}; + // Get the velocity of the particle b + Point<3,double> vb = vd.getProp<velocity>(b); - double massb = (vd.getProp<type>(b) == FLUID)?MassFluid:MassBound; - Point<3,double> vb = vd.getProp<velocity>(b); - double Pb = vd.getProp<Pressure>(b); - double rhob = vd.getProp<rho>(b); + // Get the pressure and density of particle b + double Pb = vd.getProp<Pressure>(b); + double rhob = vd.getProp<rho>(b); - // Get the distance between p and q - Point<3,double> dr = xa - xb; - // take the norm of this vector - double r2 = norm2(dr); + // Get the distance between p and q + Point<3,double> dr = xa - xb; + // take the norm of this vector + double r2 = norm2(dr); - if (r2 < 4.0*H*H) - { - double r = sqrt(r2); + // If the particles interact ... + if (r2 < 4.0*H*H) + { + // ... calculate delta rho + double r = sqrt(r2); - Point<3,double> v_rel = va - vb; + Point<3,double> dv = va - vb; - Point<3,double> DW; - DWab(dr,DW,r,false); + Point<3,double> DW; + DWab(dr,DW,r,false); - double factor = - massb*((vd.getProp<Pressure>(a) + vd.getProp<Pressure>(b)) / (rhoa * rhob) + Tensile(r,rhoa,rhob,Pa,Pb,false) + Pi(dr,r2,v_rel,rhoa,rhob,massb,visc,false)); -/* - if (create_vcluster().getProcessUnitID() == 0) - { - std::cout << "PARTICLE: " << dr.toString() << std::endl; - std::cout << "Pressure: " << Pa << " " << Pb << std::endl; - std::cout << "Density: " << rhoa << " " << rhob << std::endl; - std::cout << "FACTOR: " << factor << std::endl; - std::cout << "Tensile: " << Tensile(r,rhoa,rhob,Pa,Pb,false) << std::endl; - std::cout << "DW: " << DW.get(0) << " " << DW.get(1) << " " << DW.get(2) << std::endl; - }*/ - - vd.getProp<force>(a)[0] += factor * DW.get(0); - vd.getProp<force>(a)[1] += factor * DW.get(1); - vd.getProp<force>(a)[2] += factor * DW.get(2); - - if (xa.get(0) > 0.0085 && xa.get(0) < 0.0105 && - xa.get(1) > 0.0085 && xa.get(1) < 0.0105 && - xa.get(2) > 0.0085 && xa.get(2) < 0.0105) - { - std::cout << "POSITION: " << xb.toString() << std::endl; - std::cout << "FORCE: " << factor*DW.get(0) << " " << factor*DW.get(1) << " " << factor*DW.get(2) << std::endl; - std::cout << "FORCE TERM: " << Tensile(r,rhoa,rhob,Pa,Pb,true) << " " << Pi(dr,r2,v_rel,rhoa,rhob,massb,visc,true) << std::endl; - cnt++; - } + const double dot = dr.get(0)*dv.get(0) + dr.get(1)*dv.get(1) + dr.get(2)*dv.get(2); + const double dot_rr2 = dot/(r2+Eta2); + max_visc=std::max(dot_rr2,max_visc); - vd.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)); + vd.getProp<drho>(a) += massb*(dv.get(0)*DW.get(0)+dv.get(1)*DW.get(1)+dv.get(2)*DW.get(2)); + } -/* if (vd.getProp<type>(a) == FLUID) - { - std::cout << "DELTA RHO: " << massb*(v_rel.get(0)*DW.get(0)+v_rel.get(1)*DW.get(1)+v_rel.get(2)*DW.get(2)) << " " << v_rel.get(0) << " " << v_rel.get(1) << " " << v_rel.get(2) << " VISC: " << Pi(dr,r2,v_rel,rhoa,rhob,massb,visc,true) << std::endl; - }*/ + ++Np; } - - ++Np; } - - if (xa.get(0) > 0.0085 && xa.get(0) < 0.0105 && - xa.get(1) > 0.0085 && xa.get(1) < 0.0105 && - xa.get(2) > 0.0085 && xa.get(2) < 0.0105) + else { - std::cout << "FORCE FINAL: " << vd.getProp<force>(a)[0] << " " << vd.getProp<force>(a)[1] << " " << vd.getProp<force>(a)[2] << " " << cnt << std::endl; - } + // If it is a fluid particle calculate based on equation 1 and 2 -/* if (vd.getProp<type>(a) == FLUID) - { - std::cout << "DELTA DENSITY: " << vd.getProp<drho>(a) << std::endl; - std::cout << "+++++++++++++++++++++++++++++++++++" << std::endl; - }*/ + // Get an iterator over the neighborhood particles of p + auto Np = NN.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(a))); - ++part; + // For each neighborhood particle + while (Np.isNext() == true) + { + // ... q + auto b = Np.get(); - if (Point<3,double>(vd.getProp<force>(a)).norm() > ForceMax.norm() ) - { - ForceMax = Point<3,double>(vd.getProp<force>(a)); -// std::cout << "ForceMax: " << ForceMax.toString() << " " << a.getKey() << std::endl; + // Get the position xp of the particle + Point<3,double> xb = vd.getPos(b); - Point<3,double> p({0.01,0.0,0.0}); - Point<3,double> DW; + // if (p == q) skip this particle + if (a.getKey() == b) {++Np; continue;}; - DWab(p,DW,0.01,false); + double massb = (vd.getProp<type>(b) == FLUID)?MassFluid:MassBound; + Point<3,double> vb = vd.getProp<velocity>(b); + double Pb = vd.getProp<Pressure>(b); + double rhob = vd.getProp<rho>(b); -// std::cout << DW.get(0) << " " << DW.get(1) << " " << DW.get(2) << std::endl; - } + // Get the distance between p and q + Point<3,double> dr = xa - xb; + // take the norm of this vector + double r2 = norm2(dr); - if (Point<3,double>(vd.getProp<force>(a)).norm() < ForceMin.norm() ) - { - ForceMin = Point<3,double>(vd.getProp<force>(a)); + // if they interact + if (r2 < 4.0*H*H) + { + double r = sqrt(r2); + + Point<3,double> v_rel = va - vb; + + Point<3,double> DW; + DWab(dr,DW,r,false); + + double factor = - massb*((vd.getProp<Pressure>(a) + vd.getProp<Pressure>(b)) / (rhoa * rhob) + Tensile(r,rhoa,rhob,Pa,Pb) + Pi(dr,r2,v_rel,rhoa,rhob,massb,visc)); + + vd.getProp<force>(a)[0] += factor * DW.get(0); + vd.getProp<force>(a)[1] += factor * DW.get(1); + vd.getProp<force>(a)[2] += factor * DW.get(2); + + vd.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)); + } + + ++Np; + } } + + ++part; } +} - // Get the maximum viscosity term across processors - Vcluster & v_cl = create_vcluster(); - v_cl.max(visc); - v_cl.execute(); - max_visc = visc; +/*! \cond [calc_forces] \endcond */ -// std::cout << "---------------------------------" << std::endl; -} +/*! + * + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * This function calculate the Maximum acceleration and velocity across the particles. + * + * \snippet Vector/7_SPH_dlb/main.cpp max_acc_vel + * + * + */ +/*! \cond [max_acc_vel] \endcond */ void max_acceleration_and_velocity(particles & vd, double & max_acc, double & max_vel) { @@ -396,7 +616,30 @@ void max_acceleration_and_velocity(particles & vd, double & max_acc, double & ma max_vel = sqrt(max_vel); } -double dt_old = 0.0; +/*! \cond [max_acc_vel] \endcond */ + +/*! + * + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * In this example we are using Dynamic time-stepping. The Dynamic time stepping is + * calculated with the Courant-Friedrich-Lewy condition. See Monaghan 1992 "Smoothed Particle Hydrodynamic" + * + * \f$ \delta t = CFL \cdot min(t_f,t_{cv}) \f$ + * + * where + * + * \f$ \delta t_f = min \sqrt{h/f_a}\f$ + * + * \f$ \delta t_{cv} = min \frac{h}{c_s + max \left| \frac{hv_{ab} \cdot r_{ab}}{r_{ab}^2} \right|} \f$ + * + * + * \snippet Vector/7_SPH_dlb/main.cpp dyn_stepping + * + * + */ + +/*! \cond [dyn_stepping] \endcond */ double calc_deltaT(particles & vd, double ViscDtMax) { @@ -410,29 +653,51 @@ double calc_deltaT(particles & vd, double ViscDtMax) //-dt2 combines the Courant and the viscous time-step controls. const double dt_cv = H/(std::max(cbar,Maxvel*10.) + H*ViscDtMax); -// std::cout << "dt_f " << dt_f << " dt_cv: " << dt_cv << " Maxvel: " << Maxvel << std::endl; - //-dt new value of time step. double dt=double(CFLnumber)*std::min(dt_f,dt_cv); if(dt<double(DtMin)) dt=double(DtMin); - if (dt_old != dt) - { - std::cout << "Dt changed to " << dt << " MaxVel: " << Maxvel << " Maxacc: " << Maxacc << " lower_z: " << lower_z << std::endl; - - dt_old = dt; - } - -// std::cout << "Returned dt: " << dt << std::endl; return dt; } +/*! \cond [dyn_stepping] \endcond */ + +/*! + * + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * This function perform verlet integration accordingly to the Verlet time stepping scheme + * + * \f$ v_a^{n+1} = v_a^{n-1} + 2 \delta t F_a^{n} \f$ + * + * \f$ r_a^{n+1} = \delta t V_a^n + 0.5 \delta t^2 F_a^n \f$ + * + * \f$ \rho_a^{n+1} = \rho_a^{n-1} + 2 \delta t D_a^n \f$ + * + * Every N Verlet steps the euler stepping scheme is choosen to avoid instabilities + * + * \f$ v_a^{n+1} = v_a^{n} + \delta t F_a^n \f$ + * + * \f$ r_a^{n+1} = r_a^{n} + \delta t V_a^n + 0.5 delta t^2 F_a^n \f$ + * + * \f$ \rho_a^n + \delta t D_a^n \f$ + * + * More the integration this function also check that no particles go outside the simulation + * domain or their density go dangerously out of range + * + * \snippet Vector/7_SPH_dlb/main.cpp verlet_int + * + * + */ + +/*! \cond [verlet_int] \endcond */ + openfpm::vector<size_t> to_remove; -bool particle_out = true; +size_t cnt = 0; -void verlet_int(particles & vd, double dt) +void verlet_int(particles & vd, double dt, bool VerletStep) { to_remove.clear(); @@ -448,7 +713,26 @@ void verlet_int(particles & vd, double dt) if (vd.template getProp<type>(a) == BOUNDARY) { + double rhop = vd.template getProp<rho>(a); + // Update only the density + if (VerletStep == true) + { + vd.template getProp<velocity>(a)[0] = 0.0; + vd.template getProp<velocity>(a)[1] = 0.0; + vd.template getProp<velocity>(a)[2] = 0.0; + vd.template getProp<rho>(a) = vd.template getProp<rho_prev>(a) + dt2*vd.template getProp<drho>(a); + } + else + { + vd.template getProp<velocity>(a)[0] = 0.0; + vd.template getProp<velocity>(a)[1] = 0.0; + vd.template getProp<velocity>(a)[2] = 0.0; + vd.template getProp<rho>(a) = vd.template getProp<rho>(a) + dt*vd.template getProp<drho>(a); + } + + vd.template getProp<rho_prev>(a) = rhop; + ++part; continue; } @@ -458,75 +742,62 @@ void verlet_int(particles & vd, double dt) double dy = vd.template getProp<velocity>(a)[1]*dt + vd.template getProp<force>(a)[1]*dt205; double dz = vd.template getProp<velocity>(a)[2]*dt + vd.template getProp<force>(a)[2]*dt205; -// bool outrhop=(rhopnew<RhopOutMin||rhopnew>RhopOutMax); - -// if (vd.getPos(a)[0] > 0.0085 && vd.getPos(a)[0] < 0.0105 && -// vd.getPos(a)[1] > 0.0085 && vd.getPos(a)[1] < 0.0105 && -// vd.getPos(a)[2] > 0.0085 && vd.getPos(a)[2] < 0.0105) -// { -// std::cout << "DeltaX: " << dx << " " << dy << " " << dz << std::endl; -/* std::cout << "FORCE: " << vd.template getProp<force>(a)[0] << " " - << vd.template getProp<force>(a)[1] << " " - << vd.template getProp<force>(a)[2] << - " DENSITY: " << vd.template getProp<rho_prev>(a) + dt2*vd.template getProp<drho>(a) << - " PRESSURE: " << vd.template getProp<Pressure>(a) << - " POSITION Z: " << vd.getPos(a)[2] - << std::endl;*/ - // std::cout << "FORCE TERM: " << Tensile(r,rhoa,rhob,Pa,Pb,true) << " " << massb*Pi(dr,r2,v_rel,rhoa,rhob,massa,massb) << std::endl; -// } - vd.getPos(a)[0] += dx; vd.getPos(a)[1] += dy; vd.getPos(a)[2] += dz; - if (vd.getPos(a)[2] < lower_z) - lower_z = vd.getPos(a)[2]; - - if (vd.getPos(a)[0] < 0.000263878 || vd.getPos(a)[1] < 0.000263878 || vd.getPos(a)[2] < 0.000263878 || - vd.getPos(a)[0] > 0.000263878+1.59947 || vd.getPos(a)[1] > 0.000263878+0.672972 || vd.getPos(a)[2] > 0.000263878+0.903944) - { -// std::cout << "Particle out" << std::endl; - to_remove.add(a.getKey()); - - particle_out = true; - } - double velX = vd.template getProp<velocity>(a)[0]; double velY = vd.template getProp<velocity>(a)[1]; double velZ = vd.template getProp<velocity>(a)[2]; double rhop = vd.template getProp<rho>(a); - vd.template getProp<velocity>(a)[0] = vd.template getProp<velocity_prev>(a)[0] + vd.template getProp<force>(a)[0]*dt2; - vd.template getProp<velocity>(a)[1] = vd.template getProp<velocity_prev>(a)[1] + vd.template getProp<force>(a)[1]*dt2; - vd.template getProp<velocity>(a)[2] = vd.template getProp<velocity_prev>(a)[2] + vd.template getProp<force>(a)[2]*dt2; - vd.template getProp<rho>(a) = vd.template getProp<rho_prev>(a) + dt2*vd.template getProp<drho>(a); + if (VerletStep == true) + { + vd.template getProp<velocity>(a)[0] = vd.template getProp<velocity_prev>(a)[0] + vd.template getProp<force>(a)[0]*dt2; + vd.template getProp<velocity>(a)[1] = vd.template getProp<velocity_prev>(a)[1] + vd.template getProp<force>(a)[1]*dt2; + vd.template getProp<velocity>(a)[2] = vd.template getProp<velocity_prev>(a)[2] + vd.template getProp<force>(a)[2]*dt2; + vd.template getProp<rho>(a) = vd.template getProp<rho_prev>(a) + dt2*vd.template getProp<drho>(a); + } + else + { + vd.template getProp<velocity>(a)[0] = vd.template getProp<velocity>(a)[0] + vd.template getProp<force>(a)[0]*dt; + vd.template getProp<velocity>(a)[1] = vd.template getProp<velocity>(a)[1] + vd.template getProp<force>(a)[1]*dt; + vd.template getProp<velocity>(a)[2] = vd.template getProp<velocity>(a)[2] + vd.template getProp<force>(a)[2]*dt; + vd.template getProp<rho>(a) = vd.template getProp<rho>(a) + dt*vd.template getProp<drho>(a); + } + + // Check if there are particles to remove + + if (vd.getPos(a)[0] < 0.000263878 || vd.getPos(a)[1] < 0.000263878 || vd.getPos(a)[2] < 0.000263878 || + vd.getPos(a)[0] > 0.000263878+1.59947 || vd.getPos(a)[1] > 0.000263878+0.672972 || vd.getPos(a)[2] > 0.000263878+0.903944 || + vd.template getProp<rho>(a) < RhoMin || vd.template getProp<rho>(a) > RhoMax) + { + std::cout << "Particle_out" << std::endl; + to_remove.add(a.getKey()); + } vd.template getProp<velocity_prev>(a)[0] = velX; vd.template getProp<velocity_prev>(a)[1] = velY; vd.template getProp<velocity_prev>(a)[2] = velZ; vd.template getProp<rho_prev>(a) = rhop; -// std::cout << "VELOCITY: " << vd.template getProp<velocity>(a)[0] << " " << vd.template getProp<velocity>(a)[1] << " " << vd.template getProp<velocity>(a)[2] << std::endl; -// std::cout << "++++++++++++++++++++++++++++++++++++++++++" << std::endl; - -/* if (particle_out == true) - { - std::cout << "PARTICLE DENSITY: " << vd.template getProp<rho>(a) << " PARTICLE PRESSURE: " << vd.template getProp<Pressure>(a) << " Delta rho: " << vd.template getProp<drho>(a) << " VELOCITY: " << vd.template getProp<velocity>(a)[0] << " " << vd.template getProp<velocity>(a)[1] << " " << vd.template getProp<velocity>(a)[2] << std::endl; - }*/ - ++part; } vd.remove(to_remove,0); + + cnt++; } +/*! \cond [verlet_int] \endcond */ + int main(int argc, char* argv[]) { - /*! - * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balacing * - * ## Initialization ## + * \page Vector_7_sph_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing + * + * ## Main function ## * * Here we Initialize the library, we create a Box that define our domain, boundary conditions, ghost * @@ -542,8 +813,8 @@ int main(int argc, char* argv[]) openfpm_init(&argc,&argv); // Here we define our domain a 2D box with internals from 0 to 1.0 for x and y - Box<3,double> domain({-0.05,-0.05,-0.05},{2.0070,1.0040,1.0040}); - size_t sz[3] = {243,125,125}; + Box<3,double> domain({-0.05,-0.05,-0.05},{1.7010,0.7065,0.5025}); + size_t sz[3] = {207,90,66}; // Fill W_dap W_dap = 1.0/Wab(H/1.5); @@ -557,7 +828,7 @@ int main(int argc, char* argv[]) //! \cond [Initialization and parameters] \endcond /*! - * \page Vector_7_SPH_dlb Vector 7 SPH Dam break simulation with Dynamic load balacing + * \page Vector_7_SPH_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing * * ## %Vector create ## * @@ -573,15 +844,14 @@ int main(int argc, char* argv[]) //! \cond [vector inst] \endcond - particles vd(0,domain,bc,g); + particles vd(0,domain,bc,g,DEC_GRAN(4096)); //! \cond [vector inst] \endcond // the scalar is the element at position 0 in the aggregate const int type = 0; -// 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}); - Box<3,double> fluid_box({0.2,0.2,0.298},{0.2+2*dp,0.2+2*dp,0.298+2*dp}); + 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}); // first we create Fluid particles // Fluid particles are created @@ -592,8 +862,6 @@ int main(int argc, char* argv[]) B = (coeff_sound)*(coeff_sound)*gravity*h_swl*rho_zero / gamma_; cbar = coeff_sound * sqrt(gravity * h_swl); -// std::cout << "MAX FLUID: " << max_fluid_height << std::endl; - while (fluid_it.isNext()) { vd.add(); @@ -613,8 +881,6 @@ int main(int argc, char* argv[]) vd.template getLastProp<Pressure>() = rho_zero * gravity * (max_fluid_height - fluid_it.get().get(2)); - std::cout << "B: " << B << std::endl; - vd.template getLastProp<rho>() = pow(vd.template getLastProp<Pressure>() / B + 1, 1.0/gamma_) * rho_zero; vd.template getLastProp<rho_prev>() = vd.template getLastProp<rho>(); vd.template getLastProp<velocity>()[0] = 0.0; @@ -690,7 +956,31 @@ int main(int argc, char* argv[]) } vd.map(); - vd.ghost_get<rho,Pressure>(); + vd.getDecomposition().write("Decomposition_before_load_bal"); + + // Now that we fill the vector with particles + ModelCustom md; + + vd.addComputationCosts(md); + vd.getDecomposition().getDistribution().write("BEFORE_DECOMPOSE"); + vd.getDecomposition().decompose(); + vd.map(); + + vd.addComputationCosts(md); + vd.getDecomposition().getDistribution().write("AFTER_DECOMPOSE1"); + + vd.getDecomposition().rebalance(1); + + vd.map(); + vd.getDecomposition().getDistribution().write("AFTER_DECOMPOSE2"); + + std::cout << "N particles: " << vd.size_local() << " " << create_vcluster().getProcessUnitID() << " " << "Get processor Load " << vd.getDecomposition().getDistribution().getProcessorLoad() << std::endl; + + vd.write("Geometry"); + vd.getDecomposition().write("Decomposition_after_load_bal"); + vd.getDecomposition().getDistribution().write("Distribution_load_bal"); + + vd.ghost_get<type,rho,Pressure,velocity>(); auto NN = vd.getCellList(2*H); @@ -699,27 +989,44 @@ int main(int argc, char* argv[]) size_t write = 0; size_t it = 0; + size_t it_reb = 0; double t = 0.0; while (t <= t_end) { - const size_t type = 0; - const int rho = 1; - const int Pressure = 2; - const int drho = 3; - const int force = 4; - const int velocity = 5; - const int velocity_prev = 6; + timer it_time; + + ////// Do rebalancing every 200 timesteps + it_reb++; + if (it_reb == 10) + { + vd.map(); + + it_reb = 0; + ModelCustom md; + vd.addComputationCosts(md); + vd.getDecomposition().rebalance(1); + + std::cout << "REBALANCED " << std::endl; + } vd.map(); - vd.ghost_get<type,rho,Pressure,velocity,velocity_prev>(); + vd.ghost_get<type,rho,Pressure,velocity>(); // Calculate pressure from the density EqState(vd); double max_visc = 0.0; + it_time.start(); + // Calc forces calc_forces(vd,NN,max_visc); + it_time.stop(); + + // Get the maximum viscosity term across processors + Vcluster & v_cl = create_vcluster(); + v_cl.max(max_visc); + v_cl.execute(); // Calculate delta t integration double dt = calc_deltaT(vd,max_visc); @@ -727,7 +1034,14 @@ int main(int argc, char* argv[]) // std::cout << "Calculate deltaT: " << dt << " " << DtMin << std::endl; // VerletStep - verlet_int(vd,dt); + it++; + if (it < 40) + verlet_int(vd,dt,true); + else + { + verlet_int(vd,dt,false); + it = 0; + } t += dt; @@ -736,6 +1050,12 @@ int main(int argc, char* argv[]) vd.write("Geometry",write); write++; + + std::cout << "TIME: " << t << " write " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " " << cnt << std::endl; + } + else + { + std::cout << "TIME: " << t << " " << it_time.getwct() << " " << v_cl.getProcessUnitID() << " " << cnt << std::endl; } } @@ -746,7 +1066,7 @@ int main(int argc, char* argv[]) //! \cond [finalize] \endcond /*! - * \page Vector_7_SPH_dlb Vector 7 SPH Dam break simulation with Dynamic load balacing + * \page Vector_7_SPH_dlb Vector 7 SPH Dam break simulation with Dynamic load balancing * * ## Full code ## {#code_e0_sim} * diff --git a/openfpm_numerics b/openfpm_numerics index 2a805e31..9e49bd95 160000 --- a/openfpm_numerics +++ b/openfpm_numerics @@ -1 +1 @@ -Subproject commit 2a805e31cd0bc1e5fe89c8f6a03ba22b1691ad2d +Subproject commit 9e49bd9594b1b1c0d9cdd19e609aaba7a163d907 diff --git a/openfpm_pdata.doc b/openfpm_pdata.doc index 21a5e06b..335cc0cb 100644 --- a/openfpm_pdata.doc +++ b/openfpm_pdata.doc @@ -38,7 +38,7 @@ PROJECT_NAME = "OpenFPM_pdata" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.7.0 +PROJECT_NUMBER = 0.8.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/src/Decomposition/CartDecomposition.hpp b/src/Decomposition/CartDecomposition.hpp index d9e5e91c..be5dbdb9 100755 --- a/src/Decomposition/CartDecomposition.hpp +++ b/src/Decomposition/CartDecomposition.hpp @@ -351,11 +351,11 @@ public: for (size_t i = 0; i < dist.getNSubSubDomains(); i++) { - dist.setMigrationCost(i, norm * migration * dist.getSubSubDomainComputationCost(i)); + dist.setMigrationCost(i, norm * migration /* * dist.getSubSubDomainComputationCost(i) */); for (size_t s = 0; s < dist.getNSubSubDomainNeighbors(i); s++) { - dist.setCommunicationCost(i, s, 1 * dist.getSubSubDomainComputationCost(i) * ts); + dist.setCommunicationCost(i, s, 1 * /* dist.getSubSubDomainComputationCost(i) * */ ts); } prev += dist.getNSubSubDomainNeighbors(i); } @@ -994,6 +994,7 @@ public: sub_domains.clear(); box_nn_processor.clear(); fine_s.clear(); + loc_box.clear(); nn_prcs<dim, T>::reset(); ie_ghost<dim, T>::reset(); ie_loc_ghost<dim, T>::reset(); @@ -1122,7 +1123,7 @@ public: */ inline size_t getSubSubDomainComputationCost(size_t id) { - return dist.getComputationCost(id); + return dist.getSubSubDomainComputationCost(id); } /*! \brief Operator to access the size of the sub-graph diff --git a/src/Decomposition/Distribution/ParMetisDistribution.hpp b/src/Decomposition/Distribution/ParMetisDistribution.hpp index 3bddfc98..6790e49f 100644 --- a/src/Decomposition/Distribution/ParMetisDistribution.hpp +++ b/src/Decomposition/Distribution/ParMetisDistribution.hpp @@ -118,28 +118,33 @@ class ParMetisDistribution for (size_t i = 0; i <= Np; i++) vtxdist.get(i) = n_vtxdist.get(i); + openfpm::vector<size_t> cnt; + cnt.resize(Np); + // Renumber the main graph and re-create the map - for (size_t p = 0; p < (size_t)Np; p++) +/* for (size_t p = 0; p < (size_t)Np; p++) { size_t i = 0; for (rid j = vtxdist.get(p); j < vtxdist.get(p + 1); ++j, i++) { setMapId(j, v_per_proc.get(p).get(i)); - gp.vertex(v_per_proc.get(p).get(i).id).template get<nm_v::id>() = j.id; + gp.vertex(v_per_proc.get(p).get(i).id).template get<nm_v::id>() = cnt.get(p) + vtxdist.get(p).id; + cnt.get(p)++; } - } - } - - void createMapsFromGlobalGraph(openfpm::vector<size_t> & vtxdist) - { -/* openfpm::vector<size_t> cnt_np; + }*/ - for (size_t i = 0 ; i < gp.getNVertex() ; i++) + for (size_t i = 0 ; i < gp.getNVertex(); ++i) { - cnt_np(gp.template vertex<nm_v::proc_id>)++; + size_t pid = gp.template vertex_p<nm_v::proc_id>(i); - gp.setMapId() - }*/ + rid j = rid(vtxdist.get(pid).id + cnt.get(pid)); + gid gi = gid(i); + + gp.template vertex_p<nm_v::id>(i) = j.id; + cnt.get(pid)++; + + setMapId(j,gi); + } } /*! \brief operator to access the vertex by mapped position diff --git a/src/Graph/CartesianGraphFactory.hpp b/src/Graph/CartesianGraphFactory.hpp index a3d8d275..d9638e03 100755 --- a/src/Graph/CartesianGraphFactory.hpp +++ b/src/Graph/CartesianGraphFactory.hpp @@ -76,6 +76,9 @@ struct fill_id<dim, G_v, NO_VERTEX_ID> template<unsigned int dim, int lin_id, typename dT, typename G_v, typename v, int impl> class fill_prop { + //! Domain + const Box<dim,dT> & domain; + //! Reference to an array containing the spacing const dT (&szd)[dim]; @@ -91,8 +94,8 @@ class fill_prop public: //! Fill the object from where to take the properties - fill_prop(G_v & g_v, const dT (&szd)[dim], grid_key_dx<dim> & gk, const grid_sm<dim, void> & gs) : - szd(szd), gk(gk), g_v(g_v), gs(gs) + fill_prop(G_v & g_v, const dT (&szd)[dim], grid_key_dx<dim> & gk, const grid_sm<dim, void> & gs, const Box<dim,dT> & domain) + :domain(domain), szd(szd), gk(gk), g_v(g_v), gs(gs) { } @@ -102,7 +105,7 @@ public: { typedef typename boost::fusion::result_of::at<v, boost::mpl::int_<T::value>>::type t_val; - g_v.template get<t_val::value>() = gk.get(T::value) * szd[T::value]; + g_v.template get<t_val::value>() = gk.get(T::value) * szd[T::value] + domain.getLow(T::value); fill_id<dim, G_v, lin_id>::fill(g_v, gk, gs); } }; @@ -140,7 +143,7 @@ class fill_prop<dim, lin_id, dT, G_v, v, 0> public: //! Fill the object from where to take the properties - fill_prop(G_v & g_v, const dT (&szd)[dim], grid_key_dx<dim> & gk, const grid_sm<dim, void> & gs) + fill_prop(G_v & g_v, const dT (&szd)[dim], grid_key_dx<dim> & gk, const grid_sm<dim, void> & gs, const Box<dim,dT> & domain) { } @@ -180,6 +183,8 @@ public: template<unsigned int dim, int lin_id, typename dT, typename G_v, typename v> class fill_prop<dim, lin_id, dT, G_v, v, 2> { + //! Domain + const Box<dim,dT> & domain; //! Reference to an array containing the spacing const dT (&szd)[dim]; @@ -196,8 +201,8 @@ class fill_prop<dim, lin_id, dT, G_v, v, 2> public: //! Fill the object from where to take the properties - fill_prop(G_v & g_v, const dT (&szd)[dim], grid_key_dx<dim> & gk, const grid_sm<dim, void> & gs) : - szd(szd), gk(gk), g_v(g_v), gs(gs) + fill_prop(G_v & g_v, const dT (&szd)[dim], grid_key_dx<dim> & gk, const grid_sm<dim, void> & gs, const Box<dim,dT> & domain) + :domain(domain), szd(szd), gk(gk), g_v(g_v), gs(gs) { } @@ -212,7 +217,7 @@ public: g_v.template get<t_val::value>()[i] = 0.0; for (size_t i = 0 ; i < dim ; i++) - g_v.template get<t_val::value>()[i] = gk.get(i) * static_cast<float>(szd[i]); + g_v.template get<t_val::value>()[i] = gk.get(i) * static_cast<float>(szd[i]) + domain.getLow(i); fill_id<dim, G_v, lin_id>::fill(g_v, gk, gs); } @@ -330,7 +335,7 @@ public: // vertex spatial properties functor - fill_prop<dim, lin_id, T, decltype(gp.vertex(g.LinId(key))), typename to_boost_vmpl<pos...>::type, fill_prop_by_type<sizeof...(pos), p, Graph, pos...>::value> flp(obj, szd, key, g); + fill_prop<dim, lin_id, T, decltype(gp.vertex(g.LinId(key))), typename to_boost_vmpl<pos...>::type, fill_prop_by_type<sizeof...(pos), p, Graph, pos...>::value> flp(obj, szd, key, g, dom); // fill properties @@ -451,7 +456,7 @@ public: // vertex spatial properties functor - fill_prop<dim, lin_id, T, decltype(gp.vertex(g.LinId(key))), typename to_boost_vmpl<pos...>::type, fill_prop_by_type<sizeof...(pos), p, Graph, pos...>::value> flp(obj, szd, key, g); + fill_prop<dim, lin_id, T, decltype(gp.vertex(g.LinId(key))), typename to_boost_vmpl<pos...>::type, fill_prop_by_type<sizeof...(pos), p, Graph, pos...>::value> flp(obj, szd, key, g, dom); // fill properties diff --git a/src/Graph/ids.hpp b/src/Graph/ids.hpp index 63c3dc79..ea4826a1 100644 --- a/src/Graph/ids.hpp +++ b/src/Graph/ids.hpp @@ -17,8 +17,17 @@ */ struct rid { + //! id idx_t id; + //! Cosntructor + rid(size_t id) + :id(id) + {} + + //! Constructor + rid() {} + inline bool operator<=(const rid & r) const { return id <= r.id; @@ -79,6 +88,14 @@ struct rid struct gid { size_t id; + + //! Constructor + gid(){}; + + //! Constructor + gid(size_t id) + :id(id) + {} }; /*! Here we define different the remapped-id diff --git a/src/Makefile.am b/src/Makefile.am index 23d87159..ca89186e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ nobase_include_HEADERS = Decomposition/CartDecomposition.hpp Decomposition/CartD example.mk \ Decomposition/Distribution/metis_util.hpp Decomposition/Distribution/SpaceDistribution.hpp Decomposition/Distribution/parmetis_dist_util.hpp Decomposition/Distribution/parmetis_util.hpp Decomposition/Distribution/MetisDistribution.hpp Decomposition/Distribution/ParMetisDistribution.hpp Decomposition/Distribution/DistParMetisDistribution.hpp dec_optimizer.hpp SubdomainGraphNodes.hpp \ Graph/ids.hpp Graph/dist_map_graph.hpp Graph/DistGraphFactory.hpp \ - DLB/DLB.hpp + DLB/DLB.hpp DLB/LB_Model.hpp lib_LIBRARIES = libofpm_pdata.a libofpm_pdata_a_SOURCES = lib/pdata.cpp diff --git a/src/Vector/vector_dist.hpp b/src/Vector/vector_dist.hpp index 031a0d43..0034c7a5 100644 --- a/src/Vector/vector_dist.hpp +++ b/src/Vector/vector_dist.hpp @@ -30,10 +30,13 @@ #include "data_type/aggregate.hpp" #include "NN/VerletList/VerletList.hpp" #include "vector_dist_comm.hpp" +#include "DLB/LB_Model.hpp" #define NO_ID false #define ID true +#define DEC_GRAN(gr) ((size_t)gr << 32) + // Perform a ghost get or a ghost put #define GET 1 #define PUT 2 @@ -236,6 +239,9 @@ public: check_new(this,8,VECTOR_DIST_EVENT,4); #endif + if (opt >> 32 != 0) + this->setDecompositionGranularity(opt >> 32); + check_parameters(box); init_structures(np); @@ -1022,21 +1028,19 @@ public: g_m--; } - /*! \brief Add the computation cost on the decomposition comming from the particles + /*! \brief Add the computation cost on the decomposition coming from the particles * */ - inline void addComputationCosts() + template <typename Model=ModelLin>inline void addComputationCosts(Model md=Model()) { - CellDecomposer_sm<dim, St> cdsm; + CellDecomposer_sm<dim, St, shift<dim,St>> cdsm; Decomposition & dec = getDecomposition(); cdsm.setDimensions(dec.getDomain(), dec.getGrid().getSize(), 0); for (size_t i = 0; i < getDecomposition().getNSubSubDomains(); i++) - { dec.setSubSubDomainComputationCost(i, 1); - } auto it = getDomainIterator(); @@ -1044,11 +1048,15 @@ public: { size_t v = cdsm.getCell(this->getPos(it.get())); - dec.addComputationCost(v, 1); + md.addComputation(dec,*this,v,it.get().getKey()); ++it; } + // Go throught all the sub-sub-domains and apply the model + + for (size_t i = 0 ; i < dec.getDistribution().getNSubSubDomains(); i++) + md.applyModel(dec,i); } /*! \brief Output particle position and properties diff --git a/src/Vector/vector_dist_MP_unit_tests.hpp b/src/Vector/vector_dist_MP_unit_tests.hpp index 44797b43..4f797a77 100644 --- a/src/Vector/vector_dist_MP_unit_tests.hpp +++ b/src/Vector/vector_dist_MP_unit_tests.hpp @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE( vector_dist_multiphase_cell_list_test ) auto CL_phase1 = phases.get(1).getCellList(r_cut); // This function create a Verlet-list between phases 0 and 1 - auto NN_ver01 = createVerlet(phases.get(0),CL_phase1,r_cut); + auto NN_ver01 = createVerlet(phases.get(0),phases.get(1),CL_phase1,r_cut); // Check NNver0_1 @@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE( vector_dist_multiphase_cell_list_test ) auto CL_all = createCellListM<2>(phases,r_cut); // This create a Verlet-list between phase 0 and all the other phases - auto NNver0_all = createVerletM<2>(phases.get(0),CL_all,r_cut); + auto NNver0_all = createVerletM<2>(phases.get(0),phases,CL_all,r_cut); it = phases.get(0).getDomainIterator(); @@ -235,7 +235,7 @@ BOOST_AUTO_TEST_CASE( vector_dist_multiphase_cell_list_sym_test ) auto CL_phase1 = phases.get(1).getCellListSym(r_cut); // This function create a Verlet-list between phases 0 and 1 - auto NN_ver01 = createVerletSym(phases.get(0),CL_phase1,r_cut); + auto NN_ver01 = createVerletSym(phases.get(0),phases.get(1),CL_phase1,r_cut); // Check NNver0_1 @@ -305,15 +305,15 @@ BOOST_AUTO_TEST_CASE( vector_dist_multiphase_cell_list_sym_test ) // This function create an "Empty" Multiphase Cell List auto CL_all = createCellListSymM<2>(phases,r_cut); - typedef decltype(createVerletSymM<2>(phases.get(0),CL_all,r_cut)) verlet_type; + typedef decltype(createVerletSymM<2>(phases.get(0),phases,CL_all,r_cut)) verlet_type; verlet_type NNver_all[4]; // This create a Verlet-list between phase all phases to all the other phases - NNver_all[0] = createVerletSymM<2>(phases.get(0),CL_all,r_cut); - NNver_all[1] = createVerletSymM<2>(phases.get(1),CL_all,r_cut); - NNver_all[2] = createVerletSymM<2>(phases.get(2),CL_all,r_cut); - NNver_all[3] = createVerletSymM<2>(phases.get(3),CL_all,r_cut); + NNver_all[0] = createVerletSymM<2>(phases.get(0),phases,CL_all,r_cut); + NNver_all[1] = createVerletSymM<2>(phases.get(1),phases,CL_all,r_cut); + NNver_all[2] = createVerletSymM<2>(phases.get(2),phases,CL_all,r_cut); + NNver_all[3] = createVerletSymM<2>(phases.get(3),phases,CL_all,r_cut); // all phases to all phases diff --git a/src/Vector/vector_dist_comm.hpp b/src/Vector/vector_dist_comm.hpp index 355035dd..d79031be 100644 --- a/src/Vector/vector_dist_comm.hpp +++ b/src/Vector/vector_dist_comm.hpp @@ -8,8 +8,6 @@ #ifndef SRC_VECTOR_VECTOR_DIST_COMM_HPP_ #define SRC_VECTOR_VECTOR_DIST_COMM_HPP_ -#define V_SUB_UNIT_FACTOR 64 - #define SKIP_LABELLING 512 #define KEEP_PROPERTIES 512 @@ -47,6 +45,9 @@ inline static size_t compute_options(size_t opt) template<unsigned int dim, typename St, typename prop, typename Decomposition = CartDecomposition<dim,St>, typename Memory = HeapMemory> class vector_dist_comm { + //! Number of units for each sub-domain + size_t v_sub_unit_factor = 64; + //! definition of the send vector for position typedef openfpm::vector<Point<dim, St>, Memory> send_pos_vector; @@ -784,14 +785,24 @@ public: { } - /*! \brief Get the number of minimum sub-domain + /*! \brief Get the number of minimum sub-domain per processor * * \return minimum number * */ - static size_t getDefaultNsubsub() + size_t getDecompositionGranularity() + { + return v_sub_unit_factor; + } + + /*! \brief Set the minimum number of sub-domain per processor + * + * \param n_sub + * + */ + void setDecompositionGranularity(size_t n_sub) { - return V_SUB_UNIT_FACTOR; + this->v_sub_unit_factor = n_sub; } /*! \brief Initialize the decomposition @@ -826,7 +837,7 @@ public: // Get the number of processor and calculate the number of sub-domain // for decomposition size_t n_proc = v_cl.getProcessingUnits(); - size_t n_sub = n_proc * getDefaultNsubsub(); + size_t n_sub = n_proc * getDecompositionGranularity(); // Calculate the maximum number (before merging) of sub-domain on // each dimension diff --git a/src/Vector/vector_dist_multiphase_functions.hpp b/src/Vector/vector_dist_multiphase_functions.hpp index 4a3c6e32..543eb68e 100644 --- a/src/Vector/vector_dist_multiphase_functions.hpp +++ b/src/Vector/vector_dist_multiphase_functions.hpp @@ -11,20 +11,25 @@ #include "NN/CellList/CellListM.hpp" #include "NN/VerletList/VerletListM.hpp" -template<typename Vector,typename CL, typename T> VerletList<Vector::dims,typename Vector::stype,FAST,shift<Vector::dims,typename Vector::stype>> createVerlet(Vector & v, CL & cl, T r_cut) +template<typename Vector, typename CL, typename T> VerletList<Vector::dims,typename Vector::stype,FAST,shift<Vector::dims,typename Vector::stype>> createVerlet(Vector & v, Vector & v1, CL & cl, T r_cut) { VerletList<Vector::dims,typename Vector::stype,FAST,shift<Vector::dims,typename Vector::stype>> ver; - ver.Initialize(cl,r_cut,v.getPosVector(),v.size_local()); + ver.Initialize(cl,r_cut,v.getPosVector(),v1.getPosVector(),v.size_local()); return ver; } -template<unsigned int sh_byte, typename Vector,typename CL, typename T> VerletListM<Vector::dims,typename Vector::stype,sh_byte,shift<Vector::dims,typename Vector::stype>> createVerletM(Vector & v, CL & cl, T r_cut) +template<unsigned int sh_byte, typename Vector , typename Vector1,typename CL, typename T> VerletListM<Vector::dims,typename Vector::stype,sh_byte,CL,shift<Vector::dims,typename Vector::stype>> createVerletM(Vector & v, Vector1 & phases, CL & cl, T r_cut) { - VerletListM<Vector::dims,typename Vector::stype,sh_byte,shift<Vector::dims,typename Vector::stype>> ver; + VerletListM<Vector::dims,typename Vector::stype,sh_byte,CL,shift<Vector::dims,typename Vector::stype>> ver; - ver.Initialize(cl,r_cut,v.getPosVector(),v.size_local()); + openfpm::vector<pos_v<Vector::dims,typename Vector::stype>> v_phases; + + for (size_t i = 0 ; i < phases.size() ; i++) + v_phases.add(pos_v<Vector::dims,typename Vector::stype>(phases.get(i).getPosVector())); + + ver.Initialize(cl,r_cut,v.getPosVector(),v_phases,v.size_local()); return ver; } @@ -65,20 +70,25 @@ template<unsigned int nbit, typename Vector, typename T> CellListM<Vector::dims, /////// Symmetric version -template<typename Vector,typename CL, typename T> VerletList<Vector::dims,typename Vector::stype,FAST,shift<Vector::dims,typename Vector::stype>> createVerletSym(Vector & v, CL & cl, T r_cut) +template<typename Vector,typename CL, typename T> VerletList<Vector::dims,typename Vector::stype,FAST,shift<Vector::dims,typename Vector::stype>> createVerletSym(Vector & v, Vector & v1, CL & cl, T r_cut) { VerletList<Vector::dims,typename Vector::stype,FAST,shift<Vector::dims,typename Vector::stype>> ver; - ver.Initialize(cl,r_cut,v.getPosVector(),v.size_local()); + ver.Initialize(cl,r_cut,v.getPosVector(),v1.getPosVector(),v.size_local()); return ver; } -template<unsigned int sh_byte, typename Vector,typename CL, typename T> VerletListM<Vector::dims,typename Vector::stype,sh_byte,shift<Vector::dims,typename Vector::stype>> createVerletSymM(Vector & v, CL & cl, T r_cut) +template<unsigned int sh_byte, typename Vector, typename Vector1 ,typename CL, typename T> VerletListM<Vector::dims,typename Vector::stype,sh_byte,CL,shift<Vector::dims,typename Vector::stype>> createVerletSymM(Vector & v, Vector1 & phases, CL & cl, T r_cut) { - VerletListM<Vector::dims,typename Vector::stype,sh_byte,shift<Vector::dims,typename Vector::stype>> ver; + VerletListM<Vector::dims,typename Vector::stype,sh_byte,CL,shift<Vector::dims,typename Vector::stype>> ver; + + openfpm::vector<pos_v<Vector::dims,typename Vector::stype>> v_phases; + + for (size_t i = 0 ; i < phases.size() ; i++) + v_phases.add(pos_v<Vector::dims,typename Vector::stype>(phases.get(i).getPosVector())); - ver.Initialize(cl,r_cut,v.getPosVector(),v.size_local(),VL_SYMMETRIC); + ver.Initialize(cl,r_cut,v.getPosVector(),v_phases,v.size_local(),VL_SYMMETRIC); return ver; } diff --git a/src/Vector/vector_dist_unit_test.hpp b/src/Vector/vector_dist_unit_test.hpp index aefd55ab..9102beb4 100644 --- a/src/Vector/vector_dist_unit_test.hpp +++ b/src/Vector/vector_dist_unit_test.hpp @@ -105,7 +105,7 @@ void Test2D_ghost(Box<2,float> & box) typedef Point_test<float> p; // Get the default minimum number of sub-sub-domain per processor (granularity of the decomposition) - size_t n_sub = vector_dist<2,float, Point_test<float>, CartDecomposition<2,float> >::getDefaultNsubsub() * v_cl.getProcessingUnits(); + size_t n_sub = 64 * v_cl.getProcessingUnits(); // Convert the request of having a minimum n_sub number of sub-sub domain into grid decompsition of the space size_t sz = CartDecomposition<2,float>::getDefaultGrid(n_sub); -- GitLab