OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
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 
11 struct vx
12 {
13  typedef boost::fusion::vector<float[3]> type;
14 
16  struct attributes
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 
74 const std::string vx::attributes::name[] = { "x" };
75 
76 struct ed
77 {
78  typedef boost::fusion::vector<size_t> type;
79 
81  struct attributes
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 
122 const std::string ed::attributes::name[] = { "prop" };
123 
124 BOOST_AUTO_TEST_SUITE (dist_map_graph_test)
125 
126 BOOST_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 
241 BOOST_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 
324 BOOST_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 
480 BOOST_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 
541 BOOST_AUTO_TEST_SUITE_END()
542 
543 #endif
void syncEdge()
Execute a synchronization through processor to finalize the add of the edges requested in the e_queue...
static const unsigned int max_prop
total number of properties boost::fusion::vector
void add_vertex(const V &vrt, size_t id, size_t gid)
Add vertex vrt with global id and id properties.
size_t getNChilds(size_t c) const
Return the number of children of a vertex.
void q_move(size_t i, size_t t)
Prepare to send vertex i from the local processor to the target processor.
size_t getProcessUnitID()
Get the process unit id.
size_t getNVertex() const
Return the number of the vertices in this subgraph.
type data
The data.
static const unsigned int x
x property id in boost::fusion::vector
void reqVertex(size_t gid)
Put a vertex request in queue.
size_t getChild(size_t v, size_t i) const
Get the child edge.
void deleteGhosts()
Remove all the ghosts from this graph.
static const unsigned int prop
srcgid property id in boost::fusion::vector
type data
The data.
size_t getVertexId(size_t i) const
Get the id of a vertex given its index position.
void sync()
Execute all vertex requests and add them as ghosts inside this graph, they will be available until a ...
Implementation of VCluster class.
Definition: VCluster.hpp:58
static const unsigned int max_prop
total number of properties boost::fusion::vector
size_t getProcessingUnits()
Get the total number of processors.
Structure that store a graph in CSR format or basically in compressed adjacency matrix format.
void redistribute()
Redistribute function that wraps different stages of the redistribution.
This class represent an N-dimensional box.
Definition: Box.hpp:60
This class construct a cartesian graph.
void add_edge(size_t v1, size_t v2)
Add an edge between vertices v1 end v2, needs syncEdge() to complete the action.
Definition: ids.hpp:148
auto vertex(size_t id) -> decltype(v.get(id))
Function to access the vertexes.
void init()
Once added all the vertices this function must be called to initialize all the properties,...
float s_type
type of the positional field