944 lines
33 KiB
C++
944 lines
33 KiB
C++
|
|
// 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 "MatDiag.h"
|
|
#include <iomanip>
|
|
#include "CharUtil.h"
|
|
|
|
|
|
// par defaut
|
|
MatDiag::MatDiag () :
|
|
Mat_abstraite(DIAGONALE,DIRECT_DIAGONAL,RIEN_PRECONDITIONNEMENT)
|
|
,diago(),inv_diago(),inversion(false)
|
|
{ };
|
|
|
|
// def d'une matrice diagonale
|
|
MatDiag::MatDiag ( int dim1 ) :
|
|
Mat_abstraite(DIAGONALE,DIRECT_DIAGONAL,RIEN_PRECONDITIONNEMENT)
|
|
,diago(dim1),inv_diago(dim1),inversion(false)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim1 < 0)
|
|
{cout << "erreur de dimensionnement d une matrice diagonale";
|
|
cout << " dim = " << dim1 << '\n';
|
|
cout << "MatDiag::MatDiag ( int dim )" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
// def d'une matrice diagonale avec
|
|
// initialisation des composantes a la valeur a
|
|
MatDiag::MatDiag ( int dim1 , double a) :
|
|
Mat_abstraite(DIAGONALE,DIRECT_DIAGONAL,RIEN_PRECONDITIONNEMENT)
|
|
,diago(dim1,a),inv_diago(dim1,a),inversion(false)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dim1 < 0)
|
|
{cout << "erreur de dimensionnement d une matrice diagonale";
|
|
cout << " dim = " << dim1 << '\n';
|
|
cout << "MatDiag::MatDiag ( int dim1 , double a)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
// de copie, il y a creation d'une deuxieme matrice
|
|
MatDiag::MatDiag (const MatDiag& m) :
|
|
Mat_abstraite(m),diago(m.diago),inv_diago(m.inv_diago),inversion(m.inversion)
|
|
{ };
|
|
|
|
// DESTRUCTEUR :
|
|
MatDiag::~MatDiag ()
|
|
{ };
|
|
|
|
// fonction permettant de creer une nouvelle instance d'element
|
|
Mat_abstraite * MatDiag::NouvelElement() const
|
|
{ Mat_abstraite * a;
|
|
a = new MatDiag(*this);
|
|
return a;
|
|
};
|
|
|
|
|
|
// surcharge de l'opérateur d'affectation, cas de matrices abstraites
|
|
Mat_abstraite & MatDiag::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 << "MatDiag::operator = ( const Mat_abstraite & b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
const MatDiag & a = *((MatDiag*) & 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 (diago.Taille()!=a.diago.Taille())
|
|
{cout << "erreur dans l'operation d'affectation";
|
|
cout << " les dimensions ne sont pas equivalentes dimensions = " << diago.Taille()
|
|
<< a.diago.Taille() << '\n';
|
|
cout << "MatDiag::operator = ( const Mat_abstraite & a)" << endl;
|
|
Sortie(1);
|
|
}
|
|
|
|
#endif
|
|
diago = a.diago; inv_diago = a.inv_diago; inversion = a.inversion;
|
|
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 MatDiag::Transfert_vers_mat( Mat_abstraite & b )
|
|
{b.Initialise(0.); // init de la matrice
|
|
// puis on transfert
|
|
int taille = diago.Taille();
|
|
for (int i=1;i<=taille;i++)
|
|
b(i,i)=diago(i);
|
|
};
|
|
|
|
// surcharge de l'opérateur d'affectation, cas de matrices diagonales
|
|
MatDiag & MatDiag::operator = ( const MatDiag & a)
|
|
{
|
|
#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 (diago.Taille()!=a.diago.Taille())
|
|
{cout << "erreur dans l'operation d'affectation";
|
|
cout << " les dimensions ne sont pas equivalentes dimensions = " << diago.Taille()
|
|
<< a.diago.Taille() << '\n';
|
|
cout << "MatDiag::operator = ( const MatDiag & a)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
diago = a.diago; inv_diago = a.inv_diago; inversion = a.inversion;
|
|
return *this;
|
|
};
|
|
|
|
// surcharge de l'opérateur d'affectation avec un vecteur
|
|
MatDiag & MatDiag::operator = ( const Vecteur & vect)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où le vecteur et la matrice n'ont pas la même dimension
|
|
// il y a un message d'erreur
|
|
if (diago.Taille()!=vect.Taille())
|
|
{cout << "erreur dans l'operation d'affectation";
|
|
cout << " les dimensions ne sont pas equivalentes dimensions = " << diago.Taille()
|
|
<< vect.Taille() << '\n';
|
|
cout << "MatDiag::operator = ( const Vecteur & vect" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
diago = vect;
|
|
inv_diago.Change_taille(diago.Taille());
|
|
inversion = false;
|
|
return *this;
|
|
};
|
|
|
|
// Surcharge de l'operateur += : addition d'une matrice a la matrice courante
|
|
void MatDiag::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 les matrices sont de types différents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "MatDiag::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// si les tailles ne sont pas identique pb
|
|
if (diago.Taille() != b.Nb_ligne())
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_ligne() << " " << b.Nb_ligne() << '\n';
|
|
cout << "MatDiag::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// calcul des termes de la matrice
|
|
const MatDiag & mat_d = *((MatDiag*) & b);
|
|
int taille = diago.Taille();
|
|
for (int i=1;i<=taille;i++)
|
|
diago(i) += mat_d.diago(i);
|
|
// on ne calcul pas l'inverse pour optimiser le temps de calcul
|
|
// si on a besoin ce sera fait en temps util
|
|
inversion = false;
|
|
};
|
|
|
|
// Surcharge de l'operateur -= : soustraction d'une matrice a la matrice courante
|
|
void MatDiag::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 les matrices sont de types différents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "MatDiag::operator-= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// si les tailles ne sont pas identique pb
|
|
if (diago.Taille() != b.Nb_ligne())
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_ligne() << " " << b.Nb_ligne() << '\n';
|
|
cout << "MatDiag::operator-= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// calcul des termes de la matrice
|
|
const MatDiag & mat_d = *((MatDiag*) & b);
|
|
int taille = diago.Taille();
|
|
for (int i=1;i<=taille;i++)
|
|
diago(i) -= mat_d.diago(i);
|
|
// on ne calcul pas l'inverse pour optimiser le temps de calcul
|
|
// si on a besoin ce sera fait en temps util
|
|
inversion = false;
|
|
};
|
|
|
|
// Surcharge de l'operateur *= : multiplication de la matrice courante par un scalaire
|
|
void MatDiag::operator*= (const double r)
|
|
{
|
|
// calcul des termes de la matrice
|
|
int taille = diago.Taille();
|
|
for (int i=1;i<=taille;i++)
|
|
diago(i) *= r;
|
|
// on ne calcul pas l'inverse pour optimiser le temps de calcul
|
|
// si on a besoin ce sera fait en temps util
|
|
inversion = false;
|
|
};
|
|
|
|
// Surcharge de l'operateur == : test d'egalite entre deux matrices
|
|
int MatDiag::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 MatDiag::operator== (const Mat_abstraite& mat_pl)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// si les tailles ne sont pas identique => différentes
|
|
if (this->Nb_ligne() != b.Nb_ligne())
|
|
return 0;
|
|
const MatDiag & mat_b = *((MatDiag*) & b);
|
|
int taille = diago.Taille();
|
|
for (int i=1;i<= taille; i++)
|
|
if ( diago != mat_b.diago)
|
|
return 0;
|
|
return 1;
|
|
};
|
|
|
|
// sortie d'une valeur acces au coordonnees en matrice carree
|
|
double& MatDiag::operator () (int i, int j )
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (i != j)
|
|
{cout << "erreur d acces aux composantes d une matrice diagonale";
|
|
cout << " i est différent de j, i= " << i << " j= " << j << '\n';
|
|
cout << "double MatDiag::operator () (int i, int j )" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (i<1 || i > diago.Taille() )
|
|
{cout << "erreur d acces aux composantes d une matrice diagonale";
|
|
cout << " premier indice hors borne i = " << i << '\n';
|
|
cout << "double MatDiag::operator () (int i, int j )" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
/* // message de warning
|
|
cout << "\n **** attention avec cet acces directe on ne peut plus ce fier "
|
|
<< " à l'indicateur de calcul d'inverse, car on peut accéder aux éléments"
|
|
<< "\n à éviter à tous pris, utiliser la fonction : set_element(i,j)";
|
|
Sortie(1); */
|
|
return diago(i);
|
|
};
|
|
|
|
// modification d'une valeur
|
|
// on impose la valeur val à la position (i,j) en fait ici seul la position
|
|
// i=j est possible
|
|
void MatDiag::set_element(int i, int j, double val)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (i != j)
|
|
{cout << "erreur d acces aux composantes d une matrice diagonale";
|
|
cout << " i est différent de j, i= " << i << " j= " << j << '\n';
|
|
cout << "MatDiag::set_element(int i, int j, double val)" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (i<1 || i > diago.Taille() )
|
|
{cout << "erreur d acces aux composantes d une matrice diagonale";
|
|
cout << " premier indice hors borne i = " << i << '\n';
|
|
cout << "MatDiag::set_element(int i, int j, double val)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
diago(i) = val;
|
|
// dans le cas où l'inversion est active on tente son maintien
|
|
if (inversion)
|
|
{ if (val != 0.)
|
|
inv_diago(i) = 1./val;
|
|
else
|
|
inversion = false;
|
|
}
|
|
};
|
|
|
|
// sortie en lecture seule, d'une valeur acces au coordonnees en matrice carree
|
|
double MatDiag::operator () (int i, int j ) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (i != j)
|
|
{cout << "erreur d acces aux composantes d une matrice diagonale";
|
|
cout << " i est différent de j, i= " << i << " j= " << j << '\n';
|
|
cout << "double MatDiag::operator () (int i, int j )" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (i<1 || i > diago.Taille() )
|
|
{cout << "erreur d acces aux composantes d une matrice diagonale";
|
|
cout << " premier indice hors borne i = " << i << '\n';
|
|
cout << "double MatDiag::operator () (int i, int j )" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
return diago(i);
|
|
};
|
|
|
|
/*
|
|
pour l'addition avec des matrices autres, il faut surcharger dans les autres types de
|
|
matrices et non ici, car l'adressage d'un élément est très rapide, d'ailleurs
|
|
à revoir plus haut.
|
|
|
|
*/
|
|
// Retourne la ieme ligne de la matrice
|
|
// a priori on considère une matrice carrée équivalente
|
|
Vecteur MatDiag::Ligne(int i) const
|
|
{ Vecteur ligne(diago.Taille()); // mise a zero de ligne
|
|
ligne(i) = diago(i);
|
|
return ligne;
|
|
};
|
|
|
|
// Retourne la ieme ligne de la matrice
|
|
// sous le format de stokage propre a la matrice
|
|
// donc a n'utiliser que comme sauvegarde en parralele
|
|
// avec la fonction RemplaceLigne
|
|
Vecteur MatDiag::LigneSpe(int i) const
|
|
{ Vecteur ligne(1); // mise a zero de ligne
|
|
ligne(1) = diago(i);
|
|
return ligne;
|
|
};
|
|
|
|
// remplace la ligne de la matrice par la ligne fournie
|
|
void MatDiag::RemplaceLigneSpe(int i,const Vecteur & v)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (v.Taille() != 1)
|
|
{cout << "\nerreur d affectation pour le vecteur";
|
|
cout << " dim vecteur = " << v.Taille() << " au lieu de " << 1 <<'\n';
|
|
cout << "void MatDiag::RemplaceLigne(int i,Vecteur & v)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
diago(i) = v(1);
|
|
inv_diago(i) = 1./v(1);
|
|
};
|
|
|
|
//met une valeur identique sur toute la ligne
|
|
void MatDiag::MetValLigne(int i,double x)
|
|
{ diago(i) = x;
|
|
inv_diago(i) = 1./x;
|
|
};
|
|
|
|
// Retourne la jeme colonne de la matrice
|
|
// on considère une matrice carrée associée
|
|
Vecteur MatDiag::Colonne(int j) const
|
|
{ Vecteur col(diago.Taille()); // mise a zero de colonne
|
|
col(j) = diago(j);
|
|
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 MatDiag::ColonneSpe(int j) const
|
|
{ Vecteur col(1); // mise a zero de colonne
|
|
col(1) = diago(j);
|
|
return col;
|
|
};
|
|
|
|
// remplace la Colonne de la matrice par la colonne fournie
|
|
void MatDiag::RemplaceColonneSpe(int j,const Vecteur & v)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (v.Taille() != 1)
|
|
{cout << "\nerreur d affectation pour le vecteur";
|
|
cout << " dim vecteur = " << v.Taille() << " au lieu de " << 1 << '\n';
|
|
cout << "void MatDiag::RemplaceColonne(int j,Vecteur & v)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
diago(j) = v(1);
|
|
inv_diago(j) = 1./v(1);
|
|
};
|
|
|
|
//met une valeur identique sur toute la colonne
|
|
void MatDiag::MetValColonne(int j,double y)
|
|
{
|
|
diago(j) = y;
|
|
inv_diago(j) = 1./y;
|
|
};
|
|
|
|
// Affichage des valeurs de la matrice
|
|
// uniquement les valeurs de la diagonale
|
|
void MatDiag::Affiche () const
|
|
{ int dim = diago.Taille();
|
|
cout << "\n affichage d une matrice diagonale de dimension= "
|
|
<< dim << "(valeurs de la diagonale)" <<'\n';
|
|
for (int i=1;i<=dim;i++)
|
|
{ cout << setw(4) << " i= " << i << " * "
|
|
<< setw(14) << setprecision(7) << diago(i) << '\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 MatDiag::Affiche1(int min_i,int max_i,int pas_i,int min_j,int max_j,int pas_j)
|
|
const
|
|
{ int dim = diago.Taille();
|
|
cout << "\n affichage d une matrice diagonale de dimension= " << dim << '\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) << Affiche_elem(i,j); //(*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 MatDiag::Affiche2
|
|
(int min_i,int max_i,int pas_i,int min_j,int max_j,int pas_j,int nd)
|
|
const
|
|
{ int dim = diago.Taille();
|
|
cout << "\n affichage d une matrice diagonale de dimension= " << dim << '\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) << Affiche_elem(i,j); //(*this)(i,j);
|
|
cout << '\n';
|
|
}
|
|
cout << endl;
|
|
};
|
|
|
|
void MatDiag::Change_taille( int dim1 ) // changement de la taille de la matrice
|
|
{ diago.Change_taille(dim1);
|
|
inv_diago.Change_taille(dim1);
|
|
inversion = false;
|
|
};
|
|
|
|
void MatDiag::Initialise (double a) // initialisation de la matrice a la valeur "a"
|
|
{ int dim = diago.Taille();
|
|
if (a != 0.)
|
|
{double unSurA = 1./a;
|
|
for (int i=1;i<= dim;i++)
|
|
{diago(i) = a; inv_diago(i) = unSurA;}
|
|
inversion = true;
|
|
}
|
|
else
|
|
{for (int i=1;i<= dim;i++)
|
|
diago(i) = a;
|
|
inversion = false;
|
|
}
|
|
|
|
};
|
|
|
|
void MatDiag::Libere () // Liberation de la place memoire
|
|
{ diago.Libere(); inv_diago.Libere();
|
|
inversion = false;
|
|
};
|
|
|
|
// ---------------------------------------------------------------
|
|
// Resolution du systeme Ax=b
|
|
// ---------------------------------------------------------------
|
|
|
|
//1) avec en sortie un new vecteur
|
|
Vecteur MatDiag::Resol_syst
|
|
(const Vecteur& b,const double &tole, const int maxi, const int rest)
|
|
{ // sauvegarde du vecteur b
|
|
Vecteur bb(b);
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
ResoDiag (b,bb);
|
|
else
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
return bb;
|
|
};
|
|
//2) avec en sortie le vecteur d'entree
|
|
Vecteur& MatDiag::Resol_systID
|
|
(Vecteur& b,const double &tole, const int maxi, const int rest)
|
|
{ // résolution
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
ResoDiag (b,b);
|
|
else
|
|
{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> MatDiag::Resol_syst
|
|
(const Tableau <Vecteur>& b,const double &tole, const int maxi, const int rest)
|
|
{ // sauvegarde de b
|
|
Tableau <Vecteur> bb(b);
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
ResoDiag (b,bb);
|
|
else
|
|
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>& MatDiag::Resol_systID
|
|
(Tableau <Vecteur>& b,const double &tole, const int maxi, const int rest)
|
|
{ // résolution
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
ResoDiag (b,b);
|
|
else
|
|
{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& MatDiag::Resol_systID_2 (const Vecteur& b,Vecteur& vortie
|
|
, const double &tole,const int maxi,const int rest)
|
|
{ if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
ResoDiag (b,vortie);
|
|
else
|
|
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 MatDiag::Preparation_resol()
|
|
{
|
|
int dim = diago.Taille();
|
|
// dans le cas où l'inverse n'est pas calculé on le recalcul
|
|
if (!inversion)
|
|
{for (int i=1;i<= dim; i++)
|
|
inv_diago(i) = 1./diago(i);
|
|
inversion = true;
|
|
};
|
|
};
|
|
// 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 MatDiag::Simple_Resol_syst (const Vecteur& b,const double &tol
|
|
,const int maxi,const int rest) const
|
|
{ // sauvegarde du vecteur b
|
|
Vecteur bb(b);
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
Const_ResoDiag (b,bb);
|
|
else
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,rest);
|
|
return bb;
|
|
};
|
|
// b) avec en sortie le vecteur d'entree
|
|
Vecteur& MatDiag::Simple_Resol_systID (Vecteur& b,const double &tol
|
|
,const int maxi,const int rest ) const
|
|
{ // résolution
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
Const_ResoDiag (b,b);
|
|
else
|
|
{Vecteur bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,rest);
|
|
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> MatDiag::Simple_Resol_syst
|
|
(const Tableau <Vecteur>& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{ // sauvegarde de b
|
|
Tableau <Vecteur> bb(b);
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
Const_ResoDiag (b,bb);
|
|
else
|
|
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>& MatDiag::Simple_Resol_systID
|
|
(Tableau <Vecteur>& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{ // résolution
|
|
if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
Const_ResoDiag (b,b);
|
|
else
|
|
{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& MatDiag::Simple_Resol_systID_2 (const Vecteur& b,Vecteur& vortie
|
|
, const double &tol,const int maxi,const int restart) const
|
|
{ if ((type_resolution==CHOLESKY)||(type_resolution==DIRECT_DIAGONAL))
|
|
Const_ResoDiag (b,vortie);
|
|
else
|
|
Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,restart);
|
|
return vortie;
|
|
};
|
|
// ===== FIN RÉSOLUTION EN DEUX TEMPS ================ :
|
|
|
|
// ========= fonctions spécifiques publiques des matrices diagonales =========
|
|
|
|
// surcharge d'opérateur += avec un vecteur
|
|
MatDiag & MatDiag::operator += ( const Vecteur & vect)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où le vecteur et la matrice n'ont pas la même dimension
|
|
// il y a un message d'erreur
|
|
if (diago.Taille()!=vect.Taille())
|
|
{cout << "erreur dans l'operation d'affectation";
|
|
cout << " les dimensions ne sont pas equivalentes dimensions = " << diago.Taille()
|
|
<< vect.Taille() << '\n';
|
|
cout << "MatDiag::operator += ( const Vecteur & vect" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
diago += vect;
|
|
inversion = false;
|
|
return *this;
|
|
};
|
|
|
|
// surcharge d'opérateur -= avec un vecteur
|
|
MatDiag & MatDiag::operator -= ( const Vecteur & vect)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où le vecteur et la matrice n'ont pas la même dimension
|
|
// il y a un message d'erreur
|
|
if (diago.Taille()!=vect.Taille())
|
|
{cout << "erreur dans l'operation d'affectation";
|
|
cout << " les dimensions ne sont pas equivalentes dimensions = " << diago.Taille()
|
|
<< vect.Taille() << '\n';
|
|
cout << "MatDiag::operator -= ( const Vecteur & vect" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
diago -= vect;
|
|
inversion = false;
|
|
return *this;
|
|
};
|
|
|
|
// ++++ méthodes protégées spécifique à la classe +++++++++++++++++++++
|
|
|
|
// enchainement de la resolution
|
|
void MatDiag::ResoDiag (const Vecteur& SG,Vecteur& DX)
|
|
{
|
|
int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != SG.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << SG.Taille() << '\n';
|
|
cout << "void MatDiag::ResoDiag (const Vecteur& SG,Vecteur& DX)" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (dim != DX.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << DX.Taille() << '\n';
|
|
cout << "void MatDiag::ResoDiag (const Vecteur& SG,Vecteur& DX)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// dans le cas où l'inverse n'est pas calculé on le recalcul
|
|
if (!inversion)
|
|
{for (int i=1;i<= dim; i++)
|
|
inv_diago(i) = 1./diago(i);
|
|
inversion = true;
|
|
};
|
|
// résolution
|
|
for (int i=1;i<= dim; i++)
|
|
DX(i) = inv_diago(i) * SG(i);
|
|
};
|
|
// idem précédent mais avec plusieurs seconds membres
|
|
void MatDiag::ResoDiag (const Tableau <Vecteur>& SG,Tableau <Vecteur>& DX)
|
|
{
|
|
int nbSM = SG.Taille();
|
|
int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
for (int i=1;i<=nbSM;i++)
|
|
if (dim != SG(i).Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << SG(i).Taille() << '\n';
|
|
cout << "void MatDiag::ResoDiag (pour plusieurs second membres)"
|
|
<< "(const Tableau <Vecteur>& SG,Tableau <Vecteur>& DX)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// dans le cas où l'inverse n'est pas calculé on le recalcul
|
|
if (!inversion)
|
|
{for (int i=1;i<= dim; i++)
|
|
inv_diago(i) = 1./diago(i);
|
|
inversion = true;
|
|
};
|
|
// résolution
|
|
for (int nism =1;nism<=nbSM;nism++)
|
|
for (int i=1;i<= dim; i++)
|
|
DX(nism)(i) = inv_diago(i) * SG(nism)(i);
|
|
};
|
|
// // resolution seule sans modification de la matrice
|
|
void MatDiag::Const_ResoDiag (const Vecteur& SG,Vecteur& DX) const
|
|
{
|
|
int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != SG.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << SG.Taille() << '\n';
|
|
cout << "void MatDiag::ResoDiag (const Vecteur& SG,Vecteur& DX)" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (dim != DX.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << DX.Taille() << '\n';
|
|
cout << "void MatDiag::ResoDiag (const Vecteur& SG,Vecteur& DX)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// dans le cas où l'inverse n'est pas calculé sortie d'erreur
|
|
if (!inversion)
|
|
{cout << "erreur la préparation n'a pas été effectuée ";
|
|
cout << "void MatDiag::Const_ResoDiag (.." << endl;
|
|
Sortie(1);
|
|
};
|
|
// résolution
|
|
for (int i=1;i<= dim; i++)
|
|
DX(i) = inv_diago(i) * SG(i);
|
|
};
|
|
// idem précédent mais avec plusieurs seconds membres
|
|
void MatDiag::Const_ResoDiag (const Tableau <Vecteur>& SG,Tableau <Vecteur>& DX)const
|
|
{
|
|
int nbSM = SG.Taille();
|
|
int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
for (int i=1;i<=nbSM;i++)
|
|
if (dim != SG(i).Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << SG(i).Taille() << '\n';
|
|
cout << "void MatDiag::ResoDiag (pour plusieurs second membres)"
|
|
<< "(const Tableau <Vecteur>& SG,Tableau <Vecteur>& DX)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// dans le cas où l'inverse n'est pas calculé sortie d'erreur
|
|
if (!inversion)
|
|
{cout << "erreur la préparation n'a pas été effectuée ";
|
|
cout << "void MatDiag::Const_ResoDiag (.." << endl;
|
|
Sortie(1);
|
|
};
|
|
// résolution
|
|
for (int nism =1;nism<=nbSM;nism++)
|
|
for (int i=1;i<= dim; i++)
|
|
DX(nism)(i) = inv_diago(i) * SG(nism)(i);
|
|
};
|
|
|
|
|
|
// Multiplication d'un vecteur par une matrice ( (vec)t * A )
|
|
Vecteur MatDiag::Prod_vec_mat ( const Vecteur& vec) const
|
|
{ int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur MatDiag::Prod_vec_mat ( Vecteur& vec)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
Vecteur res(dim);
|
|
for (int j=1;j<=dim;j++)
|
|
res(j) = vec(j) * diago(j) ;
|
|
return res;
|
|
|
|
};
|
|
|
|
// Multiplication d'un vecteur par une matrice ( (vec)t * A )
|
|
// ici le second vecteur sert pour le résultat
|
|
Vecteur& MatDiag::Prod_vec_mat ( const Vecteur& vec,Vecteur& res) const
|
|
{ int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur& MatDiag::Prod_vec_mat ( Vecteur& vec,Vecteur& res)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
res.Change_taille(dim);
|
|
for (int j=1;j<=dim;j++)
|
|
res(j) = vec(j) * diago(j) ;
|
|
return res;
|
|
|
|
};
|
|
// Multiplication d'une matrice par un vecteur ( A * vec )
|
|
Vecteur MatDiag::Prod_mat_vec (const Vecteur& vec) const
|
|
{ int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur MatDiag::Prod_mat_vec (const Vecteur& vec)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
Vecteur res(dim);
|
|
for (int j=1;j<=dim;j++)
|
|
res(j) = vec(j) * diago(j) ;
|
|
return res;
|
|
};
|
|
|
|
// Multiplication d'une matrice par un vecteur ( A * vec )
|
|
// ici le second vecteur sert pour le résultat
|
|
Vecteur& MatDiag::Prod_mat_vec (const Vecteur& vec,Vecteur& res) const
|
|
{ int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != vec.Taille())
|
|
{cout << "erreur taille matrice < taille vecteur";
|
|
cout << "dimMat = " << dim << " dimVect = " << vec.Taille() << '\n';
|
|
cout << "Vecteur& MatDiag::Prod_mat_vec (const Vecteur& vec,Vecteur& res)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
|
|
res.Change_taille(dim);
|
|
for (int j=1;j<=dim;j++)
|
|
res(j) = vec(j) * diago(j) ;
|
|
return res;
|
|
};
|
|
// Multiplication d'une ligne iligne de la matrice avec un vecteur de
|
|
// dimension = le nombre de ligne de la matrice
|
|
double MatDiag::Prod_Ligne_vec ( int iligne,const Vecteur& vec) const
|
|
{ int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != vec.Taille())
|
|
{ cout << " \n erreur la taille du vecteur = " << vec.Taille() <<" n est pas correcte ";
|
|
cout << " dimMatrice = " << dim;
|
|
cout << " double MatDiag::Prod_Ligne_vec ( int iligne,Vecteur& vec)" << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
double res = diago(iligne) * vec(iligne);
|
|
return res;
|
|
};
|
|
|
|
// Multiplication d'un vecteur avec une colonne icol de la matrice
|
|
// dimension = le nombre de ligne de la matrice
|
|
double MatDiag::Prod_vec_col( int jcol,const Vecteur& vec) const
|
|
{ int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (dim != vec.Taille())
|
|
{ cout << " \n erreur la taille du vecteur = " << vec.Taille() <<" n est pas correcte ";
|
|
cout << " dimMatrice = " << dim;
|
|
cout << " double MatDiag::Prod_vec_col( int icol,Vecteur& vec)" << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
double res = diago(jcol) * vec(jcol);
|
|
return res;
|
|
};
|
|
|
|
|
|
// calcul du produit : (vec_1)^T * A * (vect_2)
|
|
double MatDiag::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2) const
|
|
{ double resu=0.; // valeur de retour
|
|
int dim = diago.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if (vec1.Taille() != dim)
|
|
{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
|
|
<< "\n MatDiag::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (vec2.Taille() != dim )
|
|
{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
|
|
<< "\n MatDiag::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
for (int i=1;i<=dim ;i++)
|
|
resu += vec1(i) * diago(i) * vec2(i);
|
|
return resu;
|
|
};
|
|
|
|
|
|
|