ViennaCL - The Vienna Computing Library  1.7.0
Free open-source GPU-accelerated linear algebra and solver library.
bandwidth-reduction.cpp
Go to the documentation of this file.
1 /* =========================================================================
2  Copyright (c) 2010-2015, Institute for Microelectronics,
3  Institute for Analysis and Scientific Computing,
4  TU Wien.
5  Portions of this software are copyright by UChicago Argonne, LLC.
6 
7  -----------------
8  ViennaCL - The Vienna Computing Library
9  -----------------
10 
11  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
12 
13  (A list of authors and contributors can be found in the PDF manual)
14 
15  License: MIT (X11), see file LICENSE in the base directory
16 ============================================================================= */
17 
27 #include <iostream>
28 #include <fstream>
29 #include <string>
30 #include <algorithm>
31 #include <map>
32 #include <vector>
33 #include <deque>
34 #include <cmath>
35 
37 
38 
49 inline std::vector< std::map<int, double> > reorder_matrix(std::vector< std::map<int, double> > const & matrix, std::vector<int> const & r)
50 {
51  std::vector< std::map<int, double> > matrix2(r.size());
52 
53  for (std::size_t i = 0; i < r.size(); i++)
54  for (std::map<int, double>::const_iterator it = matrix[i].begin(); it != matrix[i].end(); it++)
55  matrix2[static_cast<std::size_t>(r[i])][r[static_cast<std::size_t>(it->first)]] = it->second;
56 
57  return matrix2;
58 }
59 
64 inline int calc_bw(std::vector< std::map<int, double> > const & matrix)
65 {
66  int bw = 0;
67 
68  for (std::size_t i = 0; i < matrix.size(); i++)
69  {
70  int min_index = static_cast<int>(matrix.size());
71  int max_index = 0;
72  for (std::map<int, double>::const_iterator it = matrix[i].begin(); it != matrix[i].end(); it++)
73  {
74  if (it->first > max_index)
75  max_index = it->first;
76  if (it->first < min_index)
77  min_index = it->first;
78  }
79 
80  if (max_index > min_index) //row isn't empty
81  bw = std::max(bw, max_index - min_index);
82  }
83 
84  return bw;
85 }
86 
91 template<typename IndexT>
92 int calc_reordered_bw(std::vector< std::map<int, double> > const & matrix, std::vector<IndexT> const & r)
93 {
94  int bw = 0;
95 
96  for (std::size_t i = 0; i < r.size(); i++)
97  {
98  int min_index = static_cast<int>(matrix.size());
99  int max_index = 0;
100  for (std::map<int, double>::const_iterator it = matrix[i].begin(); it != matrix[i].end(); it++)
101  {
102  std::size_t col_idx = static_cast<std::size_t>(it->first);
103  if (r[col_idx] > max_index)
104  max_index = r[col_idx];
105  if (r[col_idx] < min_index)
106  min_index = r[col_idx];
107  }
108  if (max_index > min_index)
109  bw = std::max(bw, max_index - min_index);
110  }
111 
112  return bw;
113 }
114 
121 inline std::vector<int> generate_random_reordering(std::size_t n)
122 {
123  std::vector<int> r(n);
124  int tmp;
125 
126  for (std::size_t i = 0; i < n; i++)
127  r[i] = static_cast<int>(i);
128 
129  for (std::size_t i = 0; i < n - 1; i++)
130  {
131  std::size_t j = i + static_cast<std::size_t>((static_cast<double>(rand()) / static_cast<double>(RAND_MAX)) * static_cast<double>(n - 1 - i));
132  if (j != i)
133  {
134  tmp = r[i];
135  r[i] = r[j];
136  r[j] = tmp;
137  }
138  }
139 
140  return r;
141 }
142 
152 inline std::vector< std::map<int, double> > gen_3d_mesh_matrix(std::size_t l, std::size_t m, std::size_t n, bool tri)
153 {
154  std::vector< std::map<int, double> > matrix;
155  std::size_t s = l * m * n;
156  std::size_t ind;
157  std::size_t ind1;
158  std::size_t ind2;
159 
160  matrix.resize(s);
161  for (std::size_t i = 0; i < l; i++)
162  {
163  for (std::size_t j = 0; j < m; j++)
164  {
165  for (std::size_t k = 0; k < n; k++)
166  {
167  ind = i + l * j + l * m * k;
168 
169  matrix[ind][static_cast<int>(ind)] = 1.0;
170 
171  if (i > 0)
172  {
173  ind2 = ind - 1;
174  matrix[ind][static_cast<int>(ind2)] = 1.0;
175  matrix[ind2][static_cast<int>(ind)] = 1.0;
176  }
177  if (j > 0)
178  {
179  ind2 = ind - l;
180  matrix[ind][static_cast<int>(ind2)] = 1.0;
181  matrix[ind2][static_cast<int>(ind)] = 1.0;
182  }
183  if (k > 0)
184  {
185  ind2 = ind - l * m;
186  matrix[ind][static_cast<int>(ind2)] = 1.0;
187  matrix[ind2][static_cast<int>(ind)] = 1.0;
188  }
189 
190  if (tri)
191  {
192  if (i < l - 1 && j < m - 1)
193  {
194  if ((i + j + k) % 2 == 0)
195  {
196  ind1 = ind;
197  ind2 = ind + 1 + l;
198  }
199  else
200  {
201  ind1 = ind + 1;
202  ind2 = ind + l;
203  }
204  matrix[ind1][static_cast<int>(ind2)] = 1.0;
205  matrix[ind2][static_cast<int>(ind1)] = 1.0;
206  }
207  if (i < l - 1 && k < n - 1)
208  {
209  if ((i + j + k) % 2 == 0)
210  {
211  ind1 = ind;
212  ind2 = ind + 1 + l * m;
213  }
214  else
215  {
216  ind1 = ind + 1;
217  ind2 = ind + l * m;
218  }
219  matrix[ind1][static_cast<int>(ind2)] = 1.0;
220  matrix[ind2][static_cast<int>(ind1)] = 1.0;
221  }
222  if (j < m - 1 && k < n - 1)
223  {
224  if ((i + j + k) % 2 == 0)
225  {
226  ind1 = ind;
227  ind2 = ind + l + l * m;
228  }
229  else
230  {
231  ind1 = ind + l;
232  ind2 = ind + l * m;
233  }
234  matrix[ind1][static_cast<int>(ind2)] = 1.0;
235  matrix[ind2][static_cast<int>(ind1)] = 1.0;
236  }
237  }
238  }
239  }
240  }
241 
242  return matrix;
243 }
244 
245 
252 int main(int, char **)
253 {
254  srand(42);
255  std::cout << "-- Generating matrix --" << std::endl;
256  std::size_t dof_per_dim = 64; //number of grid points per coordinate direction
257  std::size_t n = dof_per_dim * dof_per_dim * dof_per_dim; //total number of unknowns
258  std::vector< std::map<int, double> > matrix = gen_3d_mesh_matrix(dof_per_dim, dof_per_dim, dof_per_dim, false); //If last parameter is 'true', a tetrahedral grid instead of a hexahedral grid is used.
259 
263  std::vector<int> r = generate_random_reordering(n);
264  std::vector< std::map<int, double> > matrix2 = reorder_matrix(matrix, r);
265 
266 
270  std::cout << " * Unknowns: " << n << std::endl;
271  std::cout << " * Initial bandwidth: " << calc_bw(matrix) << std::endl;
272  std::cout << " * Randomly reordered bandwidth: " << calc_bw(matrix2) << std::endl;
273 
277  std::cout << "-- Cuthill-McKee algorithm --" << std::endl;
280  std::cout << " * Reordered bandwidth: " << calc_reordered_bw(matrix2, r) << std::endl;
281 
285  std::cout << "-- Advanced Cuthill-McKee algorithm --" << std::endl;
286  double a = 0.0;
287  std::size_t gmax = 1;
289  std::cout << " * Reordered bandwidth: " << calc_reordered_bw(matrix2, r) << std::endl;
290 
294  std::cout << "-- Gibbs-Poole-Stockmeyer algorithm --" << std::endl;
296  std::cout << " * Reordered bandwidth: " << calc_reordered_bw(matrix2, r) << std::endl;
297 
301  std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl;
302 
303  return EXIT_SUCCESS;
304 }
std::vector< IndexT > reorder(std::vector< std::map< IndexT, ValueT > > const &matrix, cuthill_mckee_tag)
Function for the calculation of a node number permutation to reduce the bandwidth of an incidence mat...
int main()
Definition: bisect.cpp:91
Convenience include for bandwidth reduction algorithms such as Cuthill-McKee or Gibbs-Poole-Stockmeye...
T max(const T &lhs, const T &rhs)
Maximum.
Definition: util.hpp:59
Tag class for identifying the Gibbs-Poole-Stockmeyer algorithm for reducing the bandwidth of a sparse...
IndexT calc_reordered_bw(std::vector< std::map< IndexT, ValueT > > const &matrix, std::vector< bool > &dof_assigned_to_node, std::vector< IndexT > const &permutation)
Tag for the advanced Cuthill-McKee algorithm (i.e. running the 'standard' Cuthill-McKee algorithm for...
A tag class for selecting the Cuthill-McKee algorithm for reducing the bandwidth of a sparse matrix...