190 lines
6.9 KiB
C++
190 lines
6.9 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
/* ******** *** 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. */
|
|
/* */
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
|
|
#include <stdlib.h>
|
|
#include "diagpre_double_GR.h" // modif GR : découle d'une classe virtuelle
|
|
// pour avoir une interface standard
|
|
|
|
#include "Mat_pleine.h"
|
|
#include "MatBand.h"
|
|
#include "Mat_creuse_CompCol.h"
|
|
#include "ConstMath.h"
|
|
#include "MathUtil.h"
|
|
|
|
DiagPreconditioner_double::DiagPreconditioner_double(const CompRow_Mat_double &C)
|
|
: diag_(C.dim(0))
|
|
{
|
|
int i;
|
|
if ((i = CopyInvDiagonals(C.dim(0), &C.row_ptr(0), &C.col_ind(0),
|
|
&C.val(0), &diag(0))) != 0) {
|
|
cerr << "Diagonal preconditioner failure.";
|
|
cerr << " Zero detected in element " << i << endl;
|
|
Sortie(1);
|
|
}
|
|
}
|
|
|
|
|
|
DiagPreconditioner_double::DiagPreconditioner_double(const CompCol_Mat_double &C)
|
|
: diag_ (C.dim (0))
|
|
{
|
|
int i;
|
|
if ((i = CopyInvDiagonals(C.dim(0), &C.col_ptr(0), &C.row_ind(0),
|
|
&C.val(0), &diag(0))) != 0) {
|
|
cerr << "Diagonal preconditioner failure.";
|
|
cerr << " Zero detected in element " << i << endl;
|
|
Sortie(1);
|
|
}
|
|
}
|
|
|
|
// cas d'une matrice abstraite
|
|
DiagPreconditioner_double::DiagPreconditioner_double(const Mat_abstraite &A) :
|
|
diag_ (A.Nb_ligne())
|
|
{ int i;
|
|
switch (A.Type_matrice())
|
|
{ case CREUSE_COMPRESSEE_LIGNE :
|
|
{const CompRow_Mat_double &C = (CompRow_Mat_double &) A;
|
|
// 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);
|
|
if ((i = CopyInvDiagonals(C.dim(0), &C.row_ptr(0), &C.col_ind(0),
|
|
&C.val(0), &diag(0))) != 0)
|
|
{ cerr << "Diagonal preconditioner failure.";
|
|
cerr << " Zero detected in element " << i << endl;
|
|
Sortie(1);
|
|
}
|
|
break;
|
|
}
|
|
case CREUSE_COMPRESSEE_COLONNE :
|
|
{const Mat_creuse_CompCol &C = (Mat_creuse_CompCol &) A;
|
|
if ((i = CopyInvDiagonals(C.dim(0), &C.col_ptr(0), &C.row_ind(0),
|
|
&C.val(0), &diag(0))) != 0)
|
|
{ cerr << "Diagonal preconditioner failure.";
|
|
cerr << " Zero detected in element " << i << endl;
|
|
Sortie(1);
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{if ((i = CopyInvDiagonals(A)) != 0)
|
|
{ cerr << "Diagonal preconditioner failure.";
|
|
cerr << " Zero detected in element " << i << endl;
|
|
Sortie(1);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
int
|
|
DiagPreconditioner_double::CopyInvDiagonals
|
|
(int n, const int *pntr, const int *indx
|
|
,const double *sa, double *diag)
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < n; i++)
|
|
diag[i] = 0;
|
|
|
|
/* Find the diagonal elements */
|
|
for (i = 0; i < n; i++) {
|
|
for (j = pntr[i]; j < pntr[i+1]; j++) {
|
|
if (indx[j] == i) {
|
|
if (sa[j] == 0)
|
|
return i;
|
|
diag[i] = 1. / sa[j];
|
|
break;
|
|
}
|
|
}
|
|
if (diag[i] == 0)
|
|
return -i;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// surcharge de la fonction pour les matrices carrées et/ou bande
|
|
int DiagPreconditioner_double::CopyInvDiagonals(const Mat_abstraite& A)
|
|
{ switch (A.Type_matrice())
|
|
{ case CARREE :
|
|
break;
|
|
case CARREE_LAPACK :
|
|
break;
|
|
case BANDE_SYMETRIQUE :
|
|
case CARREE_SYMETRIQUE : break;
|
|
case RECTANGLE : break;
|
|
case BANDE_NON_SYMETRIQUE: break;
|
|
case CARREE_SYMETRIQUE_LAPACK : break;
|
|
case RECTANGLE_LAPACK : break;
|
|
case BANDE_SYMETRIQUE_LAPACK : break;
|
|
case BANDE_NON_SYMETRIQUE_LAPACK : break;
|
|
case CREUSE_NON_COMPRESSEE : break;
|
|
case CREUSE_COMPRESSEE_COLONNE : break;
|
|
case CREUSE_COMPRESSEE_LIGNE : break;
|
|
case DIAGONALE : 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 diagonal\n";
|
|
cout << "\n CopyInvDiagonals(Mat_abstraite& A, double *diag)\n";
|
|
Sortie(1);
|
|
};
|
|
int n = A.Nb_ligne();
|
|
for (int i = 1; i <= n; i++)
|
|
if (Abs(A(i,i)) < ConstMath::trespetit)
|
|
return -1;
|
|
else
|
|
diag(i-1) = 1./A(i,i);
|
|
return 0;
|
|
};
|
|
|
|
|
|
VECTOR_double
|
|
DiagPreconditioner_double::solve (const VECTOR_double &x) const
|
|
{
|
|
VECTOR_double y(x.size());
|
|
|
|
for (int i = 0; i < x.size(); i++)
|
|
y(i) = x(i) * diag(i);
|
|
|
|
return y;
|
|
}
|
|
|
|
|
|
VECTOR_double
|
|
DiagPreconditioner_double::trans_solve (const VECTOR_double &x) const
|
|
{
|
|
VECTOR_double y(x.size());
|
|
|
|
for (int i = 0; i < x.size(); i++)
|
|
y(i) = x(i) * diag(i);
|
|
|
|
return y;
|
|
}
|