OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
Ellip.cpp
1// ------------------------------------------------------------------------------------------
2// Copyright (C) 2021 ---- absingh
3//
4// This file is part of the Surface DCPSE Paper.
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18// ------------------------------------------------------------------------------------------
19
20#include "Vector/vector_dist_subset.hpp"
21#include "DCPSE/DCPSE_op/DCPSE_surface_op.hpp"
22#include "DCPSE/DCPSE_OP/DCPSE_Solver.hpp"
23#include "util/SphericalHarmonics.hpp"
25
26std::string p_output;
27
28constexpr int DF=0;
29constexpr int F=1;
30constexpr int ANADF=2;
31constexpr int ERR=3;
32constexpr int NORMAL=4;
33constexpr int PCOORD=5;
34constexpr int ANAG=6;
35constexpr int ERRG=7;
36constexpr int POS=8;
37constexpr int CURVT=9;
38constexpr int PCURV=10;
39
40
42openfpm::vector<std::string> propNames{{"Gauss","Mean","AnaMean","ErrorMean","Normal","PCOORD","AnaGauss","ErrorGauss","Pos","CurvatureTensor","PrincipalCurvature"}};
44
45int main(int argc, char * argv[]) {
46 openfpm_init(&argc,&argv);
47 auto & v_cl = create_vcluster();
48 timer tt;
49 tt.start();
50 size_t n;
51 unsigned int ord;
52 double spL;
53 double grid_spacing_surf,sc;
54 double rCut;
55
56 // Get command line arguments
57 if (argc != 4) {
58 std::cout << "Error: The executable requires the following arguments: number_grid_points" << std::endl;
59 return 0;
60 }
61 else {
62 n = std::stoi(argv[1]);
63 ord = std::stoi(argv[2]);
64 sc = std::stoi(argv[3]);
65 //spL=std::stof(argv[2]);
66 //grid_spacing_surf=std::stof(argv[3]);
67 //rCut=std::stof(argv[4]);
68 }
69
70 // Files and directories
71 std::string cwd{boost::filesystem::current_path().string()};
72 std::string output_dir{cwd + "/output_Ellipsoid"};
74 p_output = output_dir + "/particles";
75 size_t n_sp=n;
76 // Domain
77 double boxP1{-1.5}, boxP2{1.5};
78 double boxSize{boxP2 - boxP1};
79 size_t sz[3] = {n,n,n};
80 double grid_spacing{boxSize/(sz[0]-1)};
81 grid_spacing_surf=grid_spacing*sc;
82 rCut=2.9 * grid_spacing_surf;
83 double a=1.0,b=0.8,c=0.75;
84
85 Box<3,double> domain{{boxP1,boxP1,boxP1},{boxP2,boxP2,boxP2}};
86 size_t bc[3] = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
87 Ghost<3,double> ghost{rCut + grid_spacing/8.0};
88
89 // particles
90 vector_type particles{0,domain,bc,ghost};
91 particles.setPropNames(propNames);
92
93 // 1. particles on the Ellipsoidal surface //phi=u theta=v
94 double theta{0.0},phi{0.0};
95 double dtheta{M_PI/double(n-1)};
96 double dphi{2*M_PI/double(2.0*n-1)};
97 double Golden_angle=M_PI * (3.0 - sqrt(5.0));
98 if (v_cl.rank() == 0) {
99 for(int i=0;i<n;i++)
100 {for(int j=0;j<2*n-1;j++)
101 {
102 particles.add();
103 double xp=a*std::sin(theta)*std::cos(phi);
104 double yp=b*std::sin(theta)*std::sin(phi);
105 double zp=c*std::cos(theta);
106 particles.getLastPos()[0] = xp;
107 particles.getLastPos()[1] = yp;
108 particles.getLastPos()[2] = zp;
109 particles.getLastProp<POS>()[0] = xp;
110 particles.getLastProp<POS>()[1] = yp;
111 particles.getLastProp<POS>()[2] = zp;
112 double rm=sqrt(4*(xp*xp/(a*a*a*a)+yp*yp/(b*b*b*b)+zp*zp/(c*c*c*c)));
113 particles.getLastProp<F>() = 0;
114 particles.getLastProp<NORMAL>()[0] = 2*xp/(a*a*rm);
115 particles.getLastProp<NORMAL>()[1] = 2*yp/(b*b*rm);
116 particles.getLastProp<NORMAL>()[2] = 2*zp/(c*c*rm);
117 particles.getLastProp<PCOORD>()[0] = 0;
118 particles.getLastProp<PCOORD>()[1] = theta;
119 particles.getLastProp<PCOORD>()[2] = phi;
120 particles.getLastProp<ANADF>() = (a*b*c)*(3*(a*a+b*b)+2*c*c+(a*a+b*b-2*c*c)*std::cos(2*theta)-2*(a*a-b*b)*std::cos(2*phi)*std::sin(theta)*std::sin(theta))/(8*openfpm::math::intpowlog(sqrt((a*a*b*b*std::cos(theta)*std::cos(theta)+c*c*(b*b*std::cos(phi)*std::cos(phi)+a*a*std::sin(phi)*std::sin(phi))*std::sin(theta)*std::sin(theta))),3));
121 particles.getLastProp<ANAG>() = (a*a*b*b*c*c)/(openfpm::math::intpowlog((a*a*b*b*std::cos(theta)*std::cos(theta)+c*c*(b*b*std::cos(phi)*std::cos(phi)+a*a*std::sin(phi)*std::sin(phi))*std::sin(theta)*std::sin(theta)),2));
122 particles.getLastSubset(0);
123 phi += dphi;
124 if(i==0 || i==n-1)
125 { break;}
126 }
127 theta+=dtheta;
128 }
129 std::cout << "n: " << n*2*n << " - grid spacing: " << grid_spacing << " - rCut: " << rCut << "Nspacing" << grid_spacing_surf<< " - dTheta: "<<dtheta<<" - dPhi: "<<dphi <<std::endl;
130 }
131
132 particles.map();
135 particles.write_frame("p_output",BINARY);
137 vector_dist_subset<3,double,prop> particles_boundary(particles,1);
138 auto &bulkIds=particles_bulk.getIds();
139 auto &bdrIds=particles_boundary.getIds();
140
141 auto DErr=getV<ERR>(particles);
142 auto Af=getV<ANADF>(particles);
143 auto Df=getV<DF>(particles);
144 auto f=getV<F>(particles);
145 auto N=getV<NORMAL>(particles);
146 auto Pos=getV<POS>(particles);
147 auto CurvTensor=getV<CURVT>(particles);
148 particles.ghost_get<F,NORMAL,POS>();
149 SurfaceDerivative_x<NORMAL> Sdx{particles,ord,rCut,grid_spacing_surf};
150 SurfaceDerivative_y<NORMAL> Sdy{particles,ord,rCut,grid_spacing_surf};
151 SurfaceDerivative_z<NORMAL> Sdz{particles,ord,rCut,grid_spacing_surf};
152
153 auto Na=Sdx(N[0]),Nb=Sdy(N[0]),Nc=Sdz(N[0]),
154 Nd=Sdx(N[1]),Ne=Sdy(N[1]),Nf=Sdz(N[1]),
155 Ng=Sdx(N[2]),Nh=Sdy(N[2]),Ni=Sdz(N[2]);
156 //SurfaceDerivative_xx<NORMAL> Sdxx{particles,2,rCut,grid_spacing_surf};
157 //SurfaceDerivative_yy<NORMAL> Sdyy{particles,2,rCut,grid_spacing_surf};
158 //SurfaceDerivative_zz<NORMAL> Sdzz{particles,2,rCut,grid_spacing_surf};
159 f=(Na+Ne+Ni)/2.0; //2H=-Div(n_hat) //Note that sign of the normal matters. in our case it is negative.
160 //f=-0.5*((Sdxx(Pos[0])+Sdyy(Pos[0])+Sdzz(Pos[0]))*N[0]+(Sdxx(Pos[1])+Sdyy(Pos[1])+Sdzz(Pos[1]))*N[1]+(Sdxx(Pos[2])+Sdyy(Pos[2])+Sdzz(Pos[2]))*N[2]);
161 //Df=(Na*Ne*Ni - Na*Nf*Nh - Nb*Nd*Ni + Nb*Nf*Ng + Nc*Nd*Nh - Nc*Ne*Ng); This doesnt work because there is a 0 eigen value
162
163 CurvTensor[0][0]=Na;
164 CurvTensor[0][1]=Nb;
165 CurvTensor[0][2]=Nc;
166 CurvTensor[1][0]=Nd;
167 CurvTensor[1][1]=Ne;
168 CurvTensor[1][2]=Nf;
169 CurvTensor[2][0]=Ng;
170 CurvTensor[2][1]=Nh;
171 CurvTensor[2][2]=Ni;
172
174 while(it.isNext())
175 {
176 auto p=it.get();
177 typedef EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> MatrixType;
178 MatrixType CT(3, 3);
179 for(int i=0;i<3;i++)
180 {
181 for(int j=0;j<3;j++)
182 {CT(i, j)= particles.getProp<CURVT>(p)[i][j];}
183 }
184 //Eigen::EigenSolver<MatrixType> es(CT);
185 double a=CT.eigenvalues()[0].real(),b=CT.eigenvalues()[1].real(),c=CT.eigenvalues()[2].real();
186 if (a > c) std::swap(a, c);
187 if (a > b) std::swap(a, b);
188 if (b > c) std::swap(b, c);
189 //std::cout<<"\nEigs: "<<CT.eigenvalues();
190 particles.getProp<PCURV>(p)[0]=c;
191 particles.getProp<PCURV>(p)[1]=b;
192 particles.getProp<PCURV>(p)[2]=a;
193 particles.getProp<DF>(p)=b*c;
194 ++it;
195 }
196
198 particles.write_frame(p_output,0,BINARY);
199 /*DCPSE_scheme<equations3d1, decltype(particles)> Solver(particles);
200 auto Eig = Sdxx(f)+Sdyy(f)+Sdzz(f)+K*(K+1)*f;
201 Solver.impose(Eig, bulkIds, 0);
202 Solver.impose(f, bdrIds, Af);
203 Solver.solve(f);*/
204
205 // Error
206 double MaxError=0,L2=0,MaxErrorG=0,L2G=0;
207 for (int j = 0; j < bulkIds.size(); j++) {
208 auto p = bulkIds.get<0>(j);
209 particles.getProp<ERR>(p) = fabs(particles.getProp<F>(p)-particles.getProp<ANADF>(p));
210 particles.getProp<ERRG>(p) = fabs(particles.getProp<DF>(p)-particles.getProp<ANAG>(p));
211 if (particles.getProp<ERR>(p)>MaxError){
212 MaxError=particles.getProp<ERR>(p);
213 }
214 if (particles.getProp<ERRG>(p)>MaxErrorG){
215 MaxErrorG=particles.getProp<ERRG>(p);
216 }
217 L2+=particles.getProp<ERR>(p)*particles.getProp<ERR>(p);
218 L2G+=particles.getProp<ERRG>(p)*particles.getProp<ERRG>(p);
219 }
220 v_cl.sum(L2);
221 v_cl.sum(L2G);
222 v_cl.max(MaxError);
223 v_cl.max(MaxErrorG);
224 v_cl.execute();
225 L2=sqrt(L2);
226 L2G=sqrt(L2G);
227 std::cout.precision(16);
228 if (v_cl.rank()==0){
229 std::cout<<"Mean Curvature L2:"<<L2<<std::endl;
230 std::cout<<"Mean Curvature L_inf:"<<MaxError<<std::endl;
231 std::cout<<"Gauss Curvature L2:"<<L2G<<std::endl;
232 std::cout<<"Gauss Curvature L_inf:"<<MaxErrorG<<std::endl;
233 }
235 particles.write(p_output,BINARY);
236 //Sdxx.deallocate(particles);
237 //Sdyy.deallocate(particles);
238 //Sdzz.deallocate(particles);
239
240 tt.stop();
241 if (v_cl.rank() == 0)
242 std::cout << "Simulation took: " << tt.getcputime() << " s (CPU) - " << tt.getwct() << " s (wall)\n";
243
244 openfpm_finalize();
245 return 0;
246
247}
Header file containing functions for creating files and folders.
static void create_directory_if_not_exist(std::string path, bool silent=0)
Creates a directory if not already existent.
This class represent an N-dimensional box.
Definition Box.hpp:61
This class implement the point shape in an N-dimensional space.
Definition Point.hpp:28
Implementation of 1-D std::vector like structure.
Class for cpu time benchmarking.
Definition timer.hpp:28
void stop()
Stop the timer.
Definition timer.hpp:119
double getcputime()
Return the cpu time.
Definition timer.hpp:142
void start()
Start the timer.
Definition timer.hpp:90
double getwct()
Return the elapsed real time.
Definition timer.hpp:130
vect_dist_key_dx get()
Get the actual key.
Distributed vector.
bool write_frame(std::string out, size_t iteration, int opt=VTK_WRITER)
Output particle position and properties.
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
auto getLastProp() -> decltype(v_prp.template get< id >(0))
Get the property of the last element.
void setPropNames(const openfpm::vector< std::string > &names)
Set the properties names.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
void ghost_get(size_t opt=WITH_POSITION)
It synchronize the properties and position of the ghost particles.
void map(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor.
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 add()
Add local particle.
void deleteGhost()
Delete the particles on the ghost.
[v_transform metafunction]
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...