19 #ifndef SELDON_FILE_COMPUTATION_SPARSE_DIRECT_SOLVER_CXX
21 #include "SparseDirectSolver.hxx"
31 type_ordering = SparseMatrixOrdering::AUTO;
33 type_solver = SELDON_SOLVER;
37 #ifdef SELDON_WITH_SUPERLU
38 type_solver = SUPERLU;
40 #ifdef SELDON_WITH_SUPERLU
41 type_solver = SUPERLU;
43 #ifdef SELDON_WITH_UMFPACK
44 type_solver = UMFPACK;
46 #ifdef SELDON_WITH_PARDISO
47 type_solver = PARDISO;
49 #ifdef SELDON_WITH_WSMP
52 #ifdef SELDON_WITH_MUMPS
55 #ifdef SELDON_WITH_PASTIX
59 nb_threads_per_node = 1;
62 refine_solution =
false;
63 enforce_unsym_ilut =
false;
66 pivot_threshold = -2.0;
100 case SELDON_SOLVER:
return true;
102 #ifdef SELDON_WITH_UMFPACK
107 #ifdef SELDON_WITH_SUPERLU
112 #ifdef SELDON_WITH_MUMPS
117 #ifdef SELDON_WITH_PASTIX
122 #ifdef SELDON_WITH_PRECONDITIONING
127 #ifdef SELDON_WITH_PARDISO
132 #ifdef SELDON_WITH_WSMP
145 bool user_ordering =
false;
147 switch (type_ordering)
149 case SparseMatrixOrdering::AUTO :
153 if (type_solver == MUMPS)
157 else if (type_solver == PASTIX)
159 #ifdef SELDON_WITH_PASTIX
160 solver->SelectOrdering(PastixOrderScotch);
163 else if (type_solver == PARDISO)
165 solver->SelectOrdering(2);
167 else if (type_solver == UMFPACK)
169 #ifdef SELDON_WITH_UMFPACK
170 solver->SelectOrdering(UMFPACK_ORDERING_AMD);
173 else if (type_solver == SUPERLU)
175 #ifdef SELDON_WITH_SUPERLU
176 solver->SelectOrdering(superlu::COLAMD);
179 else if (type_solver == WSMP)
185 type_ordering = SparseMatrixOrdering::IDENTITY;
187 #ifdef SELDON_WITH_UMFPACK
188 type_ordering = SparseMatrixOrdering::AMD;
191 #ifdef SELDON_WITH_MUMPS
192 type_ordering = SparseMatrixOrdering::METIS;
195 #ifdef SELDON_WITH_PARDISO
196 type_ordering = SparseMatrixOrdering::METIS;
199 #ifdef SELDON_WITH_PASTIX
200 type_ordering = SparseMatrixOrdering::SCOTCH;
203 user_ordering =
true;
207 case SparseMatrixOrdering::IDENTITY :
208 case SparseMatrixOrdering::REVERSE_CUTHILL_MCKEE :
209 case SparseMatrixOrdering::USER :
211 user_ordering =
true;
214 case SparseMatrixOrdering::PORD :
215 case SparseMatrixOrdering::AMF :
216 case SparseMatrixOrdering::QAMD :
219 if (type_solver == MUMPS)
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);
227 solver->SelectOrdering(6);
232 user_ordering =
true;
236 case SparseMatrixOrdering::SCOTCH :
237 case SparseMatrixOrdering::PTSCOTCH :
240 if (type_solver == MUMPS)
242 #ifdef SELDON_WITH_MUMPS
243 if (type_ordering==SparseMatrixOrdering::PTSCOTCH)
244 solver->SelectParallelOrdering(1);
246 solver->SelectOrdering(3);
249 else if (type_solver == PASTIX)
251 #ifdef SELDON_WITH_SCOTCH
252 if (type_ordering==SparseMatrixOrdering::PTSCOTCH)
253 solver->SelectOrdering(PastixOrderPtScotch);
255 solver->SelectOrdering(PastixOrderScotch);
260 user_ordering =
true;
264 case SparseMatrixOrdering::METIS :
265 case SparseMatrixOrdering::PARMETIS :
268 if (type_solver == MUMPS)
270 #ifdef SELDON_WITH_MUMPS
271 if (type_ordering==SparseMatrixOrdering::PARMETIS)
272 solver->SelectParallelOrdering(2);
274 solver->SelectOrdering(5);
277 else if (type_solver == PASTIX)
279 #ifdef SELDON_WITH_PASTIX
280 if (type_ordering==SparseMatrixOrdering::PARMETIS)
281 solver->SelectOrdering(PastixOrderParMetis);
283 solver->SelectOrdering(PastixOrderMetis);
286 else if (type_solver == UMFPACK)
288 #ifdef SELDON_WITH_UMFPACK
289 solver->SelectOrdering(UMFPACK_ORDERING_METIS);
306 user_ordering =
true;
310 case SparseMatrixOrdering::AMD :
311 case SparseMatrixOrdering::COLAMD :
314 if (type_solver == UMFPACK)
316 #ifdef SELDON_WITH_UMFPACK
317 solver->SelectOrdering(UMFPACK_ORDERING_AMD);
320 else if (type_solver == MUMPS)
322 #ifdef SELDON_WITH_MUMPS
323 solver->SelectOrdering(0);
326 else if (type_solver == SUPERLU)
328 #ifdef SELDON_WITH_SUPERLU
329 solver->SelectOrdering(superlu::COLAMD);
334 user_ordering =
true;
338 case SparseMatrixOrdering::MMD_AT_PLUS_A:
340 if (type_solver == SUPERLU)
342 #ifdef SELDON_WITH_SUPERLU
343 solver->SelectOrdering(superlu::MMD_AT_PLUS_A);
348 case SparseMatrixOrdering::MMD_ATA:
350 if (type_solver == SUPERLU)
352 #ifdef SELDON_WITH_SUPERLU
353 solver->SelectOrdering(superlu::MMD_ATA);
360 return user_ordering;
365 template<
class T>
template<
class T0,
class Prop,
class Storage,
class Alloc>
369 bool user_ordering = AffectOrdering();
377 solver->SetPermutation(permut);
387 threshold_matrix = eps;
388 #ifdef SELDON_WITH_ILUT
389 if (type_solver == ILUT)
391 .SetDroppingThreshold(eps);
406 #ifdef SELDON_WITH_SUPERLU
409 cout <<
"Seldon not compiled with SuperLU" << endl;
410 cout <<
"SELDON_WITH_SUPERLU is not defined" << endl;
415 #ifdef SELDON_WITH_UMFPACK
418 cout <<
"Seldon not compiled with UmfPack" << endl;
419 cout <<
"SELDON_WITH_UMFPACK is not defined" << endl;
424 #ifdef SELDON_WITH_PARDISO
427 cout <<
"Seldon not compiled with Pardiso" << endl;
428 cout <<
"SELDON_WITH_PARDISO is not defined" << endl;
433 #ifdef SELDON_WITH_MUMPS
436 cout <<
"Seldon not compiled with Mumps" << endl;
437 cout <<
"SELDON_WITH_MUMPS is not defined" << endl;
442 #ifdef SELDON_WITH_PASTIX
445 cout <<
"Seldon not compiled with Pastix" << endl;
446 cout <<
"SELDON_WITH_PASTIX is not defined" << endl;
451 #ifdef SELDON_WITH_WSMP
454 cout <<
"Seldon not compiled with Wsmp" << endl;
455 cout <<
"SELDON_WITH_WSMP is not defined" << endl;
461 #ifdef SELDON_WITH_PRECONDITIONING
463 ilut_solver->SetDroppingThreshold(threshold_matrix);
464 solver = ilut_solver;
466 cout <<
"Seldon not compiled with Preconditioning" << endl;
467 cout <<
"SELDON_WITH_PRECONDITIONING is not defined" << endl;
476 cout <<
"Unknown solver" << endl;
480 if (pivot_threshold != -2.0)
481 solver->SetPivotThreshold(pivot_threshold);
484 solver->RefineSolution();
486 solver->DoNotRefineSolution();
488 solver->SetNumberOfThreadPerNode(nb_threads_per_node);
490 solver->ShowMessages();
492 solver->HideMessages();
502 template<
class Prop,
class Storage,
class Allocator>
508 if (type_solver == UMFPACK)
510 #ifdef SELDON_WITH_UMFPACK
514 GetLU(A, mat_umf, keep_matrix);
516 throw Undefined(
"SparseDirectSolver::Factorize(MatrixSparse&, bool)",
517 "Seldon was not compiled with UmfPack support.");
520 else if (type_solver == SUPERLU)
522 #ifdef SELDON_WITH_SUPERLU
526 GetLU(A, mat_superlu, keep_matrix);
528 throw Undefined(
"SparseDirectSolver::Factorize(MatrixSparse&, bool)",
529 "Seldon was not compiled with SuperLU support.");
532 else if (type_solver == PARDISO)
534 #ifdef SELDON_WITH_PARDISO
538 GetLU(A, mat_pardiso, keep_matrix);
540 throw Undefined(
"SparseDirectSolver::Factorize(MatrixSparse&, bool)",
541 "Seldon was not compiled with Pardiso support.");
544 else if (type_solver == MUMPS)
546 #ifdef SELDON_WITH_MUMPS
550 GetLU(A, mat_mumps, keep_matrix);
552 throw Undefined(
"SparseDirectSolver::Factorize(MatrixSparse&, bool)",
553 "Seldon was not compiled with Mumps support.");
556 else if (type_solver == PASTIX)
558 #ifdef SELDON_WITH_PASTIX
562 GetLU(A, mat_pastix, keep_matrix);
564 throw Undefined(
"SparseDirectSolver::Factorize(MatrixSparse&, bool)",
565 "Seldon was not compiled with Pastix support.");
568 else if (type_solver == WSMP)
570 #ifdef SELDON_WITH_WSMP
574 GetLU(A, mat_wsmp, keep_matrix);
576 throw Undefined(
"SparseDirectSolver::Factorize(MatrixSparse&, bool)",
577 "Seldon was not compiled with Wsmp support.");
580 else if (type_solver == ILUT)
582 #ifdef SELDON_WITH_PRECONDITIONING
588 mat_ilut.SetUnsymmetricAlgorithm();
590 mat_ilut.SetSymmetricAlgorithm();
593 GetLU(A, mat_ilut, permut, keep_matrix);
595 throw Undefined(
"SparseDirectSolver::Factorize(MatrixSparse&, bool)",
596 "Seldon was not compiled with the preconditioners.");
604 GetLU(A, mat_seldon, permut, keep_matrix);
610 template <
class T>
template<
class Prop,
class Storage,
class Allocator>
615 if (type_solver == MUMPS)
617 #ifdef SELDON_WITH_MUMPS
623 throw Undefined(
"SparseDirectSolver::PerformAnalysis(MatrixSparse&, bool)",
624 "Seldon was not compiled with Mumps support.");
629 cout <<
"Not implemented for other solvers" << endl;
636 template <
class T>
template<
class Prop,
class Storage,
class Allocator>
639 if (type_solver == MUMPS)
641 #ifdef SELDON_WITH_MUMPS
647 throw Undefined(
"SparseDirectSolver::PerformAnalysis(MatrixSparse&, bool)",
648 "Seldon was not compiled with Mumps support.");
653 cout <<
"Not implemented for other solvers" << endl;
663 ierr = solver->GetInfoFactorization();
664 if (type_solver == UMFPACK)
666 #ifdef SELDON_WITH_UMFPACK
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;
690 return INTERNAL_ERROR;
694 else if (type_solver == SUPERLU)
696 #ifdef SELDON_WITH_SUPERLU
698 return INTERNAL_ERROR;
701 else if (type_solver == MUMPS)
703 #ifdef SELDON_WITH_MUMPS
708 return MATRIX_INDICES_INCORRECT;
711 return INVALID_ARGUMENT;
714 return INVALID_PERMUTATION;
717 return OUT_OF_MEMORY;
720 return STRUCTURALLY_SINGULAR_MATRIX;
723 return OUT_OF_MEMORY;
726 return NUMERICALLY_SINGULAR_MATRIX;
729 return OUT_OF_MEMORY;
732 return INCORRECT_NUMBER_OF_ROWS;
735 return INVALID_ARGUMENT;
738 return MATRIX_INDICES_INCORRECT;
742 return INTERNAL_ERROR;
746 else if (type_solver == PARDISO)
748 #ifdef SELDON_WITH_PARDISO
752 return INVALID_ARGUMENT;
755 return OUT_OF_MEMORY;
757 return INVALID_PERMUTATION;
759 return NUMERICALLY_SINGULAR_MATRIX;
761 return ORDERING_FAILED;
763 return STRUCTURALLY_SINGULAR_MATRIX;
765 return OVERFLOW_32BIT;
769 return INTERNAL_ERROR;
785 Solve(SeldonNoTrans, x_solution);
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 "
803 solver->Solve(trans, x_solution.GetData(), 1);
816 Solve(SeldonNoTrans, x_solution);
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 ")
834 +
" while the size of the matrix is equal to "
838 solver->Solve(trans, x_sol.GetData(), x_sol.GetN());
842 #ifdef SELDON_WITH_MPI
858 template<
class T>
template<
class T
int0,
class T
int1>
862 const IVect& glob_num,
bool sym,
bool keep_matrix)
864 bool user_ordering = AffectOrdering();
867 throw Undefined(
"SparseDirectSolver::FactorizeDistributed(MPI_Comm&,"
868 " IVect&, IVect&, Vector<T>&, IVect&, bool, bool)",
869 "user orderings not available in parallel");
873 solver->FactorizeDistributedMatrix(comm_facto, Ptr, Row, Val,
874 glob_num, sym, keep_matrix);
880 template<
class T>
template<
class T
int0,
class T
int1>
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)
886 bool user_ordering = AffectOrdering();
889 throw Undefined(
"SparseDirectSolver::PerformAnalysisDistributed(MPI_Comm&,"
890 " IVect&, IVect&, Vector<T>&, IVect&, bool, bool)",
891 "user orderings not available in parallel");
895 solver->PerformAnalysisDistributed(comm_facto, Ptr, Row, Val,
896 glob_num, sym, keep_matrix);
902 template<
class T>
template<
class T
int0,
class T
int1>
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)
909 solver->PerformFactorizationDistributed(comm_facto, Ptr, Row, Val,
910 glob_num, sym, keep_matrix);
919 void SparseDirectSolver<T>::
920 SolveDistributed(MPI_Comm& comm_facto, Vector<T>& x_solution,
921 const IVect& glob_number)
923 SolveDistributed(comm_facto, SeldonNoTrans, x_solution, glob_number);
932 void SparseDirectSolver<T>::
933 SolveDistributed(MPI_Comm& comm_facto,
const SeldonTranspose& trans,
934 Vector<T>& x_solution,
const IVect& glob_number)
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 "
945 solver->SolveDistributed(comm_facto, trans,
946 x_solution.GetData(), 1, glob_number);
955 void SparseDirectSolver<T>::
956 SolveDistributed(MPI_Comm& comm_facto, Matrix<T, General, ColMajor>& x,
957 const IVect& glob_number)
959 SolveDistributed(comm_facto, SeldonNoTrans, x, glob_number);
968 void SparseDirectSolver<T>::
969 SolveDistributed(MPI_Comm& comm_facto,
const SeldonTranspose& trans,
970 Matrix<T, General, ColMajor>& x,
const IVect& glob_number)
972 #ifdef SELDON_CHECK_DIMENSIONS
974 throw WrongDim(
"SparseDirectSolver::SolveDistributed",
975 string(
"The length of x is equal to ")
977 +
" while the size of the matrix is equal to "
981 solver->SolveDistributed(comm_facto, trans,
982 x.GetData(), x.GetN(), glob_number);
987 void SolveLU_Distributed(MPI_Comm& comm,
const SeldonTranspose& transA,
988 SparseDirectSolver<T>& mat_lu,
989 Vector<T>& x, Vector<int>& global_col)
991 mat_lu.SolveDistributed(comm, transA, x, global_col);
996 void SolveLU_Distributed(MPI_Comm& comm,
const SeldonTranspose& transA,
997 SparseDirectSolver<complex<T> >& mat_lu,
998 Vector<T>& x, Vector<int>& global_col)
1000 throw WrongArgument(
"SolveLU(SparseDirectSolver, Vector, Vector)",
1001 "the result must be complex");
1006 void SolveLU_Distributed(MPI_Comm& comm,
const SeldonTranspose& transA,
1007 SparseDirectSolver<T>& mat_lu,
1008 Vector<complex<T> >& x, Vector<int>& global_col)
1010 Vector<T> xreal(x.GetM()), ximag(x.GetM());
1011 for (
int i = 0; i < x.GetM(); i++)
1013 xreal(i) = real(x(i));
1014 ximag(i) = imag(x(i));
1017 mat_lu.SolveDistributed(comm, transA, xreal, global_col);
1018 mat_lu.SolveDistributed(comm, transA, ximag, global_col);
1020 for (
int i = 0; i < x.GetM(); i++)
1021 x(i) = complex<T>(xreal(i), ximag(i));
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)
1030 mat_lu.SolveDistributed(comm, transA, x, global_col);
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)
1039 throw WrongArgument(
"SolveLU(SparseDirectSolver, Vector, Vector)",
1040 "the result must be complex");
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)
1050 throw WrongArgument(
"SolveLU(SparseDirectSolver, Vector, Vector)",
1051 "This case is currently not handled");
1057 void SolveLU(
const SeldonTranspose& transA,
1058 SparseDirectSolver<T>& mat_lu, Vector<T>& x)
1060 mat_lu.Solve(transA, x);
1065 void SolveLU(
const SeldonTranspose& transA,
1066 SparseDirectSolver<complex<T> >& mat_lu, Vector<T>& x)
1068 throw WrongArgument(
"SolveLU(SparseDirectSolver, Vector, Vector)",
1069 "the result must be complex");
1074 void SolveLU(
const SeldonTranspose& transA,
1075 SparseDirectSolver<T>& mat_lu, Vector<complex<T> >& x)
1078 Matrix<T, General, ColMajor> xm(x.GetM(), 2);
1079 for (
int i = 0; i < x.GetM(); i++)
1081 xm(i, 0) = real(x(i));
1082 xm(i, 1) = imag(x(i));
1085 mat_lu.Solve(transA, xm);
1087 for (
int i = 0; i < x.GetM(); i++)
1088 x(i) = complex<T>(xm(i, 0), xm(i, 1));
1094 void SolveLU(
const SeldonTranspose& transA,
1095 SparseDirectSolver<T>& mat_lu,
1096 Matrix<T, General, ColMajor>& x)
1098 mat_lu.Solve(transA, x);
1103 void SolveLU(
const SeldonTranspose& transA,
1104 SparseDirectSolver<complex<T> >& mat_lu,
1105 Matrix<T, General, ColMajor>& x)
1107 throw WrongArgument(
"SolveLU(SparseDirectSolver, Vector, Vector)",
1108 "the result must be complex");
1113 void SolveLU(
const SeldonTranspose& transA,
1114 SparseDirectSolver<T>& mat_lu,
1115 Matrix<complex<T>, General, ColMajor>& x)
1117 throw WrongArgument(
"SolveLU(SparseDirectSolver, Vector, Vector)",
1118 "This case is currently not handled");
1123 #define SELDON_FILE_COMPUTATION_SPARSE_DIRECT_SOLVER_CXX