OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
BoxDistribution.hpp
1 /*
2  * MetisDistribution.hpp
3  *
4  * Created on: Nov 19, 2015
5  * Author: Antonio Leo
6  */
7 
8 #ifndef SRC_DECOMPOSITION_BOXDISTRIBUTION_HPP_
9 #define SRC_DECOMPOSITION_BOXDISTRIBUTION_HPP_
10 
11 #include "SubdomainGraphNodes.hpp"
12 #include "Vector/map_vector.hpp"
13 #include "VCluster/VCluster.hpp"
14 #include "Graph/map_graph.hpp"
15 #include "Graph/CartesianGraphFactory.hpp"
16 #include "VTKWriter/VTKWriter.hpp"
17 
18 #define BOX_DISTRIBUTION_ERROR_OBJECT std::runtime_error("Box distribution runtime error");
19 
20 
21 void getPrimeFactors(int n, openfpm::vector<int> & fact )
22 {
23  while (n%2 == 0)
24  {
25  fact.add(2);
26  n = n/2;
27  }
28  for (int i = 3; i <= sqrt(n); i = i+2)
29  {
30  while (n%i == 0)
31  {
32  fact.add(i);
33  n = n/i;
34  }
35  }
36  if (n > 2)
37  {fact.add(n);}
38 }
39 
40 
54 template<unsigned int dim, typename T>
56 {
59 
62 
65 
68 
70  bool testing = false;
71 
72  openfpm::vector<int> subsub_own;
73 
79  inline void check_overflow(size_t id)
80  {
81 #ifdef SE_CLASS1
82  if (id >= gp.getNVertex())
83  {
84  std::cerr << "Error " << __FILE__ ":" << __LINE__ << " such sub-sub-domain doesn't exist (id = " << id << ", " << "total size = " << gp.getNVertex() << ")\n";
85  ACTION_ON_ERROR(BOX_DISTRIBUTION_ERROR_OBJECT)
86  }
87 #endif
88  }
89 
95  inline void check_overflowe(size_t id, size_t e)
96  {
97 #ifdef SE_CLASS1
98  if (e >= gp.getNChilds(id))
99  {
100  std::cerr << "Error " << __FILE__ ":" << __LINE__ << " for the sub-sub-domain " << id << " such neighborhood doesn't exist (e = " << e << ", " << "total size = " << gp.getNChilds(id) << ")\n";
101  ACTION_ON_ERROR(BOX_DISTRIBUTION_ERROR_OBJECT)
102  }
103 #endif
104  }
105 
106 public:
107 
108  static constexpr unsigned int computation = nm_v_computation;
109 
116  :v_cl(v_cl)
117  {
118 #ifdef SE_CLASS2
119  check_new(this,8,VECTOR_EVENT,1);
120 #endif
121  }
122 
129  :v_cl(mt.v_cl)
130  {
131 #ifdef SE_CLASS2
132  check_valid(mt);
133  check_new(this,8,VECTOR_EVENT,1);
134 #endif
135  this->operator=(mt);
136  }
137 
144  {
145 #ifdef SE_CLASS2
146  check_valid(mt);
147  check_new(this,8,VECTOR_EVENT,1);
148 #endif
149  this->operator=(mt);
150  }
151 
157  {
158 #ifdef SE_CLASS2
159  check_delete(this);
160 #endif
161  }
162 
163 
171  {
172 #ifdef SE_CLASS2
173  check_valid(this,8);
174 #endif
175  // NON periodic boundary conditions
176  size_t bc[dim];
177 
178  for (size_t i = 0 ; i < dim ; i++)
179  bc[i] = NON_PERIODIC;
180 
181  // Set grid and domain
182  gr = grid;
183  domain = dom;
184 
185  // Create a cartesian grid graph
187  gp = g_factory_part.template construct<NO_EDGE, nm_v_id, T, dim - 1, 0>(gr.getSize(), domain, bc);
188 
189  // Init to 0.0 axis z (to fix in graphFactory)
190  if (dim < 3)
191  {
192  for (size_t i = 0; i < gp.getNVertex(); i++)
193  {
194  gp.vertex(i).template get<nm_v_x>()[2] = 0.0;
195  }
196  }
197 
198  for (size_t i = 0; i < gp.getNVertex(); i++)
199  gp.vertex(i).template get<nm_v_global_id>() = i;
200  }
201 
208  {
209 #ifdef SE_CLASS2
210  check_valid(this,8);
211 #endif
212  return gp;
213  }
214 
218  void decompose()
219  {
220 #ifdef SE_CLASS2
221  check_valid(this,8);
222 #endif
223 
224  subsub_own.clear();
226 
227  openfpm::vector<int> facts;
228  getPrimeFactors(v_cl.size(),facts);
229 
230  size_t div[dim];
231  size_t ln[dim];
232  double ln_d[dim];
233 
234  for (int i = 0 ; i < dim ; i++)
235  {div[i] = 1;}
236 
237  for (int i = 0 ; i < facts.size() ; i++)
238  {div[i % dim] *= facts.get(i);}
239 
240  for (int i = 0 ; i < dim ; i++)
241  {
242  ln[i] = gr.size(i) / div[i];
243  ln_d[i] = (double)gr.size(i) / div[i];
244  }
245 
246  grid_sm<dim,void> gr_proc(div);
247 
248  while (it.isNext())
249  {
250  auto key = it.get();
251 
252  grid_key_dx<dim> key_prc;
253 
254  for (int i = 0 ; i < dim ; i++)
255  {
256  key_prc.set_d(i,key.get(i)/ln_d[i]);
257  if (key_prc.get(i) >= div[i])
258  {key_prc.set_d(i,div[i]-1);}
259  }
260 
261  size_t i = gr.LinId(key);
262 
263  gp.vertex(i).template get<nm_v_proc_id>() = gr_proc.LinId(key_prc);
264 
265  if (gp.vertex(i).template get<nm_v_proc_id>() == v_cl.rank())
266  {subsub_own.add(i);}
267 
268  ++it;
269  }
270  }
271 
277  void refine()
278  {
279 #ifdef SE_CLASS2
280  check_valid(this,8);
281 #endif
282 
283  decompose();
284  }
285 
289  void redecompose()
290  {
291 #ifdef SE_CLASS2
292  check_valid(this,8);
293 #endif
294  decompose();
295  }
296 
297 
304  void getSSDomainPos(size_t id, T (&pos)[dim])
305  {
306 #ifdef SE_CLASS2
307  check_valid(this,8);
308 #endif
309  check_overflow(id);
310 
311  // Copy the geometrical informations inside the pos vector
312  pos[0] = gp.vertex(id).template get<nm_v_x>()[0];
313  pos[1] = gp.vertex(id).template get<nm_v_x>()[1];
314  if (dim == 3)
315  {pos[2] = gp.vertex(id).template get<nm_v_x>()[2];}
316  }
317 
325  size_t getComputationalCost(size_t id)
326  {
327 #ifdef SE_CLASS2
328  check_valid(this,8);
329 #endif
330  check_overflow(id);
331  return gp.vertex(id).template get<nm_v_computation>();
332  }
333 
334 
341  void setComputationCost(size_t id, size_t cost)
342  {
343 #ifdef SE_CLASS2
344  check_valid(this,8);
345 #endif
346 #ifdef SE_CLASS1
347  check_overflow(id);
348 #endif
349  }
350 
356  void setMigrationCost(size_t id, size_t cost)
357  {
358 #ifdef SE_CLASS2
359  check_valid(this,8);
360 #endif
361 #ifdef SE_CLASS1
362  check_overflow(id);
363 #endif
364  }
365 
372  void setCommunicationCost(size_t id, size_t e, size_t cost)
373  {
374 #ifdef SE_CLASS2
375  check_valid(this,8);
376 #endif
377 #ifdef SE_CLASS1
378  check_overflow(id);
379  check_overflowe(id,e);
380 #endif
381  }
382 
389  {
390 #ifdef SE_CLASS2
391  check_valid(this,8);
392 #endif
393  return gp.getNVertex();
394  }
395 
400  size_t getNSubSubDomainNeighbors(size_t id)
401  {
402 #ifdef SE_CLASS2
403  check_valid(this,8);
404 #endif
405 #ifdef SE_CLASS1
406  check_overflow(id);
407 #endif
408 
409  return gp.getNChilds(id);
410  }
411 
418  float getUnbalance()
419  {
420 #ifdef SE_CLASS2
421  check_valid(this,8);
422 #endif
423  return 0.0;
424  }
425 
431  size_t getNOwnerSubSubDomains() const
432  {
433  return subsub_own.size();
434  }
435 
443  size_t getOwnerSubSubDomain(size_t id) const
444  {
445  return subsub_own.get(id);
446  }
447 
453  void onTest()
454  {
455 #ifdef SE_CLASS2
456  check_valid(this,8);
457 #endif
458  testing = true;
459  }
460 
466  void write(std::string out)
467  {
468 #ifdef SE_CLASS2
469  check_valid(this,8);
470 #endif
471 
472  VTKWriter<Graph_CSR<nm_v<dim>, nm_e>, VTK_GRAPH> gv2(gp);
473  gv2.write(std::to_string(v_cl.getProcessUnitID()) + "_" + out + ".vtk");
474 
475  }
476 
484  {
485 #ifdef SE_CLASS2
486  check_valid(this,8);
487 #endif
489 
490  size_t load = 0;
491 
492  if (v_cl.getProcessUnitID() == 0)
493  {
494  for (size_t i = 0; i < gp.getNVertex(); i++)
495  {loads.get(gp.template vertex_p<nm_v_proc_id>(i)) += gp.template vertex_p<nm_v_computation>(i);}
496 
497  for (size_t i = 0 ; i < v_cl.getProcessingUnits() ; i++)
498  {
499  v_cl.send(i,1234,&loads.get(i),sizeof(size_t));
500  }
501  }
502  v_cl.recv(0,1234,&load,sizeof(size_t));
503  v_cl.execute();
504 
505  return load;
506  }
507 
516  {
517 #ifdef SE_CLASS2
518  check_valid(&mt,8);
519  check_valid(this,8);
520 #endif
521 
522  this->gr = mt.gr;
523  this->domain = mt.domain;
524  this->gp = mt.gp;
525  this->subsub_own = mt.subsub_own;
526  return *this;
527  }
528 
537  {
538 #ifdef SE_CLASS2
539  check_valid(mt);
540  check_valid(this,8);
541 #endif
542  this->gr = mt.gr;
543  this->domain = mt.domain;
544  this->gp.swap(mt.gp);
545  this->subsub_own.swap(mt.subsub_own);
546  return *this;
547  }
548 
556  inline bool operator==(const BoxDistribution & mt)
557  {
558 #ifdef SE_CLASS2
559  check_valid(&mt,8);
560  check_valid(this,8);
561 #endif
562  bool ret = true;
563 
564  ret &= (this->gr == mt.gr);
565  ret &= (this->domain == mt.domain);
566  ret &= (this->gp == mt.gp);
567 
568  ret &= this->subsub_own == mt.subsub_own;
569 
570  return ret;
571  }
572 
578  void setDistTol(double tol)
579  {
580  }
581 
582 
583 
590  {
591 #ifdef SE_CLASS1
592  if (id >= gp.getNVertex())
593  std::cerr << __FILE__ << ":" << __LINE__ << "Such vertex doesn't exist (id = " << id << ", " << "total size = " << gp.getNVertex() << ")\n";
594 #endif
595  return 1;
596  }
597 
603  size_t get_ndec()
604  {
605  return 0;
606  }
607 };
608 
609 #endif /* SRC_DECOMPOSITION_METISDISTRIBUTION_HPP_ */
Box< dim, T > domain
rectangular domain to decompose
auto vertex(size_t id) -> decltype(v.get(id))
Function to access the vertex.
Definition: map_graph.hpp:596
size_t getProcessUnitID()
Get the process unit id.
Vcluster & v_cl
Vcluster.
__device__ __host__ size_t size() const
Return the size of the grid.
Definition: grid_sm.hpp:637
bool testing
Flag that indicate if we are doing a test (In general it fix the seed)
void setDistTol(double tol)
Set the tolerance for each partition.
void createCartGraph(grid_sm< dim, void > &grid, Box< dim, T > dom)
create a Cartesian distribution graph
void setComputationCost(size_t id, size_t cost)
Set computation cost on a sub-sub domain.
BoxDistribution & operator=(const BoxDistribution &mt)
operator=
size_t getProcessorLoad()
Compute the processor load.
~BoxDistribution()
Destructor.
size_t getNOwnerSubSubDomains() const
Return the total number of sub-sub-domains in the distribution graph.
__device__ __host__ index_type get(index_type i) const
Get the i index.
Definition: grid_key.hpp:503
void setMigrationCost(size_t id, size_t cost)
Set migration cost on a sub-sub domain.
Graph_CSR< nm_v< dim >, nm_e > & getGraph()
Get the current graph (main)
size_t size()
Stub size.
Definition: map_vector.hpp:211
void check_overflow(size_t id)
Check that the sub-sub-domain id exist.
BoxDistribution(const BoxDistribution &mt)
Copy constructor.
bool send(size_t proc, size_t tag, const void *mem, size_t sz)
Send data to a processor.
size_t get_ndec()
Get the decomposition counter.
Implementation of VCluster class.
Definition: VCluster.hpp:58
mem_id LinId(const grid_key_dx< N, ids_type > &gk, const char sum_id[N]) const
Linearization of the grid_key_dx with a specified shift.
Definition: grid_sm.hpp:434
void execute()
Execute all the requests.
void write(std::string out)
Write the distribution graph into file.
size_t getNSubSubDomains()
Returns total number of sub-sub-domains.
size_t getSubSubDomainComputationCost(size_t id)
function that get the weight of the vertex
This class construct a cartesian graph.
bool operator==(const BoxDistribution &mt)
operator==
grid_sm< dim, void > gr
Structure that store the cartesian grid information.
sub-domain edge graph node
const grid_key_dx< dim > & get() const
Get the actual key.
size_t rank()
Get the process unit id.
const size_t(& getSize() const)[N]
Return the size of the grid as an array.
Definition: grid_sm.hpp:740
size_t getComputationalCost(size_t id)
function that get the computational cost of the sub-sub-domain
Graph_CSR< nm_v< dim >, nm_e > gp
Global sub-sub-domain graph.
bool recv(size_t proc, size_t tag, void *v, size_t sz)
Recv data from a processor.
size_t getProcessingUnits()
Get the total number of processors.
size_t getOwnerSubSubDomain(size_t id) const
Return the id of the set sub-sub-domain.
Structure that store a graph in CSR format or basically in compressed adjacency matrix format.
Definition: map_graph.hpp:81
size_t getNVertex() const
Return the number of the vertex.
Definition: map_graph.hpp:1045
float getUnbalance()
Compute the unbalance of the processor compared to the optimal balance.
void decompose()
Distribute the sub-sub-domains.
This class represent an N-dimensional box.
Definition: Box.hpp:60
void refine()
Refine current decomposition.
size_t getNChilds(size_t c) const
Return the number of childs of a vertex.
Definition: map_graph.hpp:768
Class that distribute sub-sub-domains across processors using Metis Library.
void redecompose()
Redecompose current decomposition.
void swap(Graph_CSR< V, E > &g)
swap the memory of g with this graph
Definition: map_graph.hpp:976
size_t getNSubSubDomainNeighbors(size_t id)
Returns total number of neighbors of one sub-sub-domain.
BoxDistribution(BoxDistribution &&mt)
Copy constructor.
BoxDistribution & operator=(BoxDistribution &&mt)
operator=
void onTest()
It set the Classs on test mode.
size_t size()
Get the total number of processors.
__device__ __host__ void set_d(index_type i, index_type id)
Set the i index.
Definition: grid_key.hpp:516
void setCommunicationCost(size_t id, size_t e, size_t cost)
Set communication cost between neighborhood sub-sub-domains (weight on the edge)
bool isNext()
Check if there is the next element.
void check_overflowe(size_t id, size_t e)
Check that the sub-sub-domain id exist.
BoxDistribution(Vcluster<> &v_cl)
constructor
void getSSDomainPos(size_t id, T(&pos)[dim])
Function that return the position (point P1) of the sub-sub domain box in the space.