21 #ifndef SELDON_FILE_COMPUTATION_SPARSESOLVER_CXX
23 #include "SparseSolverInline.cxx"
113 #ifdef SELDON_WITH_MPI
120 bool sym,
bool keep_matrix)
123 cout <<
"FactorizeDistributedMatrix (32 bits) not present " << endl;
124 cout <<
"Is it implemented in the chosen solver ?" << endl;
125 cout <<
"Or the 64 bits version should be called ?" << endl;
132 void VirtualSparseDirectSolver<T>
133 ::FactorizeDistributedMatrix(MPI_Comm& comm_facto, Vector<int64_t>& Ptr,
134 Vector<int64_t>& IndRow, Vector<T>& Val,
135 const Vector<int>& glob_number,
136 bool sym,
bool keep_matrix)
139 cout <<
"FactorizeDistributedMatrix (64 bits) not present " << endl;
140 cout <<
"Is it implemented in the chosen solver ?" << endl;
141 cout <<
"Or the 32 bits version should be called ?" << endl;
148 void VirtualSparseDirectSolver<T>
149 ::PerformAnalysisDistributed(MPI_Comm& comm_facto, Vector<long>& Ptr,
150 Vector<int>& IndRow, Vector<T>& Val,
151 const Vector<int>& glob_number,
152 bool sym,
bool keep_matrix)
155 cout <<
"PerformAnalysisDistributed (32 bits) not present " << endl;
156 cout <<
"Is it implemented in the chosen solver ?" << endl;
157 cout <<
"Or the 64 bits version should be called ?" << endl;
164 void VirtualSparseDirectSolver<T>
165 ::PerformAnalysisDistributed(MPI_Comm& comm_facto, Vector<int64_t>& Ptr,
166 Vector<int64_t>& IndRow, Vector<T>& Val,
167 const Vector<int>& glob_number,
168 bool sym,
bool keep_matrix)
171 cout <<
"PerformAnalysisDistributed (64 bits) not present " << endl;
172 cout <<
"Is it implemented in the chosen solver ?" << endl;
173 cout <<
"Or the 32 bits version should be called ?" << endl;
180 void VirtualSparseDirectSolver<T>
181 ::PerformFactorizationDistributed(MPI_Comm& comm_facto, Vector<long>& Ptr,
182 Vector<int>& IndRow, Vector<T>& Val,
183 const Vector<int>& glob_number,
184 bool sym,
bool keep_matrix)
187 cout <<
"PerformAnalysisDistributed (32 bits) not present " << endl;
188 cout <<
"Is it implemented in the chosen solver ?" << endl;
189 cout <<
"Or the 64 bits version should be called ?" << endl;
196 void VirtualSparseDirectSolver<T>
197 ::PerformFactorizationDistributed(MPI_Comm& comm_facto, Vector<int64_t>& Ptr,
198 Vector<int64_t>& IndRow, Vector<T>& Val,
199 const Vector<int>& glob_number,
200 bool sym,
bool keep_matrix)
203 cout <<
"PerformAnalysisDistributed (64 bits) not present " << endl;
204 cout <<
"Is it implemented in the chosen solver ?" << endl;
205 cout <<
"Or the 32 bits version should be called ?" << endl;
213 void VirtualSparseDirectSolver<T>
214 ::SolveDistributed(MPI_Comm& comm_facto,
const SeldonTranspose& TransA,
215 T* x_ptr,
int nrhs,
const IVect& glob_num)
217 cout <<
"SolveDistributed is not present" << endl;
218 cout <<
"Is it implemented in the chosen solver ?" << endl;
229 template<
class T,
class Allocator>
232 size_t taille = mat_sym.GetMemorySize() + mat_unsym.GetMemorySize();
233 taille += permutation_row.GetMemorySize() + permutation_col.GetMemorySize();
244 template<
class T,
class Allocator>
245 template<
class T0,
class Storage0,
class Allocator0>
251 IVect inv_permutation;
254 Copy(mat, mat_unsym);
261 int n = mat_unsym.GetM();
262 if (perm.GetM() != n)
263 throw WrongArgument(
"FactorizeMatrix(IVect&, Matrix&, bool)",
264 "Numbering array is of size "
266 +
" while the matrix is of size "
267 +
to_str(mat.GetM()) +
" x "
268 +
to_str(mat.GetN()) +
".");
270 permutation_row.Reallocate(n);
271 permutation_col.Reallocate(n);
272 inv_permutation.Reallocate(n);
273 inv_permutation.Fill(-1);
274 for (
int i = 0; i < n; i++)
276 permutation_row(i) = i;
277 permutation_col(i) = i;
278 inv_permutation(perm(i)) = i;
281 for (
int i = 0; i < n; i++)
282 if (inv_permutation(i) == -1)
283 throw WrongArgument(
"FactorizeMatrix(IVect&, Matrix&, bool)",
284 "The numbering array is invalid.");
286 IVect iperm = inv_permutation;
289 ApplyInversePermutation(mat_unsym, perm, perm);
293 symmetric_matrix =
false;
294 inv_permutation.Fill();
295 GetLU(mat_unsym, permutation_col, inv_permutation, permtol, print_level);
298 IVect itmp = permutation_col;
299 for (
int i = 0; i < n; i++)
300 permutation_col(i) = iperm(itmp(i));
302 permutation_row = perm;
313 template<
class T,
class Allocator>
314 template<
class T0,
class Storage0,
class Allocator0>
320 IVect inv_permutation;
330 int n = mat_sym.GetM();
331 if (perm.GetM() != n)
332 throw WrongArgument(
"FactorizeMatrix(IVect&, Matrix&, bool)",
333 "Numbering array is of size "
335 +
" while the matrix is of size "
336 +
to_str(mat.GetM()) +
" x "
337 +
to_str(mat.GetN()) +
".");
339 permutation_row.Reallocate(n);
340 inv_permutation.Reallocate(n);
341 inv_permutation.Fill(-1);
342 for (
int i = 0; i < n; i++)
344 permutation_row(i) = perm(i);
345 inv_permutation(perm(i)) = i;
348 for (
int i = 0; i < n; i++)
349 if (inv_permutation(i) == -1)
350 throw WrongArgument(
"FactorizeMatrix(IVect&, Matrix&, bool)",
351 "The numbering array is invalid.");
354 ApplyInversePermutation(mat_sym, perm, perm);
357 symmetric_matrix =
true;
358 GetLU(mat_sym, print_level);
362 template<
class T,
class Allocator>
template<
class T1>
367 if (symmetric_matrix)
369 for (
int i = 0; i < z.GetM(); i++)
370 xtmp(permutation_row(i)) = z(i);
372 SolveLU(mat_sym, xtmp);
374 for (
int i = 0; i < z.GetM(); i++)
375 z(i) = xtmp(permutation_row(i));
379 for (
int i = 0; i < z.GetM(); i++)
380 xtmp(permutation_row(i)) = z(i);
382 SolveLU(mat_unsym, xtmp);
384 for (
int i = 0; i < z.GetM(); i++)
385 z(permutation_col(i)) = xtmp(i);
390 template<
class T,
class Allocator>
template<
class T1>
391 void SparseSeldonSolver<T, Allocator>
392 ::Solve(
const SeldonTranspose& TransA, Vector<T1>& z)
394 if (symmetric_matrix)
401 for (
int i = 0; i < z.GetM(); i++)
402 xtmp(i) = z(permutation_col(i));
404 SolveLU(SeldonTrans, mat_unsym, xtmp);
406 for (
int i = 0; i < z.GetM(); i++)
407 z(i) = xtmp(permutation_row(i));
415 template<
class T,
class Allocator>
416 void SparseSeldonSolver<T, Allocator>
417 ::Solve(
const SeldonTranspose& TransA, T* x_ptr,
int nrhs)
420 int n = permutation_row.GetM();
421 for (
int k = 0; k < nrhs; k++)
423 x.SetData(n, &x_ptr[k*n]);
436 template<
class T,
class Allocator>
439 const double& permtol,
int print_level)
444 typedef typename ClassComplexType<T>::Treal Treal;
445 Treal tnorm, zero = 0.0;
446 int length_lower, length_upper, jpos, jrow, i_row, j_col;
447 int i, j, k, length, size_row, index_lu;
450 SetComplexZero(czero);
453 IVect Index(n), Row_Ind(n), Index_Diag(n);
460 int new_percent = 0, old_percent = 0;
461 for (i_row = 0; i_row < n; i_row++)
466 new_percent = int(
double(i_row) /
double(n-1) * 78.);
467 for (
int percent = old_percent; percent < new_percent; percent++)
473 old_percent = new_percent;
476 size_row = A.GetRowSize(i_row);
480 for (k = 0 ; k < size_row; k++)
481 if (A.Value(i_row, k) != czero)
482 tnorm += abs(A.Value(i_row, k));
485 throw WrongArgument(
"GetLU(Matrix<ArrayRowSparse>&, IVect&, "
486 "IVect&, double, int)",
487 "The matrix is structurally singular. "
488 "The norm of row " +
to_str(i_row)
489 +
" is equal to 0.");
494 Row_Ind(i_row) = i_row;
495 Row_Val(i_row) = czero;
496 Index(i_row) = i_row;
498 for (j = 0; j < size_row; j++)
500 k = rperm(A.Index(i_row, j));
502 t = A.Value(i_row,j);
505 Row_Ind(length_lower) = k;
506 Row_Val(length_lower) = t;
507 Index(k) = length_lower;
516 jpos = i_row + length_upper;
528 while (j_col < length_lower)
532 jrow = Row_Ind(j_col);
536 for (j = j_col + 1; j < length_lower; j++)
537 if (Row_Ind(j) < jrow)
547 Row_Ind(j_col) = Row_Ind(k);
554 Row_Val(j_col) = Row_Val(k);
563 fact = Row_Val(j_col) * A.Value(jrow, Index_Diag(jrow));
566 for (k = (Index_Diag(jrow)+1); k < A.GetRowSize(jrow); k++)
568 s = fact * A.Value(jrow,k);
569 j = rperm(A.Index(jrow,k));
578 i = i_row + length_upper;
592 Row_Ind(length_lower) = j;
593 Index(j) = length_lower;
594 Row_Val(length_lower) = -s;
604 Row_Val(length) = fact;
605 Row_Ind(length) = jrow;
611 for (k = 0; k < length_upper; k++)
612 Index(Row_Ind(i_row + k)) = -1;
615 A.ReallocateRow(i_row,size_row);
619 for (k = 0 ; k < length ; k++)
621 A.Value(i_row,index_lu) = Row_Val(k);
622 A.Index(i_row,index_lu) = iperm(Row_Ind(k));
627 Index_Diag(i_row) = index_lu;
631 for (k = 1; k <= (length_upper-1); k++)
634 Row_Val(i_row+length) = Row_Val(i_row+k);
635 Row_Ind(i_row+length) = Row_Ind(i_row+k);
642 Treal xmax = abs(Row_Val(imax));
644 for (k = i_row + 1; k <= i_row + length - 1; k++)
646 tnorm = abs(Row_Val(k));
647 if (tnorm > xmax && tnorm * permtol > xmax0)
656 Row_Val(i_row) = Row_Val(imax);
662 iperm(i_row) = iperm(j);
666 rperm(iperm(i_row)) = i_row;
670 int index_diag = index_lu;
671 A.ResizeRow(i_row, size_row+length);
673 for (k = i_row ; k <= i_row + length - 1; k++)
675 A.Index(i_row,index_lu) = iperm(Row_Ind(k));
676 A.Value(i_row,index_lu) = Row_Val(k);
681 A.Value(i_row, index_diag) = cone / Row_Val(i_row);
689 cout <<
"The matrix takes " <<
690 int((A.GetDataSize() * (
sizeof(T) + 4)) / (1024. * 1024.))
693 for (i = 0; i < n; i++ )
694 for (j = 0; j < A.GetRowSize(i); j++)
695 A.Index(i,j) = rperm(A.Index(i,j));
700 template<
class T1,
class Allocator1,
701 class T2,
class Storage2,
class Allocator2>
702 void SolveLuVector(
const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
703 Vector<T2, Storage2, Allocator2>& x)
713 template<
class T1,
class Allocator1,
714 class T2,
class Storage2,
class Allocator2>
726 for (i = 0 ; i < n ; i++)
728 k_ = 0; k = A.Index(i,k_);
735 x(i) *= A.Value(i,k_);
736 for (k = k_ + 1; k < A.GetRowSize(i) ; k++)
737 x(A.Index(i,k)) -= A.Value(i,k) * x(i);
741 for (i = n-1 ; i>=0 ; i--)
743 k_ = 0; k = A.Index(i, k_);
746 x(k) -= A.Value(i, k_)*x(i);
755 for (i = 0; i < n; i++)
761 x(i) -= A.Value(i, k_) * x(k);
768 for (i = n-1; i >= 0; i--)
778 inv_diag = A.Value(i, k_);
779 for (k = k_ + 1; k < A.GetRowSize(i); k++)
780 x(i) -= A.Value(i, k) * x(A.Index(i, k));
789 template<
class T,
class Allocator>
795 typename ClassComplexType<T>::Treal zero(0), tnorm, one(1);
798 int length_lower, length_upper, jpos, jrow;
799 int i_row, j_col, index_lu, length;
803 IVect Index(n), Row_Ind(n);
816 int new_percent = 0, old_percent = 0;
817 for (i_row = 0; i_row < n; i_row++)
822 new_percent = int(
double(i_row) /
double(n-1) * 78.);
823 for (
int percent = old_percent; percent < new_percent; percent++)
828 old_percent = new_percent;
832 size_row = B.GetRowSize(i_row);
834 for (k = 0 ; k < size_row; k++)
835 tnorm += abs(B.Value(i_row, k));
838 throw WrongArgument(
"GetLU(Matrix<ArrayRowSymSparse>&, int)",
839 "The matrix is structurally singular. "
840 "The norm of row " +
to_str(i_row)
841 +
" is equal to 0.");
846 Row_Ind(i_row) = i_row;
847 SetComplexZero(Row_Val(i_row));
848 Index(i_row) = i_row;
850 for (j = 0; j < size_row; j++)
852 k = B.Index(i_row,j);
853 t = B.Value(i_row,j);
856 Row_Ind(length_lower) = k;
857 Row_Val(length_lower) = t;
858 Index(k) = length_lower;
867 jpos = i_row + length_upper;
882 while (j_col <length_lower)
886 jrow = Row_Ind(j_col);
890 for (j = (j_col+1) ; j < length_lower; j++)
892 if (Row_Ind(j) < jrow)
905 Row_Ind(j_col) = Row_Ind(k);
912 Row_Val(j_col) = Row_Val(k);
920 fact = Row_Val(j_col) * A.Value(jrow, 0);
923 for (k = 1; k < A.GetRowSize(jrow); k++)
925 s = fact * A.Value(jrow, k);
926 j = A.Index(jrow, k);
936 i = i_row + length_upper;
954 Row_Ind(length_lower) = j;
955 Index(j) = length_lower;
956 Row_Val(length_lower) = -s;
969 Row_Val(length) = fact;
970 Row_Ind(length) = jrow;
976 for (k = 0; k < length_upper; k++)
977 Index(Row_Ind(i_row + k)) = -1;
981 for (k = 1; k <= length_upper - 1; k++)
984 Row_Val(i_row + length) = Row_Val(i_row + k);
985 Row_Ind(i_row + length) = Row_Ind(i_row + k);
991 A.ReallocateRow(i_row, length);
993 for (k = i_row + 1 ; k <= i_row + length - 1 ; k++)
995 A.Index(i_row, index_lu) = Row_Ind(k);
996 A.Value(i_row, index_lu) = Row_Val(k);
1001 A.Value(i_row,0) = one / Row_Val(i_row);
1005 if (print_level > 0)
1009 for (
int i = 0; i < n; i++)
1010 for (
int j = 1; j < A.GetRowSize(i); j++)
1011 A.Value(i, j) *= A.Value(i, 0);
1013 if (print_level > 0)
1014 cout <<
"The matrix takes " <<
1015 int((A.GetDataSize() * (
sizeof(T) + 4)) / (1024. * 1024.))
1021 template<
class T1,
class Allocator1,
1022 class T2,
class Storage2,
class Allocator2>
1023 void SolveLuVector(
const Matrix<T1, Symmetric, ArrayRowSymSparse, Allocator1>& A,
1024 Vector<T2, Storage2, Allocator2>& x)
1034 template<
class T1,
class Allocator1,
1035 class T2,
class Storage2,
class Allocator2>
1040 int n = A.GetM(), j_row;
1044 for (
int i_col = 0; i_col < n ; i_col++)
1046 for (
int k = 1; k < A.GetRowSize(i_col) ; k++)
1048 j_row = A.Index(i_col, k);
1049 x(j_row) -= A.Value(i_col, k)*x(i_col);
1054 for (
int i_col = 0; i_col < n ; i_col++)
1055 x(i_col) *= A.Value(i_col, 0);
1058 for (
int i_col = n-1; i_col >=0 ; i_col--)
1061 for (
int k = 1; k < A.GetRowSize(i_col) ; k++)
1063 j_row = A.Index(i_col, k);
1064 tmp -= A.Value(i_col, k)*x(j_row);
1078 template<
class MatrixSparse,
class T,
class Alloc2>
1080 bool keep_matrix, T& x)
1083 IVect perm(A.GetM());
1092 template<
class MatrixSparse,
class T,
class Alloc2>
1094 bool keep_matrix, complex<T>& x)
1097 +
string(
"SparseSeldonSolver<T>& mat_lu, bool)"),
1098 "The LU matrix must be complex");
1103 template<
class MatrixSparse,
class T,
class Alloc2>
1105 bool keep_matrix, T& x)
1108 string(
"SparseSeldonSolver<complex<T> >& mat_lu, bool)"),
1109 "The sparse matrix must be complex");
1114 template<
class T0,
class Prop,
class Storage,
class Allocator,
1115 class T,
class Alloc2>
1120 GetLU(A, mat_lu, keep_matrix, x);
1125 template<
class MatrixSparse,
class T,
class Alloc2>
1127 IVect& permut,
bool keep_matrix, T& x)
1134 template<
class MatrixSparse,
class T,
class Alloc2>
1136 IVect& permut,
bool keep_matrix, complex<T>& x)
1138 throw WrongArgument(
string(
"GetLU(Matrix<complex<T> >& A, ")
1139 +
"SparseSeldonSolver<T>& mat_lu, bool)",
1140 "The LU matrix must be complex");
1145 template<
class MatrixSparse,
class T,
class Alloc2>
1147 IVect& permut,
bool keep_matrix, T& x)
1150 "SparseSeldonSolver<complex<T> >& mat_lu, bool)",
1151 "The sparse matrix must be complex");
1156 template<
class T0,
class Prop,
class Storage,
class Allocator,
1157 class T,
class Alloc2>
1160 IVect& permut,
bool keep_matrix)
1163 GetLU(A, mat_lu, permut, keep_matrix, x);
1167 template<
class T,
class Alloc2,
class T1,
class Allocator>
1168 void SolveLU(SparseSeldonSolver<T, Alloc2>& mat_lu,
1169 Vector<T1, VectFull, Allocator>& x)
1175 template<
class T,
class Alloc2,
class T1,
class Allocator>
1176 void SolveLU(
const SeldonTranspose& TransA,
1177 SparseSeldonSolver<T, Alloc2>& mat_lu,
1178 Vector<T1, VectFull, Allocator>& x)
1180 mat_lu.Solve(TransA, x);
1187 #define SELDON_FILE_COMPUTATION_SPARSESOLVER_CXX