OpenFPM  5.2.0
Project that contain the implementation of distributed structures
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"
24 #include <util/PathsAndFiles.hpp>
25 
26 std::string p_output;
27 
28 constexpr int DF=0;
29 constexpr int F=1;
30 constexpr int ANADF=2;
31 constexpr int ERR=3;
32 constexpr int NORMAL=4;
33 constexpr int PCOORD=5;
34 constexpr int ANAG=6;
35 constexpr int ERRG=7;
36 constexpr int POS=8;
37 constexpr int CURVT=9;
38 constexpr int PCURV=10;
39 
40 
42 openfpm::vector<std::string> propNames{{"Gauss","Mean","AnaMean","ErrorMean","Normal","PCOORD","AnaGauss","ErrorGauss","Pos","CurvatureTensor","PrincipalCurvature"}};
44 
45 int 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();
133  particles.ghost_get<F>();
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  auto verletList = particles.template getVerlet<VL_NON_SYMMETRIC|VL_SKIP_REF_PART>(rCut);
150  SurfaceDerivative_x<NORMAL,decltype(verletList)> Sdx{particles,verletList,ord,rCut,grid_spacing_surf,rCut/grid_spacing_surf};
151  SurfaceDerivative_y<NORMAL,decltype(verletList)> Sdy{particles,verletList,ord,rCut,grid_spacing_surf,rCut/grid_spacing_surf};
152  SurfaceDerivative_z<NORMAL,decltype(verletList)> Sdz{particles,verletList,ord,rCut,grid_spacing_surf,rCut/grid_spacing_surf};
153 
154  auto Na=Sdx(N[0]),Nb=Sdy(N[0]),Nc=Sdz(N[0]),
155  Nd=Sdx(N[1]),Ne=Sdy(N[1]),Nf=Sdz(N[1]),
156  Ng=Sdx(N[2]),Nh=Sdy(N[2]),Ni=Sdz(N[2]);
157  //SurfaceDerivative_xx<NORMAL> Sdxx{particles,2,rCut,grid_spacing_surf};
158  //SurfaceDerivative_yy<NORMAL> Sdyy{particles,2,rCut,grid_spacing_surf};
159  //SurfaceDerivative_zz<NORMAL> Sdzz{particles,2,rCut,grid_spacing_surf};
160  f=(Na+Ne+Ni)/2.0; //2H=-Div(n_hat) //Note that sign of the normal matters. in our case it is negative.
161  //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]);
162  //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
163 
164  CurvTensor[0][0]=Na;
165  CurvTensor[0][1]=Nb;
166  CurvTensor[0][2]=Nc;
167  CurvTensor[1][0]=Nd;
168  CurvTensor[1][1]=Ne;
169  CurvTensor[1][2]=Nf;
170  CurvTensor[2][0]=Ng;
171  CurvTensor[2][1]=Nh;
172  CurvTensor[2][2]=Ni;
173 
174  auto it=particles.getDomainIterator();
175  while(it.isNext())
176  {
177  auto p=it.get();
178  typedef EMatrix<double, Eigen::Dynamic, Eigen::Dynamic> MatrixType;
179  MatrixType CT(3, 3);
180  for(int i=0;i<3;i++)
181  {
182  for(int j=0;j<3;j++)
183  {CT(i, j)= particles.getProp<CURVT>(p)[i][j];}
184  }
185  //Eigen::EigenSolver<MatrixType> es(CT);
186  double a=CT.eigenvalues()[0].real(),b=CT.eigenvalues()[1].real(),c=CT.eigenvalues()[2].real();
187  if (a > c) std::swap(a, c);
188  if (a > b) std::swap(a, b);
189  if (b > c) std::swap(b, c);
190  //std::cout<<"\nEigs: "<<CT.eigenvalues();
191  particles.getProp<PCURV>(p)[0]=c;
192  particles.getProp<PCURV>(p)[1]=b;
193  particles.getProp<PCURV>(p)[2]=a;
194  particles.getProp<DF>(p)=b*c;
195  ++it;
196  }
197 
199  particles.write_frame(p_output,0,BINARY);
200  /*DCPSE_scheme<equations3d1, decltype(particles)> Solver(particles);
201  auto Eig = Sdxx(f)+Sdyy(f)+Sdzz(f)+K*(K+1)*f;
202  Solver.impose(Eig, bulkIds, 0);
203  Solver.impose(f, bdrIds, Af);
204  Solver.solve(f);*/
205 
206  // Error
207  double MaxError=0,L2=0,MaxErrorG=0,L2G=0;
208  for (int j = 0; j < bulkIds.size(); j++) {
209  auto p = bulkIds.get<0>(j);
210  particles.getProp<ERR>(p) = fabs(particles.getProp<F>(p)-particles.getProp<ANADF>(p));
211  particles.getProp<ERRG>(p) = fabs(particles.getProp<DF>(p)-particles.getProp<ANAG>(p));
212  if (particles.getProp<ERR>(p)>MaxError){
213  MaxError=particles.getProp<ERR>(p);
214  }
215  if (particles.getProp<ERRG>(p)>MaxErrorG){
216  MaxErrorG=particles.getProp<ERRG>(p);
217  }
218  L2+=particles.getProp<ERR>(p)*particles.getProp<ERR>(p);
219  L2G+=particles.getProp<ERRG>(p)*particles.getProp<ERRG>(p);
220  }
221  v_cl.sum(L2);
222  v_cl.sum(L2G);
223  v_cl.max(MaxError);
224  v_cl.max(MaxErrorG);
225  v_cl.execute();
226  L2=sqrt(L2);
227  L2G=sqrt(L2G);
228  std::cout.precision(16);
229  if (v_cl.rank()==0){
230  std::cout<<"Mean Curvature L2:"<<L2<<std::endl;
231  std::cout<<"Mean Curvature L_inf:"<<MaxError<<std::endl;
232  std::cout<<"Gauss Curvature L2:"<<L2G<<std::endl;
233  std::cout<<"Gauss Curvature L_inf:"<<MaxErrorG<<std::endl;
234  }
236  particles.write(p_output,BINARY);
237  //Sdxx.deallocate(particles);
238  //Sdyy.deallocate(particles);
239  //Sdzz.deallocate(particles);
240 
241  tt.stop();
242  if (v_cl.rank() == 0)
243  std::cout << "Simulation took: " << tt.getcputime() << " s (CPU) - " << tt.getwct() << " s (wall)\n";
244 
245  openfpm_finalize();
246  return 0;
247 
248 }
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:60
Definition: Ghost.hpp:40
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:28
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
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(vPrp.template get< id >(vec_key.getKey()))
Get the property of an 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 getLastProp() -> decltype(vPrp.template get< id >(0))
Get the property of the last element.
void add()
Add local particle.
void deleteGhost()
Delete the particles on the ghost.
auto getLastPos() -> decltype(vPos.template get< 0 >(0))
Get the position of the last element.
[v_transform metafunction]
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:221