OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
SpaceDistribution.hpp
1 /*
2  * SpaceDistribution.hpp
3  *
4  * Created on: Dec 3, 2016
5  * Author: i-bird
6  */
7 
8 #ifndef SRC_DECOMPOSITION_DISTRIBUTION_SPACEDISTRIBUTION_HPP_
9 #define SRC_DECOMPOSITION_DISTRIBUTION_SPACEDISTRIBUTION_HPP_
10 
11 #include "util/mathutil.hpp"
12 #include "NN/CellList/CellDecomposer.hpp"
13 #include "Grid/grid_key_dx_iterator_hilbert.hpp"
14 
23 template<unsigned int dim, typename T>
25 {
28 
31 
34 
37 
38 
39 public:
40 
46  :v_cl(v_cl)
47  {
48  }
49 
56  :v_cl(pm.v_cl)
57  {
58  this->operator=(pm);
59  }
60 
67  :v_cl(pm.v_cl)
68  {
69  this->operator=(pm);
70  }
71 
78  {
79  size_t bc[dim];
80 
81  for (size_t i = 0 ; i < dim ; i++)
82  bc[i] = NON_PERIODIC;
83 
84  // Set grid and domain
85  gr = grid;
86  domain = dom;
87 
88  // Create a cartesian grid graph
90  gp = g_factory_part.template construct<NO_EDGE, nm_v_id, T, dim - 1, 0>(gr.getSize(), domain, bc);
91 
92  // Init to 0.0 axis z (to fix in graphFactory)
93  if (dim < 3)
94  {
95  for (size_t i = 0; i < gp.getNVertex(); i++)
96  gp.vertex(i).template get<nm_v_x>()[2] = 0.0;
97  }
98  for (size_t i = 0; i < gp.getNVertex(); i++)
99  gp.vertex(i).template get<nm_v_global_id>() = i;
100 
101  }
102 
107  {
108  return gp;
109  }
110 
114  void decompose()
115  {
116  // Get the number of processing units
117  size_t Np = v_cl.getProcessingUnits();
118 
119  // Calculate the best number of sub-domains for each
120  // processor
121  size_t N_tot = gr.size();
122  size_t N_best_each = N_tot / Np;
123  size_t N_rest = N_tot % Np;
124 
125  openfpm::vector<size_t> accu(Np);
126  accu.get(0) = N_best_each + ((0 < N_rest)?1:0);
127  for (size_t i = 1 ; i < Np ; i++)
128  accu.get(i) = accu.get(i-1) + N_best_each + ((i < N_rest)?1:0);
129 
130  // Get the maximum along dimensions and take the smallest n number
131  // such that 2^n < m. n it will be order of the hilbert curve
132 
133  size_t max = 0;
134 
135  for (size_t i = 0; i < dim ; i++)
136  {
137  if (max < gr.size(i))
138  max = gr.size(i);
139  }
140 
141  // Get the order of the hilbert-curve
142  size_t order = openfpm::math::log2_64(max);
143  if (1ul << order < max)
144  order += 1;
145 
146  size_t n = 1 << order;
147 
148  // Create the CellDecomoser
149 
150  CellDecomposer_sm<dim,T> cd_sm;
151  cd_sm.setDimensions(domain, gr.getSize(), 0);
152 
153  // create the hilbert curve
154 
155  //hilbert curve iterator
157 
158  T spacing[dim];
159 
160  // Calculate the hilbert curve spacing
161  for (size_t i = 0 ; i < dim ; i++)
162  spacing[i] = (domain.getHigh(i) - domain.getLow(i)) / n;
163 
164  // Small grid to detect already assigned sub-sub-domains
166  g.setMemory();
167 
168  // Reset the grid to -1
170  while (it.isNext())
171  {
172  auto key = it.get();
173 
174  g.template get<0>(key) = -1;
175 
176  ++it;
177  }
178 
179  // Go along the hilbert-curve and divide the space
180 
181  size_t proc_d = 0;
182  size_t ele_d = 0;
183  while (h_it.isNext())
184  {
185  auto key = h_it.get();
186 
187  // Point p
188  Point<dim,T> p;
189 
190  for (size_t i = 0 ; i < dim ; i++)
191  p.get(i) = key.get(i) * spacing[i] + spacing[i] / 2;
192 
193  grid_key_dx<dim> sp = cd_sm.getCellGrid(p);
194 
195  if (g.template get<0>(sp) == -1)
196  {
197  g.template get<0>(sp) = proc_d;
198  ele_d++;
199 
200  if (ele_d >= accu.get(proc_d))
201  proc_d++;
202  }
203 
204  ++h_it;
205  }
206 
207  // Fill from the grid to the graph
208 
209  // Reset the grid to -1
211  while (it2.isNext())
212  {
213  auto key = it2.get();
214 
215  gp.template vertex_p<nm_v_proc_id>(gr.LinId(key)) = g.template get<0>(key);
216 
217  ++it2;
218  }
219 
220  return;
221  }
222 
228  void refine()
229  {
230  std::cout << __FILE__ << ":" << __LINE__ << " You are trying to dynamicaly balance a fixed decomposition, this operation has no effect" << std::endl;
231  }
232 
237  float getUnbalance()
238  {
239  return gr.size() % v_cl.getProcessingUnits();
240  }
241 
248  void getSubSubDomainPosition(size_t id, T (&pos)[dim])
249  {
250 #ifdef SE_CLASS1
251  if (id >= gp.getNVertex())
252  std::cerr << __FILE__ << ":" << __LINE__ << "Such vertex doesn't exist (id = " << id << ", " << "total size = " << gp.getNVertex() << ")\n";
253 #endif
254 
255  // Copy the geometrical informations inside the pos vector
256  pos[0] = gp.vertex(id).template get<nm_v_x>()[0];
257  pos[1] = gp.vertex(id).template get<nm_v_x>()[1];
258  if (dim == 3)
259  pos[2] = gp.vertex(id).template get<nm_v_x>()[2];
260  }
261 
268  inline void setComputationCost(size_t id, size_t weight)
269  {
270  std::cout << __FILE__ << ":" << __LINE__ << " You are trying to set the computation cost on a fixed decomposition, this operation has no effect" << std::endl;
271  }
272 
278  {
279  return false;
280  }
281 
290  {
291  return 1.0;
292  }
293 
299  {
300  // Get the number of processing units
301  size_t Np = v_cl.getProcessingUnits();
302 
303  // Calculate the best number of sub-domains for each
304  // processor
305  size_t N_tot = gr.size();
306  size_t N_best_each = N_tot / Np;
307  size_t N_rest = N_tot % Np;
308 
309  if (v_cl.getProcessUnitID() < N_rest)
310  N_best_each += 1;
311 
312  return N_best_each;
313  }
314 
320  void setMigrationCost(size_t id, size_t migration)
321  {
322  }
323 
330  void setCommunicationCost(size_t v_id, size_t e, size_t communication)
331  {
332  }
333 
340  {
341  return gp.getNVertex();
342  }
343 
348  size_t getNSubSubDomainNeighbors(size_t id)
349  {
350  return gp.getNChilds(id);
351  }
352 
358  void write(const std::string & file)
359  {
360  VTKWriter<Graph_CSR<nm_v<dim>, nm_e>, VTK_GRAPH> gv2(gp);
361  gv2.write(std::to_string(v_cl.getProcessUnitID()) + "_" + file + ".vtk");
362  }
363 
364  const SpaceDistribution<dim,T> & operator=(const SpaceDistribution<dim,T> & dist)
365  {
366  gr = dist.gr;
367  domain = dist.domain;
368  gp = dist.gp;
369 
370  return *this;
371  }
372 
373  const SpaceDistribution<dim,T> & operator=(SpaceDistribution<dim,T> && dist)
374  {
375  v_cl = dist.v_cl;
376  gr = dist.gr;
377  domain = dist.domain;
378  gp.swap(dist.gp);
379 
380  return *this;
381  }
382 
390  size_t get_ndec()
391  {
392  return 0;
393  }
394 };
395 
396 
397 #endif /* SRC_DECOMPOSITION_DISTRIBUTION_SPACEDISTRIBUTION_HPP_ */
bool weightsAreUsed()
Checks if weights are used on the vertices.
SpaceDistribution(const ParMetisDistribution< dim, T > &pm)
Graph_CSR< nm_v< dim >, nm_e > gp
Global sub-sub-domain graph.
Vcluster & v_cl
Vcluster.
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.
void setComputationCost(size_t id, size_t weight)
Function that set the weight of the vertex.
__device__ __host__ size_t size() const
Return the size of the grid.
Definition: grid_sm.hpp:637
SpaceDistribution(Vcluster<> &v_cl)
Class that distribute sub-sub-domains across processors using an hilbert curve to divide the space.
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:27
void write(const std::string &file)
Print the current distribution and save it to VTK file.
Graph_CSR< nm_v< dim >, nm_e > & getGraph()
Get the current graph (main)
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
This class construct a cartesian graph.
void setMigrationCost(size_t id, size_t migration)
Set migration cost of the vertex id.
Class that distribute sub-sub-domains across processors using ParMetis Library.
size_t getSubSubDomainComputationCost(size_t id)
function that get the weight of the vertex
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition: Point.hpp:172
sub-domain edge graph node
const grid_key_dx< dim > & get() const
Get the actual key.
const size_t(& getSize() const)[N]
Return the size of the grid as an array.
Definition: grid_sm.hpp:740
Box< dim, T > domain
rectangular domain to decompose
SpaceDistribution(SpaceDistribution< dim, T > &&pm)
size_t getNSubSubDomains()
Returns total number of sub-sub-domains in the distribution graph.
size_t getProcessorLoad()
Compute the processor load counting the total weights of its vertices.
size_t getProcessingUnits()
Get the total number of processors.
void setCommunicationCost(size_t v_id, size_t e, size_t communication)
Set communication cost of the edge id.
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
void getSubSubDomainPosition(size_t id, T(&pos)[dim])
function that return the position of the vertex in the space
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
void createCartGraph(grid_sm< dim, void > &grid, Box< dim, T > dom)
Create the Cartesian graph.
void swap(Graph_CSR< V, E > &g)
swap the memory of g with this graph
Definition: map_graph.hpp:976
grid_sm< dim, void > gr
Structure that store the cartesian grid information.
size_t get_ndec()
It return the decomposition id.
const grid_key_dx< dim > & get()
Get the actual key.
void decompose()
Create the decomposition.
float getUnbalance()
Compute the unbalance of the processor compared to the optimal balance.
bool isNext()
Check if there is the next element.
bool isNext()
Check if there is the next element.
size_t getNSubSubDomainNeighbors(size_t id)
Returns total number of neighbors of the sub-sub-domain id.