Ordering.cxx
1 // Copyright (C) 2011 Marc DuruflĂ©
2 // Copyright (C) 2011 Vivien Mallet
3 //
4 // This file is part of the linear-algebra library Seldon,
5 // http://seldon.sourceforge.net/.
6 //
7 // Seldon is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your option)
10 // any later version.
11 //
12 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with Seldon. If not, see http://www.gnu.org/licenses/.
19 
20 
21 #ifndef SELDON_FILE_SOLVER_ORDERING_CXX
22 #define SELDON_FILE_SOLVER_ORDERING_CXX
23 
24 
25 #include "Ordering.hxx"
26 
27 
28 namespace Seldon
29 {
30 
31 
33  template<class T, class Prop, class Storage, class Allocator,
34  class Tint, class Alloc>
36  Storage, Allocator>& A,
38  {
39  int n = A.GetM();
40  if (n <= 0)
41  {
42  num.Clear();
43  return;
44  }
45 
46  // Pattern of A + A' is retrieved in CSC format.
49  Vector<T0> Value;
50  General sym;
51  ConvertToCSC(A, sym, Ptr, Ind, Value, true);
52  Value.Clear();
53 
54  // Allocation of arrays.
55  Vector<Tint, VectFull, Alloc> vertex(n), neighbor(n);
56  Vector<bool> RowUsed(n);
57  IVect nb_neighbor(n);
58 
59  num.Reallocate(n);
60  num.Fill(0);
61  RowUsed.Fill(false);
62  vertex.Fill(0);
63  neighbor.Fill(0);
64  nb_neighbor.Fill(0);
65 
66  // Starting with the first row.
67  int nb_row = 1;
68  int nb_active_row = 1;
69  vertex(0) = 0;
70  num(0) = 0;
71  RowUsed(0) = true;
72  int first_free_row = 1;
73 
74  // Loop until all rows are found.
75  while (nb_row < n)
76  {
77  // Searching all neighboring rows.
78  int nb = 0;
79  for (int i = 0; i < nb_active_row; i++)
80  {
81  int irow = vertex(i);
82  for (int j = Ptr(irow); j < Ptr(irow+1); j++)
83  {
84  int icol = Ind(j);
85  if (!RowUsed(icol))
86  {
87  RowUsed(icol) = true;
88  neighbor(nb) = icol;
89  nb_neighbor(nb) = Ptr(icol+1) - Ptr(icol);
90  nb++;
91  }
92  }
93  }
94 
95  if (nb == 0)
96  {
97  // No row has been found, therefore there are independent blocks
98  // in the matrix; searching next free row.
99  while (RowUsed(first_free_row))
100  first_free_row++;
101 
102  RowUsed(first_free_row) = true;
103  num(nb_row) = first_free_row;
104  nb_active_row = 1;
105  vertex(0) = first_free_row;
106  nb_row++;
107  }
108  else
109  {
110  // Sorting neighboring vertices by the number of adjacent
111  // vertices.
112  Sort(nb, nb_neighbor, neighbor);
113 
114  // Then adding those rows.
115  nb_active_row = nb;
116  for (int i = 0; i < nb; i++)
117  {
118  vertex(i) = neighbor(i);
119  num(nb_row) = neighbor(i);
120  nb_row++;
121  }
122  }
123  }
124 
125  // Reverting final result.
126  for (int i = 0; i < n; i++)
127  vertex(i) = num(i);
128 
129  for (int i = 0; i < n; i++)
130  num(n-1-i) = vertex(i);
131  }
132 
133 
135  template<class T, class Prop, class Storage, class Allocator,
136  class Tint, class Alloc>
138  Vector<Tint, VectFull, Alloc>& num, int type)
139  {
141  int n = A.GetM();
142  if (n <= 0)
143  {
144  num.Clear();
145  return;
146  }
147 
148  if (type == SparseMatrixOrdering::AUTO)
149  {
150 #if defined(SELDON_WITH_MUMPS) || defined(SELDON_WITH_PASTIX)
151  type = SparseMatrixOrdering::SCOTCH;
152 #elif defined(SELDON_WITH_MUMPS) || defined(SELDON_WITH_PASTIX)
153  type = SparseMatrixOrdering::COLAMD;
154 #else
155  type = SparseMatrixOrdering::IDENTITY;
156 #endif
157  }
158 
159  switch (type)
160  {
161  case SparseMatrixOrdering::IDENTITY :
162  {
163  // No permutation.
164  num.Reallocate(n);
165  num.Fill();
166  }
167  break;
168 
169  case SparseMatrixOrdering::REVERSE_CUTHILL_MCKEE :
170  {
171  // Reverse Cuthill-McKee.
173  }
174  break;
175 
176  case SparseMatrixOrdering::PORD :
177  {
178  // Pord package provided by Mumps.
179 #ifdef SELDON_WITH_MUMPS
180  MatrixMumps<T0> mat_lu;
181  mat_lu.SelectOrdering(4);
182  mat_lu.FindOrdering(A, num, true);
183 #else
184  throw Error("FindSparseOrdering(Matrix&, Vector&, int)",
185  "PORD is supported when Mumps is available.");
186 #endif
187  }
188  break;
189 
190  case SparseMatrixOrdering::SCOTCH :
191  {
192  // Scotch interface provided by Pastix.
193 #ifdef SELDON_WITH_PASTIX
194  MatrixPastix<T0> mat_lu;
195  mat_lu.FindOrdering(A, num, true);
196 #elif defined(SELDON_WITH_MUMPS)
197  MatrixMumps<T0> mat_lu;
198  mat_lu.SelectOrdering(3);
199  mat_lu.FindOrdering(A, num, true);
200 #else
201  throw Error("FindSparseOrdering(Matrix&, Vector&, int)",
202  "SCOTCH is supported when Mumps or Pastix is available.");
203 #endif
204  }
205  break;
206 
207  case SparseMatrixOrdering::METIS :
208  {
209  // Metis ordering provided by Mumps.
210 #ifdef SELDON_WITH_MUMPS
211  MatrixMumps<T0> mat_lu;
212  mat_lu.SelectOrdering(5);
213  mat_lu.FindOrdering(A, num, true);
214 #else
215  throw Error("FindSparseOrdering(Matrix&, Vector&, int)",
216  "METIS is supported when Mumps is available.");
217 #endif
218  }
219  break;
220 
221  case SparseMatrixOrdering::AMD :
222  {
223  // Camd package in SuiteSparse (containing UmfPack).
224 #ifdef SELDON_WITH_UMFPACK
225 
226  num.Reallocate(n);
227 
228  // pattern of A+A' is retrieved in CSC format
230  Vector<T0> Value;
231  General sym;
232  ConvertToCSC(A, sym, Ptr, Ind, Value, true);
233  Value.Clear();
234 
235  // then calling camd
237  C.Fill(0);
238  double Control[CAMD_CONTROL], Info[CAMD_INFO];
239  camd_defaults(Control);
240  camd_order(n, Ptr.GetData(), Ind.GetData(),
241  num.GetData(), Control, Info, C.GetData());
242 
243 #else
244  throw Error("FindSparseOrdering(Matrix&, Vector&, int)",
245  "AMD is supported when UmfPack is available.");
246 #endif
247  }
248  break;
249 
250  case SparseMatrixOrdering::COLAMD :
251  {
252  // Colamd package in SuiteSparse (containing UmfPack).
253 #ifdef SELDON_WITH_UMFPACK
254 
255  num.Reallocate(n);
256 
257  // Pattern of A + A' is retrieved in CSC format.
259  Vector<T0> Value;
260  General sym;
261  ConvertToCSC(A, sym, Ptr, Ind, Value, true);
262  Value.Clear();
263 
264  int nnz = Ind.GetM();
265  Ind.Resize(2*nnz + 12*n);
266 
267  // then calling colamd
268  int Stats[COLAMD_STATS];
269  int ok = colamd(n, n, Ind.GetM(), Ind.GetData(), Ptr.GetData(), NULL, Stats);
270  if (ok != 1)
271  {
272 #ifndef SELDON_WITH_SUPERLU_MT
273  colamd_report(Stats);
274  throw Error("FindSparseOrdering(Matrix&, Vector&, int)",
275  "COLAMD failed");
276 #endif
277  }
278 
279  for (int i = 0; i < n; i++)
280  num(i) = Ptr(i);
281 #else
282  throw Error("FindSparseOrdering(Matrix&, Vector&, int)",
283  "COLAMD is supported when UmfPack is available.");
284 #endif
285  }
286  break;
287 
288  case SparseMatrixOrdering::QAMD :
289  {
290  // Qamd ordering provided by Mumps
291 #ifdef SELDON_WITH_MUMPS
292  MatrixMumps<T0> mat_lu;
293  mat_lu.SelectOrdering(6);
294  mat_lu.FindOrdering(A, num, true);
295 #else
296  throw Error("FindSparseOrdering(Matrix&, Vector&, int)",
297  "QAMD is supported when Mumps is available.");
298 #endif
299  }
300  break;
301 
302  case SparseMatrixOrdering::USER :
303  // nothing to do
304  break;
305  }
306  }
307 
308 } // namespace Seldon.
309 
310 
311 #endif
Seldon::MatrixPastix
Definition: Pastix.hxx:39
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::MatrixMumps::FindOrdering
void FindOrdering(Matrix< T0, Prop, Storage, Allocator > &mat, IVect &numbers, bool keep_matrix=false)
Computes an ordering for matrix renumbering.
Definition: Mumps.cxx:336
Seldon::MatrixMumps
object used to solve linear system by calling mumps subroutines
Definition: Mumps.hxx:59
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::Error
Definition: Errors.hxx:38
Seldon::FindReverseCuthillMcKeeOrdering
void FindReverseCuthillMcKeeOrdering(const Matrix< T, Prop, Storage, Allocator > &A, Vector< Tint, VectFull, Alloc > &num)
Constructs reverse Cuthill-McKee ordering from a given matrix.
Definition: Ordering.cxx:35
Seldon::FindSparseOrdering
void FindSparseOrdering(Matrix< T, Prop, Storage, Allocator > &A, Vector< Tint, VectFull, Alloc > &num, int type)
Constructs an ordering for the factorization of a sparse matrix.
Definition: Ordering.cxx:137
Seldon::General
Definition: Properties.hxx:26
Seldon::MatrixPastix::FindOrdering
void FindOrdering(Matrix< T0, Prop, Storage, Allocator > &mat, Vector< Tint > &numbers, bool keep_matrix=false)
Returning ordering found by Scotch.
Definition: Pastix.cxx:197
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::MatrixMumps::SelectOrdering
void SelectOrdering(int num_ordering)
Selects another ordering scheme.
Definition: Mumps.cxx:203