OpenFPM  5.2.0
Project that contain the implementation of distributed structures
Bump.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 <util/PathsAndFiles.hpp>
23 #include "OdeIntegrators/OdeIntegrators.hpp"
24 
25 void *PointerGlobal, *Pointer2Bulk,*Pointer2Boundary;
26 
27 typedef aggregate<double,double,Point<3,double>,double,double> prop;
30 
31 constexpr int CONC=0;
32 constexpr int DCONC=1;
33 constexpr int NORMAL=2;
34 constexpr int COLD=3;
35 openfpm::vector<std::string> propNames{{"Concentration","DConc","Normal","Conc_old","Error"}};
36 
37 double dt,tf,max_steady_tol;
38 int wr_at;
39 constexpr int dim=3;
40 
41 template<int dim>
42 struct bump {
43  const Point<2,double> & center;
44  const double alpha;
45  const double radius;
46  const double threshold;
47 };
48 
49 template <int dim>
50 double f( Point<3,double> coord,
51 bump<dim> & surf) {
52 
53 double arg, arg2;
54 
55 arg = 0.0;
56 for (int d = 0; d < dim-1; ++d)
57 arg += (coord[d]-surf.center[d])*(coord[d]-surf.center[d]);
58 arg2 = arg/(surf.radius*surf.radius);
59 
60 if (arg2 < (1 - surf.threshold)*(1 - surf.threshold))
61 return surf.alpha * std::exp(-1.0/(1.0-arg2));
62 else
63 return 0.0;
64 }
65 
66 template<int dim>
67 Point<3,double> init_normal(Point<3,double> coord,
68  bump<dim> & surf) {
69 
70  Point<3,double> normal;
71  double x, y, dist, arg, prefactor, norm_grad;
72  const double r2{surf.radius*surf.radius};
73 
74  dist = 0.0;
75  for (int d = 0; d < dim-1; ++d)
76  dist += (coord[d]-surf.center[d])*(coord[d]-surf.center[d]);
77 
78  if (std::fabs(dist - r2) < 1e-10)
79  arg = r2 / 1e-10;
80  else
81  arg = r2 / (dist - r2);
82 
83  x = coord[0]-surf.center[0];
84  y = coord[1]-surf.center[1];
85  prefactor = - 2.0 * f<dim>(coord,surf) * arg*arg / r2;
86 
87  norm_grad = std::sqrt(4.0 * f<dim>(coord,surf)*f<dim>(coord,surf) * arg*arg*arg*arg * dist / (r2*r2) + 1.0);
88 
89  normal[0] = - prefactor * x / norm_grad;
90  normal[1] = - prefactor * y / norm_grad;
91  normal[2] = 1.0 / norm_grad;
92 
93  double mag=sqrt(normal[0]*normal[0]+normal[1]*normal[1]+normal[2]*normal[2]);
94  normal=normal/mag;
95 
96  return normal;
97 }
98 
99 Point<3,double> SurfaceNormal(double &x,double &y,double &z,double alpha){
100  Point<3,double> Normal={0,0,1};
101  double dist=sqrt((x+0.5)*(x+0.5)+y*y);
102  if(dist>(1.0-0.025))
103  {
104  return Normal;
105  }
106  else{
107  dist=dist/0.25;
108  double norm_grad = -alpha*2*dist*exp(-1./(1.-dist*dist)*1./((1.-dist*dist)*(1.-dist*dist)));
109  Normal[0]=x;
110  Normal[1]=y;
111  Normal[2]=4.0*z*norm_grad*(0.5/dist)*(2*(x+0.5)+2*y);
112  return Normal/Normal.distance(Normal);
113  }
114  }
115 
116 template<typename DXX,typename DYY,typename DZZ>
117 struct RHSFunctor
118 {
119  //Intializing the operators
120  DXX &SDxx;
121  DYY &SDyy;
122  DZZ &SDzz;
123  //Constructor
124  RHSFunctor(DXX &SDxx,DYY &SDyy,DZZ &SDzz):SDxx(SDxx),SDyy(SDyy),SDzz(SDzz)
125  {}
126 
127  void operator()( const state_type_1d_ofp &X , state_type_1d_ofp &dxdt , const double t ) const
128  {
129  //Casting the pointers to OpenFPM vector distributions
130  vector_type &Particles= *(vector_type *) PointerGlobal;
131  subset_type &Particles_bulk= *(subset_type *) Pointer2Bulk;
132 
133  //Aliasing the properties.
134  auto C = getV<CONC>(Particles);
135  auto C_bulk = getV<CONC>(Particles_bulk);
136  auto dC = getV<DCONC>(Particles);
137  auto dC_bulk = getV<DCONC>(Particles_bulk);
138  C_bulk=X.data.get<0>();
139  Particles.ghost_get<CONC>();
140 
141  // We do the RHS computations for the Laplacian (Updating bulk only).
142  dC_bulk = (SDxx(C)+SDyy(C)+SDzz(C));
143 
144  //We copy back to the dxdt state_type for Odeint
145  dxdt.data.get<0>()=dC;
146  }
147 };
148 
149 struct ObserverFunctor {
150  int ctr;
151  int wctr;
152  double t_old;
153  //Constructor
154  ObserverFunctor(){
155  //a counter for counting the np. of steps
156  ctr = 0;
157  wctr= 0;
158  //Starting with t=0, we compute the step size take by t-t_old. So for the first observed step size is what we provide. Which will be 0-(-dt)=dt.
159  t_old = -dt;
160  }
161  void operator()(state_type_1d_ofp &X, double t) {
162  //Casting the pointers to OpenFPM vector distributions
163  auto & v_cl = create_vcluster();
164  vector_type &Particles = *(vector_type *) PointerGlobal;
165  subset_type &Particles_bulk = *(subset_type *) Pointer2Bulk;
166  auto &bulk=Particles_bulk.getIds();
167  auto Concentration = getV<CONC>(Particles);
168  auto Concentration_old = getV<COLD>(Particles);
169  auto Concentration_bulk = getV<CONC>(Particles_bulk);
170  Concentration_bulk = X.data.get<0>();
171  if (v_cl.rank() == 0) {
172  std::cout << "Time step " << ctr << " : " << t << " over." <<"dt is set to: "<<(t-t_old)<< std::endl;
173  std::cout << "----------------------------------------------------------" << std::endl;
174  }
175  if(ctr%wr_at==0){
176  Particles.deleteGhost();
177  Particles.write_frame("ERDiff", wctr,t,BINARY);
178  Particles.ghost_get<0>();
179  wctr++;
180  }
181  double MaxRateOfChange=0;
182  for (int j = 0; j < bulk.size(); j++) {
183  auto p = bulk.get<0>(j);
184  if(Particles.getProp<CONC>(p)<0){
185  Particles.getProp<CONC>(p)=0;
186  }
187  if(fabs(Particles.getProp<CONC>(p)-Particles.getProp<COLD>(p))>MaxRateOfChange)
188  {
189  MaxRateOfChange=fabs(Particles.getProp<CONC>(p)-Particles.getProp<COLD>(p));
190  }
191  }
192  v_cl.max(MaxRateOfChange);
193  v_cl.execute();
194  if(v_cl.rank()==0)
195  {std::cout<<"MaxRateOfChange: "<<MaxRateOfChange<<std::endl;
196  }
197  if(MaxRateOfChange<max_steady_tol && ctr>5)
198  {
199  std::cout<<"Steady State Reached."<<std::endl;
200  openfpm_finalize();
201  exit(0);
202  }
203  Concentration_old=Concentration;
204  Particles.ghost_get<0>();
205  ctr++;
206  t_old=t;
207  X.data.get<0>()=Concentration;
208  }
209 };
210 
211 int main(int argc, char * argv[]) {
212  openfpm_init(&argc,&argv);
213  auto & v_cl = create_vcluster();
214  timer tt;
215  tt.start();
216  double grid_spacing_surf;
217  double rCut,SCF,alph;
218  bool DCPSE_LOAD;
219 
220  // Get command line arguments
221  std::ifstream PCfile;
222  if (argc < 9) {
223  std::cout << "Error: Not exact no. of args." << std::endl;
224  return 0;
225  }
226  else {
227  grid_spacing_surf=0.03125;
228  PCfile.open(argv[1]);
229  tf=std::stof(argv[2]);
230  dt=std::stof(argv[3]);
231  wr_at=std::stoi(argv[4]);
232  max_steady_tol=std::stof(argv[5]);
233  SCF=std::stof(argv[6]);
234  alph=std::stof(argv[7]);
235  DCPSE_LOAD=std::stof(argv[8]);
236  }
237 
238  rCut=3.1*grid_spacing_surf;
239 
240  Box<3,double> domain{{-2.5,-2.5,-2.5},{2.5,2.5,2.5}};
241  size_t bc[3] = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
242  Ghost<3,double> ghost{rCut + grid_spacing_surf/8.0};
243  struct bump<dim> surf = {.center= Point<dim-1,double>{-0.5,0.0}, .alpha=alph, .radius=0.25, .threshold=0.025};
244 
245  // particles
246  vector_type particles{0,domain,bc,ghost};
247  particles.setPropNames(propNames);
248  double uconc,Nx,Ny,Nz,Px,Py,Pz;
249  if(v_cl.rank()==0){
250  int pctr=0;
251  while ( PCfile >>uconc>> Px >> Py >> Pz)
252  {
253  particles.add();
254  particles.getLastPos()[0]=Px;
255  particles.getLastPos()[1]=Py;
256  particles.getLastPos()[2]=Pz;
257  particles.getLastProp<CONC>()=uconc;
258  particles.getLastProp<COLD>()=sin(2*Px)*sin(2*Py);
259  particles.getLastProp<DCONC>()=-8*sin(2*Px)*sin(2*Py);
260  particles.getLastProp<NORMAL>()=init_normal<dim>(particles.getLastPos(),surf);
261 
262  particles.getLastSubset(0);
263  if(Px<-2+1e-3){
264  particles.getLastSubset(1);
265  }
266  else if(Px>2-1e-3){
267  particles.getLastSubset(1);
268  }
269  else if(Py<-2+1e-3){
270  particles.getLastSubset(1);
271  }
272  else if(Py>2-1e-3){
273  particles.getLastSubset(1);
274  }
275 
276  ++pctr;
277  }
278  std::cout << "n: " << pctr << " - rCut: " << rCut << " - nSpacing: " << grid_spacing_surf<<" - Final Time: "<<tf<<" - Initial DT: "<<dt<<std::endl;
279  }
280 
281  particles.map();
282  particles.ghost_get<CONC>();
284  particles.write("Init",BINARY);
286  vector_dist_subset<3,double,prop> particles_boundary(particles,1);
287  auto &bulk=particles_boundary.getIds();
288  auto C=getV<CONC>(particles);
289  auto DC=getV<DCONC>(particles);
290  auto C_old=getV<COLD>(particles);
291 
292 
293  //DC=0;
294  timer ttt;
295  ttt.start();
297  support_options opt;
298  if(DCPSE_LOAD){
299  opt=support_options::LOAD;
300  }
301  else
302  {
303  opt=support_options::ADAPTIVE;
304  }
305  auto verletList = particles.template getVerlet<VL_NON_SYMMETRIC|VL_SKIP_REF_PART>(rCut);
306  SurfaceDerivative_xx<NORMAL,decltype(verletList)> Sdxx{particles,verletList,2,rCut,SCF,rCut/SCF,opt};
307  SurfaceDerivative_yy<NORMAL,decltype(verletList)> Sdyy{particles,verletList,2,rCut,SCF,rCut/SCF,opt};
308  SurfaceDerivative_zz<NORMAL,decltype(verletList)> Sdzz{particles,verletList,2,rCut,SCF,rCut/SCF,opt};
309  if(DCPSE_LOAD){
310  Sdxx.load(particles,"DCPSE/Dxx");
311  Sdyy.load(particles,"DCPSE/Dyy");
312  Sdzz.load(particles,"DCPSE/Dzz");
313  }
314  else{
315  Sdxx.save(particles,"DCPSE/Dxx");
316  Sdyy.save(particles,"DCPSE/Dyy");
317  Sdzz.save(particles,"DCPSE/Dzz");
318  }
319  /*DC=0;
320  C=0;
321  C_old=0;
322  auto itNNN=particles.getDomainIterator();
323  while(itNNN.isNext()){
324  auto p=itNNN.get().getKey();
325  Point<3,double> xp=particles.getPos(p);
326  if(xp.distance(0)<1e-2)
327  {
328  Sdxx.DrawKernel<CONC,vector_type>(p);
329  Sdyy.DrawKernel<COLD,vector_type>(p);
330  Sdzz.DrawKernel<DCONC,vector_type>(p);
331  particles.write_frame("Kernel",p);
332  DC=0;
333  C=0;
334  C_old=0;
335  }
336  ++itNNN;
337  }*/
338  ttt.stop();
339  if(v_cl.rank()==0)
340  std::cout<<"DCPSE Time: "<<tt.getwct()<<" seconds."<<std::endl;
341  PointerGlobal = (void *) &particles;
342  Pointer2Bulk = (void *) &particles_bulk;
343  Pointer2Boundary = (void *) &particles_boundary;
344  RHSFunctor<SurfaceDerivative_xx<NORMAL,decltype(verletList)>, SurfaceDerivative_yy<NORMAL,decltype(verletList)>,SurfaceDerivative_zz<NORMAL,decltype(verletList)>> System(Sdxx,Sdyy,Sdzz);
345  ObserverFunctor Obs;
347  X.data.get<0>() = C;
348 
349  particles.ghost_get<COLD>();
350  //C=Sdxx(C_old)+Sdyy(C_old)+Sdzz(C_old);
351 
352  double worst1 = 0.0;
353 
354  for(int j=0;j<bulk.size();j++)
355  { auto p=bulk.get<0>(j);
356  if (fabs(particles.getProp<DCONC>(p) - particles.getProp<CONC>(p)) >= worst1) {
357  worst1 = fabs(particles.getProp<DCONC>(p) - particles.getProp<CONC>(p));
358  }
359  particles.getProp<4>(p) = fabs(particles.getProp<DCONC>(p) - particles.getProp<CONC>(p));
360 
361  }
362  std::cout << "Maximum Analytic Error: " << worst1 << std::endl;
363  DC=0;
364  //boost::numeric::odeint::adaptive_adams_bashforth_moulton<2, state_type_1d_ofp,double,state_type_1d_ofp,double,boost::numeric::odeint::vector_space_algebra_ofp > abmA;
365  //size_t steps=boost::numeric::odeint::integrate_adaptive(boost::numeric::odeint::make_controlled(max_steady_tol*0.1,max_steady_tol*0.1,abmA),System,X,0.0,tf,dt,Obs);
366  boost::numeric::odeint::euler< state_type_1d_ofp,double,state_type_1d_ofp,double,boost::numeric::odeint::vector_space_algebra_ofp > Euler;
367  size_t steps=boost::numeric::odeint::integrate_const(Euler,System,X,0.0,tf,dt,Obs);
368 
370  particles.write("Final",BINARY);
371  Sdxx.deallocate(particles);
372  Sdyy.deallocate(particles);
373  Sdzz.deallocate(particles);
374 
375  tt.stop();
376  if (v_cl.rank() == 0)
377  std::cout << "Simulation took: " << tt.getcputime() << " s (CPU) - " << tt.getwct() << " s (wall)\n";
378 
379  openfpm_finalize();
380  return 0;
381 
382 }
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
__device__ __host__ T distance(const Point< dim, T > &q) const
It calculate the distance between 2 points.
Definition: Point.hpp:265
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
openfpm::vector< aggregate< int > > & getIds()
Return the ids.
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.
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 load(const std::string &filename)
Load the distributed vector from an HDF5 file.
void ghost_get_subset()
Stub does not do anything.
void deleteGhost()
Delete the particles on the ghost.
auto getLastPos() -> decltype(vPos.template get< 0 >(0))
Get the position of the last element.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:221
Definition: Bump.cpp:42
A 1d Odeint and Openfpm compatible structure.