OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
main.cpp
1/*
2 * ### WIKI 1 ###
3 *
4 * ## Simple example
5 *
6 * In this example we show 1D PSE derivative function approximation
7 *
8 * ### WIKI END ###
9 *
10 */
11
12#include "Vector/vector_dist.hpp"
13#include "Decomposition/CartDecomposition.hpp"
14#include "PSE/Kernels.hpp"
15#include "data_type/aggregate.hpp"
16#include <cmath>
17
18
19/*
20 * ### WIKI 2 ###
21 *
22 * Here we define the function x*e^(-x*x) and its
23 * second derivative in analytic form
24 *
25 * 2x*(2*x-3)*e^(-x^2)
26 *
27 */
28
29double f_xex2(double x)
30{
31 return x*exp(-x*x);
32}
33
34double f_xex2(Point<1,double> & x)
35{
36 return x.get(0)*exp(-x.get(0)*x.get(0));
37}
38
39double Lapf_xex2(Point<1,double> & x)
40{
41 return 2.0*x.get(0)*(2.0*x.get(0)*x.get(0) - 3.0)*exp(-x.get(0)*x.get(0));
42}
43
44/*
45 *
46 * ### WIKI END ###
47 *
48 */
49
50int main(int argc, char* argv[])
51{
52 //
53 // ### WIKI 3 ###
54 //
55 // Some useful parameters. Like
56 //
57 // * Number of particles
58 // * Minimum number of padding particles
59 // * The computational domain
60 // * The spacing
61 // * The mollification length
62 // * Second order Laplacian kernel in 1D
63 //
64
65 // Number of particles
66 const size_t Npart = 125;
67
68 // Number of padding particles (At least)
69 const size_t Npad = 40;
70
71 // The domain
72 Box<1,double> box({0.0},{4.0});
73
74 // Calculated spacing
75 double spacing = box.getHigh(0) / Npart;
76
77 // Epsilon of the particle kernel
78 const double eps = 2*spacing;
79
80 // Laplacian PSE kernel 1 dimension, on double, second order
81 Lap_PSE<1,double,2> lker(eps);
82
83 //
84 // ### WIKI 2 ###
85 //
86 // Here we Initialize the library and we define Ghost size
87 // and non-periodic boundary conditions
88 //
89 openfpm_init(&argc,&argv);
90 Vcluster<> & v_cl = create_vcluster();
91
92 size_t bc[1]={NON_PERIODIC};
93 Ghost<1,double> g(12*eps);
94
95 //
96 // ### WIKI 3 ###
97 //
98 // Here we are creating a distributed vector defined by the following parameters
99 //
100 // we create a set of N+1 particles to have a fully covered domain of particles between 0.0 and 4.0
101 // Suppose we have a spacing given by 1.0 you need 4 +1 particles to cover your domain
102 //
103 vector_dist<1,double, aggregate<double> > vd(Npart+1,box,bc,g);
104
105 //
106 // ### WIKI 4 ###
107 //
108 // We assign the position to the particles, the scalar property is set to
109 // the function x*e^(-x*x) value.
110 // Each processor has parts of the particles and fill part of the space, the
111 // position is assigned independently from the decomposition.
112 //
113 // In this case, if there are 1001 particles and 3 processors the in the
114 // domain from 0.0 to 4.0
115 //
116 // * processor 0 place particles from 0.0 to 1.332 (334 particles)
117 // * processor 1 place particles from 1.336 to 2.668 (334 particles)
118 // * processor 2 place particles from 2.672 to 4.0 (333 particles)
119 //
120
121 // It return how many particles the processors with id < rank has in total
122 size_t base = vd.init_size_accum(Npart+1);
123 auto it2 = vd.getIterator();
124
125 while (it2.isNext())
126 {
127 auto key = it2.get();
128
129 // set the position of the particles
130 vd.getPos(key)[0] = (key.getKey() + base) * spacing;
131 //set the property of the particles
132 vd.template getProp<0>(key) = f_xex2((key.getKey() + base) * spacing);
133
134 ++it2;
135 }
136
137 //
138 // ### WIKI 5 ###
139 //
140 // Once defined the position, we distribute them across the processors
141 // following the decomposition, finally we get the ghost part
142 //
143 vd.map();
144 vd.ghost_get<0>();
145
146 //
147 // ### WIKI 6 ###
148 //
149 // near the boundary we have two options, or we use one sided kernels,
150 // or we add additional particles, it is required that such particles
151 // produces a 2 time differentiable function. In order to obtain such
152 // result we extend for x < 0.0 and x > 4.0 with the test function xe^(-x*x).
153 //
154 // Note that for x < 0.0 such extension is equivalent to mirror the
155 // particles changing the sign of the strength
156 //
157 // \verbatim
158 //
159 // 0.6 -0.5 0.5 0.6 Strength
160 // +----+----*----*----*-
161 // 0.0 Position
162 //
163 // with * = real particle
164 // + = mirror particle
165 //
166 // \endverbatim
167 //
168 //
169 Box<1,double> m_pad({0.0},{0.1});
170 Box<1,double> m_pad2({3.9},{4.0});
171 double enlarge = 0.1;
172
173 // Create a box
174 if (Npad * spacing > 0.1)
175 {
176 m_pad.setHigh(0,Npad * spacing);
177 m_pad2.setLow(0,4.0 - Npad*spacing);
178 enlarge = Npad * spacing;
179 }
180
181 auto it = vd.getDomainIterator();
182
183 while (it.isNext())
184 {
185 auto key = it.get();
186
187 // set the position of the particles
188 if (m_pad.isInsideNB(vd.getPos(key)) == true)
189 {
190 vd.add();
191 vd.getLastPos()[0] = - vd.getPos(key)[0];
192 vd.template getLastProp<0>() = - vd.template getProp<0>(key);
193 }
194
195 // set the position of the particles
196 if (m_pad2.isInsideNB(vd.getPos(key)) == true)
197 {
198 vd.add();
199 vd.getLastPos()[0] = 2.0 * box.getHigh(0) - vd.getPos(key)[0];
200 vd.template getLastProp<0>() = f_xex2(vd.getLastPos()[0]);
201 }
202
203 ++it;
204 }
205
206 //
207 // ### WIKI 7 ###
208 //
209 // We create a CellList with cell spacing 12 sigma
210 //
211
212 // get and construct the Cell list
213
214 Ghost<1,double> gp(enlarge);
215 auto cl = vd.getCellList(12*eps,gp);
216
217 // Maximum infinity norm
218 double linf = 0.0;
219
220 //
221 // ### WIKI 8 ###
222 //
223 // For each particle get the neighborhood of each particle
224 //
225 // This cycle is literally the formula from PSE operator approximation
226 //
227 // \$ \frac{1}{\epsilon^{2}} h (u_{q} - u_{p}) \eta_{\epsilon}(x_q - x_p) \$
228 //
229
230 auto it_p = vd.getDomainIterator();
231 while (it_p.isNext())
232 {
233 // double PSE integration accumulator
234 double pse = 0;
235
236 // key
237 vect_dist_key_dx key = it_p.get();
238
239 // Get the position of the particles
240 Point<1,double> p = vd.getPos(key);
241
242 // We are not interested in calculating out the domain
243 // note added padding particle are considered domain particles
244 if (p.get(0) < 0.0 || p.get(0) >= 4.0)
245 {
246 ++it_p;
247 continue;
248 }
249
250 // Get f(x) at the position of the particle
251 double prp_x = vd.template getProp<0>(key);
252
253 // Get the neighborhood of the particles
254 auto NN = cl.template getNNIterator<NO_CHECK>(cl.getCell(p));
255 while(NN.isNext())
256 {
257 auto nnp = NN.get();
258
259 // Calculate contribution given by the kernel value at position p,
260 // given by the Near particle
261 if (nnp != key.getKey())
262 {
263 // W(x-y)
264 double ker = lker.value(p,vd.getPos(nnp));
265
266 // f(y)
267 double prp_y = vd.template getProp<0>(nnp);
268
269 // 1.0/(eps)^2 [f(y)-f(x)]*W(x,y)*V_q
270 double prp = 1.0/eps/eps * (prp_y - prp_x) * spacing;
271 pse += prp * ker;
272 }
273
274 // Next particle
275 ++NN;
276 }
277
278 // Here we calculate the L_infinity norm or the maximum difference
279 // of the analytic solution from the PSE calculated
280
281 double sol = Lapf_xex2(p);
282
283 if (fabs(pse - sol) > linf)
284 linf = fabs(pse - sol);
285
286 ++it_p;
287 }
288
289 //
290 // ### WIKI 9 ###
291 //
292 // Calculate the maximum infinity norm across processors and
293 // print it
294 //
295
296 v_cl.max(linf);
297 v_cl.execute();
298
299 if (v_cl.getProcessUnitID() == 0)
300 std::cout << "Norm infinity: " << linf << "\n";
301
302 //
303 // ### WIKI 10 ###
304 //
305 // Deinitialize the library
306 //
307 openfpm_finalize();
308}
This class represent an N-dimensional box.
Definition Box.hpp:61
__device__ __host__ T getHigh(int i) const
get the high interval of the box
Definition Box.hpp:567
__device__ __host__ void setHigh(int i, T val)
set the high interval of the box
Definition Box.hpp:544
This class implement the point shape in an N-dimensional space.
Definition Point.hpp:28
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition Point.hpp:172
void execute()
Execute all the requests.
size_t getProcessUnitID()
Get the process unit id.
void max(T &num)
Get the maximum number across all processors (or reduction with infinity norm)
Implementation of VCluster class.
Definition VCluster.hpp:59
Grid key for a distributed grid.
__device__ __host__ size_t getKey() const
Get the key.
Distributed vector.
Implementation of the Laplacian kernels for PSE.
Definition Kernels.hpp:26