28 #include "Vector/vector_dist.hpp"
29 #include "regression/regression.hpp"
34 size_t max_iter = 1000;
35 double tolerance = 1e-11;
38 double r_cutoff_factor;
39 double sampling_radius;
41 int compute_normals = 0;
42 int compute_curvatures = 0;
47 unsigned int minter_poly_degree = 4;
48 float minter_lp_degree = 1.0;
51 int min_num_particles = 0;
55 float r_cutoff_factor_min_num_particles;
56 int only_narrowband = 1;
57 int project_particles = 0;
62 template <
typename particles_in_type,
size_t phi_field,
size_t closest_po
int_field,
size_t normal_field,
size_t curvature_field,
unsigned int num_m
inter_coeffs>
68 vd_s(vd.getDecomposition(), 0),
69 r_cutoff2(redistOptions.r_cutoff_factor*redistOptions.r_cutoff_factor*redistOptions.H*redistOptions.H),
71 redistOptions.minter_poly_degree, redistOptions.minter_lp_degree))
76 void run_redistancing()
78 if (redistOptions.verbose)
80 std::cout<<
"Verbose mode. Make sure the vd.getProp<4>(a) is an integer that pcp can write surface flags onto."<<std::endl;
83 detect_surface_particles();
85 interpolate_sdf_field();
87 find_closest_point(vd_in);
90 void redistance_separate_particle_set(particles_in_type & vd_generic)
92 find_closest_point(vd_generic);
96 particles_in_type initialize_surface_discretization()
98 detect_surface_particles();
100 interpolate_sdf_field();
102 particles_in_type sampleParticles = format_vd_s();
104 return(sampleParticles);
108 template <
size_t prp_
id,
size_t prp_
id_to>
void regress_field(particles_in_type & vd_generic)
110 regress_field_to_particles<prp_id, prp_id_to>(vd_generic);
114 static constexpr
size_t num_neibs = 0;
115 static constexpr
size_t vd_s_close_part = 1;
116 static constexpr
size_t vd_s_sdf = 2;
117 static constexpr
size_t vd_s_sample = 3;
118 static constexpr
size_t minter_coeff = 4;
120 static constexpr
size_t vd_in_sdf = phi_field;
121 static constexpr
size_t vd_in_close_part = 4;
124 static constexpr
size_t vd_in_normal = normal_field;
125 static constexpr
size_t vd_in_curvature = curvature_field;
126 static constexpr
size_t vd_in_cp = closest_point_field;
129 particles_in_type &vd_in;
130 static constexpr
unsigned int dim = particles_in_type::dims;
131 static constexpr
unsigned int n_c = num_minter_coeffs;
140 int return_sign(
double phi)
142 if (phi > 0)
return 1;
143 if (phi < 0)
return -1;
155 void detect_surface_particles()
157 vd_in.template ghost_get<vd_in_sdf>();
159 auto NN = vd_in.getCellList(sqrt(r_cutoff2) + redistOptions.H);
160 auto part = vd_in.getDomainIterator();
162 while (part.isNext())
166 if ((redistOptions.only_narrowband) && (std::abs(vd_in.template getProp<vd_in_sdf>(akey)) > redistOptions.sampling_radius))
172 int sgn_a = return_sign(vd_in.template getProp<vd_in_sdf>(akey));
175 double min_sdf = abs(vd_in.template getProp<vd_in_sdf>(akey));
177 if (redistOptions.verbose) vd_in.template getProp<vd_in_close_part>(akey) = 0;
180 auto Np = NN.getNNIteratorBox(NN.getCell(xa));
184 int sgn_b = return_sign(vd_in.template getProp<vd_in_sdf>(bkey));
187 double r2 = norm2(dr);
190 if ((sqrt(r2) < (1.5*redistOptions.H)) and (sgn_a != sgn_b)) isclose = 1;
193 if (r2 < r_cutoff2) ++num_neibs_a;
197 if ((sqrt(r2) < ((redistOptions.r_cutoff_factor + 1.5)*redistOptions.H)) && (sgn_a != sgn_b)) surfaceflag = 1;
205 for(
int k = 0; k < dim; k++) vd_s.
getLastPos()[k] = vd_in.getPos(akey)[k];
206 vd_s.template getLastProp<vd_s_sdf>() = vd_in.template getProp<vd_in_sdf>(akey);
207 vd_s.template getLastProp<num_neibs>() = num_neibs_a;
211 vd_s.template getLastProp<vd_s_close_part>() = 1;
212 if (redistOptions.verbose) vd_in.template getProp<vd_in_close_part>(akey) = 1;
216 vd_s.template getLastProp<vd_s_close_part>() = 0;
217 if (redistOptions.verbose) vd_in.template getProp<vd_in_close_part>(akey) = 0;
224 void interpolate_sdf_field()
226 int message_insufficient_support = 0;
227 int message_projection_fail = 0;
229 vd_s.template ghost_get<vd_s_sdf>();
230 double r_cutoff_celllist = sqrt(r_cutoff2);
231 if (redistOptions.min_num_particles != 0) r_cutoff_celllist = redistOptions.r_cutoff_factor_min_num_particles*redistOptions.H;
236 while (part.isNext())
241 if (vd_s.template getProp<vd_s_close_part>(a) != 1)
247 const int num_neibs_a = vd_s.template getProp<num_neibs>(a);
252 if(redistOptions.min_num_particles == 0)
255 if (regSupport.getNumParticles() < n_c) message_insufficient_support = 1;
256 minterModelpcp.computeCoeffs(vd_s, regSupport);
261 if (regSupport.getNumParticles() < n_c) message_insufficient_support = 1;
262 minterModelpcp.computeCoeffs(vd_s, regSupport);
265 auto& minterModel = minterModelpcp.model;
266 for(
int k = 0; k < n_c; k++) vd_s.template getProp<minter_coeff>(a)[k] = minterModel->getCoeffs()[k];
268 double grad_p_minter_mag2;
270 EMatrix<double, Eigen::Dynamic, 1> grad_p_minter(dim_r, 1);
271 EMatrix<double, Eigen::Dynamic, 1> x_minter(dim_r, 1);
272 for(
int k = 0; k < dim_r; k++) x_minter[k] = xa[k];
274 double p_minter = get_p_minter(x_minter, minterModel);
276 while ((abs(p_minter) > redistOptions.tolerance) && (k_project < redistOptions.max_iter))
278 grad_p_minter = get_grad_p_minter(x_minter, minterModel);
279 grad_p_minter_mag2 = grad_p_minter.dot(grad_p_minter);
280 x_minter = x_minter - p_minter*grad_p_minter/grad_p_minter_mag2;
281 p_minter = get_p_minter(x_minter, minterModel);
286 for(
int k = 0; k < dim; k++) vd_s.template getProp<vd_s_sample>(a)[k] = x_minter[k];
287 if (k_project == redistOptions.max_iter)
289 if (redistOptions.verbose) std::cout<<
"didnt work for "<<a.getKey()<<std::endl;
290 message_projection_fail = 1;
296 if (message_insufficient_support) std::cout<<
"Warning: less number of neighbours than required for interpolation"
297 <<
" for some particles. Consider using at least N particles function."<<std::endl;
298 if (message_projection_fail) std::cout<<
"Warning: Newton-style projections towards the interface do not satisfy"
299 <<
" given tolerance for some particles"<<std::endl;
313 void find_closest_point(particles_in_type & vd_generic)
318 vd_s.template ghost_get<vd_s_close_part,vd_s_sample,minter_coeff>();
319 auto NN_s = vd_s.
getCellList(redistOptions.sampling_radius);
322 int message_step_limitation = 0;
323 int message_convergence_problem = 0;
326 while (part.isNext())
330 if ((redistOptions.only_narrowband) && (std::abs(vd_generic.template getProp<vd_in_sdf>(a)) > redistOptions.sampling_radius))
337 EMatrix<double, Eigen::Dynamic, 1> xa(dim_r, 1);
338 for(
int k = 0; k < dim; k++) xa[k] = vd_generic.getPos(a)[k];
342 EMatrix<double, Eigen::Dynamic, 1> x(dim_r, 1);
344 EMatrix<double, Eigen::Dynamic, 1> dx(dim_r + 1, 1);
345 for(
int k = 0; k < (dim + 1); k++) dx[k] = 1.0;
352 EMatrix<double, Eigen::Dynamic, 1> grad_p(dim_r, 1);
353 for(
int k = 0; k < dim; k++) grad_p[k] = 0.0;
355 EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> H_p(dim_r, dim_r);
356 for(
int k = 0; k < dim; k++)
358 for(
int l = 0; l < dim; l++) H_p(k, l) = 0.0;
361 EMatrix<double, Eigen::Dynamic, 1> c(n_c_r, 1);
362 for (
int k = 0; k < n_c_r; k++) c[k] = 0.0;
365 EMatrix<double, Eigen::Dynamic, 1> nabla_f(dim_r + 1, 1);
366 EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> H_f(dim_r + 1, dim_r + 1);
367 for(
int k = 0; k < (dim + 1); k++)
370 for(
int l = 0; l < (dim + 1); l++) H_f(k, l) = 0.0;
379 auto Np = NN_s.getNNIteratorBox(NN_s.getCell(vd_generic.getPos(a)));
384 for(
int k = 0; k < dim; k++) x[k] = vd_s.template getProp<vd_s_sample>(b_min)[k];
388 EMatrix<double, Eigen::Dynamic, 1> x00(dim_r,1);
389 for(
int k = 0; k < dim; k++) x00[k] = x[k];
391 EMatrix<double, Eigen::Dynamic, 1> x00x(dim_r,1);
392 for(
int k = 0; k < dim; k++) x00x[k] = 0.0;
394 auto& model = minterModelpcp.model;
395 EVectorXd temp(n_c_r,1);
396 for(
int k = 0; k < n_c_r; k++) temp[k] = vd_s.template getProp<minter_coeff>(b_min)[k];
397 model->setCoeffs(temp);
399 if(redistOptions.verbose)
401 std::cout<<std::setprecision(16)<<
"VERBOSE%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for particle "<<a.getKey()<<std::endl;
402 std::cout<<
"x_poly: "<<vd_s.
getPos(b_min)[0]<<
", "<<vd_s.
getPos(b_min)[1]<<
"\nxa: "<<xa[0]<<
", "<<xa[1]<<
"\nx_0: "<<x[0]<<
", "<<x[1]<<
"\nc: "<<c<<std::endl;
404 std::cout<<
"interpol_i(x_0) = "<<get_p_minter(x, model)<<std::endl;
408 EMatrix<double, Eigen::Dynamic, 1> xax = x - xa;
413 p = get_p_minter(x, model);
414 grad_p = get_grad_p_minter(x, model);
418 lambda = -xax.dot(grad_p)/grad_p.dot(grad_p);
420 for(
int k = 0; k < dim; k++) nabla_f[k] = xax[k] + lambda*grad_p[k];
423 nabla_f(Eigen::seq(0, dim - 1)) = xax + lambda*grad_p;
427 double nabla_f_norm = nabla_f.norm();
430 while((nabla_f_norm > redistOptions.tolerance) && (k_newton<redistOptions.max_iter))
433 H_p = get_H_p_minter(x, model);
436 H_f(Eigen::seq(0, dim_r - 1), Eigen::seq(0, dim_r - 1)) = lambda*H_p;
437 for(
int k = 0; k < dim; k++) H_f(k, k) = H_f(k, k) + 1.0;
438 H_f(Eigen::seq(0, dim_r - 1), dim_r) = grad_p;
439 H_f(dim_r, Eigen::seq(0, dim_r - 1)) = grad_p.transpose();
440 H_f(dim_r, dim_r) = 0.0;
443 dx = - H_f.inverse()*nabla_f;
449 while((dx.dot(dx)) > 0.25*r_cutoff2)
451 message_step_limitation = 1;
456 x = x + dx(Eigen::seq(0, dim - 1));
457 lambda = lambda + dx[dim];
461 p = get_p_minter(x, model);
462 grad_p = get_grad_p_minter(x, model);
464 nabla_f(Eigen::seq(0, dim - 1)) = xax + lambda*grad_p;
468 nabla_f_norm = nabla_f.norm();
472 if(redistOptions.verbose)
474 std::cout<<
"dx: "<<dx[0]<<
", "<<dx[1]<<std::endl;
475 std::cout<<
"H_f:\n"<<H_f<<
"\nH_f_inv:\n"<<H_f.inverse()<<std::endl;
476 std::cout<<
"x:"<<x[0]<<
", "<<x[1]<<
"\nc:"<<std::endl;
477 std::cout<<c<<std::endl;
478 std::cout<<
"dpdx: "<<grad_p<<std::endl;
479 std::cout<<
"k = "<<k_newton<<std::endl;
480 std::cout<<
"x_k = "<<x[0]<<
", "<<x[1]<<std::endl;
481 std::cout<<x[0]<<
", "<<x[1]<<
", "<<nabla_f_norm<<std::endl;
488 if (k_newton == redistOptions.max_iter) message_convergence_problem = 1;
493 if (redistOptions.write_sdf) vd_generic.template getProp<vd_in_sdf>(a) = return_sign(vd_generic.template getProp<vd_in_sdf>(a))*xax.norm();
494 if (redistOptions.write_cp)
for(
int k = 0; k <dim; k++) vd_generic.template getProp<vd_in_cp>(a)[k] = x[k];
497 if ((!redistOptions.verbose) and (vd_generic.template getProp<vd_in_close_part>(a)) and redistOptions.project_particles)
499 for(
int k = 0; k < dim; k++) vd_generic.getPos(a)[k] = vd_generic.template getProp<vd_in_cp>(a)[k];
505 if ((k_newton == 0) && (xax.norm() < redistOptions.tolerance))
507 vd_generic.template getProp<vd_in_sdf>(a) = return_sign(vd_generic.template getProp<vd_in_sdf>(a))*redistOptions.tolerance;
511 if(redistOptions.verbose)
514 std::cout<<
"x_final: "<<x[0]<<
", "<<x[1]<<std::endl;
515 std::cout<<
"p(x_final) :"<<get_p_minter(x, model)<<std::endl;
516 std::cout<<
"nabla p(x_final)"<<get_grad_p_minter(x, model)<<std::endl;
518 std::cout<<
"lambda: "<<lambda<<std::endl;
521 if (redistOptions.compute_normals)
523 EMatrix<double, Eigen::Dynamic, 1> normal = get_normal(grad_p, return_sign(vd_generic.template getProp<vd_in_sdf>(a)));
524 for(
int k = 0; k<dim; k++) vd_generic.template getProp<vd_in_normal>(a)[k] = normal[k];
526 EMatrix<double, Eigen::Dynamic, 1> grad_p_iso(dim_r, 1);
527 grad_p_iso = get_grad_p_minter(xa, model);
532 if (redistOptions.compute_curvatures)
534 H_p = get_H_p_minter(x, model);
535 vd_generic.template getProp<vd_in_curvature>(a) = get_curvature(grad_p, H_p);
539 if (redistOptions.verbose and message_step_limitation)
541 std::cout<<
"Step size limitation invoked"<<std::endl;
543 if (message_convergence_problem)
545 std::cout<<
"Warning: Newton algorithm has reached maximum number of iterations, does not converge for some particles"<<std::endl;
552 auto Np = NN_s.getNNIteratorBox(NN_s.getCell(xa));
555 double distance = 1000000.0;
557 double dist_calc = 1000000000.0;
565 if (!vd_s.template getProp<vd_s_close_part>(b))
571 dist_calc = norm(xa - xb);
572 if (dist_calc < distance)
574 distance = dist_calc;
584 particles_in_type format_vd_s()
588 particles_in_type sampleParticles(vd_in.getDecomposition(), 0);
595 if ((vd_s.template getProp<vd_s_sdf>(a) < 0) and (vd_s.template getProp<vd_s_close_part>(a)))
597 sampleParticles.add();
598 for(
int k = 0; k < dim; k++) sampleParticles.getLastPos()[k] = vd_s.template getProp<vd_s_sample>(a)[k];
599 sampleParticles.template getLastProp<vd_in_sdf>() = 0.0;
600 for(
int k = 0; k < dim; k++) sampleParticles.template getLastProp<vd_in_cp>()[k] = vd_s.template getProp<vd_s_sample>(a)[k];
601 sampleParticles.template getLastProp<vd_in_close_part>() = 1;
603 auto& model = minterModelpcp.model;
604 EVectorXd temp(n_c,1);
605 for(
int k = 0; k < n_c; k++) temp[k] = vd_s.template getProp<minter_coeff>(a)[k];
606 model->setCoeffs(temp);
607 EMatrix<double, Eigen::Dynamic, 1> grad_p(dim, 1);
608 EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> H_p(dim, dim);
609 EMatrix<double, Eigen::Dynamic, 1> normal(dim, 1);
610 EMatrix<double, Eigen::Dynamic, 1> x(dim, 1);
611 for (
int k = 0; k < dim; k++) x[k] = vd_s.template getProp<vd_s_sample>(a)[k];
612 grad_p = get_grad_p_minter(x, model);
613 H_p = get_H_p_minter(x, model);
614 normal = get_normal(grad_p, 1);
616 for (
int k = 0; k < dim; k++) sampleParticles.template getLastProp<vd_in_normal>()[k] = normal[k];
617 sampleParticles.template getLastProp<vd_in_curvature>() = get_curvature(grad_p, H_p);
622 return(sampleParticles);
625 template <
size_t prp_
id,
size_t prp_
id_to>
void regress_field_to_particles(particles_in_type & vd_generic)
627 int message_insufficient_support = 0;
628 double r_cutoff_celllist = sqrt(r_cutoff2);
629 auto NN = vd_in.getCellList(r_cutoff_celllist);
630 auto part = vd_generic.getDomainIterator();
637 auto Np = NN.getNNIterator(NN.getCell(xa));
644 double dist2 = norm2(xb - xa);
646 if(dist2 < r_cutoff2) keys.add(b.getKey());
652 if (regSupport.getNumParticles() < n_c) message_insufficient_support = 1;
653 double divergence = 0.0;
654 for(
int k = 0; k < dim; k++)
656 genericMinterModel.computeCoeffs(vd_in, regSupport, k);
657 auto& minterModel = genericMinterModel.model;
658 EMatrix<double, Eigen::Dynamic, 1> x(dim, 1);
659 EMatrix<double, Eigen::Dynamic, 1> grad_p_minter(dim, 1);
660 for (
int l = 0; l < dim; l++) x[l] = xa[l];
661 vd_generic.template getProp<prp_id_to>(a)[k] = get_p_minter(x, minterModel);
663 grad_p_minter = get_grad_p_minter(x, minterModel);
664 divergence = divergence + grad_p_minter[k];
666 vd_generic.template getProp<5>(a) = divergence;
670 if (message_insufficient_support) std::cout<<
"Warning: less number of neighbours than required for property regression"
671 <<
" for some particles. Consider using at least N particles function."<<std::endl;
676 template<
typename PolyType>
677 inline double get_p_minter(EMatrix<double, Eigen::Dynamic, 1> xvector, PolyType model)
679 return(model->eval(xvector.transpose())(0));
683 template<
typename PolyType>
684 inline EMatrix<double, Eigen::Dynamic, 1> get_grad_p_minter(EMatrix<double, Eigen::Dynamic, 1> xvector, PolyType model)
686 EMatrix<double, Eigen::Dynamic, 1> grad_p(dim_r, 1);
687 std::vector<int> derivOrder(dim_r, 0);
688 for(
int k = 0; k < dim_r; k++){
689 std::fill(derivOrder.begin(), derivOrder.end(), 0);
691 grad_p[k] = model->deriv_eval(xvector.transpose(), derivOrder)(0);
696 template<
typename PolyType>
697 inline EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> get_H_p_minter(EMatrix<double, Eigen::Dynamic, 1> xvector, PolyType model)
699 EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> H_p(dim_r, dim_r);
700 std::vector<int> derivOrder(dim_r, 0);
702 for(
int k = 0; k < dim_r; k++){
703 for(
int l = 0; l < dim_r; l++)
705 std::fill(derivOrder.begin(), derivOrder.end(), 0);
708 H_p(k, l) = model->deriv_eval(xvector.transpose(), derivOrder)(0);
714 inline EMatrix<double, Eigen::Dynamic, 1> get_normal(EMatrix<double, Eigen::Dynamic, 1> grad_p,
float direction)
716 EMatrix<double, Eigen::Dynamic, 1> normal(dim_r, 1);
718 for(
int k = 0; k<dim_r; k++) normal[k] = direction*grad_p(k)*1/grad_p.norm();
723 inline double get_curvature(EMatrix<double, Eigen::Dynamic, 1> grad_p, EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> H_p)
729 kappa = (H_p(0,0)*grad_p(1)*grad_p(1) - 2*grad_p(1)*grad_p(0)*H_p(0,1) + H_p(1,1)*grad_p(0)*grad_p(0))/std::pow(sqrt(grad_p(0)*grad_p(0) + grad_p(1)*grad_p(1)),3);
733 kappa = ((H_p(1,1) + H_p(2,2))*std::pow(grad_p(0), 2) + (H_p(0,0) + H_p(2,2))*std::pow(grad_p(1), 2) + (H_p(0,0) + H_p(1,1))*std::pow(grad_p(2), 2)
734 - 2*grad_p(0)*grad_p(1)*H_p(0,1) - 2*grad_p(0)*grad_p(2)*H_p(0,2) - 2*grad_p(1)*grad_p(2)*H_p(1,2))*std::pow(std::pow(grad_p(0), 2) + std::pow(grad_p(1), 2) + std::pow(grad_p(2), 2), -1.5);
ParticleIt_Cells< dim, CellList< dim, T, Mem_fast<>, transform > > getDomainIterator(openfpm::vector< size_t > &dom_cells)
Get an iterator over particles following the cell structure.
This class implement the point shape in an N-dimensional space.
Class for reinitializing a level-set function into a signed distance function using the Closest-Point...
Grid key for a distributed grid.
auto getPos(vect_dist_key_dx vec_key) -> decltype(vPos.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 add()
Add local particle.
CellList_type getCellList(St r_cut, size_t opt=CL_NON_SYMMETRIC|CL_LINEAR_CELL_KEYS, bool no_se3=false, float ghostEnlargeFactor=1.013)
Construct a cell list starting from the stored particles.
auto getLastPos() -> decltype(vPos.template get< 0 >(0))
Get the position of the last element.
Structure to bundle options for redistancing.