/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* ******** *** SparseLib++ */ /* ******* ** *** *** *** v. 1.5c */ /* ***** *** ******** ******** */ /* ***** *** ******** ******** R. Pozo */ /* ** ******* *** ** *** *** K. Remington */ /* ******** ******** A. Lumsdaine */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* */ /* */ /* SparseLib++ : Sparse Matrix Library */ /* */ /* National Institute of Standards and Technology */ /* University of Notre Dame */ /* Authors: R. Pozo, K. Remington, A. Lumsdaine */ /* */ /* NOTICE */ /* */ /* Permission to use, copy, modify, and distribute this software and */ /* its documentation for any purpose and without fee is hereby granted */ /* provided that the above notice appear in all copies and supporting */ /* documentation. */ /* */ /* Neither the Institutions (National Institute of Standards and Technology, */ /* University of Notre Dame) nor the Authors make any representations about */ /* the suitability of this software for any purpose. This software is */ /* provided ``as is'' without expressed or implied warranty. */ /* */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ // modification GR : // introduction du cas de la matrice abstraite // utilisation de deux fonctions d'initialisation internes #include #include #include "icpre_double_GR.h" // modif GR : découle d'une classe virtuelle // pour avoir une interface standard #include "qsort_double.h" #include "qsort_int.h" #include "spblas.h" #include "Sortie.h" #include "Mat_creuse_CompCol.h" static void ICFactor(const VECTOR_int &ia, const VECTOR_int &ja, VECTOR_double &sa); static void ICSolve(const VECTOR_int &ia, const VECTOR_int &ja, const VECTOR_double &sa, VECTOR_double &dest); ICPreconditioner_double::ICPreconditioner_double(const CompCol_Mat_double &A) : val_(0), pntr_(A.dim(1)+1), indx_(0), nz_(0) { Init_CompCol_Mat_double( A); } ICPreconditioner_double::ICPreconditioner_double(const CompRow_Mat_double &A) : val_(0), pntr_(A.dim(0)+1), indx_(0), nz_(0) {Init_CompRow_Mat_double( A); } // cas d'une matrice abstraite qui est en faite de type sparse_col_comp ICPreconditioner_double::ICPreconditioner_double(const Mat_abstraite &A) : val_(0), pntr_(0), indx_(0), nz_(0) { switch (A.Type_matrice()) { case CREUSE_COMPRESSEE_COLONNE : {pntr_.newsize(A.Nb_colonne()+1); Init_Mat_creuse_CompCol(A); break; } case CREUSE_COMPRESSEE_LIGNE : // ici il y aura une modif a faire comme pour les matrices compressées colonne // il faut passer la matrice dérivée et non la matrice mère {cout << "\n problème dans DiagPreconditioner_double(.. " << "voir le source .cpp, il y a du travail a faire"; Sortie(1); pntr_.newsize(A.Nb_ligne()+1); Init_CompRow_Mat_double((CompRow_Mat_double&) A); break; } default : cout << "\nErreur : valeur incorrecte du type de matrice !" << " = " << A.Type_matrice() << " , ce tye n'est pas encore " << " pris en compte dans le préconditionnement de cholesky incomplet\n"; cout << "\n ICPreconditioner_double::ICPreconditioner_double(... )\n"; Sortie(1); }; } VECTOR_double ICPreconditioner_double::solve(const VECTOR_double &x) const { VECTOR_double y(x); ICSolve(pntr_, indx_, val_, y); return y; } VECTOR_double ICPreconditioner_double::trans_solve(const VECTOR_double &x) const { VECTOR_double y(x); ICSolve(pntr_, indx_, val_, y); return y; } static void ICFactor(const VECTOR_int &pntr, const VECTOR_int &indx, VECTOR_double &val) { int d, g, h, i, j, k, n = pntr.size() - 1; double z; for (k = 0; k < n - 1; k++) { d = pntr[k]; z = val[d] = sqrt(val[d]); for (i = d + 1; i < pntr[k+1]; i++) val[i] /= z; for (i = d + 1; i < pntr[k+1]; i++) { z = val[i]; h = indx[i]; g = i; for (j = pntr[h] ; j < pntr[h+1]; j++) for ( ; g < pntr[k+1] && indx[g+1] <= indx[j]; g++) if (indx[g] == indx[j]) val[j] -= z * val[g]; } } d = pntr[n-1]; val[d] = sqrt(val[d]); } static void ICSolve(const VECTOR_int &pntr, const VECTOR_int &indx, const VECTOR_double &val, VECTOR_double &dest) { int M = dest.size(); VECTOR_double work(M); int descra[9]; descra[0] = 0; // lower diag descra[1] = 1; descra[2] = 0; F77NAME(dcscsm) (0, M, 1, 1, NULL, 1.0, descra, &val(0), &indx(0), &pntr(0), &dest(0), M, 0.0, &dest(1), M, &work(0), M); // lower diag transpose F77NAME(dcscsm) (1, M, 1, 1, NULL, 1.0, descra, &val(0), &indx(0), &pntr(0), &dest(0), M, 0.0, &dest(1), M, &work(0), M); } //====================== protégée ======================== // fonction interne d'initialisation pour éviter la recopie void ICPreconditioner_double::Init_CompCol_Mat_double(const CompCol_Mat_double &A) { dim_[0] = A.dim(0); dim_[1] = A.dim(1); int i, j, k; for (k = 0; k < dim_[1]; k++) for (j = A.col_ptr(k); j < A.col_ptr(k+1); j++) if (A.row_ind(j) >= k) nz_++; val_.newsize(nz_); indx_.newsize(nz_); // Copy just triangular part pntr_(0) = 0; for (k = 0; k < dim_[1]; k++) { pntr_(k+1) = pntr_(k); for (j = A.col_ptr(k); j < A.col_ptr(k+1); j++) { if (A.row_ind(j) >= k) { i = pntr_(k+1)++; val_(i) = A.val(j); indx_(i) = A.row_ind(j); } } } for (i = 0; i < dim_[1]; i++) QSort(indx_, val_, pntr_[i], pntr_[i+1] - pntr_[i]); for (i = 0; i < dim_[1]; i++) if (indx_[pntr_(i)] != i) { cerr << "IC Preconditioner: diagonal not found!" << i << endl; Sortie(1); } ICFactor(pntr_, indx_, val_); }; void ICPreconditioner_double::Init_Mat_creuse_CompCol(const Mat_abstraite &B) { Mat_creuse_CompCol & A = (Mat_creuse_CompCol &) B; dim_[0] = A.dim(0); dim_[1] = A.dim(1); int i, j, k; for (k = 0; k < dim_[1]; k++) for (j = A.col_ptr(k); j < A.col_ptr(k+1); j++) if (A.row_ind(j) >= k) nz_++; val_.newsize(nz_); indx_.newsize(nz_); // Copy just triangular part pntr_(0) = 0; for (k = 0; k < dim_[1]; k++) { pntr_(k+1) = pntr_(k); for (j = A.col_ptr(k); j < A.col_ptr(k+1); j++) { if (A.row_ind(j) >= k) { i = pntr_(k+1)++; val_(i) = A.val(j); indx_(i) = A.row_ind(j); } } } for (i = 0; i < dim_[1]; i++) QSort(indx_, val_, pntr_[i], pntr_[i+1] - pntr_[i]); for (i = 0; i < dim_[1]; i++) if (indx_[pntr_(i)] != i) { cerr << "IC Preconditioner: diagonal not found!" << i << endl; Sortie(1); } ICFactor(pntr_, indx_, val_); }; void ICPreconditioner_double::Init_CompRow_Mat_double(const CompRow_Mat_double &A) { dim_[0] = A.dim(0); dim_[1] = A.dim(1); int i, j, k; for (k = 0; k < dim_[0]; k++) for (j = A.row_ptr(k); j < A.row_ptr(k+1); j++) if (A.col_ind(j) >= k) nz_++; val_.newsize(nz_); indx_.newsize(nz_); // Copy just triangular part (including diagonal) pntr_(0) = 0; for (k = 0; k < dim_[0]; k++) { pntr_(k+1) = pntr_(k); for (j = A.row_ptr(k); j < A.row_ptr(k+1); j++) { if (A.col_ind(j) >= k) { i = pntr_(k+1)++; val_(i) = A.val(j); indx_(i) = A.col_ind(j); } } } for (i = 0; i < dim_[0]; i++) QSort(indx_, val_, pntr_[i], pntr_[i+1] - pntr_[i]); for (i = 0; i < dim_[0]; i++) if (indx_[pntr_(i)] != i) { cerr << "IC Preconditioner: diagonal not found!" << i << endl; Sortie(1); } ICFactor(pntr_, indx_, val_); };