// 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) . // // 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 . // // For more information, please consult: . //#include "Debug.h" #include "MatDiag.h" #include #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 MatDiag::Resol_syst (const Tableau & b,const double &tole, const int maxi, const int rest) { // sauvegarde de b Tableau 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 & MatDiag::Resol_systID (Tableau & 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 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 MatDiag::Simple_Resol_syst (const Tableau & b,const double &tol ,const int maxi,const int restart ) const { // sauvegarde de b Tableau 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 & MatDiag::Simple_Resol_systID (Tableau & 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 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 & SG,Tableau & 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 & SG,Tableau & 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 & SG,Tableau & 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 & SG,Tableau & 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; };