Pardiso.cxx
1 // Copyright (C) 2003-20013 Marc DuruflĂ©
2 //
3 // This file is part of the linear-algebra library Seldon,
4 // http://seldon.sourceforge.net/.
5 //
6 // Seldon is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your option)
9 // any later version.
10 //
11 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
14 // more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with Seldon. If not, see http://www.gnu.org/licenses/.
18 
19 
20 #ifndef SELDON_FILE_PARDISO_CXX
21 
22 #include "Pardiso.hxx"
23 
24 namespace Seldon
25 {
26 
28  template<class T>
30  {
31  size_matrix = 0;
32  mtype = 0;
33  maxfct = 1;
34  mnum = 1;
35  msglvl = 0;
36  info_facto = 0;
37  type_ordering = 2;
38  }
39 
40 
42  template<class T>
44  {
45  Clear();
46  }
47 
48 
49  template<class T>
50  bool MatrixPardiso<T>::UseInteger8() const
51  {
52  if (sizeof(pardiso_int_t) == 8)
53  return true;
54 
55  return false;
56  }
57 
58 
60  template<class T>
62  {
63  // releasing internal memory
64  if (size_matrix > 0)
65  {
66  double ddum;
67  pardiso_int_t nrhs = 0;
68  pardiso_int_t phase = 0, error;
69  // MKL version :
70  call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
71  valA.GetData(), ptrA.GetData(), indA.GetData(),
72  perm.GetData(), &nrhs, iparm, &msglvl,
73  &ddum, &ddum, &error);
74 
75  // recent version :
76  /* call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
77  valA.GetData(), ptrA.GetData(), indA.GetData(),
78  perm.GetData(), &nrhs, iparm, &msglvl,
79  &ddum, &ddum, &error, dparm); */
80 
81  size_matrix = 0;
82 
83  // and values of matrix
84  ptrA.Clear();
85  indA.Clear();
86  valA.Clear();
87  }
88  }
89 
90 
92  template<class T>
94  {
95  type_ordering = 2;
96  }
97 
98 
100  template<class T>
102  {
103  perm.Reallocate(permut.GetM());
104  for (int i = 0; i < perm.GetM(); i++)
105  perm(i) = permut(i) + 1;
106  }
107 
108 
110  template<class T>
112  {
113  msglvl = 0;
114  }
115 
116 
118  template<class T>
120  {
121  msglvl = 1;
122  }
123 
124 
126  template<class T>
128  {
129  return info_facto;
130  }
131 
132 
134  template<class T>
136  {
137  size_t taille = sizeof(pardiso_int_t)*ptrA.GetM();
138  if (size_matrix <= 0)
139  return taille;
140 
141  taille += sizeof(pardiso_int_t)*indA.GetM();
142  taille += sizeof(T)*valA.GetM();
143  taille += sizeof(pardiso_int_t)*perm.GetM();
144  taille += 1024*size_t(iparm[15]+iparm[16]);
145  return taille;
146  }
147 
148 
150  template<class T> template<class T0, class Prop, class Storage, class Allocator>
152  bool keep_matrix)
153  {
154  // previous factorization is cleared if present
155  Clear();
156 
157  // conversion of sparse matrix into CSR form
158  Prop prop;
159  ConvertToCSR(mat, prop, ptrA, indA, valA);
160  if (!keep_matrix)
161  mat.Clear();
162 
163  FactorizeCSR(IsSymmetricMatrix(mat));
164  }
165 
166 
168  template<class T>
170  Vector<pardiso_int_t>& IndCol,
171  Vector<T>& Values, bool sym)
172  {
173  // previous factorization is cleared if present
174  Clear();
175 
176  // structures are stored internally
177  ptrA.SetData(Ptr); Ptr.Nullify();
178  indA.SetData(IndCol); IndCol.Nullify();
179  valA.SetData(Values); Values.Nullify();
180 
181  // then factorization is performed
182  FactorizeCSR(sym);
183  }
184 
185 
186  template<class T>
187  void MatrixPardiso<T>::FactorizeCSR(bool sym)
188  {
189  // checking that the matrix is non-empty
190  size_matrix = ptrA.GetM()-1;
191  if (size_matrix <= 0)
192  return;
193 
194  // matrix type mtype
195  double ddum;
196  pardiso_int_t nrhs = 0;
197  mtype = 0;
198  if (IsComplexNumber(T()))
199  {
200  if (sym)
201  mtype = 6;
202  else
203  mtype = 13;
204  }
205  else
206  {
207  if (sym)
208  mtype = -2;
209  else
210  mtype = 11;
211  }
212 
213  // initialization of solver
214 
215  // recent version of pardiso :
216  /* pardiso_int_t solver = 0, error = 0;
217  iparm[0] = 0; iparm[2] = 1;
218  pardisoinit(pt, &mtype, &solver, iparm, dparm, &error);
219 
220  if (error != 0)
221  {
222  cout << "Error in the license file of Pardiso" << endl;
223  if (error == -10)
224  cout << "No license file pardiso.lic found" << endl;
225  else if (error == -11)
226  cout << "License is expired" << endl;
227  else if (error == -12)
228  cout << "Wrong username or hostname" << endl;
229 
230  abort();
231  } */
232 
233  // MKL version of pardiso :
234  pardiso_int_t error = 0; int mtype_ = mtype;
235  int iparm_[64]; iparm_[0] = 0; iparm_[2] = 1;
236  pardisoinit(pt, &mtype_, iparm_);
237 
238  for (int i = 0; i < 64; i++)
239  iparm[i] = iparm_[i];
240 
241  for (int i = 0; i < ptrA.GetM(); i++)
242  ptrA(i)++;
243 
244  for (int i = 0; i < indA.GetM(); i++)
245  indA(i)++;
246 
247  iparm[4] = 0;
248  if (perm.GetM() == size_matrix)
249  iparm[4] = 1;
250  else
251  iparm[1] = type_ordering;
252 
253  // reordering and symbolic factorization
254  pardiso_int_t phase = 11;
255  // MKL version
256  call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
257  valA.GetData(), ptrA.GetData(), indA.GetData(),
258  perm.GetData(), &nrhs, iparm, &msglvl,
259  &ddum, &ddum, &error);
260 
261  // recent version
262  /* call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
263  valA.GetData(), ptrA.GetData(), indA.GetData(),
264  perm.GetData(), &nrhs, iparm, &msglvl,
265  &ddum, &ddum, &error, dparm); */
266 
267  if (error != 0)
268  {
269  info_facto = error;
270  return;
271  }
272 
273  if (msglvl >= 1)
274  {
275  cout << "Reordering completed" << endl;
276  cout << "Number of non-zero factors = " << iparm[17] << endl;
277  cout << "Number of factorization MFLOPS = " << iparm[18] << endl;
278  }
279 
280  // numerical factorization
281  phase = 22;
282  // MKL version
283  call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
284  valA.GetData(), ptrA.GetData(), indA.GetData(),
285  perm.GetData(), &nrhs, iparm, &msglvl,
286  &ddum, &ddum, &error);
287 
288  // recent version
289  /*call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
290  valA.GetData(), ptrA.GetData(), indA.GetData(),
291  perm.GetData(), &nrhs, iparm, &msglvl,
292  &ddum, &ddum, &error, dparm); */
293 
294  if (error != 0)
295  {
296  info_facto = error;
297  cout << "Error during factorization " << error << endl;
298  return;
299  }
300 
301  if (msglvl >= 1)
302  cout << "Factorization completed" << endl;
303  }
304 
305 
307  template<class T> template<class Allocator2>
309  {
310  Solve(SeldonNoTrans, x);
311  }
312 
313 
316  template<class T> template<class Allocator2>
319  {
320  Solve(TransA, x.GetData(), 1);
321  }
322 
323 
326  template<class T>
328  T* x_ptr, int nrhs_)
329  {
330  if (size_matrix <= 0)
331  return;
332 
333  Matrix<T, General, ColMajor> b(size_matrix, nrhs_);
334  for (int i = 0; i < size_matrix; i++)
335  for (int j = 0; j < nrhs_; j++)
336  b(i, j) = x_ptr[i+j*size_matrix];
337 
338  pardiso_int_t nrhs = nrhs_;
339 
340  pardiso_int_t phase = 33, error;
341  iparm[5] = 0;
342  if (TransA.Trans())
343  iparm[11] = 2;
344  else
345  iparm[11] = 0;
346 
347  // MKL version
348  call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
349  valA.GetData(), ptrA.GetData(), indA.GetData(),
350  perm.GetData(), &nrhs, iparm, &msglvl,
351  b.GetData(), x_ptr, &error);
352 
353  // recent version
354  /* call_pardiso(pt, &maxfct, &mnum, &mtype, &phase, &size_matrix,
355  valA.GetData(), ptrA.GetData(), indA.GetData(),
356  perm.GetData(), &nrhs, iparm, &msglvl,
357  b.GetData(), x.GetData(), &error, dparm); */
358  }
359 
360 
363  template<class T>
364  template<class Allocator2, class Prop>
367  {
368  Solve(TransA, x.GetData(), x.GetN());
369  }
370 
371 
373  template<class MatrixSparse, class T>
374  void GetLU(MatrixSparse& A, MatrixPardiso<T>& mat_lu, bool keep_matrix, T& x)
375  {
376  mat_lu.FactorizeMatrix(A, keep_matrix);
377  }
378 
379 
381  template<class MatrixSparse, class T>
382  void GetLU(MatrixSparse& A, MatrixPardiso<T>& mat_lu,
383  bool keep_matrix, complex<T>& x)
384  {
385  throw WrongArgument("GetLU(Matrix<complex<T> >& A, MatrixPardiso<T>& mat_lu, bool)",
386  "The LU matrix must be complex");
387  }
388 
389 
391  template<class MatrixSparse, class T>
392  void GetLU(MatrixSparse& A, MatrixPardiso<complex<T> >& mat_lu,
393  bool keep_matrix, T& x)
394  {
395  throw WrongArgument("GetLU(Matrix<T>& A, MatrixPardiso<complex<T> >& mat_lu, bool)",
396  "The sparse matrix must be complex");
397  }
398 
399 
401  template<class T0, class Prop, class Storage, class Allocator, class T>
403  bool keep_matrix)
404  {
405  // we check if the type of non-zero entries of matrix A
406  // and of the Pardiso object (T) are different
407  // we call one of the GetLUs written above
408  // such a protection avoids to compile the factorisation of a complex
409  // matrix with a real Pardiso object
411  GetLU(A, mat_lu, keep_matrix, x);
412  }
413 
414 
416  template<class T, class Allocator>
418  {
419  mat_lu.Solve(x);
420  }
421 
422 
425  template<class T, class Allocator>
426  void SolveLU(const SeldonTranspose& TransA,
428  {
429  mat_lu.Solve(TransA, x);
430  }
431 
432 
434  template<class T, class Prop, class Allocator>
435  void SolveLU(MatrixPardiso<T>& mat_lu,
437  {
438  mat_lu.Solve(SeldonNoTrans, x);
439  }
440 
441 
444  template<class T, class Allocator, class Prop>
445  void SolveLU(const SeldonTranspose& TransA,
447  {
448  mat_lu.Solve(TransA, x);
449  }
450 
451 
453  template<class Allocator>
454  void SolveLU(MatrixPardiso<double>& mat_lu,
455  Vector<complex<double>, VectFull, Allocator>& x)
456  {
457  Matrix<double, General, ColMajor> y(x.GetM(), 2);
458 
459  for (int i = 0; i < x.GetM(); i++)
460  {
461  y(i, 0) = real(x(i));
462  y(i, 1) = imag(x(i));
463  }
464 
465  SolveLU(mat_lu, y);
466 
467  for (int i = 0; i < x.GetM(); i++)
468  x(i) = complex<double>(y(i, 0), y(i, 1));
469  }
470 
471 
473  template<class Allocator>
474  void SolveLU(const SeldonTranspose& TransA,
475  MatrixPardiso<double>& mat_lu,
476  Vector<complex<double>, VectFull, Allocator>& x)
477  {
478  Matrix<double, General, ColMajor> y(x.GetM(), 2);
479 
480  for (int i = 0; i < x.GetM(); i++)
481  {
482  y(i, 0) = real(x(i));
483  y(i, 1) = imag(x(i));
484  }
485 
486  SolveLU(TransA, mat_lu, y);
487 
488  for (int i = 0; i < x.GetM(); i++)
489  x(i) = complex<double>(y(i, 0), y(i, 1));
490  }
491 
492 
494  template<class Allocator>
495  void SolveLU(MatrixPardiso<complex<double> >& mat_lu,
497  {
498  throw WrongArgument("SolveLU(MatrixPardiso<complex<double> >, Vector<double>)",
499  "The result should be a complex vector");
500  }
501 
502 
504  template<class Allocator>
505  void SolveLU(const SeldonTranspose& TransA,
506  MatrixPardiso<complex<double> >& mat_lu,
508  {
509  throw WrongArgument("SolveLU(MatrixPardiso<complex<double> >, Vector<double>)",
510  "The result should be a complex vector");
511  }
512 
513 }
514 
515 #define SELDON_FILE_PARDISO_CXX
516 #endif
Seldon::MatrixPardiso::FactorizeCSR
void FactorizeCSR(Vector< pardiso_int_t > &Ptr, Vector< pardiso_int_t > &IndCol, Vector< T > &Values, bool sym)
Performs analysis and factorisation of a matrix given in CSR form.
Definition: Pardiso.cxx:169
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::MatrixPardiso
Definition: Pardiso.hxx:58
Seldon::Vector< int, VectFull >
Seldon::IsSymmetricMatrix
bool IsSymmetricMatrix(const Matrix< T, Prop, Storage, Allocator > &A)
returns true if the matrix is symmetric
Definition: Functions_BaseInline.cxx:778
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::MatrixPardiso::Solve
void Solve(Vector< T, VectFull, Allocator2 > &x)
solves A x = b, x contains the source b on input, the solution x on output
Definition: Pardiso.cxx:308
Seldon::MatrixPardiso::Clear
void Clear()
LU factorization is cleared.
Definition: Pardiso.cxx:61
Seldon::VectFull
Definition: StorageInline.cxx:74
Seldon::IsComplexNumber
bool IsComplexNumber(const T &number)
Returns true for a complex number.
Definition: CommonInline.cxx:293
Seldon::MatrixPardiso::GetMemorySize
size_t GetMemorySize() const
returns the size of memory used by numerical factorization in bytes
Definition: Pardiso.cxx:135
Seldon::MatrixPardiso::MatrixPardiso
MatrixPardiso()
default constructor
Definition: Pardiso.cxx:29
Seldon::MatrixPardiso::~MatrixPardiso
~MatrixPardiso()
destructor
Definition: Pardiso.cxx:43
Seldon::MatrixPardiso::SetPermutation
void SetPermutation(const IVect &permut)
Sets ordering.
Definition: Pardiso.cxx:101
Seldon::MatrixPardiso::ShowMessages
void ShowMessages()
Enables output messages.
Definition: Pardiso.cxx:119
Seldon::Vector< T, VectFull, Allocator >
Full vector class.
Definition: Vector.hxx:88
Seldon::GetLU
void GetLU(Matrix< T0, Prop0, Storage0, Allocator0 > &A)
Returns the LU factorization of a matrix.
Definition: Functions_Matrix.cxx:2073
Seldon::MatrixPardiso::SelectOrdering
void SelectOrdering(int type)
sets ordering algorithm to use
Definition: Pardiso.cxx:93
Seldon::MatrixPardiso::GetInfoFactorization
int GetInfoFactorization() const
returns the error code obtained during numerical factorization
Definition: Pardiso.cxx:127
Seldon::WrongArgument
Definition: Errors.hxx:76
Seldon::MatrixPardiso::FactorizeMatrix
void FactorizeMatrix(Matrix< T0, Prop, Storage, Allocator > &mat, bool keep_matrix=false)
performs analysis and factorization of matrix mat
Definition: Pardiso.cxx:151
Seldon::MatrixPardiso::HideMessages
void HideMessages()
Disables output messages.
Definition: Pardiso.cxx:111
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::Matrix< T, Prop, ColMajor, Allocator >
Column-major full-matrix class.
Definition: Matrix_Pointers.hxx:176