diff --git a/src/DCPSE/DCPSE_op/tests/DCPSE_op_Surface_tests.cpp b/src/DCPSE/DCPSE_op/tests/DCPSE_op_Surface_tests.cpp index 3d4c38fc38097c545df2a3bdc1791d4c108415ea..ed225ee05dc2345f1e918bf2067e3944520e8052 100644 --- a/src/DCPSE/DCPSE_op/tests/DCPSE_op_Surface_tests.cpp +++ b/src/DCPSE/DCPSE_op/tests/DCPSE_op_Surface_tests.cpp @@ -519,6 +519,345 @@ BOOST_AUTO_TEST_CASE(dcpse_surface_sphere_old) { //std::cout<<"Worst: "<<worst<<std::endl; BOOST_REQUIRE(worst < 0.03); } + +/*BOOST_AUTO_TEST_CASE(dcpse_surface_sphere_proj) { + auto & v_cl = create_vcluster(); + timer tt; + tt.start(); + size_t n=512; + size_t n_sp=n; + // Domain + double boxP1{-1.5}, boxP2{1.5}; + double boxSize{boxP2 - boxP1}; + size_t sz[3] = {n,n,n}; + double grid_spacing{boxSize/(sz[0]-1)}; + double grid_spacing_surf=grid_spacing*30; + double rCut{2.5 * grid_spacing_surf}; + + Box<3,double> domain{{boxP1,boxP1,boxP1},{boxP2,boxP2,boxP2}}; + size_t bc[3] = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC}; + Ghost<3,double> ghost{rCut + grid_spacing/8.0}; + + constexpr int K = 1; + // particles + vector_dist_ws<3, double, aggregate<VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,double>> Sparticles(0, domain,bc,ghost); + // 1. particles on the Spherical surface + double Golden_angle=M_PI * (3.0 - sqrt(5.0)); + if (v_cl.rank() == 0) { + //std::vector<Vector3f> data; + //GenerateSphere(1,data); + for(int i=1;i<n_sp;i++) + { + double y = 1.0 - (i /double(n_sp - 1.0)) * 2.0; + double radius = sqrt(1 - y * y); + double Golden_theta = Golden_angle * i; + double x = cos(Golden_theta) * radius; + double z = sin(Golden_theta) * radius; + Sparticles.add(); + Sparticles.getLastPos()[0] = x; + Sparticles.getLastPos()[1] = y; + Sparticles.getLastPos()[2] = z; + double rm=sqrt(x*x+y*y+z*z); + Sparticles.getLastProp<2>()[0] = x/rm; + Sparticles.getLastProp<2>()[1] = y/rm; + Sparticles.getLastProp<2>()[2] = z/rm; + Sparticles.getLastProp<4>()[0] = 1.0 ; + Sparticles.getLastProp<4>()[1] = std::atan2(sqrt(x*x+y*y),z); + Sparticles.getLastProp<4>()[2] = std::atan2(y,x); + if(i<=2*(K)+1) + {Sparticles.getLastSubset(1);} + else + {Sparticles.getLastSubset(0);} + } + //std::cout << "n: " << n << " - grid spacing: " << grid_spacing << " - rCut: " << rCut << "Surf Normal spacing" << grid_spacing<<std::endl; + } + + Sparticles.map(); + Sparticles.ghost_get<3>(); + + vector_dist_subset<3,double,aggregate<VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,double>> Sparticles_bulk(Sparticles,0); + vector_dist_subset<3,double,aggregate<VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,VectorS<3,double>,double>> Sparticles_boundary(Sparticles,1); + auto &bulkIds=Sparticles_bulk.getIds(); + auto &bdrIds=Sparticles_boundary.getIds(); + std::unordered_map<const lm,double,key_hash,key_equal> Alm; + //Setting max mode l_max + //Setting amplitudes to 1 + for(int l=0;l<=K;l++){ + for(int m=-l;m<=l;m++){ + Alm[std::make_tuple(l,m)]=0; + } + } + Alm[std::make_tuple(1,0)]=1; + auto it2 = Sparticles.getDomainIterator(); + while (it2.isNext()) { + auto p = it2.get(); + Point<3, double> xP = Sparticles.getProp<4>(p); + *//*double Sum=0; + for(int m=-spL;m<=spL;++m) + { + Sum+=openfpm::math::Y(spL,m,xP[1],xP[2]); + }*//* + //Sparticles.getProp<ANADF>(p) = Sum;//openfpm::math::Y(K,K,xP[1],xP[2]);openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm);; + Sparticles.getProp<3>(p)[0]=openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm); + Sparticles.getProp<3>(p)[1]=openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm); + Sparticles.getProp<3>(p)[2]=openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm); + Sparticles.getProp<1>(p)[0]=-(K)*(K+1)*openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm); + Sparticles.getProp<1>(p)[1]=-(K)*(K+1)*openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm); + Sparticles.getProp<1>(p)[2]=-(K)*(K+1)*openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm); + ++it2; + } + auto f=getV<3>(Sparticles); + auto Df=getV<0>(Sparticles); + + SurfaceProjectedGradient<2> SGP{Sparticles,2,rCut,grid_spacing_surf}; + + Sparticles.ghost_get<3>(); + Df=SGP(f); + //Df=SLap(f); + auto it3 = Sparticles.getDomainIterator(); + double worst = 0.0; + while (it3.isNext()) { + auto p = it3.get(); + //Sparticles.getProp<5>(p) = fabs(Sparticles.getProp<1>(p) - Sparticles.getProp<0>(p)); + if (fabs(Sparticles.getProp<1>(p)[0] - Sparticles.getProp<0>(p)[0]) > worst) { + worst = fabs(Sparticles.getProp<1>(p)[0] - Sparticles.getProp<0>(p)[0]); + } + ++it3; + } + Sparticles.deleteGhost(); + //Sparticles.write("Sparticles"); + //std::cout<<worst; + BOOST_REQUIRE(worst < 0.03); +}*/ + + + BOOST_AUTO_TEST_CASE(dcpse_surface_adaptive) { +// int rank; +// MPI_Comm_rank(MPI_COMM_WORLD, &rank); + const size_t sz[3] = {81,81,1}; + Box<3, double> box({0, 0,-5}, {0.5, 0.5,5}); + size_t bc[3] = {NON_PERIODIC, NON_PERIODIC,NON_PERIODIC}; + double spacing = box.getHigh(0) / (sz[0] - 1); + Ghost<3, double> ghost(spacing * 3.1); + double rCut = 3.1 * spacing; + BOOST_TEST_MESSAGE("Init vector_dist..."); + + vector_dist<3, double, aggregate<double,double,double,double,double,double,double[3]>> domain(0, box, bc, ghost); + + + //Init_DCPSE(domain) + BOOST_TEST_MESSAGE("Init domain..."); + + auto it = domain.getGridIterator(sz); + while (it.isNext()) { + domain.add(); + + auto key = it.get(); + double x = key.get(0) * it.getSpacing(0); + domain.getLastPos()[0] = x; + double y = key.get(1) * it.getSpacing(1); + domain.getLastPos()[1] = y; + + domain.getLastPos()[2] = 0; + + ++it; + } + + // Add multi res patch 1 + + { + const size_t sz2[3] = {40,40,1}; + Box<3,double> bx({0.25 + it.getSpacing(0)/4.0,0.25 + it.getSpacing(0)/4.0,-0.5},{sz2[0]*it.getSpacing(0)/2.0 + 0.25 + it.getSpacing(0)/4.0, sz2[1]*it.getSpacing(0)/2.0 + 0.25 + it.getSpacing(0)/4.0,0.5}); + openfpm::vector<size_t> rem; + + auto it = domain.getDomainIterator(); + + while (it.isNext()) + { + auto k = it.get(); + + Point<3,double> xp = domain.getPos(k); + + if (bx.isInside(xp) == true) + { + rem.add(k.getKey()); + } + + ++it; + } + + domain.remove(rem); + + auto it2 = domain.getGridIterator(sz2); + while (it2.isNext()) { + domain.add(); + + auto key = it2.get(); + double x = key.get(0) * spacing/2.0 + 0.25 + spacing/4.0; + domain.getLastPos()[0] = x; + double y = key.get(1) * spacing/2.0 + 0.25 + spacing/4.0; + domain.getLastPos()[1] = y; + domain.getLastPos()[2] = 0; + + ++it2; + } + } + + // Add multi res patch 2 + + { + const size_t sz2[3] = {40,40,1}; + Box<3,double> bx({0.25 + 21.0*spacing/8.0,0.25 + 21.0*spacing/8.0,-5},{sz2[0]*spacing/4.0 + 0.25 + 21.0*spacing/8.0, sz2[1]*spacing/4.0 + 0.25 + 21*spacing/8.0,5}); + openfpm::vector<size_t> rem; + + auto it = domain.getDomainIterator(); + + while (it.isNext()) + { + auto k = it.get(); + + Point<3,double> xp = domain.getPos(k); + + if (bx.isInside(xp) == true) + { + rem.add(k.getKey()); + } + + ++it; + } + + domain.remove(rem); + + auto it2 = domain.getGridIterator(sz2); + while (it2.isNext()) { + domain.add(); + + auto key = it2.get(); + double x = key.get(0) * spacing/4.0 + 0.25 + 21*spacing/8.0; + domain.getLastPos()[0] = x; + double y = key.get(1) * spacing/4.0 + 0.25 + 21*spacing/8.0; + domain.getLastPos()[1] = y; + domain.getLastPos()[2] = 0; + + ++it2; + } + } + + /////////////////////// + + BOOST_TEST_MESSAGE("Sync domain across processors..."); + + domain.map(); + domain.ghost_get<0>(); + + openfpm::vector<aggregate<int>> bulk; + openfpm::vector<aggregate<int>> up_p; + openfpm::vector<aggregate<int>> dw_p; + openfpm::vector<aggregate<int>> l_p; + openfpm::vector<aggregate<int>> r_p; + openfpm::vector<aggregate<int>> ref_p; + + auto v = getV<0>(domain); + auto RHS=getV<1>(domain); + auto sol = getV<2>(domain); + auto anasol = getV<3>(domain); + auto err = getV<4>(domain); + auto DCPSE_sol=getV<5>(domain); + + // Here fill me + + Box<3, double> up({box.getLow(0) - spacing / 2.0, box.getHigh(1) - spacing / 2.0,-5}, + {box.getHigh(0) + spacing / 2.0, box.getHigh(1) + spacing / 2.0,5}); + + Box<3, double> down({box.getLow(0) - spacing / 2.0, box.getLow(1) - spacing / 2.0,-5}, + {box.getHigh(0) + spacing / 2.0, box.getLow(1) + spacing / 2.0,5}); + + Box<3, double> left({box.getLow(0) - spacing / 2.0, box.getLow(1) + spacing / 2.0,-5}, + {box.getLow(0) + spacing / 2.0, box.getHigh(1) - spacing / 2.0,5}); + + Box<3, double> right({box.getHigh(0) - spacing / 2.0, box.getLow(1) + spacing / 2.0,-5}, + {box.getHigh(0) + spacing / 2.0, box.getHigh(1) - spacing / 2.0,5}); + + openfpm::vector<Box<3, double>> boxes; + boxes.add(up); + boxes.add(down); + boxes.add(left); + boxes.add(right); + + // Create a writer and write + VTKWriter<openfpm::vector<Box<3, double>>, VECTOR_BOX> vtk_box; + vtk_box.add(boxes); + //vtk_box.write("vtk_box.vtk"); + + + auto it2 = domain.getDomainIterator(); + + while (it2.isNext()) { + auto p = it2.get(); + Point<3, double> xp = domain.getPos(p); + if (up.isInside(xp) == true) { + up_p.add(); + up_p.last().get<0>() = p.getKey(); + domain.getProp<1>(p) = -2*M_PI*M_PI*sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + domain.getProp<3>(p) = sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + } else if (down.isInside(xp) == true) { + dw_p.add(); + dw_p.last().get<0>() = p.getKey(); + domain.getProp<1>(p) = -2*M_PI*M_PI*sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + domain.getProp<3>(p) = sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + + } else if (left.isInside(xp) == true) { + l_p.add(); + l_p.last().get<0>() = p.getKey(); + domain.getProp<1>(p) = -2*M_PI*M_PI*sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + domain.getProp<3>(p) = sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + + } else if (right.isInside(xp) == true) { + r_p.add(); + r_p.last().get<0>() = p.getKey(); + domain.getProp<1>(p) = -2*M_PI*M_PI*sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + domain.getProp<3>(p) = sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + + } else { + bulk.add(); + bulk.last().get<0>() = p.getKey(); + domain.getProp<1>(p) = -2*M_PI*M_PI*sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + domain.getProp<3>(p) = sin(M_PI*xp.get(0))*sin(M_PI*xp.get(1)); + } + domain.getProp<6>(p)[0] = 0; + domain.getProp<6>(p)[1] = 0; + domain.getProp<6>(p)[2] = 1; + + ++it2; + } + + domain.ghost_get<1,2,3>(); + SurfaceDerivative_xx<6> Dxx(domain, 2, rCut,6.0,support_options::ADAPTIVE_SURFACE); + SurfaceDerivative_yy<6> Dyy(domain, 2, rCut,6.0,support_options::ADAPTIVE_SURFACE); + SurfaceDerivative_zz<6> Dzz(domain, 2, rCut,6.0,support_options::ADAPTIVE_SURFACE); + + + domain.ghost_get<2>(); + sol=Dxx(anasol)+Dyy(anasol)+Dzz(anasol); + domain.ghost_get<5>(); + + double worst1 = 0.0; + + for(int j=0;j<bulk.size();j++) + { auto p=bulk.get<0>(j); + if (fabs(domain.getProp<1>(p) - domain.getProp<2>(p)) >= worst1) { + worst1 = fabs(domain.getProp<1>(p) - domain.getProp<2>(p)); + } + domain.getProp<4>(p) = fabs(domain.getProp<1>(p) - domain.getProp<2>(p)); + + } + //std::cout << "Maximum Analytic Error: " << worst1 << std::endl; + + //domain.ghost_get<4>(); + domain.write("Robin_anasol"); + BOOST_REQUIRE(worst1 < 0.03); + + } BOOST_AUTO_TEST_SUITE_END() #endif diff --git a/src/DCPSE/Dcpse.hpp b/src/DCPSE/Dcpse.hpp index f2db680be66e3ac45ee789cce62120c0ffbf4bc3..f2c051536ef0ccc6fa7d901c1cfb11895301f1b7 100644 --- a/src/DCPSE/Dcpse.hpp +++ b/src/DCPSE/Dcpse.hpp @@ -72,7 +72,7 @@ private: openfpm::vector<size_t> kerOffsets,accKerOffsets; openfpm::vector<T> calcKernels; openfpm::vector<T> accCalcKernels; - + openfpm::vector<T> nSpacings; vector_type & particlesFrom; vector_type2 & particlesTo; double rCut,supportSizeFactor=1,nSpacing; @@ -93,6 +93,10 @@ public: while(it.isNext()){ auto key=it.get(); Point<dim,T> xp=particles.getPos(key), Normals=particles.template getProp<NORMAL_ID>(key); + if(opt==support_options::ADAPTIVE_SURFACE) + { + nSpacing=nSpacings.get(key.getKey()); + } for(int i=1;i<=nCount;i++){ particles.addAtEnd(); for(size_t j=0;j<dim;j++) @@ -207,6 +211,27 @@ public: opt(opt),isSurfaceDerivative(true),nSpacing(nSpacing),nCount(floor(rCut/nSpacing)) { particles.ghost_get_subset(); // This communicates which ghost particles to be excluded from support + + if(opt==support_options::ADAPTIVE_SURFACE) { + supportSizeFactor=nSpacing; + if(dim==2){ + nCount=3; + } + else{ + nCount=2; + } + SupportBuilder<vector_type,vector_type2> + supportBuilder(particlesFrom,particlesTo, differentialSignature, rCut, differentialOrder == 0); + + auto it = particlesTo.getDomainIterator(); + while (it.isNext()) { + auto key_o = particlesTo.getOriginKey(it.get()); + Support support = supportBuilder.getSupport(it,1,opt); + nSpacings.add(supportBuilder.getLastAvgspacing()); + ++it; + } + + } createNormalParticles<NORMAL_ID>(particles); #ifdef SE_CLASS1 particles.write("WithNormalParticlesQC"); diff --git a/src/DCPSE/SupportBuilder.hpp b/src/DCPSE/SupportBuilder.hpp index ee3ec25479aff7addda56ffb6379a508fd6e3a26..1e6b19e9f885c350479e792f93ba046cbc7493be 100644 --- a/src/DCPSE/SupportBuilder.hpp +++ b/src/DCPSE/SupportBuilder.hpp @@ -18,7 +18,8 @@ enum support_options { N_PARTICLES, RADIUS, - LOAD + LOAD, + ADAPTIVE_SURFACE }; @@ -30,7 +31,7 @@ private: vector_type2 &domainTo; decltype(std::declval<vector_type>().getCellList(0.0)) cellList; const Point<vector_type::dims, unsigned int> differentialSignature; - typename vector_type::stype rCut; + typename vector_type::stype rCut,AvgSpacing; bool is_interpolation; public: @@ -78,6 +79,12 @@ public: auto p_o = domainTo.getOriginKey(p.getKey()); return Support(p_o.getKey(), openfpm::vector_std<size_t>(supportKeys.begin(), supportKeys.end())); } + + typename vector_type::stype getLastAvgspacing() + { + return this->AvgSpacing; + } + private: size_t getCellLinId(const grid_key_dx<vector_type::dims> &cellKey) @@ -213,10 +220,17 @@ private: } else { rp.sort(); + AvgSpacing=rp.get(0).dist; for (int i = 0 ; i < requiredSupportSize ; i++) { + if(opt==support_options::ADAPTIVE_SURFACE && rp.get(i).dist > rCut) + {} + else{ points.push_back(rp.get(i).offset); + } + //AvgSpacing+=rp.get(i).dist; } + //AvgSpacing=AvgSpacing/requiredSupportSize; } return points;