34#include "interpolation/interpolation.hpp"
35#include "Grid/grid_dist_id.hpp"
36#include "Vector/vector_dist.hpp"
37#include "Matrix/SparseMatrix.hpp"
38#include "Vector/Vector.hpp"
39#include "FiniteDifference/FDScheme.hpp"
40#include "Solvers/petsc_solver.hpp"
41#include "interpolation/mp4_kernel.hpp"
42#include "Solvers/petsc_solver_AMG_report.hpp"
43#include "Decomposition/Distribution/SpaceDistribution.hpp"
48constexpr unsigned int phi = 0;
76float sigma = 1.0/3.523;
89const unsigned int nsteps = 10;
91const unsigned int nsteps = 10001;
95constexpr unsigned int vorticity = 0;
96constexpr unsigned int velocity = 0;
97constexpr unsigned int p_vel = 1;
98constexpr int rhs_part = 2;
99constexpr unsigned int old_vort = 3;
100constexpr unsigned int old_pos = 4;
102template<
typename gr
id>
void calc_and_print_max_div_and_int(
grid & g_vort)
104 g_vort.template ghost_get<vorticity>();
105 auto it5 = g_vort.getDomainIterator();
107 double max_vort = 0.0;
109 double int_vort[3] = {0.0,0.0,0.0};
113 auto key = it5.get();
117 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] ) +
118 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] ) +
119 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] );
121 int_vort[x] += g_vort.template get<vorticity>(key)[x];
122 int_vort[y] += g_vort.template get<vorticity>(key)[y];
123 int_vort[z] += g_vort.template get<vorticity>(key)[z];
133 v_cl.
sum(int_vort[0]);
134 v_cl.
sum(int_vort[1]);
135 v_cl.
sum(int_vort[2]);
139 {std::cout <<
"Max div for vorticity " << max_vort <<
" Integral: " << int_vort[0] <<
" " << int_vort[1] <<
" " << int_vort[2] << std::endl;}
146 constexpr int nk = 32;
151 for (
size_t i = 0 ; i < nk ; i++)
153 ak[i] = rand()/RAND_MAX;
154 bk[i] = rand()/RAND_MAX;
158 float gamma = nu * tgtre;
159 float rinv2 = 1.0f/(sigma*sigma);
160 float max_vorticity = gamma*rinv2/M_PI;
167 auto key_d = it.get();
168 auto key = it.getGKey(key_d);
170 float tx = (key.get(x)-2)*gr.
spacing(x) + domain.getLow(x);
171 float ty = (key.get(y)-2)*gr.
spacing(y) + domain.getLow(y);
172 float tz = (key.get(z)-2)*gr.
spacing(z) + domain.getLow(z);
173 float theta1 = atan2((ty-domain.getHigh(1)/2.0f),(tz-domain.getHigh(2)/2.0f));
176 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;
177 float rad1t = tx - 1.0f;
178 float rad1sq = rad1r*rad1r + rad1t*rad1t;
179 float radstr = -exp(-rad1sq*rinv2)*rinv2*gamma/M_PI;
180 gr.template get<vorticity>(key_d)[x] = 0.0f;
181 gr.template get<vorticity>(key_d)[y] = -radstr * cos(theta1);
182 gr.template get<vorticity>(key_d)[z] = radstr * sin(theta1);
186 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;
187 float rad1sqTILDA = rad1sq*rinv2;
188 radstr = exp(-rad1sq*rinv2)*rinv2*gamma/M_PI;
189 gr.template get<vorticity>(key_d)[x] = 0.0f;
190 gr.template get<vorticity>(key_d)[y] = -radstr * cos(theta1);
191 gr.template get<vorticity>(key_d)[z] = radstr * sin(theta1);
196 gr.
write(
"Initialization");
203 static const unsigned int dims = 3;
205 static const unsigned int nvar = 1;
217 static const int grid_type = NORMAL_GRID;
233 gr.template ghost_get<vorticity>();
245 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] ) +
246 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] ) +
247 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] );
252 calc_and_print_max_div_and_int(gr);
257 fd.template impose_dit_b<0>(psi,psi.getDomainIterator());
265 solver.setSolver(KSPBCGS);
268 solver.setAbsTol(0.0001);
271 solver.setMaxIter(500);
275 solver.setPreconditioner(PCHYPRE_BOOMERAMG);
276 solver.setPreconditionerAMG_nl(6);
277 solver.setPreconditionerAMG_maxit(1);
278 solver.setPreconditionerAMG_relax(
"SOR/Jacobi");
279 solver.setPreconditionerAMG_cycleType(
"V",0,4);
280 solver.setPreconditionerAMG_coarsenNodalType(0);
281 solver.setPreconditionerAMG_coarsen(
"HMIS");
301 fd.template copy<phi>(x_,psi);
303 psi.template ghost_get<phi>();
311 auto key = it2.get();
313 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)));
314 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)));
315 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)));
320 calc_and_print_max_div_and_int(gr);
336 auto key = git.get_dist();
347 vd.template getLastProp<vorticity>()[x] = gr.template get<vorticity>(key)[x];
348 vd.template getLastProp<vorticity>()[y] = gr.template get<vorticity>(key)[y];
349 vd.template getLastProp<vorticity>()[z] = gr.template get<vorticity>(key)[z];
371 calc_and_print_max_div_and_int(g_vort);
374 for (
size_t i = 0 ; i < 3 ; i++)
384 auto key = it2.get();
387 gr_ps.
get<vorticity>(key) = g_vort.template get<vorticity>(key)[i];
396 solver.setAbsTol(0.01);
407 solver.
solve(phi_s[i],b);
414 serr = solver.get_residual_error(phi_s[i],b);
418 {std::cout <<
"Solved component " << i <<
" Error: " << serr.
err_inf << std::endl;}
421 fd.template copy<phi>(phi_s[i],gr_ps);
428 auto key = it3.get();
430 phi_v.
get<velocity>(key)[i] = gr_ps.
get<phi>(key);
438 float inv_dx = 0.5f / g_vort.
spacing(0);
439 float inv_dy = 0.5f / g_vort.
spacing(1);
440 float inv_dz = 0.5f / g_vort.
spacing(2);
447 auto key = it3.get();
449 float phi_xy = (phi_v.
get<phi>(key.move(y,1))[x] - phi_v.
get<phi>(key.move(y,-1))[x])*inv_dy;
450 float phi_xz = (phi_v.
get<phi>(key.move(z,1))[x] - phi_v.
get<phi>(key.move(z,-1))[x])*inv_dz;
451 float phi_yx = (phi_v.
get<phi>(key.move(x,1))[y] - phi_v.
get<phi>(key.move(x,-1))[y])*inv_dx;
452 float phi_yz = (phi_v.
get<phi>(key.move(z,1))[y] - phi_v.
get<phi>(key.move(z,-1))[y])*inv_dz;
453 float phi_zx = (phi_v.
get<phi>(key.move(x,1))[z] - phi_v.
get<phi>(key.move(x,-1))[z])*inv_dx;
454 float phi_zy = (phi_v.
get<phi>(key.move(y,1))[z] - phi_v.
get<phi>(key.move(y,-1))[z])*inv_dy;
456 g_vel.template get<velocity>(key)[x] = phi_zy - phi_yz;
457 g_vel.template get<velocity>(key)[y] = phi_xz - phi_zx;
458 g_vel.template get<velocity>(key)[z] = phi_yx - phi_xy;
474 gr.template get<prp>(key)[0] = 0.0;
475 gr.template get<prp>(key)[1] = 0.0;
476 gr.template get<prp>(key)[2] = 0.0;
492 vd.template getProp<prp>(key)[0] = 0.0;
493 vd.template getProp<prp>(key)[1] = 0.0;
494 vd.template getProp<prp>(key)[2] = 0.0;
501template<
typename gr
id>
void calc_rhs(
grid & g_vort,
grid & g_vel,
grid & g_dwp)
504 constexpr int rhs = 0;
508 float fac1 = 2.0f*nu/(g_vort.spacing(0)*g_vort.spacing(0));
509 float fac2 = 2.0f*nu/(g_vort.spacing(1)*g_vort.spacing(1));
510 float fac3 = 2.0f*nu/(g_vort.spacing(2)*g_vort.spacing(2));
512 float fac4 = 0.5f/(g_vort.spacing(0));
513 float fac5 = 0.5f/(g_vort.spacing(1));
514 float fac6 = 0.5f/(g_vort.spacing(2));
516 auto it = g_dwp.getDomainIterator();
518 g_vort.template ghost_get<vorticity>();
524 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])+
525 fac2*(g_vort.template get<vorticity>(key.move(y,1))[x]+g_vort.template get<vorticity>(key.move(y,-1))[x])+
526 fac3*(g_vort.template get<vorticity>(key.move(z,1))[x]+g_vort.template get<vorticity>(key.move(z,-1))[x])-
527 2.0f*(fac1+fac2+fac3)*g_vort.template get<vorticity>(key)[x]+
528 fac4*g_vort.template get<vorticity>(key)[x]*
529 (g_vel.template get<velocity>(key.move(x,1))[x] - g_vel.template get<velocity>(key.move(x,-1))[x])+
530 fac5*g_vort.template get<vorticity>(key)[y]*
531 (g_vel.template get<velocity>(key.move(y,1))[x] - g_vel.template get<velocity>(key.move(y,-1))[x])+
532 fac6*g_vort.template get<vorticity>(key)[z]*
533 (g_vel.template get<velocity>(key.move(z,1))[x] - g_vel.template get<velocity>(key.move(z,-1))[x]);
535 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])+
536 fac2*(g_vort.template get<vorticity>(key.move(y,1))[y]+g_vort.template get<vorticity>(key.move(y,-1))[y])+
537 fac3*(g_vort.template get<vorticity>(key.move(z,1))[y]+g_vort.template get<vorticity>(key.move(z,-1))[y])-
538 2.0f*(fac1+fac2+fac3)*g_vort.template get<vorticity>(key)[y]+
539 fac4*g_vort.template get<vorticity>(key)[x]*
540 (g_vel.template get<velocity>(key.move(x,1))[y] - g_vel.template get<velocity>(key.move(x,-1))[y])+
541 fac5*g_vort.template get<vorticity>(key)[y]*
542 (g_vel.template get<velocity>(key.move(y,1))[y] - g_vel.template get<velocity>(key.move(y,-1))[y])+
543 fac6*g_vort.template get<vorticity>(key)[z]*
544 (g_vel.template get<velocity>(key.move(z,1))[y] - g_vel.template get<velocity>(key.move(z,-1))[y]);
547 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])+
548 fac2*(g_vort.template get<vorticity>(key.move(y,1))[z]+g_vort.template get<vorticity>(key.move(y,-1))[z])+
549 fac3*(g_vort.template get<vorticity>(key.move(z,1))[z]+g_vort.template get<vorticity>(key.move(z,-1))[z])-
550 2.0f*(fac1+fac2+fac3)*g_vort.template get<vorticity>(key)[z]+
551 fac4*g_vort.template get<vorticity>(key)[x]*
552 (g_vel.template get<velocity>(key.move(x,1))[z] - g_vel.template get<velocity>(key.move(x,-1))[z])+
553 fac5*g_vort.template get<vorticity>(key)[y]*
554 (g_vel.template get<velocity>(key.move(y,1))[z] - g_vel.template get<velocity>(key.move(y,-1))[z])+
555 fac6*g_vort.template get<vorticity>(key)[z]*
556 (g_vel.template get<velocity>(key.move(z,1))[z] - g_vel.template get<velocity>(key.move(z,-1))[z]);
587 auto key = it2.
get();
624 auto key = it2.
get();
636template<
typename gr
id,
typename vector>
void do_step(
grid_type_s & psi,
648 constexpr int rhs = 0;
651 inte.template p2m<vorticity,vorticity>(
particles,g_vort);
653 g_vort.template ghost_put<add_,vorticity>();
656 comp_vel(psi,phi_v,fd,domain,g_vort,g_vel,phi_s,solver);
657 calc_rhs(g_vort,g_vel,g_dvort);
659 g_dvort.template ghost_get<rhs>();
660 g_vel.template ghost_get<velocity>();
663 inte.template m2p<rhs,rhs_part>(g_dvort,
particles);
664 inte.template m2p<velocity,p_vel>(g_vel,
particles);
669template<
typename vector,
typename gr
id>
void check_point_and_save(vector &
particles,
679 particles.
write(
"part_out_" + std::to_string(i),VTK_WRITER | FORMAT_BINARY);
680 g_vort.template ghost_get<vorticity>();
681 g_vel.template ghost_get<velocity>();
682 g_vel.write_frame(
"grid_velocity",i, VTK_WRITER | FORMAT_BINARY);
683 g_vort.write_frame(
"grid_vorticity",i, VTK_WRITER | FORMAT_BINARY);
692 while (it_s.isNext())
696 float vort_magn = sqrt(
particles.template getProp<vorticity>(p)[0] *
particles.template getProp<vorticity>(p)[0] +
697 particles.template getProp<vorticity>(p)[1] *
particles.template getProp<vorticity>(p)[1] +
698 particles.template getProp<vorticity>(p)[2] *
particles.template getProp<vorticity>(p)[2]);
712 part_save.template getLastProp<0>() = vort_magn;
722int main(
int argc,
char* argv[])
725 openfpm_init(&argc,&argv);
738 long int sz[] = {128,128,128};
739 size_t szu[] = {(size_t)sz[0],(
size_t)sz[1],(size_t)sz[2]};
746 grid_type g_vel(g_vort.getDecomposition(),szu,g);
747 grid_type g_dvort(g_vort.getDecomposition(),szu,g);
756 grid_type_s psi(g_vort.getDecomposition(),g_vort.getGridInfo().getSize(),g);
757 grid_type phi_v(g_vort.getDecomposition(),g_vort.getGridInfo().getSize(),g);
789 {std::cout <<
"SPACING " << g_vort.spacing(0) <<
" " << g_vort.spacing(1) <<
" " << g_vort.spacing(2) << std::endl;}
792 init_ring(g_vort,domain);
794 x_.
resize(g_vort.size(),g_vort.getLocalDomainSize());
801 helmotz_hodge_projection(psi,fd,g_vort,domain,solver,x_,
true);
812 phi_s[0].
resize(g_vort.size(),g_vort.getLocalDomainSize());
813 phi_s[1].
resize(g_vort.size(),g_vort.getLocalDomainSize());
814 phi_s[2].
resize(g_vort.size(),g_vort.getLocalDomainSize());
830 {g_vort.write(
"grid_vorticity_init", VTK_WRITER | FORMAT_BINARY);}
841 std::string restart(argv[1]);
844 i = std::stoi(restart);
852 {std::cout <<
"Restarting from " << i << std::endl;}
856 for ( ; i < nsteps ; i++)
859 do_step(psi,phi_v,fd,
particles,g_vort,g_vel,g_dvort,domain,inte,phi_s,solver);
865 do_step(psi,phi_v,fd,
particles,g_vort,g_vel,g_dvort,domain,inte,phi_s,solver);
872 inte.template p2m<vorticity,vorticity>(
particles,g_vort);
873 g_vort.template ghost_put<add_,vorticity>();
876 helmotz_hodge_projection(psi,fd,g_vort,domain,solver,x_,
false);
882 {std::cout <<
"Step " << i << std::endl;}
885 if (i % 100 == 0) {check_point_and_save(
particles,g_vort,g_vel,g_dvort,i);}
895int main(
int argc,
char* argv[])
This class represent an N-dimensional box.
This class decompose a space into sub-sub-domains and distribute them across processors.
Sys_eqs::Vector_type & getB()
produce the B vector
Sys_eqs::SparseMatrix_type & getA()
produce the Matrix
void new_b()
In case we want to impose a new b re-using FDScheme we have to call This function.
This class allocate, and destroy CPU memory.
Laplacian second order on h (spacing)
Class that distribute sub-sub-domains across processors using an hilbert curve to divide the space.
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.
const grid_sm< dim, T > & getGridInfo() const
Get an object containing the grid informations.
void ghost_get(size_t opt=0)
It synchronize the ghost parts.
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.
bool write(std::string output, size_t opt=VTK_WRITER|FORMAT_BINARY)
Write the distributed grid information.
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)
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.
__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.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Transform the boost::fusion::vector into memory specification (memory_traits)
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.
grid_type_s b_grid
grid that store \psi
static const unsigned int dims
Number of dimansions of the problem.
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