114 #include "interpolation/interpolation.hpp" 115 #include "Grid/grid_dist_id.hpp" 116 #include "Vector/vector_dist.hpp" 117 #include "Matrix/SparseMatrix.hpp" 118 #include "Vector/Vector.hpp" 119 #include "FiniteDifference/FDScheme.hpp" 120 #include "Solvers/petsc_solver.hpp" 121 #include "interpolation/mp4_kernel.hpp" 122 #include "Solvers/petsc_solver_AMG_report.hpp" 137 float sigma = 1.0/3.523;
140 float tgtre = 3000.0;
143 float nu = 1.0/tgtre;
150 const unsigned int nsteps = 10;
152 const unsigned int nsteps = 10001;
156 constexpr
unsigned int vorticity = 0;
157 constexpr
unsigned int velocity = 0;
158 constexpr
unsigned int p_vel = 1;
159 constexpr
int rhs_part = 2;
160 constexpr
unsigned int old_vort = 3;
161 constexpr
unsigned int old_pos = 4;
165 template<
typename gr
id>
void calc_and_print_max_div_and_int(
grid & g_vort)
169 g_vort.template ghost_get<vorticity>();
170 auto it5 = g_vort.getDomainIterator();
172 double max_vort = 0.0;
174 double int_vort[3] = {0.0,0.0,0.0};
178 auto key = it5.get();
182 tmp = 1.0f/g_vort.spacing(x)/2.0f*(g_vort.template get<vorticity>(key.move(x,1))[x] - g_vort.template get<vorticity>(key.move(x,-1))[x] ) +
183 1.0f/g_vort.spacing(y)/2.0f*(g_vort.template get<vorticity>(key.move(y,1))[y] - g_vort.template get<vorticity>(key.move(y,-1))[y] ) +
184 1.0f/g_vort.spacing(z)/2.0f*(g_vort.template get<vorticity>(key.move(z,1))[z] - g_vort.template get<vorticity>(key.move(z,-1))[z] );
186 int_vort[x] += g_vort.template get<vorticity>(key)[x];
187 int_vort[y] += g_vort.template get<vorticity>(key)[y];
188 int_vort[z] += g_vort.template get<vorticity>(key)[z];
198 v_cl.
sum(int_vort[0]);
199 v_cl.
sum(int_vort[1]);
200 v_cl.
sum(int_vort[2]);
204 {std::cout <<
"Max div for vorticity " << max_vort <<
" Integral: " << int_vort[0] <<
" " << int_vort[1] <<
" " << int_vort[2] << std::endl;}
243 constexpr
int nk = 32;
248 for (
size_t i = 0 ; i < nk ; i++)
250 ak[i] = rand()/RAND_MAX;
251 bk[i] = rand()/RAND_MAX;
255 float gamma = nu * tgtre;
256 float rinv2 = 1.0f/(sigma*sigma);
257 float max_vorticity = gamma*rinv2/M_PI;
264 auto key_d = it.get();
265 auto key = it.getGKey(key_d);
270 float theta1 = atan2((ty-domain.
getHigh(1)/2.0f),(tz-domain.
getHigh(2)/2.0f));
273 float rad1r = sqrt((ty-domain.
getHigh(1)/2.0f)*(ty-domain.
getHigh(1)/2.0f) + (tz-domain.
getHigh(2)/2.0f)*(tz-domain.
getHigh(2)/2.0f)) - ringr1;
274 float rad1t = tx - 1.0f;
275 float rad1sq = rad1r*rad1r + rad1t*rad1t;
276 float radstr = -exp(-rad1sq*rinv2)*rinv2*gamma/M_PI;
277 gr.template get<vorticity>(key_d)[x] = 0.0f;
278 gr.template get<vorticity>(key_d)[y] = -radstr * cos(theta1);
279 gr.template get<vorticity>(key_d)[z] = radstr * sin(theta1);
283 float rad1r_ = sqrt((ty-domain.
getHigh(1)/2.0f)*(ty-domain.
getHigh(1)/2.0f) + (tz-domain.
getHigh(2)/2.0f)*(tz-domain.
getHigh(2)/2.0f)) + ringr1;
284 float rad1sqTILDA = rad1sq*rinv2;
285 radstr = exp(-rad1sq*rinv2)*rinv2*gamma/M_PI;
286 gr.template get<vorticity>(key_d)[x] = 0.0f;
287 gr.template get<vorticity>(key_d)[y] = -radstr * cos(theta1);
288 gr.template get<vorticity>(key_d)[z] = radstr * sin(theta1);
307 static const unsigned int dims = 3;
309 static const unsigned int nvar = 1;
321 static const int grid_type = NORMAL_GRID;
450 constexpr
unsigned int phi = 0;
466 gr.template ghost_get<vorticity>();
481 psi.template get<phi>(key) = 1.0f/gr.
spacing(x)/2.0f*(gr.template get<vorticity>(key.move(x,1))[x] - gr.template get<vorticity>(key.move(x,-1))[x] ) +
482 1.0f/gr.
spacing(y)/2.0f*(gr.template get<vorticity>(key.move(y,1))[y] - gr.template get<vorticity>(key.move(y,-1))[y] ) +
483 1.0f/gr.
spacing(z)/2.0f*(gr.template get<vorticity>(key.move(z,1))[z] - gr.template get<vorticity>(key.move(z,-1))[z] );
491 calc_and_print_max_div_and_int(gr);
507 fd.template impose_dit<0>(poisson(),psi,psi.getDomainIterator());
541 solver.
solve(fd.getA(),x_,fd.getB());
548 solver.
solve(x_,fd.getB());
553 fd.template copy<phi>(x_,psi);
559 psi.template ghost_get<phi>();
567 auto key = it2.get();
569 gr.template get<vorticity>(key)[x] -= 1.0f/2.0f/psi.
spacing(x)*(psi.template get<phi>(key.move(x,1))-psi.template get<phi>(key.move(x,-1)));
570 gr.template get<vorticity>(key)[y] -= 1.0f/2.0f/psi.
spacing(y)*(psi.template get<phi>(key.move(y,1))-psi.template get<phi>(key.move(y,-1)));
571 gr.template get<vorticity>(key)[z] -= 1.0f/2.0f/psi.
spacing(z)*(psi.template get<phi>(key.move(z,1))-psi.template get<phi>(key.move(z,-1)));
578 calc_and_print_max_div_and_int(gr);
612 auto key = git.get_dist();
623 vd.template getLastProp<vorticity>()[x] = gr.template get<vorticity>(key)[x];
624 vd.template getLastProp<vorticity>()[y] = gr.template get<vorticity>(key)[y];
625 vd.template getLastProp<vorticity>()[z] = gr.template get<vorticity>(key)[z];
695 constexpr
unsigned int phi = 0;
717 calc_and_print_max_div_and_int(g_vort);
720 for (
size_t i = 0 ; i < 3 ; i++)
725 auto it2 = gr_ps.getDomainIterator();
730 auto key = it2.get();
733 gr_ps.get<vorticity>(key) = g_vort.template get<vorticity>(key)[i];
745 fd.template impose_dit<phi>(poisson(),gr_ps,gr_ps.getDomainIterator());
758 solver.
solve(phi_s[i],b);
769 {std::cout <<
"Solved component " << i <<
" Error: " << serr.
err_inf << std::endl;}
772 fd.template copy<phi>(phi_s[i],gr_ps);
778 auto it3 = gr_ps.getDomainIterator();
783 auto key = it3.get();
785 phi_v.get<velocity>(key)[i] = gr_ps.get<phi>(key);
795 phi_v.ghost_get<phi>();
797 float inv_dx = 0.5f / g_vort.
spacing(0);
798 float inv_dy = 0.5f / g_vort.
spacing(1);
799 float inv_dz = 0.5f / g_vort.
spacing(2);
801 auto it3 = phi_v.getDomainIterator();
806 auto key = it3.get();
808 float phi_xy = (phi_v.get<phi>(key.move(y,1))[x] - phi_v.get<phi>(key.move(y,-1))[x])*inv_dy;
809 float phi_xz = (phi_v.get<phi>(key.move(z,1))[x] - phi_v.get<phi>(key.move(z,-1))[x])*inv_dz;
810 float phi_yx = (phi_v.get<phi>(key.move(x,1))[y] - phi_v.get<phi>(key.move(x,-1))[y])*inv_dx;
811 float phi_yz = (phi_v.get<phi>(key.move(z,1))[y] - phi_v.get<phi>(key.move(z,-1))[y])*inv_dz;
812 float phi_zx = (phi_v.get<phi>(key.move(x,1))[z] - phi_v.get<phi>(key.move(x,-1))[z])*inv_dx;
813 float phi_zy = (phi_v.get<phi>(key.move(y,1))[z] - phi_v.get<phi>(key.move(y,-1))[z])*inv_dy;
815 g_vel.template get<velocity>(key)[x] = phi_zy - phi_yz;
816 g_vel.template get<velocity>(key)[y] = phi_xz - phi_zx;
817 g_vel.template get<velocity>(key)[z] = phi_yx - phi_xy;
835 gr.template get<prp>(key)[0] = 0.0;
836 gr.template get<prp>(key)[1] = 0.0;
837 gr.template get<prp>(key)[2] = 0.0;
853 vd.template getProp<prp>(key)[0] = 0.0;
854 vd.template getProp<prp>(key)[1] = 0.0;
855 vd.template getProp<prp>(key)[2] = 0.0;
877 template<
typename gr
id>
void calc_rhs(
grid & g_vort,
grid & g_vel,
grid & g_dwp)
880 constexpr
int rhs = 0;
884 float fac1 = 2.0f*nu/(g_vort.spacing(0)*g_vort.spacing(0));
885 float fac2 = 2.0f*nu/(g_vort.spacing(1)*g_vort.spacing(1));
886 float fac3 = 2.0f*nu/(g_vort.spacing(2)*g_vort.spacing(2));
888 float fac4 = 0.5f/(g_vort.spacing(0));
889 float fac5 = 0.5f/(g_vort.spacing(1));
890 float fac6 = 0.5f/(g_vort.spacing(2));
892 auto it = g_dwp.getDomainIterator();
894 g_vort.template ghost_get<vorticity>();
900 g_dwp.template get<rhs>(key)[x] = fac1*(g_vort.template get<vorticity>(key.move(x,1))[x]+g_vort.template get<vorticity>(key.move(x,-1))[x])+
901 fac2*(g_vort.template get<vorticity>(key.move(y,1))[x]+g_vort.template get<vorticity>(key.move(y,-1))[x])+
902 fac3*(g_vort.template get<vorticity>(key.move(z,1))[x]+g_vort.template get<vorticity>(key.move(z,-1))[x])-
903 2.0f*(fac1+fac2+fac3)*g_vort.template get<vorticity>(key)[x]+
904 fac4*g_vort.template get<vorticity>(key)[x]*
905 (g_vel.template get<velocity>(key.move(x,1))[x] - g_vel.template get<velocity>(key.move(x,-1))[x])+
906 fac5*g_vort.template get<vorticity>(key)[y]*
907 (g_vel.template get<velocity>(key.move(y,1))[x] - g_vel.template get<velocity>(key.move(y,-1))[x])+
908 fac6*g_vort.template get<vorticity>(key)[z]*
909 (g_vel.template get<velocity>(key.move(z,1))[x] - g_vel.template get<velocity>(key.move(z,-1))[x]);
911 g_dwp.template get<rhs>(key)[y] = fac1*(g_vort.template get<vorticity>(key.move(x,1))[y]+g_vort.template get<vorticity>(key.move(x,-1))[y])+
912 fac2*(g_vort.template get<vorticity>(key.move(y,1))[y]+g_vort.template get<vorticity>(key.move(y,-1))[y])+
913 fac3*(g_vort.template get<vorticity>(key.move(z,1))[y]+g_vort.template get<vorticity>(key.move(z,-1))[y])-
914 2.0f*(fac1+fac2+fac3)*g_vort.template get<vorticity>(key)[y]+
915 fac4*g_vort.template get<vorticity>(key)[x]*
916 (g_vel.template get<velocity>(key.move(x,1))[y] - g_vel.template get<velocity>(key.move(x,-1))[y])+
917 fac5*g_vort.template get<vorticity>(key)[y]*
918 (g_vel.template get<velocity>(key.move(y,1))[y] - g_vel.template get<velocity>(key.move(y,-1))[y])+
919 fac6*g_vort.template get<vorticity>(key)[z]*
920 (g_vel.template get<velocity>(key.move(z,1))[y] - g_vel.template get<velocity>(key.move(z,-1))[y]);
923 g_dwp.template get<rhs>(key)[z] = fac1*(g_vort.template get<vorticity>(key.move(x,1))[z]+g_vort.template get<vorticity>(key.move(x,-1))[z])+
924 fac2*(g_vort.template get<vorticity>(key.move(y,1))[z]+g_vort.template get<vorticity>(key.move(y,-1))[z])+
925 fac3*(g_vort.template get<vorticity>(key.move(z,1))[z]+g_vort.template get<vorticity>(key.move(z,-1))[z])-
926 2.0f*(fac1+fac2+fac3)*g_vort.template get<vorticity>(key)[z]+
927 fac4*g_vort.template get<vorticity>(key)[x]*
928 (g_vel.template get<velocity>(key.move(x,1))[z] - g_vel.template get<velocity>(key.move(x,-1))[z])+
929 fac5*g_vort.template get<vorticity>(key)[y]*
930 (g_vel.template get<velocity>(key.move(y,1))[z] - g_vel.template get<velocity>(key.move(y,-1))[z])+
931 fac6*g_vort.template get<vorticity>(key)[z]*
932 (g_vel.template get<velocity>(key.move(z,1))[z] - g_vel.template get<velocity>(key.move(z,-1))[z]);
984 auto key = it2.
get();
1029 auto key = it.
get();
1040 while (it2.isNext())
1042 auto key = it2.
get();
1078 template<
typename gr
id,
typename vector>
void do_step(vector &
particles,
1087 constexpr
int rhs = 0;
1092 inte.template p2m<vorticity,vorticity>(
particles,g_vort);
1094 g_vort.template ghost_put<add_,vorticity>();
1101 comp_vel(domain,g_vort,g_vel,phi_s,solver);
1102 calc_rhs(g_vort,g_vel,g_dvort);
1108 g_dvort.template ghost_get<rhs>();
1109 g_vel.template ghost_get<velocity>();
1112 inte.template m2p<rhs,rhs_part>(g_dvort,
particles);
1113 inte.template m2p<velocity,p_vel>(g_vel,
particles);
1118 template<
typename vector,
typename gr
id>
void check_point_and_save(vector &
particles,
1128 particles.
write(
"part_out_" + std::to_string(i),VTK_WRITER | FORMAT_BINARY);
1129 g_vort.template ghost_get<vorticity>();
1130 g_vel.template ghost_get<velocity>();
1131 g_vel.write_frame(
"grid_velocity",i, VTK_WRITER | FORMAT_BINARY);
1132 g_vort.write_frame(
"grid_vorticity",i, VTK_WRITER | FORMAT_BINARY);
1141 while (it_s.isNext())
1143 auto p = it_s.get();
1145 float vort_magn = sqrt(
particles.template getProp<vorticity>(p)[0] *
particles.template getProp<vorticity>(p)[0] +
1146 particles.template getProp<vorticity>(p)[1] *
particles.template getProp<vorticity>(p)[1] +
1147 particles.template getProp<vorticity>(p)[2] *
particles.template getProp<vorticity>(p)[2]);
1149 if (vort_magn < 0.1)
1161 part_save.template getLastProp<0>() = vort_magn;
1190 int main(
int argc,
char* argv[])
1193 openfpm_init(&argc,&argv);
1206 long int sz[] = {96,96,96};
1207 size_t szu[] = {(size_t)sz[0],(
size_t)sz[1],(size_t)sz[2]};
1212 grid_type g_vel(g_vort.getDecomposition(),szu,g);
1213 grid_type g_dvort(g_vort.getDecomposition(),szu,g);
1226 {std::cout <<
"SPACING " << g_vort.spacing(0) <<
" " << g_vort.spacing(1) <<
" " << g_vort.spacing(2) << std::endl;}
1229 init_ring(g_vort,domain);
1231 x_.
resize(g_vort.size(),g_vort.getLocalDomainSize());
1238 helmotz_hodge_projection(g_vort,domain,solver,x_,
true);
1249 phi_s[0].resize(g_vort.size(),g_vort.getLocalDomainSize());
1250 phi_s[1].resize(g_vort.size(),g_vort.getLocalDomainSize());
1251 phi_s[2].resize(g_vort.size(),g_vort.getLocalDomainSize());
1267 {g_vort.write(
"grid_vorticity_init", VTK_WRITER | FORMAT_BINARY);}
1278 std::string restart(argv[1]);
1281 i = std::stoi(restart);
1289 {std::cout <<
"Restarting from " << i << std::endl;}
1293 for ( ; i < nsteps ; i++)
1296 do_step(
particles,g_vort,g_vel,g_dvort,domain,inte,phi_s,solver);
1302 do_step(
particles,g_vort,g_vel,g_dvort,domain,inte,phi_s,solver);
1309 inte.template p2m<vorticity,vorticity>(
particles,g_vort);
1310 g_vort.template ghost_put<add_,vorticity>();
1313 helmotz_hodge_projection(g_vort,domain,solver,x_,
false);
1319 {std::cout <<
"Step " << i << std::endl;}
1322 if (i % 100 == 0) {check_point_and_save(
particles,g_vort,g_vel,g_dvort,i);}
1332 int main(
int argc,
char* argv[])
void setPreconditioner(PCType type)
Set the preconditioner of the linear solver.
Decomposition & getDecomposition()
Get the decomposition.
size_t getProcessUnitID()
Get the process unit id.
Sparse Matrix implementation stub object when OpenFPM is compiled with no linear algebra support.
__device__ __host__ T getLow(int i) const
get the i-coordinate of the low bound interval of the box
static const unsigned int dims
Number of dimansions of the problem.
void setMaxIter(PetscInt n)
Set the maximum number of iteration for Krylov solvers.
In case T does not match the PETSC precision compilation create a stub structure.
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
SparseMatrix< double, int, PETSC_BASE > SparseMatrix_type
Sparse matrix used to sove the linear system (we use PETSC)
Meta-function to return a compatible zero-element.
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
It contain statistic of the error of the calculated solution.
auto get(const grid_dist_key_dx< dim, bg_key > &v1) const -> typename std::add_lvalue_reference< decltype(loc_grid.get(v1.getSub()).template get< p >(v1.getKey()))>::type
Get the reference of the selected element.
void setPreconditionerAMG_cycleType(const std::string &cycle_type, int sweep_up=-1, int sweep_dw=-1, int sweep_crs=-1)
It set the type of cycle and optionally the number of sweep.
float stype
type of the spatial coordinates
void setAbsTol(PetscReal abstol_)
Set the absolute tolerance as stop criteria.
St spacing(size_t i) const
Get the spacing of the grid in direction i.
Vector< double, PETSC_BASE > solve(SparseMatrix< double, int, PETSC_BASE > &A, const Vector< double, PETSC_BASE > &b, bool initial_guess=false)
Here we invert the matrix and solve the system.
void save(const std::string &filename) const
Save the distributed vector on HDF5 file.
Vector< double, PETSC_BASE > Vector_type
Vector to solve the system (PETSC)
Implementation of VCluster class.
void setPreconditionerAMG_maxit(int nit)
Set the maximum number of V or W cycle for algebraic-multi-grid.
void execute()
Execute all the requests.
grid_dist_iterator< dim, device_grid, decltype(device_grid::type_of_iterator()), FIXED > getDomainGhostIterator() const
It return an iterator that span the grid domain + ghost part.
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.
Sparse Matrix implementation.
This is a distributed grid.
void resize(size_t row, size_t row_n)
stub resize
grid_dist_id_iterator_dec< Decomposition > getGridIterator(const size_t(&sz)[dim])
size_t size_local() const
return the local size of the vector
static const unsigned int nvar
We have only one scalar unknown.
const size_t(& getSize() const)[N]
Return the size of the grid as an array.
void setPreconditionerAMG_nl(int nl)
Set the number of levels for the algebraic-multigrid preconditioner.
This class is able to do Matrix inversion in parallel with PETSC solvers.
void setSolver(KSPType type)
Set the Petsc solver.
void start()
Start the timer.
bool write(std::string out, int opt=VTK_WRITER)
Output particle position and properties.
size_t getProcessingUnits()
Get the total number of processors.
Laplacian second order on h (spacing)
void add()
Add local particle.
grid_dist_iterator< dim, device_grid, decltype(device_grid::type_of_subiterator()), FREE > getDomainIterator() const
It return an iterator that span the full grid domain (each processor span its local domain)
void sum(T &num)
Sum the numbers across all processors and get the result.
grid_dist_id< 3, float, aggregate< float > > b_grid
grid that store \psi
const grid_sm< dim, T > & getGridInfo() const
Get an object containing the grid informations.
void setPreconditionerAMG_coarsen(const std::string &type)
Set the coarsening method for the algebraic-multi-grid preconditioner.
void setPreconditionerAMG_relax(const std::string &type, int k=REL_ALL)
Set the relaxation method for the algebraic-multi-grid preconditioner.
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.
static const bool boundary[]
specify the boundary conditions
OutputIteratorT OffsetT ReductionOpT OuputT init
< [in] The initial value of the reduction
solError get_residual_error(SparseMatrix< double, int, PETSC_BASE > &A, const Vector< double, PETSC_BASE > &x, const Vector< double, PETSC_BASE > &b)
It return the resiual error.
__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.
void clear()
remove all the elements
Decomposition & getDecomposition()
Get the object that store the information about the decomposition.
void load(const std::string &filename)
Load the distributed vector from an HDF5 file.
Class for cpu time benchmarking.
void setPreconditionerAMG_coarsenNodalType(int norm)
Set the block coarsening norm type.
grid_key_dx< Decomposition::dims > get()
Get the actual global key of the grid.
Main class for interpolation Particle to mest p2m and Mesh to particle m2p.
void stop()
Stop the timer.
PetscReal err_inf
infinity norm of the error