diff --git a/src/level_set/particle_cp/particle_cp.hpp b/src/level_set/particle_cp/particle_cp.hpp index 982c7318b3342856d35181d0734baf8e58cd58c3..53838cf6b586d01b24cf3024d7e1cade9f26becf 100644 --- a/src/level_set/particle_cp/particle_cp.hpp +++ b/src/level_set/particle_cp/particle_cp.hpp @@ -33,9 +33,9 @@ #include "Operators/Vector/vector_dist_operators.hpp" #include <chrono> -typedef vector_dist<2, double, aggregate<vect_dist_key_dx, int, int, int, double, double[2], double[16]>> particles_surface; -// | | | | | | | -// key to particle in vd surface flag num neibs | sdf sample version interpolation coefficients +template<unsigned int dim, unsigned int n_c> using particles_surface = vector_dist<dim, double, aggregate<int, int, double, double[dim], double[n_c]>>; +// | | | | | +// num neibs | sdf sample version interpolation coefficients // flag for distinguishing closest particles to surface, for which the interpolation has to be done struct Redist_options { @@ -54,7 +54,14 @@ struct Redist_options int init_project = 0; }; -template <typename particles_in_type> +// Add new polynomial degrees here in case new interpolation schemes are implemented. +// Template typenames for initialization of vd_s +struct quadratic {}; +struct bicubic {}; +struct taylor4 {}; + + +template <typename particles_in_type, typename polynomial_degree> class particle_cp_redistancing { public: @@ -64,6 +71,10 @@ 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"; + else throw std::invalid_argument("Invalid polynomial degree given. Valid choices currently are quadratic, bicubic and taylor4."); } void run_redistancing() @@ -72,38 +83,42 @@ public: std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); detect_surface_particles(); 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 << "Time difference for detection = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl; std::cout<<"interpolating..."<<std::endl; begin = std::chrono::steady_clock::now(); interpolate_sdf_field(); end = std::chrono::steady_clock::now(); - std::cout << "Time difference for interpolation= " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl; + std::cout << "Time difference for interpolation = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl; std::cout<<"optimizing..."<<std::endl; begin = std::chrono::steady_clock::now(); find_closest_point(); end = std::chrono::steady_clock::now(); - std::cout << "Time difference for optimization= " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl; + std::cout << "Time difference for optimization = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl; std::cout<<"finishing..."<<std::endl; } private: - static constexpr size_t vdkey = 0; //todo: this should be dispensable as well by adding the interesting properties to vd_s - static constexpr size_t surf_flag = 1; //todo: get rid of this flag as well, as no non-surface_flag particles should be in vd_s anyways - static constexpr size_t num_neibs = 2; - static constexpr size_t vd_s_close_part = 3; - static constexpr size_t vd_s_sdf = 4; - static constexpr size_t vd_s_sample = 5; - static constexpr size_t interpol_coeff = 6; - static constexpr size_t vd_in_sdf = 0; //this is needed in the vd_in vector - static constexpr size_t vd_in_close_part = 3; + static constexpr size_t num_neibs = 0; + static constexpr size_t vd_s_close_part = 1; + static constexpr size_t vd_s_sdf = 2; + static constexpr size_t vd_s_sample = 3; + static constexpr size_t interpol_coeff = 4; + static constexpr size_t vd_in_sdf = 0; // this is really required in the vd_in vector, so users need to know about it. + static constexpr size_t vd_in_close_part = 3; // this is not needed by the method, but more for debugging purposes, as it shows all particles for which + // interpolation and sampling is performed. Redist_options redistOptions; particles_in_type &vd_in; - particles_surface vd_s; + static constexpr unsigned int dim = particles_in_type::dims; + static constexpr unsigned int n_c = (dim == 2 && std::is_same<polynomial_degree,quadratic>::value) ? 6 : + (dim == 2 && std::is_same<polynomial_degree,bicubic>::value) ? 16 : + (dim == 2 && std::is_same<polynomial_degree,taylor4>::value) ? 15 : + (dim == 3 && std::is_same<polynomial_degree,taylor4>::value) ? 35 : 1; + + particles_surface<dim, n_c> vd_s; double r_cutoff2; - static constexpr int dim = particles_in_type::dims; @@ -126,8 +141,9 @@ private: void detect_surface_particles() { + vd_in.template ghost_get<vd_in_sdf>(); + auto NN = vd_in.getCellList(sqrt(r_cutoff2) + redistOptions.H); - vd_in.updateCellList(NN); auto part = vd_in.getDomainIterator(); while (part.isNext()) @@ -195,6 +211,7 @@ private: // within the loop itself. void interpolate_sdf_field() { + vd_s.template ghost_get<vd_s_sdf>(); int verbose = 0; auto NN_s = vd_s.getCellList(sqrt(r_cutoff2)); vd_s.updateCellList(NN_s); @@ -235,7 +252,9 @@ private: { unsigned int degrees[dim]; for(int k = 0; k < dim; k++) degrees[k] = 1; - m = MonomialBasis<dim>(degrees, 3); + unsigned int degrees_2 = 3; + if (dim == 3) degrees_2 = 2; + m = MonomialBasis<dim>(degrees, degrees_2); } else if (redistOptions.polynomial_degree == "bicubic") { @@ -270,7 +289,7 @@ private: //std::cout<<std::setprecision(15)<<xb[0]<<"\t"<<xb[1]<<"\t"<<vd.getProp<sdf>(b)<<std::endl; //xb[0] = 0.1; //xb[1] = 0.5; - //xb[2] = 1.0; + //xb[2] = 3.0; // Fill phi-vector from the right hand side phi[neib] = vd_s.template getProp<vd_s_sdf>(b); @@ -328,9 +347,10 @@ private: // debugging stuff: //if (a.getKey() == 5424) verbose = 1; - //verbose = 0; + //verbose = 1; if (verbose) { + std::cout<<"VERBOSEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"<<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); @@ -369,14 +389,21 @@ private: { // iterate over all particles, i.e. do closest point optimisation for all particles, and initialize // all relevant variables. + + vd_s.template ghost_get<vd_s_close_part,vd_s_sample,interpol_coeff>(); + auto NN_s = vd_s.getCellList(redistOptions.sampling_radius); auto part = vd_in.getDomainIterator(); //todo: include the sampling radius somewhere (bandwidth) - vd_s.updateCellList(NN_s); + 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") msize = 15; + 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 @@ -479,7 +506,7 @@ private: for (int k = 0 ; k < msize ; k++) c[k] = vd_s.template getProp<interpol_coeff>(b_min)[k]; // debugging stuff - if (a.getKey() == 2425) verbose = 1; + //if (a.getKey() == 2425) verbose = 1; if(verbose) { val = get_p(x, c, redistOptions.polynomial_degree); @@ -656,9 +683,14 @@ private: // prevent Newton algorithm from leaving the support radius by scaling step size. This is pretty much // the only subroutine that should stay. It is invoked in case the increment exceeds 50% of the cutoff // radius and simply scales the step length down to 10% until it does not exceed 50% of the cutoff radius. + while((dx.dot(dx)) > 0.25*r_cutoff2) { - std::cout<<"invoked"<<std::endl; + auto & v_cl = create_vcluster(); + + std::cout<<"invoked " << a.getKey() << " " << v_cl.rank() << " " <<std::endl; + + dx = 0.1*dx; } @@ -756,7 +788,9 @@ private: const double z = xvector[2]; if (polynomialdegree == "taylor4") { - //implement 3D taylor4 + return(c[0] + c[1]*x + c[2]*x*x + c[3]*x*x*x + c[4]*x*x*x*x + c[5]*y + c[6]*x*y + c[7]*x*x*y + c[8]*x*x*x*y + c[9]*y*y + c[10]*y*y*x + c[11]*x*x*y*y + c[12]*y*y*y + c[13]*y*y*y*x + c[14]*y*y*y*y + + c[15]*z + c[16]*x*z + c[17]*x*x*z + c[18]*x*x*x*z + c[19]*y*z + c[20]*x*y*z + c[21]*x*x*y*z + c[22]*y*y*z + c[23]*x*y*y*z + c[24]*y*y*y*z + c[25]*z*z + c[26]*x*z*z + c[27]*x*x*z*z + + c[28]*y*z*z + c[29]*x*y*z*z + c[30]*y*y*z*z + c[31]*z*z*z + c[32]*x*z*z*z + c[33]*y*z*z*z + c[34]*z*z*z*z); } } else throw std::invalid_argument("received unknown input dimension. Spatial variable needs to be either 2D or 3D."); @@ -789,9 +823,15 @@ private: } else if (dim == 3) { + const double z = xvector[2]; if (polynomialdegree == "taylor4") { - //implement 3D taylor 4 + grad_p[0] = c[1] + 2*c[2]*x + 3*c[3]*x*x + 4*c[4]*x*x*x + c[6]*y + 2*c[7]*x*y + 3*c[8]*x*x*y + c[10]*y*y + 2*c[11]*x*y*y + c[13]*y*y*y + + c[16]*z + 2*c[17]*x*z + 3*c[18]*x*x*z + c[20]*y*z + 2*c[21]*x*y*z + c[23]*y*y*z + c[26]*z*z + 2*c[27]*x*z*z + c[29]*y*z*z + c[32]*z*z*z; + grad_p[1] = c[5] + c[6]*x + c[7]*x*x + c[8]*x*x*x + 2*c[9]*y + 2*c[10]*x*y + 2*c[11]*x*x*y + 3*c[12]*y*y + 3*c[13]*y*y*x + 4*c[14]*y*y*y + + c[19]*z + c[20]*x*z + c[21]*x*x*z + 2*c[22]*y*z + 2*c[23]*x*y*z + 3*c[24]*y*y*z + c[28]*z*z + c[29]*x*z*z + 2*c[30]*y*z*z + c[33]*z*z*z; + grad_p[2] = c[15] + c[16]*x + c[17]*x*x + c[18]*x*x*x + c[19]*y + c[20]*x*y + c[21]*x*x*y + c[22]*y*y + c[23]*x*y*y + c[24]*y*y*y + + 2*c[25]*z + 2*c[26]*x*z + 2*c[27]*x*x*z + 2*c[28]*y*z + 2*c[29]*x*y*z + 2*c[30]*y*y*z + 3*c[31]*z*z + 3*c[32]*x*z*z + 3*c[33]*y*z*z + 4*c[34]*z*z*z; } } else throw std::invalid_argument("received unknown input dimension. Spatial variable needs to be either 2D or 3D."); @@ -833,9 +873,25 @@ private: } else if (dim == 3) { + const double z = xvector[2]; if (polynomialdegree == "taylor4") { - //implement 3D taylor 4 + H_p(0, 0) = 2*c[2] + 6*c[3]*x + 12*c[4]*x*x + 2*c[7]*y + 6*c[8]*x*y + 2*c[11]*y*y + + 2*c[17]*z + 6*c[18]*x*z + 2*c[21]*y*z + 2*c[27]*z*z; + H_p(1, 1) = 2*c[9] + 2*c[10]*x + 2*c[11]*x*x + 6*c[12]*y + 6*c[13]*x*y + 12*c[14]*y*y + + 2*c[22]*z + 2*c[23]*x*z + 6*c[24]*y*z + 2*c[30]*z*z; + H_p(2, 2) = 2*c[25] + 2*c[26]*x + 2*c[27]*x*x + 2*c[28]*y + 2*c[29]*x*y + 2*c[30]*y*y + + 6*c[31]*z + 6*c[32]*x*z + 6*c[33]*y*z + 12*c[34]*z*z; + + H_p(0, 1) = c[6] + 2*c[7]*x + 3*c[8]*x*x + 2*c[10]*y +4*c[11]*x*y + 3*c[13]*y*y + + c[20]*z + 2*c[21]*x*z + 2*c[23]*y*z + c[29]*z*z; + H_p(0, 2) = c[16] + 2*c[17]*x + 3*c[18]*x*x + c[20]*y + 2*c[21]*x*y + c[23]*y*y + + 2*c[26]*z + 4*c[27]*x*z + 2*c[29]*y*z + 3*c[32]*z*z; + H_p(1, 2) = c[19] + c[20]*x + c[21]*x*x + c[22]*y + 2*c[23]*x*y + 3*c[24]*y*y + + 2*c[28]*z + 2*c[29]*x*z + 4*c[30]*y*z + 3*c[33]*z*z; + H_p(1, 0) = H_p(0, 1); + H_p(2, 0) = H_p(0, 2); + H_p(2, 1) = H_p(1, 2); } } else throw std::invalid_argument("received unknown input dimension. Spatial variable needs to be either 2D or 3D.");