OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
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.
void q_move(size_t i, size_t t)
Prepare to send vertex i from the local processor to the target processor.
size_t getChild(size_t v, size_t i) const
Get the child edge.
type data
The data.
size_t getProcessUnitID()
Get the process unit id.
static const unsigned int x
x property id in boost::fusion::vector
void reqVertex(size_t gid)
Put a vertex request in queue.
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 getNVertex() const
Return the number of the vertices in this subgraph.
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:36
size_t getVertexId(size_t i) const
Get the id of a vertex given its index position.
static const unsigned int max_prop
total number of properties boost::fusion::vector
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:56
size_t getNChilds(size_t c) const
Return the number of children of a vertex.
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
size_t getProcessingUnits()
Get the total number of processors.
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, useless if a graph factory is used.
float s_type
type of the positional field