SparseDirectSolver.cxx
1 // Copyright (C) 2015 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 #ifndef SELDON_FILE_COMPUTATION_SPARSE_DIRECT_SOLVER_CXX
20 
21 #include "SparseDirectSolver.hxx"
22 
23 namespace Seldon
24 {
25 
27  template<class T>
29  {
30  n = 0;
31  type_ordering = SparseMatrixOrdering::AUTO;
32 
33  type_solver = SELDON_SOLVER;
34 
35  // we try to use an other available solver
36  // The order of preference is Pastix, Mumps, Pardiso, UmfPack and SuperLU
37 #ifdef SELDON_WITH_SUPERLU
38  type_solver = SUPERLU;
39 #endif
40 #ifdef SELDON_WITH_SUPERLU
41  type_solver = SUPERLU;
42 #endif
43 #ifdef SELDON_WITH_UMFPACK
44  type_solver = UMFPACK;
45 #endif
46 #ifdef SELDON_WITH_PARDISO
47  type_solver = PARDISO;
48 #endif
49 #ifdef SELDON_WITH_WSMP
50  type_solver = WSMP;
51 #endif
52 #ifdef SELDON_WITH_MUMPS
53  type_solver = MUMPS;
54 #endif
55 #ifdef SELDON_WITH_PASTIX
56  type_solver = PASTIX;
57 #endif
58 
59  nb_threads_per_node = 1;
60  threshold_matrix = 0;
61  print_level = 0;
62  refine_solution = false;
63  enforce_unsym_ilut = false;
64  // for this default value, the corresponding method of the
65  // sparse solver will not be called
66  pivot_threshold = -2.0;
67 
68  solver = NULL;
69  InitSolver();
70  }
71 
72 
74  template<class T>
76  {
77  if (solver != NULL)
78  delete solver;
79  }
80 
81 
83  template<class T>
85  {
86  if (n > 0)
87  {
88  solver->Clear();
89  n = 0;
90  }
91  }
92 
93 
95  template<class T>
97  {
98  switch (type)
99  {
100  case SELDON_SOLVER: return true;
101  case UMFPACK:
102 #ifdef SELDON_WITH_UMFPACK
103  return true;
104 #endif
105  return false;
106  case SUPERLU:
107 #ifdef SELDON_WITH_SUPERLU
108  return true;
109 #endif
110  return false;
111  case MUMPS:
112 #ifdef SELDON_WITH_MUMPS
113  return true;
114 #endif
115  return false;
116  case PASTIX:
117 #ifdef SELDON_WITH_PASTIX
118  return true;
119 #endif
120  return false;
121  case ILUT:
122 #ifdef SELDON_WITH_PRECONDITIONING
123  return true;
124 #endif
125  return false;
126  case PARDISO:
127 #ifdef SELDON_WITH_PARDISO
128  return true;
129 #endif
130  return false;
131  case WSMP:
132 #ifdef SELDON_WITH_WSMP
133  return true;
134 #endif
135  return false;
136  default:
137  return false;
138  }
139  }
140 
141 
142  template<class T>
144  {
145  bool user_ordering = false;
146  // we set the ordering for each direct solver interfaced
147  switch (type_ordering)
148  {
149  case SparseMatrixOrdering::AUTO :
150  {
151  // we choose the default strategy
152  // proposed by the direct solver that will be called
153  if (type_solver == MUMPS)
154  {
155  solver->SelectOrdering(7);
156  }
157  else if (type_solver == PASTIX)
158  {
159 #ifdef SELDON_WITH_PASTIX
160  solver->SelectOrdering(PastixOrderScotch);
161 #endif
162  }
163  else if (type_solver == PARDISO)
164  {
165  solver->SelectOrdering(2);
166  }
167  else if (type_solver == UMFPACK)
168  {
169 #ifdef SELDON_WITH_UMFPACK
170  solver->SelectOrdering(UMFPACK_ORDERING_AMD);
171 #endif
172  }
173  else if (type_solver == SUPERLU)
174  {
175 #ifdef SELDON_WITH_SUPERLU
176  solver->SelectOrdering(superlu::COLAMD);
177 #endif
178  }
179  else if (type_solver == WSMP)
180  {
181  }
182  else
183  {
184 
185  type_ordering = SparseMatrixOrdering::IDENTITY;
186 
187 #ifdef SELDON_WITH_UMFPACK
188  type_ordering = SparseMatrixOrdering::AMD;
189 #endif
190 
191 #ifdef SELDON_WITH_MUMPS
192  type_ordering = SparseMatrixOrdering::METIS;
193 #endif
194 
195 #ifdef SELDON_WITH_PARDISO
196  type_ordering = SparseMatrixOrdering::METIS;
197 #endif
198 
199 #ifdef SELDON_WITH_PASTIX
200  type_ordering = SparseMatrixOrdering::SCOTCH;
201 #endif
202 
203  user_ordering = true;
204  }
205  }
206  break;
207  case SparseMatrixOrdering::IDENTITY :
208  case SparseMatrixOrdering::REVERSE_CUTHILL_MCKEE :
209  case SparseMatrixOrdering::USER :
210  {
211  user_ordering = true;
212  }
213  break;
214  case SparseMatrixOrdering::PORD :
215  case SparseMatrixOrdering::AMF :
216  case SparseMatrixOrdering::QAMD :
217  {
218  // Mumps orderings
219  if (type_solver == MUMPS)
220  {
221 #ifdef SELDON_WITH_MUMPS
222  if (type_ordering == SparseMatrixOrdering::PORD)
223  solver->SelectOrdering(4);
224  else if (type_ordering == SparseMatrixOrdering::AMF)
225  solver->SelectOrdering(2);
226  else
227  solver->SelectOrdering(6);
228 #endif
229  }
230  else
231  {
232  user_ordering = true;
233  }
234  }
235  break;
236  case SparseMatrixOrdering::SCOTCH :
237  case SparseMatrixOrdering::PTSCOTCH :
238  {
239  // available for Mumps and Pastix
240  if (type_solver == MUMPS)
241  {
242 #ifdef SELDON_WITH_MUMPS
243  if (type_ordering==SparseMatrixOrdering::PTSCOTCH)
244  solver->SelectParallelOrdering(1);
245  else
246  solver->SelectOrdering(3);
247 #endif
248  }
249  else if (type_solver == PASTIX)
250  {
251 #ifdef SELDON_WITH_SCOTCH
252  if (type_ordering==SparseMatrixOrdering::PTSCOTCH)
253  solver->SelectOrdering(PastixOrderPtScotch);
254  else
255  solver->SelectOrdering(PastixOrderScotch);
256 #endif
257  }
258  else
259  {
260  user_ordering = true;
261  }
262  }
263  break;
264  case SparseMatrixOrdering::METIS :
265  case SparseMatrixOrdering::PARMETIS :
266  {
267  // available for Mumps and Pastix
268  if (type_solver == MUMPS)
269  {
270 #ifdef SELDON_WITH_MUMPS
271  if (type_ordering==SparseMatrixOrdering::PARMETIS)
272  solver->SelectParallelOrdering(2);
273  else
274  solver->SelectOrdering(5);
275 #endif
276  }
277  else if (type_solver == PASTIX)
278  {
279 #ifdef SELDON_WITH_PASTIX
280  if (type_ordering==SparseMatrixOrdering::PARMETIS)
281  solver->SelectOrdering(PastixOrderParMetis);
282  else
283  solver->SelectOrdering(PastixOrderMetis);
284 #endif
285  }
286  else if (type_solver == UMFPACK)
287  {
288 #ifdef SELDON_WITH_UMFPACK
289  solver->SelectOrdering(UMFPACK_ORDERING_METIS);
290 #endif
291  }
292  /*
293  currently not implemented in SuperLU
294  else if (type_solver == SUPERLU)
295  {
296 #ifdef SELDON_WITH_SUPERLU
297  if (type_ordering==SparseMatrixOrdering::PARMETIS)
298  solver->SelectOrdering(superlu::PARMETIS);
299  else
300  solver->SelectOrdering(superlu::METIS_AT_PLUS_A);
301 #endif
302  }
303  */
304  else
305  {
306  user_ordering = true;
307  }
308  }
309  break;
310  case SparseMatrixOrdering::AMD :
311  case SparseMatrixOrdering::COLAMD :
312  {
313  // default ordering for UmfPack
314  if (type_solver == UMFPACK)
315  {
316 #ifdef SELDON_WITH_UMFPACK
317  solver->SelectOrdering(UMFPACK_ORDERING_AMD);
318 #endif
319  }
320  else if (type_solver == MUMPS)
321  {
322 #ifdef SELDON_WITH_MUMPS
323  solver->SelectOrdering(0);
324 #endif
325  }
326  else if (type_solver == SUPERLU)
327  {
328 #ifdef SELDON_WITH_SUPERLU
329  solver->SelectOrdering(superlu::COLAMD);
330 #endif
331  }
332  else
333  {
334  user_ordering = true;
335  }
336  }
337  break;
338  case SparseMatrixOrdering::MMD_AT_PLUS_A:
339  {
340  if (type_solver == SUPERLU)
341  {
342 #ifdef SELDON_WITH_SUPERLU
343  solver->SelectOrdering(superlu::MMD_AT_PLUS_A);
344 #endif
345  }
346  }
347  break;
348  case SparseMatrixOrdering::MMD_ATA:
349  {
350  if (type_solver == SUPERLU)
351  {
352 #ifdef SELDON_WITH_SUPERLU
353  solver->SelectOrdering(superlu::MMD_ATA);
354 #endif
355  }
356  }
357  break;
358  }
359 
360  return user_ordering;
361  }
362 
363 
365  template<class T> template<class T0, class Prop, class Storage, class Alloc>
368  {
369  bool user_ordering = AffectOrdering();
370 
371  if (user_ordering)
372  {
373  // case where the ordering is not natively available in the direct solver
374  // computing separetely the ordering
375  FindSparseOrdering(A, permut, type_ordering);
376 
377  solver->SetPermutation(permut);
378  }
379 
380  }
381 
382 
384  template<class T>
386  {
387  threshold_matrix = eps;
388 #ifdef SELDON_WITH_ILUT
389  if (type_solver == ILUT)
390  dynamic_cast<IlutPreconditioning<T>& >(*solver)
391  .SetDroppingThreshold(eps);
392 #endif
393  }
394 
395 
397  template<class T>
399  {
400  if (solver != NULL)
401  delete solver;
402 
403  switch (type_solver)
404  {
405  case SUPERLU:
406 #ifdef SELDON_WITH_SUPERLU
407  solver = new MatrixSuperLU<T>();
408 #else
409  cout << "Seldon not compiled with SuperLU" << endl;
410  cout << "SELDON_WITH_SUPERLU is not defined" << endl;
411  abort();
412 #endif
413  break;
414  case UMFPACK:
415 #ifdef SELDON_WITH_UMFPACK
416  solver = new MatrixUmfPack<T>();
417 #else
418  cout << "Seldon not compiled with UmfPack" << endl;
419  cout << "SELDON_WITH_UMFPACK is not defined" << endl;
420  abort();
421 #endif
422  break;
423  case PARDISO:
424 #ifdef SELDON_WITH_PARDISO
425  solver = new MatrixPardiso<T>();
426 #else
427  cout << "Seldon not compiled with Pardiso" << endl;
428  cout << "SELDON_WITH_PARDISO is not defined" << endl;
429  abort();
430 #endif
431  break;
432  case MUMPS:
433 #ifdef SELDON_WITH_MUMPS
434  solver = new MatrixMumps<T>();
435 #else
436  cout << "Seldon not compiled with Mumps" << endl;
437  cout << "SELDON_WITH_MUMPS is not defined" << endl;
438  abort();
439 #endif
440  break;
441  case PASTIX:
442 #ifdef SELDON_WITH_PASTIX
443  solver = new MatrixPastix<T>();
444 #else
445  cout << "Seldon not compiled with Pastix" << endl;
446  cout << "SELDON_WITH_PASTIX is not defined" << endl;
447  abort();
448 #endif
449  break;
450  case WSMP:
451 #ifdef SELDON_WITH_WSMP
452  solver = new MatrixWsmp<T>();
453 #else
454  cout << "Seldon not compiled with Wsmp" << endl;
455  cout << "SELDON_WITH_WSMP is not defined" << endl;
456  abort();
457 #endif
458  break;
459  case ILUT:
460  {
461 #ifdef SELDON_WITH_PRECONDITIONING
462  IlutPreconditioning<T>* ilut_solver = new IlutPreconditioning<T>();
463  ilut_solver->SetDroppingThreshold(threshold_matrix);
464  solver = ilut_solver;
465 #else
466  cout << "Seldon not compiled with Preconditioning" << endl;
467  cout << "SELDON_WITH_PRECONDITIONING is not defined" << endl;
468  abort();
469 #endif
470  }
471  break;
472  case SELDON_SOLVER:
473  solver = new SparseSeldonSolver<T>();
474  break;
475  default:
476  cout << "Unknown solver" << endl;
477  abort();
478  }
479 
480  if (pivot_threshold != -2.0)
481  solver->SetPivotThreshold(pivot_threshold);
482 
483  if (refine_solution)
484  solver->RefineSolution();
485  else
486  solver->DoNotRefineSolution();
487 
488  solver->SetNumberOfThreadPerNode(nb_threads_per_node);
489  if (print_level > 0)
490  solver->ShowMessages();
491  else
492  solver->HideMessages();
493  }
494 
495 
497 
501  template<class T>
502  template<class Prop, class Storage, class Allocator>
504  bool keep_matrix)
505  {
506  ComputeOrdering(A);
507  n = A.GetM();
508  if (type_solver == UMFPACK)
509  {
510 #ifdef SELDON_WITH_UMFPACK
511  MatrixUmfPack<T>& mat_umf =
512  dynamic_cast<MatrixUmfPack<T>& >(*solver);
513 
514  GetLU(A, mat_umf, keep_matrix);
515 #else
516  throw Undefined("SparseDirectSolver::Factorize(MatrixSparse&, bool)",
517  "Seldon was not compiled with UmfPack support.");
518 #endif
519  }
520  else if (type_solver == SUPERLU)
521  {
522 #ifdef SELDON_WITH_SUPERLU
523  MatrixSuperLU<T>& mat_superlu =
524  dynamic_cast<MatrixSuperLU<T>& >(*solver);
525 
526  GetLU(A, mat_superlu, keep_matrix);
527 #else
528  throw Undefined("SparseDirectSolver::Factorize(MatrixSparse&, bool)",
529  "Seldon was not compiled with SuperLU support.");
530 #endif
531  }
532  else if (type_solver == PARDISO)
533  {
534 #ifdef SELDON_WITH_PARDISO
535  MatrixPardiso<T>& mat_pardiso =
536  dynamic_cast<MatrixPardiso<T>& >(*solver);
537 
538  GetLU(A, mat_pardiso, keep_matrix);
539 #else
540  throw Undefined("SparseDirectSolver::Factorize(MatrixSparse&, bool)",
541  "Seldon was not compiled with Pardiso support.");
542 #endif
543  }
544  else if (type_solver == MUMPS)
545  {
546 #ifdef SELDON_WITH_MUMPS
547  MatrixMumps<T>& mat_mumps =
548  dynamic_cast<MatrixMumps<T>& >(*solver);
549 
550  GetLU(A, mat_mumps, keep_matrix);
551 #else
552  throw Undefined("SparseDirectSolver::Factorize(MatrixSparse&, bool)",
553  "Seldon was not compiled with Mumps support.");
554 #endif
555  }
556  else if (type_solver == PASTIX)
557  {
558 #ifdef SELDON_WITH_PASTIX
559  MatrixPastix<T>& mat_pastix =
560  dynamic_cast<MatrixPastix<T>& >(*solver);
561 
562  GetLU(A, mat_pastix, keep_matrix);
563 #else
564  throw Undefined("SparseDirectSolver::Factorize(MatrixSparse&, bool)",
565  "Seldon was not compiled with Pastix support.");
566 #endif
567  }
568  else if (type_solver == WSMP)
569  {
570 #ifdef SELDON_WITH_WSMP
571  MatrixWsmp<T>& mat_wsmp =
572  dynamic_cast<MatrixWsmp<T>& >(*solver);
573 
574  GetLU(A, mat_wsmp, keep_matrix);
575 #else
576  throw Undefined("SparseDirectSolver::Factorize(MatrixSparse&, bool)",
577  "Seldon was not compiled with Wsmp support.");
578 #endif
579  }
580  else if (type_solver == ILUT)
581  {
582 #ifdef SELDON_WITH_PRECONDITIONING
583  IlutPreconditioning<T>& mat_ilut =
584  dynamic_cast<IlutPreconditioning<T>& >(*solver);
585 
586  // setting some parameters
587  if (enforce_unsym_ilut || (!IsSymmetricMatrix(A)))
588  mat_ilut.SetUnsymmetricAlgorithm();
589  else
590  mat_ilut.SetSymmetricAlgorithm();
591 
592  // then performing factorization
593  GetLU(A, mat_ilut, permut, keep_matrix);
594 #else
595  throw Undefined("SparseDirectSolver::Factorize(MatrixSparse&, bool)",
596  "Seldon was not compiled with the preconditioners.");
597 #endif
598  }
599  else
600  {
601  SparseSeldonSolver<T>& mat_seldon =
602  static_cast<SparseSeldonSolver<T>& >(*solver);
603 
604  GetLU(A, mat_seldon, permut, keep_matrix);
605  }
606  }
607 
608 
610  template <class T> template<class Prop, class Storage, class Allocator>
612  {
613  ComputeOrdering(A);
614  n = A.GetM();
615  if (type_solver == MUMPS)
616  {
617 #ifdef SELDON_WITH_MUMPS
618  MatrixMumps<T>& mat_mumps =
619  dynamic_cast<MatrixMumps<T>& >(*solver);
620 
621  mat_mumps.PerformAnalysis(A);
622 #else
623  throw Undefined("SparseDirectSolver::PerformAnalysis(MatrixSparse&, bool)",
624  "Seldon was not compiled with Mumps support.");
625 #endif
626  }
627  else
628  {
629  cout << "Not implemented for other solvers" << endl;
630  abort();
631  }
632  }
633 
634 
636  template <class T> template<class Prop, class Storage, class Allocator>
638  {
639  if (type_solver == MUMPS)
640  {
641 #ifdef SELDON_WITH_MUMPS
642  MatrixMumps<T>& mat_mumps =
643  dynamic_cast<MatrixMumps<T>& >(*solver);
644 
645  mat_mumps.PerformFactorization(A);
646 #else
647  throw Undefined("SparseDirectSolver::PerformAnalysis(MatrixSparse&, bool)",
648  "Seldon was not compiled with Mumps support.");
649 #endif
650  }
651  else
652  {
653  cout << "Not implemented for other solvers" << endl;
654  abort();
655  }
656  }
657 
658 
660  template <class T>
662  {
663  ierr = solver->GetInfoFactorization();
664  if (type_solver == UMFPACK)
665  {
666 #ifdef SELDON_WITH_UMFPACK
667  switch (ierr)
668  {
669  case UMFPACK_OK :
670  return FACTO_OK;
671  case UMFPACK_WARNING_singular_matrix :
672  return NUMERICALLY_SINGULAR_MATRIX;
673  case UMFPACK_ERROR_out_of_memory :
674  return OUT_OF_MEMORY;
675  case UMFPACK_ERROR_invalid_Numeric_object :
676  case UMFPACK_ERROR_invalid_Symbolic_object :
677  case UMFPACK_ERROR_argument_missing :
678  case UMFPACK_ERROR_different_pattern :
679  case UMFPACK_ERROR_invalid_system :
680  return INVALID_ARGUMENT;
681  case UMFPACK_ERROR_n_nonpositive :
682  return INCORRECT_NUMBER_OF_ROWS;
683  case UMFPACK_ERROR_invalid_matrix :
684  return MATRIX_INDICES_INCORRECT;
685  case UMFPACK_ERROR_invalid_permutation :
686  return INVALID_PERMUTATION;
687  case UMFPACK_ERROR_ordering_failed :
688  return ORDERING_FAILED;
689  default :
690  return INTERNAL_ERROR;
691  }
692 #endif
693  }
694  else if (type_solver == SUPERLU)
695  {
696 #ifdef SELDON_WITH_SUPERLU
697  if (ierr > 0)
698  return INTERNAL_ERROR;
699 #endif
700  }
701  else if (type_solver == MUMPS)
702  {
703 #ifdef SELDON_WITH_MUMPS
704  switch (ierr)
705  {
706  case -2 :
707  // nz out of range
708  return MATRIX_INDICES_INCORRECT;
709  case -3 :
710  // invalid job number
711  return INVALID_ARGUMENT;
712  case -4 :
713  // invalid permutation
714  return INVALID_PERMUTATION;
715  case -5 :
716  // problem of real workspace allocation
717  return OUT_OF_MEMORY;
718  case -6 :
719  // structurally singular matrix
720  return STRUCTURALLY_SINGULAR_MATRIX;
721  case -7 :
722  // problem of integer workspace allocation
723  return OUT_OF_MEMORY;
724  case -10 :
725  // numerically singular matrix
726  return NUMERICALLY_SINGULAR_MATRIX;
727  case -13 :
728  // allocate failed
729  return OUT_OF_MEMORY;
730  case -16 :
731  // N out of range
732  return INCORRECT_NUMBER_OF_ROWS;
733  case -22 :
734  // invalid pointer
735  return INVALID_ARGUMENT;
736  case 1 :
737  // index out of range
738  return MATRIX_INDICES_INCORRECT;
739  case 0 :
740  return FACTO_OK;
741  default :
742  return INTERNAL_ERROR;
743  }
744 #endif
745  }
746  else if (type_solver == PARDISO)
747  {
748 #ifdef SELDON_WITH_PARDISO
749  switch (ierr)
750  {
751  case -1 :
752  return INVALID_ARGUMENT;
753  case -2 :
754  case -9 :
755  return OUT_OF_MEMORY;
756  case -3 :
757  return INVALID_PERMUTATION;
758  case -4 :
759  return NUMERICALLY_SINGULAR_MATRIX;
760  case -6 :
761  return ORDERING_FAILED;
762  case -7 :
763  return STRUCTURALLY_SINGULAR_MATRIX;
764  case -8 :
765  return OVERFLOW_32BIT;
766  case 0 :
767  return FACTO_OK;
768  default :
769  return INTERNAL_ERROR;
770  }
771 #endif
772  }
773 
774  return FACTO_OK;
775  }
776 
777 
779 
782  template<class T>
784  {
785  Solve(SeldonNoTrans, x_solution);
786  }
787 
788 
790  template<class T>
792  Vector<T>& x_solution, bool assemble)
793  {
794 #ifdef SELDON_CHECK_DIMENSIONS
795  if (n != x_solution.GetM())
796  throw WrongDim("SparseDirectSolver::Solve",
797  string("The length of x is equal to ")
798  + to_str(x_solution.GetM())
799  + " while the size of the matrix is equal to "
800  + to_str(n) + ".");
801 #endif
802 
803  solver->Solve(trans, x_solution.GetData(), 1);
804  }
805 
806 
808 
812  template<class T>
815  {
816  Solve(SeldonNoTrans, x_solution);
817  }
818 
819 
821 
825  template<class T>
828  {
829 #ifdef SELDON_CHECK_DIMENSIONS
830  if (n != x_sol.GetM())
831  throw WrongDim("SparseDirectSolver::Solve",
832  string("The length of x is equal to ")
833  + to_str(x_sol.GetM())
834  + " while the size of the matrix is equal to "
835  + to_str(n) + ".");
836 #endif
837 
838  solver->Solve(trans, x_sol.GetData(), x_sol.GetN());
839  }
840 
841 
842 #ifdef SELDON_WITH_MPI
843 
858  template<class T> template<class Tint0, class Tint1>
860  FactorizeDistributed(MPI_Comm& comm_facto,
861  Vector<Tint0>& Ptr, Vector<Tint1>& Row, Vector<T>& Val,
862  const IVect& glob_num, bool sym, bool keep_matrix)
863  {
864  bool user_ordering = AffectOrdering();
865  if (user_ordering)
866  {
867  throw Undefined("SparseDirectSolver::FactorizeDistributed(MPI_Comm&,"
868  " IVect&, IVect&, Vector<T>&, IVect&, bool, bool)",
869  "user orderings not available in parallel");
870  }
871 
872  n = Ptr.GetM()-1;
873  solver->FactorizeDistributedMatrix(comm_facto, Ptr, Row, Val,
874  glob_num, sym, keep_matrix);
875 
876  }
877 
878 
880  template<class T> template<class Tint0, class Tint1>
881  void SparseDirectSolver<T>::
882  PerformAnalysisDistributed(MPI_Comm& comm_facto,
883  Vector<Tint0>& Ptr, Vector<Tint1>& Row, Vector<T>& Val,
884  const IVect& glob_num, bool sym, bool keep_matrix)
885  {
886  bool user_ordering = AffectOrdering();
887  if (user_ordering)
888  {
889  throw Undefined("SparseDirectSolver::PerformAnalysisDistributed(MPI_Comm&,"
890  " IVect&, IVect&, Vector<T>&, IVect&, bool, bool)",
891  "user orderings not available in parallel");
892  }
893 
894  n = Ptr.GetM()-1;
895  solver->PerformAnalysisDistributed(comm_facto, Ptr, Row, Val,
896  glob_num, sym, keep_matrix);
897 
898  }
899 
900 
902  template<class T> template<class Tint0, class Tint1>
903  void SparseDirectSolver<T>::
904  PerformFactorizationDistributed(MPI_Comm& comm_facto,
905  Vector<Tint0>& Ptr, Vector<Tint1>& Row, Vector<T>& Val,
906  const IVect& glob_num, bool sym, bool keep_matrix)
907  {
908  n = Ptr.GetM()-1;
909  solver->PerformFactorizationDistributed(comm_facto, Ptr, Row, Val,
910  glob_num, sym, keep_matrix);
911  }
912 
913 
915 
918  template<class T>
919  void SparseDirectSolver<T>::
920  SolveDistributed(MPI_Comm& comm_facto, Vector<T>& x_solution,
921  const IVect& glob_number)
922  {
923  SolveDistributed(comm_facto, SeldonNoTrans, x_solution, glob_number);
924  }
925 
926 
928 
931  template<class T>
932  void SparseDirectSolver<T>::
933  SolveDistributed(MPI_Comm& comm_facto, const SeldonTranspose& trans,
934  Vector<T>& x_solution, const IVect& glob_number)
935  {
936 #ifdef SELDON_CHECK_DIMENSIONS
937  if (n != x_solution.GetM())
938  throw WrongDim("SparseDirectSolver::SolveDistributed",
939  string("The length of x is equal to ")
940  + to_str(x_solution.GetM())
941  + " while the size of the matrix is equal to "
942  + to_str(n) + ".");
943 #endif
944 
945  solver->SolveDistributed(comm_facto, trans,
946  x_solution.GetData(), 1, glob_number);
947  }
948 
949 
951 
954  template<class T>
955  void SparseDirectSolver<T>::
956  SolveDistributed(MPI_Comm& comm_facto, Matrix<T, General, ColMajor>& x,
957  const IVect& glob_number)
958  {
959  SolveDistributed(comm_facto, SeldonNoTrans, x, glob_number);
960  }
961 
962 
964 
967  template<class T>
968  void SparseDirectSolver<T>::
969  SolveDistributed(MPI_Comm& comm_facto, const SeldonTranspose& trans,
970  Matrix<T, General, ColMajor>& x, const IVect& glob_number)
971  {
972 #ifdef SELDON_CHECK_DIMENSIONS
973  if (n != x.GetM())
974  throw WrongDim("SparseDirectSolver::SolveDistributed",
975  string("The length of x is equal to ")
976  + to_str(x.GetM())
977  + " while the size of the matrix is equal to "
978  + to_str(n) + ".");
979 #endif
980 
981  solver->SolveDistributed(comm_facto, trans,
982  x.GetData(), x.GetN(), glob_number);
983  }
984 
985 
986  template<class T>
987  void SolveLU_Distributed(MPI_Comm& comm, const SeldonTranspose& transA,
988  SparseDirectSolver<T>& mat_lu,
989  Vector<T>& x, Vector<int>& global_col)
990  {
991  mat_lu.SolveDistributed(comm, transA, x, global_col);
992  }
993 
994 
995  template<class T>
996  void SolveLU_Distributed(MPI_Comm& comm, const SeldonTranspose& transA,
997  SparseDirectSolver<complex<T> >& mat_lu,
998  Vector<T>& x, Vector<int>& global_col)
999  {
1000  throw WrongArgument("SolveLU(SparseDirectSolver, Vector, Vector)",
1001  "the result must be complex");
1002  }
1003 
1004 
1005  template<class T>
1006  void SolveLU_Distributed(MPI_Comm& comm, const SeldonTranspose& transA,
1007  SparseDirectSolver<T>& mat_lu,
1008  Vector<complex<T> >& x, Vector<int>& global_col)
1009  {
1010  Vector<T> xreal(x.GetM()), ximag(x.GetM());
1011  for (int i = 0; i < x.GetM(); i++)
1012  {
1013  xreal(i) = real(x(i));
1014  ximag(i) = imag(x(i));
1015  }
1016 
1017  mat_lu.SolveDistributed(comm, transA, xreal, global_col);
1018  mat_lu.SolveDistributed(comm, transA, ximag, global_col);
1019 
1020  for (int i = 0; i < x.GetM(); i++)
1021  x(i) = complex<T>(xreal(i), ximag(i));
1022  }
1023 
1024 
1025  template<class T>
1026  void SolveLU_Distributed(MPI_Comm& comm, const SeldonTranspose& transA,
1027  SparseDirectSolver<T>& mat_lu,
1028  Matrix<T, General, ColMajor>& x, Vector<int>& global_col)
1029  {
1030  mat_lu.SolveDistributed(comm, transA, x, global_col);
1031  }
1032 
1033 
1034  template<class T>
1035  void SolveLU_Distributed(MPI_Comm& comm, const SeldonTranspose& transA,
1036  SparseDirectSolver<complex<T> >& mat_lu,
1037  Matrix<T, General, ColMajor>& x, Vector<int>& global_col)
1038  {
1039  throw WrongArgument("SolveLU(SparseDirectSolver, Vector, Vector)",
1040  "the result must be complex");
1041  }
1042 
1043 
1044  template<class T>
1045  void SolveLU_Distributed(MPI_Comm& comm, const SeldonTranspose& transA,
1046  SparseDirectSolver<T>& mat_lu,
1047  Matrix<complex<T>, General, ColMajor>& x,
1048  Vector<int>& global_col)
1049  {
1050  throw WrongArgument("SolveLU(SparseDirectSolver, Vector, Vector)",
1051  "This case is currently not handled");
1052  }
1053 #endif
1054 
1055  // Solve LU with vector
1056  template<class T>
1057  void SolveLU(const SeldonTranspose& transA,
1058  SparseDirectSolver<T>& mat_lu, Vector<T>& x)
1059  {
1060  mat_lu.Solve(transA, x);
1061  }
1062 
1063 
1064  template<class T>
1065  void SolveLU(const SeldonTranspose& transA,
1066  SparseDirectSolver<complex<T> >& mat_lu, Vector<T>& x)
1067  {
1068  throw WrongArgument("SolveLU(SparseDirectSolver, Vector, Vector)",
1069  "the result must be complex");
1070  }
1071 
1072 
1073  template<class T>
1074  void SolveLU(const SeldonTranspose& transA,
1075  SparseDirectSolver<T>& mat_lu, Vector<complex<T> >& x)
1076  {
1077  // using a matrix with two columns
1078  Matrix<T, General, ColMajor> xm(x.GetM(), 2);
1079  for (int i = 0; i < x.GetM(); i++)
1080  {
1081  xm(i, 0) = real(x(i));
1082  xm(i, 1) = imag(x(i));
1083  }
1084 
1085  mat_lu.Solve(transA, xm);
1086 
1087  for (int i = 0; i < x.GetM(); i++)
1088  x(i) = complex<T>(xm(i, 0), xm(i, 1));
1089  }
1090 
1091 
1092  // Solve LU with matrix
1093  template<class T>
1094  void SolveLU(const SeldonTranspose& transA,
1095  SparseDirectSolver<T>& mat_lu,
1096  Matrix<T, General, ColMajor>& x)
1097  {
1098  mat_lu.Solve(transA, x);
1099  }
1100 
1101 
1102  template<class T>
1103  void SolveLU(const SeldonTranspose& transA,
1104  SparseDirectSolver<complex<T> >& mat_lu,
1105  Matrix<T, General, ColMajor>& x)
1106  {
1107  throw WrongArgument("SolveLU(SparseDirectSolver, Vector, Vector)",
1108  "the result must be complex");
1109  }
1110 
1111 
1112  template<class T>
1113  void SolveLU(const SeldonTranspose& transA,
1114  SparseDirectSolver<T>& mat_lu,
1115  Matrix<complex<T>, General, ColMajor>& x)
1116  {
1117  throw WrongArgument("SolveLU(SparseDirectSolver, Vector, Vector)",
1118  "This case is currently not handled");
1119  }
1120 
1121 }
1122 
1123 #define SELDON_FILE_COMPUTATION_SPARSE_DIRECT_SOLVER_CXX
1124 #endif
1125 
Seldon::SparseDirectSolver::InitSolver
void InitSolver()
initializes the solver (internal method)
Definition: SparseDirectSolver.cxx:398
Seldon::MatrixPastix
Definition: Pastix.hxx:39
Seldon::SparseDirectSolver::Factorize
void Factorize(Matrix< T, Prop, Storage, Allocator > &A, bool keep_matrix=false)
factorisation of matrix A
Definition: SparseDirectSolver.cxx:503
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::SparseDirectSolver::SparseDirectSolver
SparseDirectSolver()
Default constructor.
Definition: SparseDirectSolver.cxx:28
Seldon::SparseDirectSolver::ComputeOrdering
void ComputeOrdering(Matrix< T0, Prop, Storage, Alloc > &A)
computation of the permutation vector in order to reduce fill-in
Definition: SparseDirectSolver.cxx:367
Seldon::SparseDirectSolver::Solve
void Solve(Vector< T > &x)
x_solution is overwritten by solution of A x = b
Definition: SparseDirectSolver.cxx:783
Seldon::to_str
std::string to_str(const T &input)
Converts most types to string.
Definition: CommonInline.cxx:137
Seldon::MatrixPardiso
Definition: Pardiso.hxx:58
Seldon::SparseDirectSolver::SetThresholdMatrix
void SetThresholdMatrix(const double &)
modifies threshold used for ilut
Definition: SparseDirectSolver.cxx:385
Seldon::Vector< T >
Seldon::SparseDirectSolver::SelectOrdering
void SelectOrdering(int)
modifies the ordering algorithm to use
Definition: SparseDirectSolverInline.cxx:59
Seldon::MatrixMumps
object used to solve linear system by calling mumps subroutines
Definition: Mumps.hxx:59
Seldon::IsSymmetricMatrix
bool IsSymmetricMatrix(const Matrix< T, Prop, Storage, Allocator > &A)
returns true if the matrix is symmetric
Definition: Functions_BaseInline.cxx:778
Seldon::MatrixUmfPack
empty class
Definition: UmfPack.hxx:67
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::MatrixMumps::PerformAnalysis
void PerformAnalysis(Matrix< T, Prop, Storage, Allocator > &mat)
Symbolic factorization.
Definition: Mumps.cxx:419
Seldon::SparseDirectSolver
Class grouping different direct solvers.
Definition: SparseDirectSolver.hxx:26
Seldon::SparseDirectSolver::GetInfoFactorization
int GetInfoFactorization(int &ierr) const
Returns error code of the direct solver.
Definition: SparseDirectSolver.cxx:661
Seldon::SparseDirectSolver::IsAvailableSolver
static bool IsAvailableSolver(int type)
returns true if the solver type is available
Definition: SparseDirectSolver.cxx:96
Seldon::SparseDirectSolver::Clear
void Clear()
clearing factorisation
Definition: SparseDirectSolver.cxx:84
Seldon::Undefined
Definition: Errors.hxx:62
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::MatrixSuperLU
empty matrix
Definition: SuperLU.hxx:125
Seldon::GetLU
void GetLU(Matrix< T0, Prop0, Storage0, Allocator0 > &A)
Returns the LU factorization of a matrix.
Definition: Functions_Matrix.cxx:2073
Seldon::SparseSeldonSolver
Default solver in Seldon.
Definition: SparseSolver.hxx:111
Seldon::SparseDirectSolver::PerformAnalysis
void PerformAnalysis(Matrix< T, Prop, Storage, Allocator > &A)
Performs the analysis of the matrix before numerical factorization.
Definition: SparseDirectSolver.cxx:611
Seldon::SparseDirectSolver::PerformFactorization
void PerformFactorization(Matrix< T, Prop, Storage, Allocator > &A)
Performs the numerical factorization.
Definition: SparseDirectSolver.cxx:637
Seldon::MatrixMumps::PerformFactorization
void PerformFactorization(Matrix< T, Prop, RowSparse, Allocator > &mat)
Numerical factorization.
Definition: Mumps.cxx:452
Seldon::IlutPreconditioning
Definition: IlutPreconditioning.hxx:27
Seldon::MatrixWsmp
Definition: Wsmp.hxx:58
Seldon::WrongDim
Definition: Errors.hxx:102
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::SparseDirectSolver::~SparseDirectSolver
~SparseDirectSolver()
Destructor.
Definition: SparseDirectSolver.cxx:75