103#include "interpolation/interpolation.hpp"
104#include "Grid/grid_dist_id.hpp"
105#include "Vector/vector_dist.hpp"
106#include "Matrix/SparseMatrix.hpp"
107#include "Vector/Vector.hpp"
108#include "FiniteDifference/FDScheme.hpp"
109#include "Solvers/petsc_solver.hpp"
110#include "interpolation/mp4_kernel.hpp"
111#include "Solvers/petsc_solver_AMG_report.hpp"
126double sigma = 1.0/3.523;
128double tgtre = 7500.0;
133double nu = 1.0/tgtre;
139constexpr unsigned int vorticity = 0;
140constexpr unsigned int velocity = 0;
141constexpr unsigned int p_vel = 1;
142constexpr int rhs_part = 2;
143constexpr unsigned int old_vort = 3;
144constexpr unsigned int old_pos = 4;
148template<
typename gr
id>
void calc_and_print_max_div_and_int(
grid & g_vort)
152 g_vort.template ghost_get<vorticity>();
153 auto it5 = g_vort.getDomainIterator();
155 double max_vort = 0.0;
157 double int_vort[3] = {0.0,0.0,0.0};
161 auto key = it5.get();
165 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] ) +
166 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] ) +
167 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] );
169 int_vort[x] += g_vort.template get<vorticity>(key)[x];
170 int_vort[y] += g_vort.template get<vorticity>(key)[y];
171 int_vort[z] += g_vort.template get<vorticity>(key)[z];
179 Vcluster & v_cl = create_vcluster();
181 v_cl.
sum(int_vort[0]);
182 v_cl.
sum(int_vort[1]);
183 v_cl.
sum(int_vort[2]);
187 {std::cout <<
"Max div for vorticity " << max_vort <<
" Integral: " << int_vort[0] <<
" " << int_vort[1] <<
" " << int_vort[2] << std::endl;}
226 constexpr int nk = 32;
231 for (
size_t i = 0 ; i < nk ; i++)
233 ak[i] = rand()/RAND_MAX;
234 bk[i] = rand()/RAND_MAX;
238 double gamma = nu * tgtre;
239 double rinv2 = 1.0f/(sigma*sigma);
240 double max_vorticity = gamma*rinv2/M_PI;
247 auto key_d = it.get();
248 auto key = it.getGKey(key_d);
250 double tx = (key.get(x)-2)*gr.
spacing(x) + domain.getLow(x);
251 double ty = (key.get(y)-2)*gr.
spacing(y) + domain.getLow(y);
252 double tz = (key.get(z)-2)*gr.
spacing(z) + domain.getLow(z);
253 double theta1 = atan2((ty-2.5f),(tz-2.5f));
261 double rad1r = sqrt((ty-2.5f)*(ty-2.5f) + (tz-2.5f)*(tz-2.5f)) - ringr1*(1.0f + ringnz * noise);
262 double rad1t = tx - 1.0f;
263 double rad1sq = rad1r*rad1r + rad1t*rad1t;
264 double radstr = -exp(-rad1sq*rinv2)*rinv2*gamma/M_PI;
265 gr.template get<vorticity>(key_d)[x] = 0.0f;
266 gr.template get<vorticity>(key_d)[y] = -radstr * cos(theta1);
267 gr.template get<vorticity>(key_d)[z] = radstr * sin(theta1);
286 static const unsigned int dims = 3;
287 static const unsigned int nvar = 1;
289 typedef double stype;
293 static const int grid_type = NORMAL_GRID;
421 constexpr unsigned int phi = 0;
437 gr.template ghost_get<vorticity>();
452 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] ) +
453 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] ) +
454 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] );
462 calc_and_print_max_div_and_int(gr);
478 fd.template impose_dit<0>(poisson(),psi,psi.getDomainIterator());
488 solver.setSolver(KSPBCGS);
491 solver.setAbsTol(0.001);
494 solver.setMaxIter(500);
496 solver.setPreconditioner(PCHYPRE_BOOMERAMG);
497 solver.setPreconditionerAMG_nl(6);
498 solver.setPreconditionerAMG_maxit(1);
499 solver.setPreconditionerAMG_relax(
"SOR/Jacobi");
500 solver.setPreconditionerAMG_cycleType(
"V",0,4);
501 solver.setPreconditionerAMG_coarsenNodalType(0);
502 solver.setPreconditionerAMG_coarsen(
"HMIS");
507 solver.
solve(fd.getA(),x_,fd.getB());
514 solver.
solve(x_,fd.getB());
519 fd.template copy<phi>(x_,psi);
525 psi.template ghost_get<phi>();
533 auto key = it2.get();
535 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)));
536 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)));
537 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)));
544 calc_and_print_max_div_and_int(gr);
578 auto key = git.get_dist();
589 vd.template getLastProp<vorticity>()[x] = gr.template get<vorticity>(key)[x];
590 vd.template getLastProp<vorticity>()[y] = gr.template get<vorticity>(key)[y];
591 vd.template getLastProp<vorticity>()[z] = gr.template get<vorticity>(key)[z];
661 constexpr unsigned int phi = 0;
683 calc_and_print_max_div_and_int(g_vort);
686 for (
size_t i = 0 ; i < 3 ; i++)
691 auto it2 = gr_ps.getDomainIterator();
696 auto key = it2.get();
699 gr_ps.get<vorticity>(key) = g_vort.template get<vorticity>(key)[i];
711 fd.template impose_dit<phi>(poisson(),gr_ps,gr_ps.getDomainIterator());
713 solver.setAbsTol(0.01);
724 solver.
solve(phi_s[i],b);
731 serr = solver.get_residual_error(phi_s[i],b);
733 Vcluster & v_cl = create_vcluster();
735 {std::cout <<
"Solved component " << i <<
" Error: " << serr.
err_inf << std::endl;}
738 fd.template copy<phi>(phi_s[i],gr_ps);
744 auto it3 = gr_ps.getDomainIterator();
749 auto key = it3.get();
751 phi_v.get<velocity>(key)[i] = gr_ps.get<phi>(key);
761 phi_v.ghost_get<phi>();
763 double inv_dx = 0.5f / g_vort.
spacing(0);
764 double inv_dy = 0.5f / g_vort.
spacing(1);
765 double inv_dz = 0.5f / g_vort.
spacing(2);
767 auto it3 = phi_v.getDomainIterator();
772 auto key = it3.get();
774 double phi_xy = (phi_v.get<phi>(key.move(y,1))[x] - phi_v.get<phi>(key.move(y,-1))[x])*inv_dy;
775 double phi_xz = (phi_v.get<phi>(key.move(z,1))[x] - phi_v.get<phi>(key.move(z,-1))[x])*inv_dz;
776 double phi_yx = (phi_v.get<phi>(key.move(x,1))[y] - phi_v.get<phi>(key.move(x,-1))[y])*inv_dx;
777 double phi_yz = (phi_v.get<phi>(key.move(z,1))[y] - phi_v.get<phi>(key.move(z,-1))[y])*inv_dz;
778 double phi_zx = (phi_v.get<phi>(key.move(x,1))[z] - phi_v.get<phi>(key.move(x,-1))[z])*inv_dx;
779 double phi_zy = (phi_v.get<phi>(key.move(y,1))[z] - phi_v.get<phi>(key.move(y,-1))[z])*inv_dy;
781 g_vel.template get<velocity>(key)[x] = phi_zy - phi_yz;
782 g_vel.template get<velocity>(key)[y] = phi_xz - phi_zx;
783 g_vel.template get<velocity>(key)[z] = phi_yx - phi_xy;
801 gr.template get<prp>(key)[0] = 0.0;
802 gr.template get<prp>(key)[1] = 0.0;
803 gr.template get<prp>(key)[2] = 0.0;
819 vd.template getProp<prp>(key)[0] = 0.0;
820 vd.template getProp<prp>(key)[1] = 0.0;
821 vd.template getProp<prp>(key)[2] = 0.0;
843template<
typename gr
id>
void calc_rhs(
grid & g_vort,
grid & g_vel,
grid & g_dwp)
846 constexpr int rhs = 0;
850 double fac1 = 2.0f*nu/(g_vort.spacing(0));
851 double fac2 = 2.0f*nu/(g_vort.spacing(1));
852 double fac3 = 2.0f*nu/(g_vort.spacing(2));
854 double fac4 = 0.5f/(g_vort.spacing(0));
855 double fac5 = 0.5f/(g_vort.spacing(1));
856 double fac6 = 0.5f/(g_vort.spacing(2));
858 auto it = g_dwp.getDomainIterator();
860 g_vort.template ghost_get<vorticity>();
866 g_dwp.template get<rhs>(key)[x] =
870 fac4*g_vort.template get<vorticity>(key)[x]*
871 (g_vel.template get<velocity>(key.move(x,1))[x] - g_vel.template get<velocity>(key.move(x,-1))[x])+
872 fac5*g_vort.template get<vorticity>(key)[y]*
873 (g_vel.template get<velocity>(key.move(y,1))[x] - g_vel.template get<velocity>(key.move(y,-1))[x])+
874 fac6*g_vort.template get<vorticity>(key)[z]*
875 (g_vel.template get<velocity>(key.move(z,1))[x] - g_vel.template get<velocity>(key.move(z,-1))[x]);
877 g_dwp.template get<rhs>(key)[y] =
881 fac4*g_vort.template get<vorticity>(key)[x]*
882 (g_vel.template get<velocity>(key.move(x,1))[y] - g_vel.template get<velocity>(key.move(x,-1))[y])+
883 fac5*g_vort.template get<vorticity>(key)[y]*
884 (g_vel.template get<velocity>(key.move(y,1))[y] - g_vel.template get<velocity>(key.move(y,-1))[y])+
885 fac6*g_vort.template get<vorticity>(key)[z]*
886 (g_vel.template get<velocity>(key.move(z,1))[y] - g_vel.template get<velocity>(key.move(z,-1))[y]);
889 g_dwp.template get<rhs>(key)[z] =
893 fac4*g_vort.template get<vorticity>(key)[x]*
894 (g_vel.template get<velocity>(key.move(x,1))[z] - g_vel.template get<velocity>(key.move(x,-1))[z])+
895 fac5*g_vort.template get<vorticity>(key)[y]*
896 (g_vel.template get<velocity>(key.move(y,1))[z] - g_vel.template get<velocity>(key.move(y,-1))[z])+
897 fac6*g_vort.template get<vorticity>(key)[z]*
898 (g_vel.template get<velocity>(key.move(z,1))[z] - g_vel.template get<velocity>(key.move(z,-1))[z]);
950 auto key = it2.
get();
1006 while (it2.isNext())
1008 auto key = it2.
get();
1044template<
typename gr
id,
typename vector>
void do_step(vector &
particles,
1053 constexpr int rhs = 0;
1058 inte.template p2m<vorticity,vorticity>(
particles,g_vort);
1060 g_vort.template ghost_put<add_,vorticity>();
1067 comp_vel(domain,g_vort,g_vel,phi_s,solver);
1068 calc_rhs(g_vort,g_vel,g_dvort);
1074 g_dvort.template ghost_get<rhs>();
1075 g_vel.template ghost_get<velocity>();
1078 inte.template m2p<rhs,rhs_part>(g_dvort,
particles);
1079 inte.template m2p<velocity,p_vel>(g_vel,
particles);
1084template<
typename vector,
typename gr
id>
void check_point_and_save(vector &
particles,
1090 Vcluster & v_cl = create_vcluster();
1094 particles.
write(
"part_out_" + std::to_string(i),VTK_WRITER | FORMAT_BINARY);
1095 g_vort.template ghost_get<vorticity>();
1096 g_vel.template ghost_get<velocity>();
1097 g_vel.write(
"grid_velocity_" + std::to_string(i), VTK_WRITER | FORMAT_BINARY);
1098 g_vort.write(
"grid_vorticity_" + std::to_string(i), VTK_WRITER | FORMAT_BINARY);
1107 while (it_s.isNext())
1109 auto p = it_s.
get();
1111 double vort_magn = sqrt(
particles.template getProp<vorticity>(p)[0] *
particles.template getProp<vorticity>(p)[0] +
1112 particles.template getProp<vorticity>(p)[1] *
particles.template getProp<vorticity>(p)[1] +
1113 particles.template getProp<vorticity>(p)[2] *
particles.template getProp<vorticity>(p)[2]);
1115 if (vort_magn < 0.1)
1127 part_save.template getLastProp<0>() = vort_magn;
1156int main(
int argc,
char* argv[])
1159 openfpm_init(&argc,&argv);
1168 long int sz[] = {512,64,64};
1169 size_t szu[] = {(size_t)sz[0],(
size_t)sz[1],(size_t)sz[2]};
1174 grid_type g_vel(g_vort.getDecomposition(),szu,g);
1175 grid_type g_dvort(g_vort.getDecomposition(),szu,g);
1184 Vcluster & v_cl = create_vcluster();
1188 {std::cout <<
"SPACING " << g_vort.spacing(0) <<
" " << g_vort.spacing(1) <<
" " << g_vort.spacing(2) << std::endl;}
1191 init_ring(g_vort,domain);
1193 x_.
resize(g_vort.size(),g_vort.getLocalDomainSize());
1200 helmotz_hodge_projection(g_vort,domain,solver,x_,
true);
1211 phi_s[0].
resize(g_vort.size(),g_vort.getLocalDomainSize());
1212 phi_s[1].
resize(g_vort.size(),g_vort.getLocalDomainSize());
1213 phi_s[2].
resize(g_vort.size(),g_vort.getLocalDomainSize());
1229 {g_vort.write(
"grid_vorticity_init", VTK_WRITER | FORMAT_BINARY);}
1240 std::string restart(argv[1]);
1243 i = std::stoi(restart);
1251 {std::cout <<
"Restarting from " << i << std::endl;}
1255 for ( ; i < 10001 ; i++)
1258 do_step(
particles,g_vort,g_vel,g_dvort,domain,inte,phi_s,solver);
1264 do_step(
particles,g_vort,g_vel,g_dvort,domain,inte,phi_s,solver);
1271 inte.template p2m<vorticity,vorticity>(
particles,g_vort);
1272 g_vort.template ghost_put<add_,vorticity>();
1275 helmotz_hodge_projection(g_vort,domain,solver,x_,
false);
1281 {std::cout <<
"Step " << i << std::endl;}
1284 if (i % 100 == 0) {check_point_and_save(
particles,g_vort,g_vel,g_dvort,i);}
1295int 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
type of vector that store the solution
float stype
type of the space
SparseMatrix< double, int, PETSC_BASE > SparseMatrix_type
type of sparse grid that store the Matrix A
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 the solution.
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