OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
dist_map_graph_unit_test.hpp
1#ifndef DIST_MAP_GRAPH_UNIT_TEST_HPP
2#define DIST_MAP_GRAPH_UNIT_TEST_HPP
3
4#include "Graph/DistGraphFactory.hpp"
5#include "Graph/dist_map_graph.hpp"
6#include "Packer_Unpacker/Packer.hpp"
7#include "Packer_Unpacker/Unpacker.hpp"
8
9#define DGRAPH_GS_SIZE 4
10
11struct vx
12{
13 typedef boost::fusion::vector<float[3]> type;
14
17 {
18 static const std::string name[];
19 };
20
22 typedef float s_type;
23
25 type data;
26
28 static const unsigned int x = 0;
30 static const unsigned int max_prop = 1;
31
32 vx()
33 {
34
35 }
36
37 inline vx(const vx & p)
38 {
39 boost::fusion::at_c<0>(data)[0] = boost::fusion::at_c<0>(p.data)[0];
40 boost::fusion::at_c<0>(data)[1] = boost::fusion::at_c<0>(p.data)[1];
41 boost::fusion::at_c<0>(data)[2] = boost::fusion::at_c<0>(p.data)[2];
42 }
43
44 template<unsigned int id> inline auto get() -> decltype(boost::fusion::at_c < id > (data))
45 {
46 return boost::fusion::at_c<id>(data);
47 }
48
49 template<unsigned int id> inline auto get() const -> const decltype(boost::fusion::at_c < id > (data))
50 {
51 return boost::fusion::at_c<id>(data);
52 }
53
54 template<unsigned int dim, typename Mem> inline vx(const encapc<dim, vx, Mem> & p)
55 {
56 this->operator=(p);
57 }
58
59 template<unsigned int dim, typename Mem> inline vx & operator=(const encapc<dim, vx, Mem> & p)
60 {
61 boost::fusion::at_c<0>(data)[0] = p.template get<0>()[0];
62 boost::fusion::at_c<0>(data)[1] = p.template get<0>()[1];
63 boost::fusion::at_c<0>(data)[2] = p.template get<0>()[2];
64
65 return *this;
66 }
67
68 static bool noPointers()
69 {
70 return true;
71 }
72};
73
74const std::string vx::attributes::name[] = { "x" };
75
76struct ed
77{
78 typedef boost::fusion::vector<size_t> type;
79
82 {
83 static const std::string name[];
84 };
85
87 type data;
88
90 static const unsigned int prop = 0;
92 static const unsigned int max_prop = 1;
93
94 ed()
95 {
96
97 }
98
99 template<unsigned int id> inline auto get() -> decltype(boost::fusion::at_c < id > (data))
100 {
101 return boost::fusion::at_c<id>(data);
102 }
103
104 template<unsigned int dim, typename Mem> inline ed(const encapc<dim, ed, Mem> & p)
105 {
106 this->operator=(p);
107 }
108
109 template<unsigned int dim, typename Mem> inline ed & operator=(const encapc<dim, ed, Mem> & p)
110 {
111 boost::fusion::at_c<0>(data) = p.template get<0>();
112
113 return *this;
114 }
115
116 static bool noPointers()
117 {
118 return true;
119 }
120};
121
122const std::string ed::attributes::name[] = { "prop" };
123
124BOOST_AUTO_TEST_SUITE (dist_map_graph_test)
125
126BOOST_AUTO_TEST_CASE( dist_map_graph_use)
127{
128
130 Vcluster<> & vcl = create_vcluster();
131
132 if(vcl.getProcessingUnits() != 4)
133 return;
134
136 size_t sz[2] = { DGRAPH_GS_SIZE, DGRAPH_GS_SIZE };
137
139 Box<2, float> box( { 0.0, 0.0 }, { 1.0, 1.0 });
140
143
145 DistGraph_CSR<vx, ed> gd = g_factory.construct<NO_EDGE, float, 2 - 1, 0, 1, 2>(sz, box);
146
148
149 gd.reqVertex(13);
150 gd.reqVertex(1);
151 gd.reqVertex(14);
152 gd.sync();
153
154 gd.reqVertex(15);
155 gd.reqVertex(2);
156 gd.reqVertex(10);
157 gd.sync();
158
159 gd.deleteGhosts();
160
162
163 if(vcl.getProcessUnitID() == 0)
164 {
165 for(size_t i = 0; i < 4; i++)
166 gd.q_move(i, 1);
167 }
168
169 if(vcl.getProcessUnitID() == 1)
170 {
171 for(size_t i = 0; i < 4; i++)
172 gd.q_move(i, 0);
173 }
174
175 if(vcl.getProcessUnitID() == 2)
176 {
177 for(size_t i = 0; i < 2; i++)
178 gd.q_move(i, 3);
179 }
180
181 if(vcl.getProcessUnitID() == 3)
182 {
183 for(size_t i = 0; i < 4; i++)
184 gd.q_move(i, 2);
185 }
186
188 gd.redistribute();
189
190 if(vcl.getProcessUnitID() == 0)
191 {
192 BOOST_REQUIRE_EQUAL(gd.getVertexId(0), 0ul);
193 BOOST_REQUIRE_EQUAL(gd.getVertexId(1), 1ul);
194 BOOST_REQUIRE_EQUAL(gd.getVertexId(2), 2ul);
195 BOOST_REQUIRE_EQUAL(gd.getVertexId(3), 3ul);
196 BOOST_REQUIRE_EQUAL(gd.getNChilds(0), 3ul);
197 BOOST_REQUIRE_EQUAL(gd.getChild(0,0), 1ul);
198 BOOST_REQUIRE_EQUAL(gd.getChild(0,1), 14ul);
199 BOOST_REQUIRE_EQUAL(gd.getChild(0,2), 4ul);
200 BOOST_REQUIRE_EQUAL(gd.getNChilds(1), 4ul);
201 BOOST_REQUIRE_EQUAL(gd.getChild(1,0), 2ul);
202 BOOST_REQUIRE_EQUAL(gd.getChild(1,1), 0ul);
203 BOOST_REQUIRE_EQUAL(gd.getChild(1,2), 15ul);
204 BOOST_REQUIRE_EQUAL(gd.getChild(1,3), 5ul);
205 BOOST_REQUIRE_EQUAL(gd.getNChilds(2), 4ul);
206 BOOST_REQUIRE_EQUAL(gd.getChild(2,0), 3ul);
207 BOOST_REQUIRE_EQUAL(gd.getChild(2,1), 1ul);
208 BOOST_REQUIRE_EQUAL(gd.getChild(2,2), 8ul);
209 BOOST_REQUIRE_EQUAL(gd.getChild(2,3), 6ul);
210 BOOST_REQUIRE_EQUAL(gd.getNChilds(3), 3ul);
211 BOOST_REQUIRE_EQUAL(gd.getChild(3,0), 2ul);
212 BOOST_REQUIRE_EQUAL(gd.getChild(3,1), 9ul);
213 BOOST_REQUIRE_EQUAL(gd.getChild(3,2), 7ul);
214 }
215
216 if(vcl.getProcessUnitID() == 1)
217 {
218 BOOST_REQUIRE_EQUAL(gd.getVertexId(0), 4ul);
219 BOOST_REQUIRE_EQUAL(gd.getVertexId(1), 5ul);
220 BOOST_REQUIRE_EQUAL(gd.getVertexId(2), 6ul);
221 BOOST_REQUIRE_EQUAL(gd.getVertexId(3), 7ul);
222 }
223
224 if(vcl.getProcessUnitID() == 2)
225 {
226 BOOST_REQUIRE_EQUAL(gd.getVertexId(0), 8ul);
227 BOOST_REQUIRE_EQUAL(gd.getVertexId(1), 9ul);
228 BOOST_REQUIRE_EQUAL(gd.getVertexId(2), 10ul);
229 BOOST_REQUIRE_EQUAL(gd.getVertexId(3), 11ul);
230 BOOST_REQUIRE_EQUAL(gd.getVertexId(4), 12ul);
231 BOOST_REQUIRE_EQUAL(gd.getVertexId(5), 13ul);
232 }
233
234 if(vcl.getProcessUnitID() == 3)
235 {
236 BOOST_REQUIRE_EQUAL(gd.getVertexId(0), 14ul);
237 BOOST_REQUIRE_EQUAL(gd.getVertexId(1), 15ul);
238 }
239}
240
241BOOST_AUTO_TEST_CASE( dist_map_graph_use_redistribution)
242{
244 Vcluster<> & vcl = create_vcluster();
245
246 if(vcl.getProcessingUnits() != 4)
247 return;
248
250 size_t sz[2] = { 4, 4 };
251
253 Box<2, float> box( { 0.0, 0.0 }, { 1.0, 1.0 });
254
257
259 DistGraph_CSR<vx, ed> gd = g_factory.construct<NO_EDGE, float, 2 - 1, 0, 1, 2>(sz, box);
260
261 for(size_t i=0; i< gd.getNVertex(); i++)
262 gd.vertex(i).get<vx::x>()[2] = 0;
263
264 if (vcl.getProcessUnitID() == 0)
265 {
266 gd.q_move(0,1);
267 gd.q_move(1,1);
268 }
269
270 if (vcl.getProcessUnitID() == 1)
271 {
272 gd.q_move(2,0);
273 gd.q_move(3,0);
274 }
275
276 if (vcl.getProcessUnitID() == 2)
277 {
278 gd.q_move(0,3);
279 gd.q_move(1,3);
280 }
281
282 if (vcl.getProcessUnitID() == 3)
283 {
284 gd.q_move(2,2);
285 gd.q_move(3,2);
286 }
287
288 gd.redistribute();
289
290 VTKWriter<DistGraph_CSR<vx, ed>, DIST_GRAPH> gv2(gd);
291 gv2.write("dist_graph_redistribution_0.vtk");
292
293 if(vcl.getProcessUnitID() == 0)
294 {
295 bool test = compare("dist_graph_redistribution_0.vtk", "src/Graph/test_data/dist_graph_redistribution_0_test.vtk");
296 BOOST_REQUIRE_EQUAL(true,test);
297 }
298
299 if (vcl.getProcessUnitID() == 2)
300 {
301 gd.q_move(0,0);
302 gd.q_move(1,0);
303 }
304
305 if (vcl.getProcessUnitID() == 3)
306 {
307 gd.q_move(0,0);
308 gd.q_move(2,0);
309 }
310
311 gd.redistribute();
312
313 gv2.write("dist_graph_redistribution_1.vtk");
314
315 if(vcl.getProcessUnitID() == 0)
316 {
317 bool test = compare("dist_graph_redistribution_1.vtk","src/Graph/test_data/dist_graph_redistribution_1_test.vtk");
318 BOOST_REQUIRE_EQUAL(true,test);
319 }
320
321}
322
323
324BOOST_AUTO_TEST_CASE( dist_map_graph_use_free_add)
325{
326 // Vcluster
327 Vcluster<> & vcl = create_vcluster();
328
329 if(vcl.getProcessingUnits() != 4)
330 return;
331
332 // [create graph adding freely the vertices and the edges ]
333
334 // Distributed graph
336
337 // Add vertices
338 for (size_t i = 0; i < 4; ++i)
339 {
340 vx v;
341 v.get<vx::x>()[0] = vcl.getProcessUnitID();
342 v.get<vx::x>()[1] = i;
343 v.get<vx::x>()[2] = 0;
344 size_t gid = vcl.getProcessUnitID()*4 + i;
345 gd.add_vertex(v, gid);
346 }
347
348 // This method must be called after adding vertices
349 gd.init();
350
351 // Add edges
352 if(vcl.getProcessUnitID()==0)
353 {
354 gd.add_edge(0,1);
355 gd.add_edge(1,2);
356 gd.add_edge(2,3);
357 gd.add_edge(0,4);
358 gd.add_edge(1,5);
359 gd.add_edge(2,6);
360 gd.add_edge(3,7);
361 }
362
363 if(vcl.getProcessUnitID()==1)
364 {
365 gd.add_edge(4,5);
366 gd.add_edge(5,6);
367 gd.add_edge(6,7);
368 gd.add_edge(4,8);
369 gd.add_edge(5,9);
370 gd.add_edge(6,10);
371 gd.add_edge(7,11);
372 }
373
374 if(vcl.getProcessUnitID()==2)
375 {
376 gd.add_edge(8,9);
377 gd.add_edge(9,10);
378 gd.add_edge(10,11);
379 gd.add_edge(8,12);
380 gd.add_edge(9,13);
381 gd.add_edge(10,14);
382 gd.add_edge(11,15);
383 }
384
385 if(vcl.getProcessUnitID()==3)
386 {
387 gd.add_edge(12,13);
388 gd.add_edge(13,14);
389 gd.add_edge(14,15);
390 }
391
392 gd.syncEdge();
393
395
396 if(vcl.getProcessUnitID() == 0)
397 {
398 for (size_t i = 0; i < 4; ++i)
399 {
400 BOOST_REQUIRE_EQUAL(gd.getVertexId(i), i);
401 }
402 }
403
404 if(vcl.getProcessUnitID() == 2)
405 {
406 for (size_t i = 8, j = 0; i < 12 && j < gd.getNVertex(); ++i, ++j)
407 {
408 BOOST_REQUIRE_EQUAL(gd.getVertexId(j), i);
409 }
410 }
411
412 if(vcl.getProcessUnitID() == 0)
413 gd.reqVertex(5);
414
415 gd.sync();
416
417 if(vcl.getProcessUnitID() == 0)
418 BOOST_REQUIRE_EQUAL(gd.getVertexId(4), 5ul);
419
420 gd.deleteGhosts();
421
422 if (vcl.getProcessUnitID() == 0)
423 {
424 gd.q_move(0,1);
425 gd.q_move(1,1);
426 }
427
428 if (vcl.getProcessUnitID() == 1)
429 {
430 gd.q_move(2,0);
431 gd.q_move(3,0);
432 }
433
434 if (vcl.getProcessUnitID() == 2)
435 {
436 gd.q_move(0,3);
437 gd.q_move(1,3);
438 }
439
440 if (vcl.getProcessUnitID() == 3)
441 {
442 gd.q_move(2,2);
443 gd.q_move(3,2);
444 }
445
446 gd.redistribute();
447
448 VTKWriter<DistGraph_CSR<vx, ed>, DIST_GRAPH> gv2(gd);
449 gv2.write("dist_graph_free_0.vtk");
450
451 if(vcl.getProcessUnitID() == 0)
452 {
453 bool test = compare("dist_graph_free_0.vtk", "src/Graph/test_data/dist_graph_free_0_test.vtk");
454 BOOST_REQUIRE_EQUAL(true,test);
455 }
456
457 if (vcl.getProcessUnitID() == 2)
458 {
459 gd.q_move(0,0);
460 gd.q_move(1,0);
461 }
462
463 if (vcl.getProcessUnitID() == 3)
464 {
465 gd.q_move(0,0);
466 gd.q_move(2,0);
467 }
468
469 gd.redistribute();
470
471 gv2.write("dist_graph_free_1.vtk");
472
473 if(vcl.getProcessUnitID() == 0)
474 {
475 bool test = compare("dist_graph_free_1.vtk", "src/Graph/test_data/dist_graph_free_1_test.vtk");
476 BOOST_REQUIRE_EQUAL(true,test);
477 }
478}
479
480BOOST_AUTO_TEST_CASE( dist_map_graph_use_multi_free_add)
481{
482 // Vcluster
483 Vcluster<> & vcl = create_vcluster();
484
485 if(vcl.getProcessingUnits() != 4)
486 return;
487
488 // Distributed graph
490
491 // Add vertices
492 if(vcl.getProcessUnitID()==0)
493 {
494 vx v;
495 gd.add_vertex(v, 0);
496 gd.add_vertex(v, 1);
497 gd.add_vertex(v, 2);
498 gd.add_vertex(v, 3);
499 }
500
501 if(vcl.getProcessUnitID()==1)
502 {
503 vx v;
504 gd.add_vertex(v, 4);
505 gd.add_vertex(v, 5);
506 gd.add_vertex(v, 6);
507 gd.add_vertex(v, 7);
508 }
509
510 // This method must be called ALWAYS after adding vertices
511 gd.init();
512
513 if(vcl.getProcessUnitID()==2)
514 {
515 vx v;
516 gd.add_vertex(v, 8);
517 gd.add_vertex(v, 9);
518 gd.add_vertex(v, 10);
519 gd.add_vertex(v, 11);
520 }
521
522 if(vcl.getProcessUnitID()==3)
523 {
524 vx v;
525 gd.add_vertex(v, 12);
526 gd.add_vertex(v, 13);
527 gd.add_vertex(v, 14);
528 gd.add_vertex(v, 15);
529 }
530
531 // This method must be called ALWAYS after adding vertices
532 gd.init();
533
534 gd.reqVertex(15);
535
536 gd.sync();
537
538 BOOST_REQUIRE_EQUAL(gd.getVertexId(gd.getNVertex()-1), 15ul);
539}
540
541BOOST_AUTO_TEST_SUITE_END()
542
543#endif
This class represent an N-dimensional box.
Definition Box.hpp:61
This class construct a cartesian graph.
Structure that store a graph in CSR format or basically in compressed adjacency matrix format.
size_t getNVertex() const
Return the number of the vertices in this subgraph.
void deleteGhosts()
Remove all the ghosts from this graph.
void q_move(size_t i, size_t t)
Prepare to send vertex i from the local processor to the target processor.
void init()
Once added all the vertices this function must be called to initialize all the properties,...
void sync()
Execute all vertex requests and add them as ghosts inside this graph, they will be available until a ...
size_t getVertexId(size_t i) const
Get the id of a vertex given its index position.
void add_edge(size_t v1, size_t v2)
Add an edge between vertices v1 end v2, needs syncEdge() to complete the action.
void redistribute()
Redistribute function that wraps different stages of the redistribution.
size_t getNChilds(size_t c) const
Return the number of children of a vertex.
void add_vertex(const V &vrt, size_t id, size_t gid)
Add vertex vrt with global id and id properties.
size_t getChild(size_t v, size_t i) const
Get the child edge.
void reqVertex(size_t gid)
Put a vertex request in queue.
auto vertex(size_t id) -> decltype(v.get(id))
Function to access the vertexes.
void syncEdge()
Execute a synchronization through processor to finalize the add of the edges requested in the e_queue...
size_t getProcessUnitID()
Get the process unit id.
size_t getProcessingUnits()
Get the total number of processors.
Implementation of VCluster class.
Definition VCluster.hpp:59
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
type data
The data.
static const unsigned int max_prop
total number of properties boost::fusion::vector
Definition ids.hpp:149
static const unsigned int x
x property id in boost::fusion::vector
float s_type
type of the positional field
static const unsigned int max_prop
total number of properties boost::fusion::vector
type data
The data.