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"
137float sigma = 1.0/3.523;
150const unsigned int nsteps = 10;
152const unsigned int nsteps = 10001;
156constexpr unsigned int vorticity = 0;
157constexpr unsigned int velocity = 0;
158constexpr unsigned int p_vel = 1;
159constexpr int rhs_part = 2;
160constexpr unsigned int old_vort = 3;
161constexpr unsigned int old_pos = 4;
165template<
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);
267 float tx = (key.get(x)-2)*gr.
spacing(x) + domain.getLow(x);
268 float ty = (key.get(y)-2)*gr.
spacing(y) + domain.getLow(y);
269 float tz = (key.get(z)-2)*gr.
spacing(z) + domain.getLow(z);
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());
517 solver.setSolver(KSPBCGS);
520 solver.setAbsTol(0.0001);
523 solver.setMaxIter(500);
527 solver.setPreconditioner(PCHYPRE_BOOMERAMG);
528 solver.setPreconditionerAMG_nl(6);
529 solver.setPreconditionerAMG_maxit(1);
530 solver.setPreconditionerAMG_relax(
"SOR/Jacobi");
531 solver.setPreconditionerAMG_cycleType(
"V",0,4);
532 solver.setPreconditionerAMG_coarsenNodalType(0);
533 solver.setPreconditionerAMG_coarsen(
"HMIS");
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());
747 solver.setAbsTol(0.01);
758 solver.
solve(phi_s[i],b);
765 serr = solver.get_residual_error(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;
877template<
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();
1078template<
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);
1118template<
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;
1190int 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);}
1332int main(
int argc,
char* argv[])
This class represent an N-dimensional box.
Laplacian second order on h (spacing)
Sparse Matrix implementation.
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.
size_t getProcessingUnits()
Get the total number of processors.
void max(T &num)
Get the maximum number across all processors (or reduction with infinity norm)
Implementation of VCluster class.
Sparse Matrix implementation stub object when OpenFPM is compiled with no linear algebra support.
void resize(size_t row, size_t row_n)
stub resize
This is a distributed grid.
Decomposition & getDecomposition()
Get the object that store the information about the decomposition.
const grid_sm< dim, T > & getGridInfo() const
Get an object containing the grid informations.
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.
St spacing(size_t i) const
Get the spacing of the grid in direction i.
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)
__device__ __host__ const size_t(& getSize() const)[N]
Return the size of the grid as an array.
Main class for interpolation Particle to mest p2m and Mesh to particle m2p.
In case T does not match the PETSC precision compilation create a stub structure.
static Vector< T > solve(const SparseMatrix< T, impl > &A, const Vector< T > &b)
Solve the linear system.
Class for cpu time benchmarking.
void stop()
Stop the timer.
void start()
Start the timer.
vect_dist_key_dx get()
Get the actual key.
size_t size_local() const
return the local size of the vector
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
grid_dist_id_iterator_dec< Decomposition > getGridIterator(const size_t(&sz)[dim])
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
void map(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor.
void clear()
remove all the elements
bool write(std::string out, int opt=VTK_WRITER)
Output particle position and properties.
auto getLastPos() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element.
void save(const std::string &filename) const
Save the distributed vector on HDF5 file.
void add()
Add local particle.
void load(const std::string &filename)
Load the distributed vector from an HDF5 file.
Decomposition & getDecomposition()
Get the decomposition.
Vector< double, PETSC_BASE > Vector_type
Vector to solve the system (PETSC)
float stype
type of the spatial coordinates
SparseMatrix< double, int, PETSC_BASE > SparseMatrix_type
Sparse matrix used to sove the linear system (we use PETSC)
static const bool boundary[]
specify the boundary conditions
static const unsigned int nvar
We have only one scalar unknown.
static const unsigned int dims
Number of dimansions of the problem.
grid_dist_id< 3, float, aggregate< float > > b_grid
grid that store \psi
Meta-function to return a compatible zero-element.
It contain statistic of the error of the calculated solution.
PetscReal err_inf
infinity norm of the error