From a9b4bf33cdf5886332305ff8ecf53771c4d25c27 Mon Sep 17 00:00:00 2001
From: lschulze <lschulze@mpi-cbg.de>
Date: Wed, 16 Feb 2022 15:18:51 +0100
Subject: [PATCH] Use cell lists in find_closest_point and make parallelization
 work

---
 src/level_set/particle_cp/particle_cp.hpp | 131 +++++++++++++---------
 1 file changed, 76 insertions(+), 55 deletions(-)

diff --git a/src/level_set/particle_cp/particle_cp.hpp b/src/level_set/particle_cp/particle_cp.hpp
index 53838cf6..792c3458 100644
--- a/src/level_set/particle_cp/particle_cp.hpp
+++ b/src/level_set/particle_cp/particle_cp.hpp
@@ -39,13 +39,12 @@ template<unsigned int dim, unsigned int n_c> using particles_surface = vector_di
 //												flag for distinguishing closest particles to surface, for which the interpolation has to be done
 struct Redist_options
 {
-	size_t max_iter = 1000;				// params for the Newton algorithm for the solution of the constrained optimization problem
-	double tolerance = 1e-11;
+	size_t max_iter = 1000;				// params for the Newton algorithm for the solution of the constrained
+	double tolerance = 1e-11;			// optimization problem, and for the projection of the sample points on the interface
 	
 	double H;							// interparticle spacing
 	double r_cutoff_factor = 2.5;		// radius of neighbors to consider during interpolation, as factor of H
 	double sampling_radius;
-	std::string polynomial_degree = "taylor4";
 	double barrier_coefficient = 0.0;	// coefficient for barrier term in optimisation
 	double armijo_tau = 0.0;			// armijo line search parameters
 	double armijo_c = 0.0;
@@ -71,9 +70,9 @@ public:
 																					  r_cutoff2(redistOptions.r_cutoff_factor*redistOptions.r_cutoff_factor*redistOptions.H*redistOptions.H)
 	{
 		// do constructor things
-		if (std::is_same<polynomial_degree,quadratic>::value) redistOptions.polynomial_degree = "quadratic";
-		else if (std::is_same<polynomial_degree,bicubic>::value) redistOptions.polynomial_degree = "bicubic";
-		else if (std::is_same<polynomial_degree,taylor4>::value) redistOptions.polynomial_degree = "taylor4";
+		if (std::is_same<polynomial_degree,quadratic>::value) polynomialDegree = "quadratic";
+		else if (std::is_same<polynomial_degree,bicubic>::value) polynomialDegree = "bicubic";
+		else if (std::is_same<polynomial_degree,taylor4>::value) polynomialDegree = "taylor4";
 		else throw std::invalid_argument("Invalid polynomial degree given. Valid choices currently are quadratic, bicubic and taylor4.");
 	}
 	
@@ -85,7 +84,7 @@ public:
 		std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
 		std::cout << "Time difference for detection = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
 
-		std::cout<<"interpolating..."<<std::endl;
+		std::cout<<"interpolating with "<<polynomialDegree<<"..."<<std::endl;
 		begin = std::chrono::steady_clock::now();
 		interpolate_sdf_field();
 		end = std::chrono::steady_clock::now();
@@ -119,6 +118,7 @@ private:
 
 	particles_surface<dim, n_c> vd_s;
 	double r_cutoff2;
+	std::string polynomialDegree;
 
 
 
@@ -242,13 +242,13 @@ private:
 			// part of the MonomialBasis used here in the interpolation.
 			MonomialBasis<dim> m(4);
 
-			if (redistOptions.polynomial_degree == "quadratic")
+			if (polynomialDegree == "quadratic")
 			{
 				unsigned int degrees[dim];
 				for(int k = 0; k < dim; k++) degrees[k] = 1;
 				m = MonomialBasis<dim>(degrees, 1);
 			}
-			else if (redistOptions.polynomial_degree == "taylor4")
+			else if (polynomialDegree == "taylor4")
 			{
 				unsigned int degrees[dim];
 				for(int k = 0; k < dim; k++) degrees[k] = 1;
@@ -256,7 +256,7 @@ private:
 				if (dim == 3) degrees_2 = 2;
 				m = MonomialBasis<dim>(degrees, degrees_2);
 			}
-			else if (redistOptions.polynomial_degree == "bicubic")
+			else if (polynomialDegree == "bicubic")
 			{
 				// do nothing as it has already been initialized like this
 			}
@@ -310,7 +310,6 @@ private:
 				vd_s.template getProp<interpol_coeff>(a)[k] = c[k];
 			}
 
-
 			// after interpolation coefficients have been computed and stored, perform Newton-style projections
 			// towards the interface in order to obtain a sample.
 			// initialise derivatives of the interpolation polynomial and an interim position vector x. The iterations
@@ -323,7 +322,7 @@ private:
 
 			EMatrix<double, Eigen::Dynamic, 1> x(dim, 1);
 			for(int k = 0; k < dim; k++) x[k] = xa[k];
-			double p = get_p(x, c, redistOptions.polynomial_degree);
+			double p = get_p(x, c, polynomialDegree);
 			int k_project = 0;
 
 			// do the projections.
@@ -331,11 +330,11 @@ private:
 			// while(incr > 0.01*redistOptions.H)
 			while ((abs(p) > redistOptions.tolerance) && (k_project < redistOptions.max_iter))
 			{
-				grad_p = get_grad_p(x, c, redistOptions.polynomial_degree);
+				grad_p = get_grad_p(x, c, polynomialDegree);
 				grad_p_mag2 = grad_p.dot(grad_p);
 
 				x = x - p*grad_p/grad_p_mag2;
-				p = get_p(x, c, redistOptions.polynomial_degree);
+				p = get_p(x, c, polynomialDegree);
 				//incr = sqrt(p*p*dpdx*dpdx/(grad_p_mag2*grad_p_mag2) + p*p*dpdy*dpdy/(grad_p_mag2*grad_p_mag2));
 				++k_project;
 			}
@@ -350,7 +349,7 @@ private:
 			//verbose = 1;
 			if (verbose)
 			{
-				std::cout<<"VERBOSEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"<<std::endl;
+				std::cout<<"VERBOSE"<<std::endl;
 				EMatrix<double, Eigen::Dynamic, 1> xaa(dim,1);
 				for(int k = 0; k < dim; k++) xaa[k] = xa[k];
 				//double curvature = get_dpdxdx(xaa, c) + get_dpdydy(xaa, c);
@@ -396,15 +395,6 @@ private:
 		auto part = vd_in.getDomainIterator(); //todo: include the sampling radius somewhere (bandwidth)
 
 		int verbose = 0;
-		int msize;
-		if(redistOptions.polynomial_degree == "quadratic") msize = 6;
-		else if(redistOptions.polynomial_degree == "bicubic") msize = 16;
-		else if(redistOptions.polynomial_degree == "taylor4")
-			{
-				if (dim == 2) msize = 15;
-				else msize = 35;
-			}
-		else throw std::invalid_argument("Received unknown polynomial degree.");
 
 		// do iteration over all query particles
 		while (part.isNext())
@@ -436,8 +426,8 @@ private:
 				for(int l = 0; l < dim; l++) H_p(k, l) = 0.0;
 			}
 
-			EMatrix<double, Eigen::Dynamic, 1> c(msize, 1);
-			for (int k = 0; k < msize; k++) c[k] = 0.0;
+			EMatrix<double, Eigen::Dynamic, 1> c(n_c, 1);
+			for (int k = 0; k < n_c; k++) c[k] = 0.0;
 
 			// f(x, lambda) is the Lagrangian, initialize its gradient and Hessian
 			EMatrix<double, Eigen::Dynamic, 1> nabla_f(dim + 1, 1);
@@ -452,11 +442,10 @@ private:
 			// solution to initialise another x_a vector, but it is done because of the two different types EMatrix and
 			// point vector, and can probably be made nicer.
 			Point<dim, double> xaa = vd_in.getPos(a);
-			//auto Np = NN_s.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(a)));
-			//vd_s.updateCellList(NN_s);
 
 			// Now we will iterate over the sample points, which means iterating over vd_s.
-			auto Np = vd_s.getDomainIterator();
+			auto Np = NN_s.template getNNIterator<NO_CHECK>(NN_s.getCell(vd_in.getPos(a)));
+
 			// distance is the the minimum distance to be beaten
 			double distance = 1000000.0;
 			// dist_calc is the variable for the distance that is computed per sample point
@@ -503,18 +492,18 @@ private:
 			for(int k = 0; k < dim; k++) x00x[k] = 0.0;
 
 			// take the interpolation polynomial of the sample particle closest to the query particle
-			for (int k = 0 ; k < msize ; k++) c[k] = vd_s.template getProp<interpol_coeff>(b_min)[k];
+			for (int k = 0 ; k < n_c ; k++) c[k] = vd_s.template getProp<interpol_coeff>(b_min)[k];
 
 			// debugging stuff
 			//if (a.getKey() == 2425) verbose = 1;
 			if(verbose)
-				{
-					val = get_p(x, c, redistOptions.polynomial_degree);
-					std::cout<<std::setprecision(16)<<"VERBOSE%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%:"<<std::endl;
-					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;
-					std::cout<<"phi(x_0): "<<val<<std::endl;
-					std::cout<<"interpol_i(x_0) = "<<get_p(x, c, redistOptions.polynomial_degree)<<std::endl;
-				}
+			{
+				val = get_p(x, c, polynomialDegree);
+				std::cout<<std::setprecision(16)<<"VERBOSE%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%:"<<std::endl;
+				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;
+				std::cout<<"phi(x_0): "<<val<<std::endl;
+				std::cout<<"interpol_i(x_0) = "<<get_p(x, c, polynomialDegree)<<std::endl;
+			}
 
 			// variable containing updated distance at iteration k
 			EMatrix<double, Eigen::Dynamic, 1> xax = x - xa;
@@ -527,8 +516,8 @@ private:
 			double barrier3 = 0.0;
 
 			// calculations needed specifically for k_newton == 0
-			p = get_p(x, c, redistOptions.polynomial_degree);
-			grad_p = get_grad_p(x, c, redistOptions.polynomial_degree);
+			p = get_p(x, c, polynomialDegree);
+			grad_p = get_grad_p(x, c, polynomialDegree);
 
 			// this guess for the Lagrange multiplier is taken from the original paper by Saye and can be done since
 			// p is approximately zero at the sample point.
@@ -549,26 +538,58 @@ private:
 //			{
 //				while(abs(p) > redistOptions.tolerance)
 //				{
-//					dpdx = get_dpdx(x, c, redistOptions.polynomial_degree);
-//					dpdy = get_dpdy(x, c, redistOptions.polynomial_degree);
-//					p = get_p(x, c, redistOptions.polynomial_degree);
+//					dpdx = get_dpdx(x, c, polynomialDegree);
+//					dpdy = get_dpdy(x, c, polynomialDegree);
+//					p = get_p(x, c, polynomialDegree);
 //					double grad_p_mag2 = dpdx*dpdx + dpdy*dpdy;
 //
 //					x[0] = x[0] - p*dpdx/grad_p_mag2;
 //					x[1] = x[1] - p*dpdy/grad_p_mag2;
 //				}
-//				dpdx = get_dpdx(x, c, redistOptions.polynomial_degree);
-//				dpdy = get_dpdy(x, c, redistOptions.polynomial_degree);
+//				dpdx = get_dpdx(x, c, polynomialDegree);
+//				dpdy = get_dpdy(x, c, polynomialDegree);
 //				xax = x - xa;
 //				lambda = (-xax[0]*dpdx - xax[1]*dpdy)/(dpdx*dpdx + dpdy*dpdy);
 //			}
 
 
+			/////// parallel DEBUG ////////////////////////
+			if (false)
+			{
+				//Box<dim,double> detect({ -0.613708, 0.165925, -0.0531703},{ -0.613706, 0.165927, -0.0531701});
+				Box<dim,double> detect({ -0.613708, 0.165925},{ -0.613706, 0.165927});
+
+				Point<dim,double> pp = vd_in.getPos(a);
+
+				if (detect.isInside(pp))
+				{
+					std::cout<<"xa:  \n"<<xa<< std::endl;
+					std::cout<<"x:  \n"<<x<<std::endl;
+					std::cout<<"sample key bmin: "<<b_min.getKey()<<std::endl;
+					std::cout<<"c:  \n"<<c<<std::endl;
+					std::cout<<"key: "<<a.getKey()<<std::endl;
+				}
+
+				auto & v_cl = create_vcluster();
+
+				if (a.getKey() == 131 && v_cl.rank() == 1)
+				{
+					std::cout<<"xa:  \n"<<xa<< std::endl;
+					std::cout<<"x:  \n"<<x<<std::endl;
+					std::cout<<"sample key bmin: "<<b_min.getKey()<<std::endl;
+					std::cout<<"c:  \n"<<c<<std::endl;
+				}
+
+				if ((abs(x[0] + 0.6659)<0.0005)&&(abs(x[1] - 0.2223)<0.0005)&&(abs(x[2] + 0.0594)<0.0005)) std::cout<<"its there and x = \n"<<x
+						<<"\nbmin key is "<<b_min.getKey()<<" and the processor is "<<v_cl.rank()<<std::endl;
+			}
+			//////////////////////////////
+
 			// Do Newton iterations.
 			while((nabla_f_norm > redistOptions.tolerance) && (k_newton<redistOptions.max_iter))
 			{
 				// gather required derivative values
-				H_p = get_H_p(x, c, redistOptions.polynomial_degree);
+				H_p = get_H_p(x, c, polynomialDegree);
 
 				// Assemble Hessian matrix, grad f has been computed at the end of the last iteration.
 				H_f(Eigen::seq(0, dim - 1), Eigen::seq(0, dim - 1)) = lambda*H_p;
@@ -605,12 +626,12 @@ private:
 					double alpha_armijo = 1.0;
 					double t_armijo = -redistOptions.armijo_c*(nabla_f[0]*dx[0] + nabla_f[1]*dx[1] + nabla_f[2]*dx[2]);
 					// int k_armijo = 0;
-					double f = 0.5*(x - xa).norm()*(x - xa).norm() + lambda*get_p(x, c, redistOptions.polynomial_degree);
+					double f = 0.5*(x - xa).norm()*(x - xa).norm() + lambda*get_p(x, c, polynomialDegree);
 					EMatrix<double, Eigen::Dynamic, 1> x_armijo(2,1);
 					x_armijo[0] = x[0] + alpha_armijo*dx[0];
 					x_armijo[1] = x[1] + alpha_armijo*dx[1];
 					double lambda_armijo = lambda + alpha_armijo*dx[2];
-					double f_armijo = 0.5*(xa - x_armijo).norm()*(xa - x_armijo).norm() + lambda_armijo*get_p(x_armijo, c, redistOptions.polynomial_degree);
+					double f_armijo = 0.5*(xa - x_armijo).norm()*(xa - x_armijo).norm() + lambda_armijo*get_p(x_armijo, c, polynomialDegree);
 					if (verbose) std::cout<<"start armijo\n"<<"x: "<<x[0]<<", "<<x[1]<<"\ndx: "<<dx[0]<<", "<<dx[1]<<"\nt: "<<t_armijo<<"\nf: "<<f<<"\nf_armijo: "<<f_armijo<<std::endl;
 					while((f - f_armijo) < alpha_armijo*t_armijo)
 					{
@@ -619,7 +640,7 @@ private:
 						x_armijo[0] = x[0] + alpha_armijo*dx[0];
 						x_armijo[1] = x[1] + alpha_armijo*dx[1];
 						lambda_armijo = lambda + alpha_armijo*dx[2];
-						f_armijo = 0.5*(xa - x_armijo).norm()*(xa - x_armijo).norm() + lambda_armijo*get_p(x_armijo, c, redistOptions.polynomial_degree);
+						f_armijo = 0.5*(xa - x_armijo).norm()*(xa - x_armijo).norm() + lambda_armijo*get_p(x_armijo, c, polynomialDegree);
 						//std::cout<<alpha_armijo<<std::endl;
 						if (verbose) std::cout<<"\narmijo++\n"<<"x: "<<x[0]<<", "<<x[1]<<"\ndx: "<<dx[0]<<", "<<dx[1]<<"\nt: "<<t_armijo<<"\nf: "<<f<<"\nf_armijo: "<<f_armijo<<"\ndiff f: "<<f-f_armijo<<"\n&&&&&&&&&&&&&&&&&&&&&&&&&"<<std::endl;
 					}
@@ -644,10 +665,10 @@ private:
 						{
 							dx = redistOptions.support_prevent*dx;
 							if(j == 0) x_interm = x;
-							dpdx_interm = get_dpdx(x_interm, c, redistOptions.polynomial_degree);
-							dpdy_interm = get_dpdy(x_interm, c, redistOptions.polynomial_degree);
+							dpdx_interm = get_dpdx(x_interm, c, polynomialDegree);
+							dpdy_interm = get_dpdy(x_interm, c, polynomialDegree);
 							grad_p_mag_interm2 = dpdx_interm*dpdx_interm + dpdy_interm*dpdy_interm;
-							p_interm = get_p(x_interm, c, redistOptions.polynomial_degree);
+							p_interm = get_p(x_interm, c, polynomialDegree);
 							x_interm[0] = x_interm[0] - redistOptions.support_prevent*p_interm*dpdx_interm/grad_p_mag_interm2;
 							x_interm[1] = x_interm[1] - redistOptions.support_prevent*p_interm*dpdy_interm/grad_p_mag_interm2;
 							++j;
@@ -700,8 +721,8 @@ private:
 
 				// prepare values for next iteration and update the exit criterion
 				xax = x - xa;
-				p = get_p(x, c, redistOptions.polynomial_degree);
-				grad_p = get_grad_p(x, c, redistOptions.polynomial_degree);
+				p = get_p(x, c, polynomialDegree);
+				grad_p = get_grad_p(x, c, polynomialDegree);
 				nabla_f(Eigen::seq(0, dim - 1)) = xax + lambda*grad_p;
 				nabla_f[dim] = p;
 
@@ -739,8 +760,8 @@ private:
 				//std::cout<<"new sdf: "<<vd.getProp<sdf>(a)<<std::endl;
 				//std::cout<<"c:\n"<<vd.getProp<interpol_coeff>(a)<<"\nmin_sdf: "<<vd.getProp<min_sdf>(a)<<" , min_sdf_x: "<<vd.getProp<min_sdf_x>(a)<<std::endl;
 				std::cout<<"x_final: "<<x[0]<<", "<<x[1]<<std::endl;
-				std::cout<<"p(x_final) :"<<get_p(x, c, redistOptions.polynomial_degree)<<std::endl;
-				std::cout<<"nabla p(x_final)"<<get_dpdx(x, c, redistOptions.polynomial_degree)<<", "<<get_dpdy(x, c, redistOptions.polynomial_degree)<<std::endl;
+				std::cout<<"p(x_final) :"<<get_p(x, c, polynomialDegree)<<std::endl;
+				std::cout<<"nabla p(x_final)"<<get_dpdx(x, c, polynomialDegree)<<", "<<get_dpdy(x, c, polynomialDegree)<<std::endl;
 				std::cout<<"lambda: "<<lambda<<std::endl;
 			}
 			verbose = 0;
-- 
GitLab