OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
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"
23#include "OdeIntegrators/OdeIntegrators.hpp"
24
25void *PointerGlobal, *Pointer2Bulk,*Pointer2Boundary;
26
30
31constexpr int CONC=0;
32constexpr int DCONC=1;
33constexpr int NORMAL=2;
34constexpr int COLD=3;
35openfpm::vector<std::string> propNames{{"Concentration","DConc","Normal","Conc_old","Error"}};
36
37double dt,tf,max_steady_tol;
38int wr_at;
39constexpr int dim=3;
40
41template<int dim>
42struct bump {
43 const Point<2,double> & center;
44 const double alpha;
45 const double radius;
46 const double threshold;
47};
48
49template <int dim>
50double f( Point<3,double> coord,
51bump<dim> & surf) {
52
53double arg, arg2;
54
55arg = 0.0;
56for (int d = 0; d < dim-1; ++d)
57arg += (coord[d]-surf.center[d])*(coord[d]-surf.center[d]);
58arg2 = arg/(surf.radius*surf.radius);
59
60if (arg2 < (1 - surf.threshold)*(1 - surf.threshold))
61return surf.alpha * std::exp(-1.0/(1.0-arg2));
62else
63return 0.0;
64}
65
66template<int dim>
67Point<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
99Point<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
116template<typename DXX,typename DYY,typename DZZ>
117struct 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
149struct ObserverFunctor {
150 int ctr;
151 int wctr;
152 double t_old;
153 //Constructor
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
211int 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>();
283 particles.write("Init",BINARY);
285 vector_dist_subset<3,double,prop> particles_boundary(particles,1);
286 auto &bulk=particles_boundary.getIds();
287 auto C=getV<CONC>(particles);
288 auto DC=getV<DCONC>(particles);
289 auto C_old=getV<COLD>(particles);
290
291
292 //DC=0;
293 timer ttt;
294 ttt.start();
296 support_options opt;
297 if(DCPSE_LOAD){
298 opt=support_options::LOAD;
299 }
300 else
301 {
302 opt=support_options::ADAPTIVE_SURFACE;
303 }
304 SurfaceDerivative_xx<NORMAL> Sdxx{particles,2,rCut,SCF,opt};
305 SurfaceDerivative_yy<NORMAL> Sdyy{particles,2,rCut,SCF,opt};
306 SurfaceDerivative_zz<NORMAL> Sdzz{particles,2,rCut,SCF,opt};
307 if(DCPSE_LOAD){
308 Sdxx.load(particles,"DCPSE/Dxx");
309 Sdyy.load(particles,"DCPSE/Dyy");
310 Sdzz.load(particles,"DCPSE/Dzz");
311 }
312 else{
313 Sdxx.save(particles,"DCPSE/Dxx");
314 Sdyy.save(particles,"DCPSE/Dyy");
315 Sdzz.save(particles,"DCPSE/Dzz");
316 }
317 /*DC=0;
318 C=0;
319 C_old=0;
320 auto itNNN=particles.getDomainIterator();
321 while(itNNN.isNext()){
322 auto p=itNNN.get().getKey();
323 Point<3,double> xp=particles.getPos(p);
324 if(xp.distance(0)<1e-2)
325 {
326 Sdxx.DrawKernel<CONC,vector_type>(particles,p);
327 Sdyy.DrawKernel<COLD,vector_type>(particles,p);
328 Sdzz.DrawKernel<DCONC,vector_type>(particles,p);
329 particles.write_frame("Kernel",p);
330 DC=0;
331 C=0;
332 C_old=0;
333 }
334 ++itNNN;
335 }*/
336 ttt.stop();
337 if(v_cl.rank()==0)
338 std::cout<<"DCPSE Time: "<<tt.getwct()<<" seconds."<<std::endl;
339 PointerGlobal = (void *) &particles;
340 Pointer2Bulk = (void *) &particles_bulk;
341 Pointer2Boundary = (void *) &particles_boundary;
342 RHSFunctor<SurfaceDerivative_xx<NORMAL>, SurfaceDerivative_yy<NORMAL>,SurfaceDerivative_zz<NORMAL>> System(Sdxx,Sdyy,Sdzz);
343 ObserverFunctor Obs;
345 X.data.get<0>() = C;
346
347 particles.ghost_get<COLD>();
348 //C=Sdxx(C_old)+Sdyy(C_old)+Sdzz(C_old);
349
350 double worst1 = 0.0;
351
352 for(int j=0;j<bulk.size();j++)
353 { auto p=bulk.get<0>(j);
354 if (fabs(particles.getProp<DCONC>(p) - particles.getProp<CONC>(p)) >= worst1) {
355 worst1 = fabs(particles.getProp<DCONC>(p) - particles.getProp<CONC>(p));
356 }
357 particles.getProp<4>(p) = fabs(particles.getProp<DCONC>(p) - particles.getProp<CONC>(p));
358
359 }
360 std::cout << "Maximum Analytic Error: " << worst1 << std::endl;
361 DC=0;
362 //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;
363 //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);
364 boost::numeric::odeint::euler< state_type_1d_ofp,double,state_type_1d_ofp,double,boost::numeric::odeint::vector_space_algebra_ofp > Euler;
365 size_t steps=boost::numeric::odeint::integrate_const(Euler,System,X,0.0,tf,dt,Obs);
366
368 particles.write("Final",BINARY);
369 Sdxx.deallocate(particles);
370 Sdyy.deallocate(particles);
371 Sdzz.deallocate(particles);
372
373 tt.stop();
374 if (v_cl.rank() == 0)
375 std::cout << "Simulation took: " << tt.getcputime() << " s (CPU) - " << tt.getwct() << " s (wall)\n";
376
377 openfpm_finalize();
378 return 0;
379
380}
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
__device__ __host__ T distance(const Point< dim, T > &q) const
It calculate the distance between 2 points.
Definition Point.hpp:250
System of equations.
Definition System.hpp:24
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
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(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.
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 load(const std::string &filename)
Load the distributed vector from an HDF5 file.
void deleteGhost()
Delete the particles on the ghost.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition Bump.cpp:42
A 1d Odeint and Openfpm compatible structure.