OpenFPM  5.2.0
Project that contain the implementation of distributed structures
Sph.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 
36 openfpm::vector<std::string> propNames{{"Df","f","AnaDf","error","Normal","PCOORD"}};
38 
39 int main(int argc, char * argv[]) {
40  openfpm_init(&argc,&argv);
41  auto & v_cl = create_vcluster();
42  timer tt;
43  tt.start();
44  size_t n;
45  double spL;
46  double grid_spacing_surf;
47  double rCut;
48  constexpr int K = 4;
49  // Get command line arguments
50  if (argc > 3) {
51  std::cout << "Maybe Error: The executable requires the following arguments: number_grid_points order_of_operator" << std::endl;
52  }
53  n = std::stoi(argv[1]);
54  unsigned int ord=std::stoi(argv[2]);
55  //spL=std::stof(argv[2]);
56  //grid_spacing_surf=std::stof(argv[3]);
57  //rCut=std::stof(argv[4]);
58 
59  // Files and directories
60  std::string cwd{boost::filesystem::current_path().string()};
61  std::string output_dir{cwd + "/output_Sphere"};
63  p_output = output_dir + "/particles";
64  size_t n_sp=n;
65  // Domain
66  double boxP1{-1.5}, boxP2{1.5};
67  double boxSize{boxP2 - boxP1};
68  size_t sz[3] = {n,n,n};
69  double grid_spacing{0.8/((std::pow(sz[0],1/3.0)-1))};;//grid_spacing{boxSize/(sz[0]-1)};
70  grid_spacing_surf=grid_spacing;//grid_spacing*50;
71  rCut=2.9 * grid_spacing_surf; //3.1
72 
73  Box<3,double> domain{{boxP1,boxP1,boxP1},{boxP2,boxP2,boxP2}};
74  size_t bc[3] = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
75  Ghost<3,double> ghost{rCut + grid_spacing/8.0};
76 
77  // particles
78  vector_type particles{0,domain,bc,ghost};
79  particles.setPropNames(propNames);
80 
81  Point<3,double> coord;
82  // 1. particles on the Circular surface
83  double theta{0.0};
84  double Golden_angle=M_PI * (3.0 - sqrt(5.0));
85  if (v_cl.rank() == 0) {
86  for(int i=1;i<n_sp-1;i++)
87  {
88  double y = 1.0 - (i /double(n_sp - 1.0)) * 2.0;
89  double radius = sqrt(1 - y * y);
90  double Golden_theta = Golden_angle * i;
91  double x = cos(Golden_theta) * radius;
92  double z = sin(Golden_theta) * radius;
93  particles.add();
94  particles.getLastPos()[0] = x;
95  particles.getLastPos()[1] = y;
96  particles.getLastPos()[2] = z;
97  double rm=sqrt(x*x+y*y+z*z);
98  particles.getLastProp<NORMAL>()[0] = x/rm;
99  particles.getLastProp<NORMAL>()[1] = y/rm;
100  particles.getLastProp<NORMAL>()[2] = z/rm;
101  particles.getLastProp<PCOORD>()[0] = 1.0 ;
102  particles.getLastProp<PCOORD>()[1] = std::atan2(sqrt(x*x+y*y),z);
103  particles.getLastProp<PCOORD>()[2] = std::atan2(y,x);
104  //if((i>n_sp/4.0 && i<=n_sp/4.0+K) || (i>3*n_sp/4.0 && i<=3*n_sp/4.0+K+1))
105  //if(i<20*K+1)
106  double tol=1e-2;
107  if(fabs(particles.getLastProp<PCOORD>()[2])<M_PI+tol && fabs(particles.getLastProp<PCOORD>()[2])>M_PI-tol)
108  {particles.getLastSubset(0);}
109  else if(fabs(particles.getLastProp<PCOORD>()[2])<M_PI/2.+tol && fabs(particles.getLastProp<PCOORD>()[2])>M_PI/2.-tol)
110  {particles.getLastSubset(1);}
111  else if(fabs(particles.getLastProp<PCOORD>()[2])<tol && fabs(particles.getLastProp<PCOORD>()[2])>-tol)
112  {particles.getLastSubset(0);}
113  else
114  {particles.getLastSubset(0);}
115 
116 
117 
118 
119  }
120 
121  double x,y,z;
122  x=0;
123  y=0;
124  z=-1;
125  particles.add();
126  particles.getLastPos()[0] = x;
127  particles.getLastPos()[1] = y;
128  particles.getLastPos()[2] = z;
129  double rm=sqrt(x*x+y*y+z*z);
130  particles.getLastProp<NORMAL>()[0] = x/rm;
131  particles.getLastProp<NORMAL>()[1] = y/rm;
132  particles.getLastProp<NORMAL>()[2] = z/rm;
133  particles.getLastProp<PCOORD>()[0] = 1.0 ;
134  particles.getLastProp<PCOORD>()[1] = std::atan2(sqrt(x*x+y*y),z);
135  particles.getLastProp<PCOORD>()[2] = std::atan2(y,x);
136  particles.getLastSubset(1);
137  x=0;
138  y=0;
139  z=1;
140  particles.add();
141  particles.getLastPos()[0] = x;
142  particles.getLastPos()[1] = y;
143  particles.getLastPos()[2] = z;
144  rm=sqrt(x*x+y*y+z*z);
145  particles.getLastProp<NORMAL>()[0] = x/rm;
146  particles.getLastProp<NORMAL>()[1] = y/rm;
147  particles.getLastProp<NORMAL>()[2] = z/rm;
148  particles.getLastProp<PCOORD>()[0] = 1.0 ;
149  particles.getLastProp<PCOORD>()[1] = std::atan2(sqrt(x*x+y*y),z);
150  particles.getLastProp<PCOORD>()[2] = std::atan2(y,x);
151  particles.getLastSubset(1);
152  std::cout << "n: " << n << " - grid spacing: " << grid_spacing << " - rCut: " << rCut << "YDtheta" << grid_spacing_surf<<std::endl;
153  }
154 
155  particles.map();
156  particles.ghost_get<F>();
157 
159  vector_dist_subset<3,double,prop> particles_boundary(particles,1);
160  auto &bulkIds=particles_bulk.getIds();
161  auto &bdrIds=particles_boundary.getIds();
162  std::unordered_map<const lm,double,key_hash,key_equal> Alm;
163  //Setting max mode l_max
164  //Setting amplitudes to 1
165  for(int l=0;l<=K;l++){
166  for(int m=-l;m<=l;m++){
167  Alm[std::make_tuple(l,m)]=0;
168  }
169  }
170  //2Alm[std::make_tuple(1,0)]=1;
171  Alm[std::make_tuple(K,0)]=1;
172  //Alm[std::make_tuple(3,2)]=1;
173 
174  spL=K;
175  auto it2 = particles.getDomainIterator();
176  while (it2.isNext()) {
177  auto p = it2.get();
178  Point<3, double> xP = particles.getProp<PCOORD>(p);
179  /*double Sum=0;
180  for(int m=-spL;m<=spL;++m)
181  {
182  Sum+=openfpm::math::Y(spL,m,xP[1],xP[2]);
183  }*/
184  //particles.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);;
185  particles.getProp<ANADF>(p)=openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm);
186  particles.getProp<DF>(p)=-(K)*(K+1)*openfpm::math::sumY_Scalar<K>(xP[0],xP[1],xP[2],Alm);
187  ++it2;
188  }
189  auto DErr=getV<ERR>(particles);
190  auto Af=getV<ANADF>(particles);
191  auto Df=getV<DF>(particles);
192  auto f=getV<F>(particles);
193 
194  auto verletList = particles.template getVerlet<VL_NON_SYMMETRIC|VL_SKIP_REF_PART>(rCut);
195 
196  SurfaceDerivative_xx<NORMAL,decltype(verletList)> Sdxx{particles,verletList,ord,rCut,grid_spacing_surf,rCut/grid_spacing_surf};
197  SurfaceDerivative_yy<NORMAL,decltype(verletList)> Sdyy{particles,verletList,ord,rCut,grid_spacing_surf,rCut/grid_spacing_surf};
198  SurfaceDerivative_zz<NORMAL,decltype(verletList)> Sdzz{particles,verletList,ord,rCut,grid_spacing_surf,rCut/grid_spacing_surf};
199 
200  DErr=(Sdxx(Af)+Sdyy(Af)+Sdzz(Af))-f;
202  particles.write_frame(p_output,0,BINARY);
203 
204 
205  DCPSE_scheme<equations3d1, decltype(particles)> Solver(particles);
206  auto Eig = Sdxx(f)+Sdyy(f)+Sdzz(f);//+K*(K+1)*f;
207  Solver.impose(Eig, bulkIds, Df);
208  Solver.impose(f, bdrIds, Af);
209  Solver.solve(f);
210 
211  // Error
212  double MaxError=0,L2=0;
213  for (int j = 0; j < bulkIds.size(); j++) {
214  auto p = bulkIds.get<0>(j);
215  particles.getProp<ERR>(p) = fabs(particles.getProp<F>(p)-particles.getProp<ANADF>(p));
216  if (particles.getProp<ERR>(p)>MaxError){
217  MaxError=particles.getProp<ERR>(p);
218  }
219  L2+=particles.getProp<ERR>(p)*particles.getProp<ERR>(p);
220  }
221  v_cl.sum(L2);
222  v_cl.max(MaxError);
223  v_cl.execute();
224  L2=sqrt(L2);
225  std::cout.precision(16);
226  if (v_cl.rank()==0){
227  std::cout<<"L2:"<<L2<<std::endl;
228  std::cout<<"L_inf:"<<MaxError<<std::endl;
229  }
231  particles.write(p_output,BINARY);
232  Sdxx.deallocate(particles);
233  Sdyy.deallocate(particles);
234  Sdzz.deallocate(particles);
235 
236  tt.stop();
237  if (v_cl.rank() == 0)
238  std::cout << "Simulation took: " << tt.getcputime() << " s (CPU) - " << tt.getwct() << " s (wall)\n";
239 
240  openfpm_finalize();
241  return 0;
242 
243 }
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