853 lines
33 KiB
C++
Executable file
853 lines
33 KiB
C++
Executable file
|
|
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
//#include "Debug.h"
|
|
#include "Mat_creuse_CompCol.h"
|
|
#include <iomanip>
|
|
#include "CharUtil.h"
|
|
#include <algorithm>
|
|
#include "MatDiag.h"
|
|
|
|
#include "Vector_io.h"
|
|
|
|
// constructeur par défaut
|
|
Mat_creuse_CompCol::Mat_creuse_CompCol () :
|
|
Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL)
|
|
,CompCol_Mat_double()
|
|
{};
|
|
// constructeur parmettant la création d'une matrice creuse
|
|
// ici aucun élément de la matrice n'est créé, il faut ensuite utiliser l'initialisation
|
|
// pour créer les éléments non nulles dans la matrice
|
|
// M : nombre de lignes
|
|
// N : nombre de colonnes
|
|
|
|
Mat_creuse_CompCol::Mat_creuse_CompCol(int M, int N) :
|
|
Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL)
|
|
// ,CompCol_Mat_double(M,N,0,NULL,NULL,NULL)
|
|
,CompCol_Mat_double()
|
|
{ // dimensionnement et initialisation
|
|
this->newsize(M,N,0);
|
|
#ifdef MISE_AU_POINT
|
|
if ((M < 0) || (N < 0))
|
|
{cout << "erreur de dimensionnement d une matrice creuse";
|
|
cout << " M = " << M << " N = " << N << '\n';
|
|
cout << "Mat_creuse_CompCol::Mat_creuse_CompCol (int M, int N )" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
};
|
|
|
|
// constructeur parmettant la création d'une matrice creuse complete
|
|
// à partir de la donnée d'un ensemble de sous matrices
|
|
// M : nombre de lignes
|
|
// N : nombre de colonnes
|
|
//
|
|
Mat_creuse_CompCol::Mat_creuse_CompCol
|
|
(int M, int N,const Tableau < Tableau <int> >& petites_matrices):
|
|
Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL)
|
|
// ,CompCol_Mat_double(M,N,0,NULL,NULL,NULL)
|
|
,CompCol_Mat_double()
|
|
{ // dimensionnement et initialisation
|
|
this->newsize(M,N,0);
|
|
// appel de la routine permettant le dimentionnement effectif
|
|
Change_taille(M,N,petites_matrices);
|
|
};
|
|
|
|
// de copie à partir d'une sparse matrice compressée par ligne
|
|
//Mat_creuse_CompCol::Mat_creuse_CompCol(const Mat_creuse_CompRow &R) :
|
|
// Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL)
|
|
// ,CompRow_Mat_double(R)
|
|
// {};
|
|
// de copie à partir d'une sparse matrice non compressée
|
|
//Mat_creuse_CompCol::Mat_creuse_CompCol(const Mat_creuse_Coord &CO) :
|
|
// Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL)
|
|
// ,Coord_Mat_double(CO)
|
|
// {};
|
|
|
|
// constructeur de copie à partir d'une même instance
|
|
Mat_creuse_CompCol::Mat_creuse_CompCol(const Mat_creuse_CompCol &S) :
|
|
Mat_abstraite(S),CompCol_Mat_double(S)
|
|
{};
|
|
|
|
// fonction permettant de creer une nouvelle instance d'element
|
|
Mat_abstraite * Mat_creuse_CompCol::NouvelElement() const
|
|
{ Mat_abstraite * a;
|
|
a = new Mat_creuse_CompCol(*this);
|
|
return a;
|
|
};
|
|
|
|
// surcharge de l'opérateur d'affectation, cas de matrices abstraites
|
|
Mat_abstraite & Mat_creuse_CompCol::operator = ( const Mat_abstraite & b)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if (type_matrice != b.Type_matrice())
|
|
{cout << "erreur dans l'operation d'affectation";
|
|
cout << " les matrices sont de types différents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "Mat_creuse_CompCol::operator = ( const Mat_abstraite & b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
const Mat_creuse_CompCol & a = *((Mat_creuse_CompCol*) & b);
|
|
// affectation de la partie matrice creuse
|
|
(CompCol_Mat_double) a = (CompCol_Mat_double) *this;
|
|
return *this;
|
|
};
|
|
|
|
// surcharge de l'opérateur d'affectation, cas de matrices creuses
|
|
Mat_creuse_CompCol & Mat_creuse_CompCol::operator = ( const Mat_creuse_CompCol & a)
|
|
{
|
|
// affectation de la partie matrice creuse
|
|
(CompCol_Mat_double) a = (CompCol_Mat_double) *this;
|
|
return *this;
|
|
};
|
|
|
|
// transfert des informations de *this dans la matrice passée en paramètre
|
|
// la matrice paramètre est au préalable, mise à 0.
|
|
void Mat_creuse_CompCol::Transfert_vers_mat( Mat_abstraite & b )
|
|
{b.Initialise(0.); // init de la matrice
|
|
// puis on transfert
|
|
int taille_j = colptr_.size(); //
|
|
int nb_col_plus_1 = colptr_.size();
|
|
|
|
for (int j=1;j<nb_col_plus_1;j++)
|
|
{ int colptr_jplus1 = colptr_(j+1) ;
|
|
for (int t=colptr_(j); t<colptr_jplus1; t++)
|
|
b(rowind_(t),j)= val_(t);
|
|
};
|
|
};
|
|
|
|
// Surcharge de l'operateur += : addition d'une matrice a la matrice courante
|
|
// cette méthode n'est possible si et seulement les termes existant de mat_pl
|
|
void Mat_creuse_CompCol::operator+= (const Mat_abstraite& b)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if ((b.Type_matrice() != DIAGONALE) && ((*this) != b))
|
|
{cout << " erreur la matrice b à ajouter n'est pas soit diagonale ou soit "
|
|
<< " matrice creuse de même topologie "
|
|
<< Nom_matrice(b.Type_matrice());
|
|
cout << "Mat_creuse_CompCol::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// si les tailles ne sont pas identique pb
|
|
if (this->Nb_ligne() != b.Nb_ligne())
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_ligne() << " " << b.Nb_ligne() << '\n';
|
|
cout << "Mat_creuse_CompCol::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
if (b.Type_matrice() == CREUSE_COMPRESSEE_COLONNE)
|
|
// cas matrice creuse, on travaille directement sur les données de base
|
|
{
|
|
const Mat_creuse_CompCol & mat_b = *((Mat_creuse_CompCol*) & b);
|
|
val_ += mat_b.val_;
|
|
}
|
|
else
|
|
// cas d'une matrice diagonale
|
|
{ const MatDiag & mat_b = *((MatDiag*) & b);
|
|
int taille = this->Nb_ligne();
|
|
for (int i=1;i<= taille; i++)
|
|
(*this)(i,i) += mat_b(i,i);
|
|
}
|
|
};
|
|
|
|
// Surcharge de l'operateur -= : soustraction d'une matrice a la matrice courante
|
|
// cette méthode n'est possible si et seulement les termes existant de mat_pl
|
|
void Mat_creuse_CompCol::operator-= (const Mat_abstraite& b)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if ((b.Type_matrice() != DIAGONALE) && ((*this) != b))
|
|
{cout << " erreur la matrice b à ajouter n'est pas soit diagonale ou soit "
|
|
<< " matrice creuse de même topologie "
|
|
<< Nom_matrice(b.Type_matrice());
|
|
cout << "Mat_creuse_CompCol::operator-= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// si les tailles ne sont pas identique pb
|
|
if (this->Nb_ligne() != b.Nb_ligne())
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_ligne() << " " << b.Nb_ligne() << '\n';
|
|
cout << "Mat_creuse_CompCol::operator-= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
if (b.Type_matrice() == CREUSE_COMPRESSEE_COLONNE)
|
|
// cas matrice creuse, on travaille directement sur les données de base
|
|
{
|
|
const Mat_creuse_CompCol & mat_b = *((Mat_creuse_CompCol*) & b);
|
|
val_ -= mat_b.val_;
|
|
}
|
|
else
|
|
// cas d'une matrice diagonale
|
|
{ const MatDiag & mat_b = *((MatDiag*) & b);
|
|
int taille = this->Nb_ligne();
|
|
for (int i=1;i<= taille; i++)
|
|
(*this)(i,i) -= mat_b(i,i);
|
|
}
|
|
};
|
|
|
|
// Surcharge de l'operateur *= : multiplication de la matrice courante par un scalaire
|
|
void Mat_creuse_CompCol::operator*= (const double r)
|
|
{ // on multiplie les valeurs de la matrice
|
|
val_ *= r;
|
|
};
|
|
|
|
// Surcharge de l'operateur == : test d'egalite entre deux matrices
|
|
int Mat_creuse_CompCol::operator== (const Mat_abstraite& b) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if (type_matrice != b.Type_matrice())
|
|
{cout << " erreur les matrices sont de types différents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "int Mat_creuse_CompCol::operator== (const Mat_abstraite& mat_pl)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
const Mat_creuse_CompCol & mat_b = *((Mat_creuse_CompCol*) & b);
|
|
// on regarde si la partie classe de base CompCol_Mat_double
|
|
// est égale ou pas
|
|
if ( val_ != mat_b.val_ ) return 0;
|
|
if ( rowind_ != mat_b.rowind_ ) return 0;
|
|
if ( colptr_ != mat_b.colptr_ ) return 0;
|
|
if (base_ != mat_b.base_) return 0;
|
|
if (nz_ != mat_b.nz_) return 0;
|
|
if (dim_[0] != mat_b.dim_[0]) return 0;
|
|
if (dim_[1] != mat_b.dim_[1]) return 0;
|
|
// pour les données de classe abstraite, à part le type de matrice
|
|
// on autorise que les autres variables soient différentes
|
|
return 1;
|
|
};
|
|
|
|
|
|
|
|
// Retourne la ieme ligne de la matrice
|
|
Vecteur Mat_creuse_CompCol::Ligne(int i) const
|
|
{ Vecteur ligne(dim(1)); // mise a zero de ligne
|
|
for (int j=0;j<dim(1);j++)
|
|
{int tmax = colptr_(j+1);
|
|
for (int t=colptr_(j); t<tmax; t++)
|
|
if (rowind_(t) == i-1) ligne(j+1) = val_(t);
|
|
}
|
|
return ligne;
|
|
};
|
|
|
|
// Retourne la ieme ligne de la matrice
|
|
// sous le format de stokage propre a la matrice
|
|
// en fait ici il faut dans tous les cas reconstruire le vecteur
|
|
Vecteur Mat_creuse_CompCol::LigneSpe(int i) const
|
|
{ return Ligne(i);
|
|
};
|
|
|
|
// remplace la ligne de la matrice par la ligne fournie
|
|
void Mat_creuse_CompCol::RemplaceLigneSpe(int i,const Vecteur & v)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (v.Taille() != dim(1))
|
|
{cout << "\nerreur d affectation pour le vecteur";
|
|
cout << " dim vecteur = " << v.Taille() << " au lieu de " << dim(1) <<'\n';
|
|
cout << "void Mat_creuse_CompCol::RemplaceLigne(int i,Vecteur & v)" << endl;
|
|
}
|
|
#endif
|
|
for (int j=0;j<dim(1);j++)
|
|
{int tmax = colptr_(j+1);
|
|
for (int t=colptr_(j); t<tmax; t++)
|
|
if (rowind_(t) == i-1) val_(t) = v(j+1);
|
|
}
|
|
};
|
|
|
|
//met une valeur identique sur toute la ligne
|
|
void Mat_creuse_CompCol::MetValLigne(int i,double x)
|
|
{
|
|
for (int j=0;j<dim(1);j++)
|
|
{int tmax = colptr_(j+1);
|
|
for (int t=colptr_(j); t<tmax; t++)
|
|
if (rowind_(t) == i-1) val_(t) = x;
|
|
}
|
|
};
|
|
|
|
// Retourne la jeme colonne de la matrice
|
|
Vecteur Mat_creuse_CompCol::Colonne(int j) const
|
|
{ Vecteur col(dim(0)); // mise a zero de la colonne
|
|
int tmax = colptr_(j);
|
|
for (int t=colptr_(j-1); t<tmax; t++)
|
|
col(rowind_(t)+1) = val_(t);
|
|
return col;
|
|
};
|
|
|
|
// Retourne la jeme colonne de la matrice
|
|
// sous le format de stokage propre a la matrice
|
|
// donc a n'utiliser que comme sauvegarde en parralele
|
|
// avec la fonction RemplaceColonne
|
|
Vecteur Mat_creuse_CompCol::ColonneSpe(int j) const
|
|
{ int tmin = colptr_(j-1); int tmax = colptr_(j);
|
|
Vecteur col(tmax-tmin); // mise a zero de colonne
|
|
int i=1;
|
|
for (int t=tmin; t<tmax; t++,i++)
|
|
col(i) = val_(t);
|
|
return col;
|
|
};
|
|
|
|
// remplace la Colonne de la matrice par la colonne fournie
|
|
void Mat_creuse_CompCol::RemplaceColonneSpe(int j,const Vecteur & v)
|
|
{ int tmin = colptr_(j-1); int tmax = colptr_(j);
|
|
#ifdef MISE_AU_POINT
|
|
if (v.Taille() != tmax-tmin)
|
|
{cout << "\nerreur d affectation pour le vecteur";
|
|
cout << " dim vecteur = " << v.Taille() << " au lieu de " << tmax-tmin << '\n';
|
|
cout << "void Mat_creuse_CompCol::RemplaceColonne(int j,Vecteur & v)" << endl;
|
|
}
|
|
#endif
|
|
int i=1;
|
|
for (int t=tmin; t<tmax; t++,i++)
|
|
val_(t) = v(i);
|
|
};
|
|
|
|
//met une valeur identique sur toute la colonne
|
|
void Mat_creuse_CompCol::MetValColonne(int j,double y)
|
|
{ int tmin = colptr_(j-1); int tmax = colptr_(j);
|
|
int i=1;
|
|
for (int t=tmin; t<tmax; t++,i++)
|
|
val_(t) = y;
|
|
};
|
|
|
|
// Affichage des valeurs de la matrice
|
|
void Mat_creuse_CompCol::Affiche () const
|
|
{ cout << "\n affichage d une matrice creuse générale "
|
|
<< " de dimension= " << dim(0) << " * " << dim(1) << '\n';
|
|
int i,j;
|
|
for (i=1;i<=dim(0)+1;i++)
|
|
{ Vecteur ligne = Ligne(i);
|
|
for (j=1;j<=i;j++)
|
|
{ cout << setw(4) << " i= " << i << " j= " << j << " * "
|
|
<< setw(14) << setprecision(7) << Ligne(j) << '\n';
|
|
}
|
|
}
|
|
cout << endl ;
|
|
};
|
|
|
|
// Affiche une partie de la matrice (util pour le debug)
|
|
// MiN_ et max_ sont les bornes de la sous_matrice
|
|
// pas_ indique le pas en i et j pour les indices
|
|
void Mat_creuse_CompCol::Affiche1(int min_i,int max_i,int pas_i,int min_j,int max_j,int pas_j)
|
|
const
|
|
{ cout << "\n affichage d une matrice creuse générale "
|
|
<< " de dimension= " << dim(0) << " * " << dim(1) << '\n';
|
|
int i,j;
|
|
cout << " ";
|
|
for (j=min_j;j<=max_j;j+=pas_j) cout << "col " << setw(4) << j << " " ;
|
|
cout << '\n';
|
|
for (i=min_i;i<=max_i;i+=pas_i)
|
|
{ cout << "lig " << setw(4) << i << " * ";
|
|
for (j=min_j;j<=max_j;j+=pas_j)
|
|
cout << setw(11) << setprecision(7) << (*this)(i,j);
|
|
cout << '\n';
|
|
}
|
|
cout << endl;
|
|
};
|
|
// Affiche une partie de la matrice (util pour le debug)
|
|
// MiN_ et max_ sont les bornes de la sous_matrice
|
|
// pas_ indique le pas en i et j pour les indices
|
|
// avec en plus le nb de digit = nd
|
|
void Mat_creuse_CompCol::Affiche2
|
|
(int min_i,int max_i,int pas_i,int min_j,int max_j,int pas_j,int nd)
|
|
const
|
|
{ cout << "\n affichage d une matrice creuse générale "
|
|
<< " de dimension= " << dim(0) << " * " << dim(1) << '\n';
|
|
if (nd < 7)
|
|
{ cout << " dimension des colonnes trop faible (<7 ! ) " << endl;
|
|
return;
|
|
}
|
|
int i,j;
|
|
SortBlanc(7);
|
|
|
|
for (j=min_j;j<=max_j;j+=pas_j)
|
|
{ cout << "col " << setw(2) << j ;
|
|
SortBlanc(nd-6);
|
|
}
|
|
cout << '\n';
|
|
for (i=min_i;i<=max_i;i+=pas_i)
|
|
{ cout << "li " << setw(3) << i << "* ";
|
|
for (j=min_j;j<=max_j;j+=pas_j)
|
|
cout << setw(nd) << setprecision(7) << (*this)(i,j);
|
|
cout << '\n';
|
|
}
|
|
cout << endl;
|
|
};
|
|
|
|
// changement de la taille de la matrice : c-a-d permet de redimentionner
|
|
// la matrice creuse
|
|
// 1) cas d'un utilisateur qui connait un ensemble de petite matrice qui doivent être contenue
|
|
// dans la matrice creuse, la matrice initiale est effacée
|
|
// les petites matrices sont carrées, ils sont définit par un tableau ligne qui contiend
|
|
// la position d'un terme de la petite matrice dans la grande matrice
|
|
// exemple : pet_mat(k)(i), pet_mat(k)(j) : indique le numéro de ligne et le numéro de colonne
|
|
// d'un élément non nul dans la grande matrice
|
|
// M et N : nb ligne et nb colonne,
|
|
void Mat_creuse_CompCol::Change_taille
|
|
(const int M,const int N , const Tableau < Tableau <int> >& pet_mat)
|
|
{ // def du tableau d'indice de colonnes et de lignes
|
|
// mat(j) représente contiend l'ensemble des indices de lignes non nuls pour la colonne j
|
|
Tableau < Vector_io <int> > mat(N);
|
|
// on remplit le tableau
|
|
int nb_matrices = pet_mat.Taille();
|
|
for (int k= 1; k<= nb_matrices; k++)
|
|
{ int ligcol_max = pet_mat(k).Taille();
|
|
for (int j=1;j<= ligcol_max;j++)
|
|
{ // le vecteur des indices de colonne
|
|
Vector_io <int>& v_col = mat(pet_mat(k)(j));
|
|
// boucle sur les lignes
|
|
for (int i=1;i<= ligcol_max;i++)
|
|
// on recherche la position à insérer
|
|
{int jmat_glob = pet_mat(k)(i); // le numero de ligne
|
|
// cout << "\n le vecteur " ;
|
|
// for (int a=0;a< v_col.size();a++)
|
|
// cout << v_col[a] << "";
|
|
// cout << endl;
|
|
// cout << "\n v_col.begin() " << v_col.begin() << ", v_col.end() " << v_col.end()
|
|
// << " jmat_glob " << jmat_glob ;
|
|
Vector_io<int>::iterator p = lower_bound(v_col.begin(),v_col.end(),jmat_glob);
|
|
// int truc;
|
|
// cout << "\n valeur de *p " << *p << endl; cin >> truc;
|
|
// insertion s'il n'existe pas déjà
|
|
// normalement l'insertion respecte l'ordre déjà existant
|
|
// premier test est-ce que l'on doit mettre à la fin
|
|
if (p == v_col.end())
|
|
// cas ou le nouvel élément est le plus grand
|
|
v_col.insert(p,jmat_glob);
|
|
else if (*p != jmat_glob)
|
|
// cas ou l'on est inférieur au maxi, on teste s'il n'existe pas déjà
|
|
v_col.insert(p,jmat_glob);
|
|
// cout << "\n le vecteur après insertion" ;
|
|
// for (int a=0;a< v_col.size();a++)
|
|
// cout << v_col[a] << "";
|
|
// cout << endl; cin >> truc;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// maintenant on va passer en revue les éléments non nulle de la matrice
|
|
// 1) on regarde les éléments non nuls
|
|
int nb_nonnul = 0;
|
|
for (int j=1;j<= N;j++)
|
|
{ // le vecteur des indices de colonne
|
|
Vector_io <int>& v_cal = mat(j);
|
|
int taille_v_cal = (int) v_cal.size(); // le nb d'élément non nul de la colonne
|
|
// dans le cas ou aucun élément de la colonne n'est nulle
|
|
// on prévoit de retenir l'élément diagonal quand même, il sera donc nulle
|
|
// car a priori il y a un pb si aucun élément de la colonne n'exite
|
|
if (taille_v_cal == 0)
|
|
{ v_cal.push_back(min(j,M));
|
|
taille_v_cal++;
|
|
}
|
|
// mise a jour du pointeur global
|
|
nb_nonnul += taille_v_cal;
|
|
}
|
|
|
|
// 2) on redimentionne
|
|
newsize(M,N,nb_nonnul);
|
|
// on met à zéro les termes de la matrice
|
|
for (int iv=0;iv<nb_nonnul;iv++) val(iv)=0.;
|
|
|
|
// 3) on définit précisemment le vecteur pointeur de colonne
|
|
int iptcol = 0; // le pointeur courant de l'élément non nul de la colonne considérée
|
|
// initialisation de la première valeur qui existe forcément vu le 1)
|
|
colptr_[0] = 0;
|
|
// puis les autres colonnes
|
|
for (int jcol=1;jcol<= N;jcol++)
|
|
{ // le vecteur des indices de colonne
|
|
Vector_io <int>& v_cul = mat(jcol);
|
|
int taille_v_cul = (int) v_cul.size(); // le nb d'élément non nul de la colonne
|
|
// les indices de lignes avec mise à jour du pointeur iptcol
|
|
for (int i_v_cul = 1; i_v_cul <= taille_v_cul; i_v_cul++,iptcol++)
|
|
rowind_(iptcol) = v_cul[(unsigned long) i_v_cul-1] - 1;
|
|
// on ressort de la boucle avec iptcol bon pour le jcol suivant
|
|
// mise a jour du pointeur de colonne
|
|
colptr_(jcol) = iptcol;
|
|
}
|
|
};
|
|
|
|
// 2) cas d'un utilisateur qui connait le stockage par colonne
|
|
// M et N : nb ligne et nb colonne,
|
|
// pointeur_colonne : donne dans le vecteur de stockage global le début de chaque colonne
|
|
// nz : nb de termes non nulles dans la matrice
|
|
void Mat_creuse_CompCol::Change_taille
|
|
(const int M,const int N , const Tableau<int>& pointeur_colonne,const int nz)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((M < 0) || (N < 0))
|
|
{cout << "erreur de dimensionnement d une matrice creuse compressée colonne";
|
|
cout << " nb ligne " << M << " nb col = " << N << '\n';
|
|
cout << "void Mat_creuse_CompCol::Change_taille(int M, int N )" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
CompCol_Mat_double::newsize(M,N,nz); // dimensionnement générique
|
|
// puis on définit précisément le vecteur pointeur
|
|
#ifdef MISE_AU_POINT
|
|
// on vérifie la taille
|
|
if (pointeur_colonne.Taille() != (dim_[1]+1) )
|
|
{cout << "\n erreur de dimensionnement d une matrice creuse compressée colonne";
|
|
cout << " la taille du vecteur pointeur colonne= " << pointeur_colonne.Taille()
|
|
<< " devrait être de " << (dim_[1]+1) << '\n';
|
|
cout << "\n void Mat_creuse_CompCol::Change_taille(int M, int N,"
|
|
<< " Tableau<int> pointeur_colonne, )" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
for (int i=1;i<= dim_[1]+1;i++)
|
|
colptr_(i-1) = pointeur_colonne(i);
|
|
};
|
|
|
|
void Mat_creuse_CompCol::Initialise (double a) // initialisation de la matrice a la valeur "a"
|
|
{ CompCol_Mat_double::val_ = a;
|
|
};
|
|
|
|
void Mat_creuse_CompCol::Libere () // Liberation de la place memoire
|
|
{
|
|
CompCol_Mat_double::newsize(0,0,0);
|
|
};
|
|
|
|
// ---------------------------------------------------------------
|
|
// Resolution du systeme Ax=b
|
|
// ---------------------------------------------------------------
|
|
|
|
//1) avec en sortie un new vecteur
|
|
Vecteur Mat_creuse_CompCol::Resol_syst
|
|
(const Vecteur& b,const double &tole, const int maxi, const int rest)
|
|
{ // sauvegarde du vecteur b
|
|
Vecteur bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
return bb;
|
|
};
|
|
|
|
//2) avec en sortie le vecteur d'entree
|
|
Vecteur& Mat_creuse_CompCol::Resol_systID
|
|
(Vecteur& b,const double &tole, const int maxi, const int rest)
|
|
{ // résolution
|
|
Vecteur bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
b=bb;
|
|
return b;
|
|
};
|
|
|
|
//3) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie un nouveau tableau de vecteurs
|
|
Tableau <Vecteur> Mat_creuse_CompCol::Resol_syst
|
|
(const Tableau <Vecteur>& b,const double &tole, const int maxi, const int rest)
|
|
{ // sauvegarde de b
|
|
Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
return bb;
|
|
};
|
|
|
|
//4) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie le tableau de vecteurs d'entree
|
|
Tableau <Vecteur>& Mat_creuse_CompCol::Resol_systID
|
|
(Tableau <Vecteur>& b,const double &tole, const int maxi, const int rest)
|
|
{ // résolution
|
|
Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
b=bb;
|
|
return b;
|
|
};
|
|
|
|
//5) avec en sortie le dernier vecteur d'entree, le premier étant le second membre
|
|
// et restant inchangé, en sortie c'est donc soit le retour ou soit vortie, les
|
|
// deux étant identiques
|
|
Vecteur& Mat_creuse_CompCol::Resol_systID_2 (const Vecteur& b,Vecteur& vortie
|
|
, const double &tole,const int maxi,const int rest)
|
|
{ Mat_abstraite::Resolution_syst(b,vortie,tole,maxi,rest);
|
|
return vortie;
|
|
};
|
|
|
|
// ===== RÉSOLUTION EN DEUX TEMPS ================ :
|
|
// 1) préparation de la matrice donc modification de la matrice éventuellement
|
|
// par exemple pour les matrices bandes avec cholesky : triangulation
|
|
void Mat_creuse_CompCol::Preparation_resol()
|
|
{ // les seules résolutions possibles sont celles itératives qui laissent la matrice inchangée
|
|
// donc ici on n'a rien à préparer
|
|
};
|
|
// 2) *** résolution sans modification de la matrice DOIT ÊTRE PRÉCÉDÉ DE L'APPEL DE
|
|
// Preparation_resol
|
|
// a) avec en sortie un new vecteur
|
|
Vecteur Mat_creuse_CompCol::Simple_Resol_syst (const Vecteur& b,const double &tol
|
|
,const int maxi,const int rest) const
|
|
{ // sauvegarde du vecteur b
|
|
Vecteur bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,rest);
|
|
return bb;
|
|
};
|
|
// b) avec en sortie le vecteur d'entree
|
|
Vecteur& Mat_creuse_CompCol::Simple_Resol_systID (Vecteur& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{ // résolution
|
|
Vecteur bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart);
|
|
b=bb;
|
|
return b;
|
|
};
|
|
// c) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie un nouveau tableau de vecteurs
|
|
Tableau <Vecteur> Mat_creuse_CompCol::Simple_Resol_syst
|
|
(const Tableau <Vecteur>& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{ // sauvegarde de b
|
|
Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart);
|
|
return bb;
|
|
};
|
|
// d) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie le tableau de vecteurs d'entree
|
|
Tableau <Vecteur>& Mat_creuse_CompCol::Simple_Resol_systID
|
|
(Tableau <Vecteur>& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{ // résolution
|
|
Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart);
|
|
b=bb;
|
|
return b;
|
|
};
|
|
// e) avec en sortie le dernier vecteur d'entree, le premier étant le second membre
|
|
// et restant inchangé, en sortie c'est donc soit le retour ou soit vortie, les
|
|
// deux étant identiques
|
|
Vecteur& Mat_creuse_CompCol::Simple_Resol_systID_2 (const Vecteur& b,Vecteur& vortie
|
|
, const double &tol,const int maxi,const int restart) const
|
|
{ Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,restart);
|
|
return vortie;
|
|
};
|
|
// ===== FIN RÉSOLUTION EN DEUX TEMPS ================ : */
|
|
|
|
// Multiplication d'un vecteur par une matrice ( (vec)t * A )
|
|
Vecteur Mat_creuse_CompCol::Prod_vec_mat ( const Vecteur& vec) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim(0) != vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim(0) << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur Mat_creuse_CompCol::Prod_vec_mat ( Vecteur& vec)" << endl;
|
|
}
|
|
#endif
|
|
|
|
// récup de l'homologue de vec en vecteur_double
|
|
const VECTOR_double vec_double(vec.MV_vecteur_double());
|
|
// définition du vecteur de retour
|
|
Vecteur res(dim(1));
|
|
// utilisation de la multiplication dèjà définie
|
|
VECTOR_double res_double = this->CompCol_Mat_double::trans_mult(vec_double);
|
|
res = res_double;
|
|
return res;
|
|
|
|
};
|
|
|
|
// Multiplication d'un vecteur par une matrice ( (vec)t * A )
|
|
// ici on se sert du second vecteur pour le résultat
|
|
Vecteur& Mat_creuse_CompCol::Prod_vec_mat ( const Vecteur& vec,Vecteur& res) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim(0) != vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim(0) << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur& Mat_creuse_CompCol::Prod_vec_mat ( Vecteur& vec,Vecteur& res)" << endl;
|
|
}
|
|
#endif
|
|
|
|
// récup de l'homologue de vec en vecteur_double
|
|
const VECTOR_double vec_double(vec.MV_vecteur_double());
|
|
// définition du vecteur de retour
|
|
res.Change_taille(dim(1));
|
|
// utilisation de la multiplication dèjà définie
|
|
VECTOR_double res_double = this->CompCol_Mat_double::trans_mult(vec_double);
|
|
res = res_double;
|
|
return res;
|
|
};
|
|
|
|
// Multiplication d'une matrice par un vecteur ( A * vec )
|
|
Vecteur Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim(1) != vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim(1) << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec)" << endl;
|
|
}
|
|
#endif
|
|
// récup de l'homologue de vec en vecteur_double
|
|
const VECTOR_double * vec_double_pt = vec.Nouveau_MV_Vector_double_const();
|
|
const VECTOR_double& vec_double = (*vec_double_pt);
|
|
// const VECTOR_double vec_double(vec.MV_vecteur_double());
|
|
// définition du vecteur de retour
|
|
Vecteur res(dim(0));
|
|
// utilisation de la multiplication dèjà définie
|
|
VECTOR_double res_double = this->CompCol_Mat_double::operator *(vec_double);
|
|
res = res_double;
|
|
delete vec_double_pt;
|
|
return res;
|
|
};
|
|
|
|
// Multiplication d'une matrice par un vecteur ( A * vec )
|
|
// ici on se sert du second vecteur pour le résultat
|
|
Vecteur& Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec,Vecteur& res) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim(1)> vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim(1) << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur& Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec,Vecteur& res)" << endl;
|
|
}
|
|
#endif
|
|
// récup de l'homologue de vec en vecteur_double
|
|
const VECTOR_double * vec_double_pt = vec.Nouveau_MV_Vector_double_const();
|
|
const VECTOR_double& vec_double = (*vec_double_pt);
|
|
// const VECTOR_double vec_double(vec.MV_vecteur_double());
|
|
// définition du vecteur de retour
|
|
res.Change_taille(dim(0));
|
|
// utilisation de la multiplication dèjà définie
|
|
VECTOR_double res_double = this->CompCol_Mat_double::operator *(vec_double);
|
|
res = res_double;
|
|
delete vec_double_pt;
|
|
return res;
|
|
};
|
|
|
|
|
|
// Multiplication d'une ligne iligne de la matrice avec un vecteur de
|
|
// dimension = le nombre de colonne de la matrice
|
|
double Mat_creuse_CompCol::Prod_Ligne_vec ( int iligne,const Vecteur& vec) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim(1) != vec.Taille())
|
|
{ cout << " \n erreur la taille du vecteur = " << vec.Taille() <<" n est pas correcte ";
|
|
cout << " dimMatrice = " << dim(1);
|
|
cout << " double Mat_creuse_CompCol::Prod_Ligne_vec ( int iligne,Vecteur& vec)" << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
// retour du produit scalaire
|
|
return Ligne(iligne) * vec;
|
|
};
|
|
|
|
// Multiplication d'un vecteur avec une colonne icol de la matrice
|
|
// dimension = le nombre de ligne de la matrice
|
|
double Mat_creuse_CompCol::Prod_vec_col( int jcol,const Vecteur& vec) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim(0) != vec.Taille())
|
|
{ cout << " \n erreur la taille du vecteur = " << vec.Taille() <<" n est pas correcte ";
|
|
cout << " dimMatrice = " << dim(0);
|
|
cout << " double Mat_creuse_CompCol::Prod_vec_col( int icol,Vecteur& vec)" << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
// retour du produit scalaire
|
|
return Colonne(jcol) * vec;
|
|
};
|
|
|
|
// calcul du produit : (vec_1)^T * A * (vect_2)
|
|
double Mat_creuse_CompCol::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (vec1.Taille() != dim(0))
|
|
{cout << "erreur de taille, la dimension de (vec1)^T= " << vec1.Taille() << " n'a pas la même dimension";
|
|
cout << " que le le nombre de ligne de la matrice= " << dim(0)
|
|
<< "\n Mat_creuse_CompCol::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (vec2.Taille() != dim(1))
|
|
{cout << "erreur de taille, la dimension de (vec2)= " << vec2.Taille() << " n'a pas la même dimension";
|
|
cout << " que le le nombre de colonne de la matrice= " << dim(1)
|
|
<< "\n Mat_creuse_CompCol::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
// récup de l'homologue de vec2 en vecteur_double
|
|
const VECTOR_double * vec_double_pt = vec2.Nouveau_MV_Vector_double_const();
|
|
const VECTOR_double& vec_double = (*vec_double_pt);
|
|
// utilisation de la multiplication dèjà définie
|
|
VECTOR_double res_double = this->CompCol_Mat_double::operator *(vec_double);
|
|
// produit scalaire
|
|
double retour = 0.;
|
|
for (int i=0;i<dim(0);i++)
|
|
retour += vec_double(i) * res_double(i);
|
|
return retour;
|
|
};
|
|
|
|
|
|
|
|
//========================================================
|
|
// METHODES externes
|
|
//========================================================
|
|
|
|
// surcharge de l'operateur de lecture typée
|
|
istream & operator >> (istream & entree, Mat_creuse_CompCol & mat)
|
|
{ // vérification du type
|
|
string type;
|
|
entree >> type;
|
|
if (type != "Mat_creuse_CompCol")
|
|
{Sortie (1);
|
|
return entree;
|
|
}
|
|
// les dimensions
|
|
entree >> mat.dim_[0] >> mat.dim_[1] >> mat.nz_ >> mat.base_;
|
|
// les datas
|
|
string toto;
|
|
entree >> toto >> mat.val_;
|
|
entree >> toto >> mat.rowind_;
|
|
entree >> toto >> mat.colptr_;
|
|
|
|
return entree;
|
|
};
|
|
|
|
// surcharge de l'operateur d'ecriture typée
|
|
ostream & operator << ( ostream & sort,const Mat_creuse_CompCol & mat)
|
|
{ // un indicateur donnant le type puis les dimensions
|
|
sort << "Mat_creuse_CompCol " << mat.dim(0) << " " << mat.dim(1) << " "
|
|
<< mat.nz_ << " " << mat.base_;
|
|
// les datas
|
|
sort << "\n données " << mat.val_;
|
|
sort << "\n indices_ligne " << mat.rowind_;
|
|
sort << "\n indices_colonnes " << mat.colptr_;
|
|
|
|
return sort;
|
|
};
|
|
|
|
|
|
|