568 lines
23 KiB
C++
568 lines
23 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 "Mat_abstraite.h"
|
||
|
#include "ConstMath.h"
|
||
|
#include <math.h>
|
||
|
#include "MathUtil.h"
|
||
|
#include <iomanip>
|
||
|
#include "CharUtil.h"
|
||
|
|
||
|
// partie relative à la résolution
|
||
|
#include "vecdefs_GR.h" // modif GR
|
||
|
//#include "mvblasd.h" // MV_Vector level 1 BLAS
|
||
|
#include "diagpre_double_GR.h" // Diagonal preconditioner
|
||
|
#include "icpre_double_GR.h" // preconditioner cholesky incomplet
|
||
|
#include "ilupre_double_GR.h" // preconditioner ILU
|
||
|
#include "cgs.h" // IML++ CGS template
|
||
|
#include "cg.h" // IML++ CG template
|
||
|
#include "bicg.h" // IML++ BiCG template
|
||
|
#include "cheby.h" // IML++ Cheby template
|
||
|
#include "bicgstab.h" // IML++ BiCGSTAB template
|
||
|
#include "gmres.h" // IML++ GMRES template
|
||
|
#include "ir.h" // IML++ IR template
|
||
|
#include "qmr.h" // IML++ QMR template
|
||
|
|
||
|
// grandeur par défaut déclarées avant car on s'en sert dans les passages de paramètres
|
||
|
const double Mat_abstraite::tol_defaut = 1.E-7; // tolérance sur le résidu dans les méthodes itératives
|
||
|
const int Mat_abstraite::maxit_defaut = 150 ; // maximum d'itération dans les méthodes itératives
|
||
|
const int Mat_abstraite::restart_defaut = 32;// maximum de restart itération (nb de vecteur sauvegardé)
|
||
|
|
||
|
|
||
|
//calcul des valeurs propres par la méthode des puissances itérées
|
||
|
// inverses.
|
||
|
// --> Utilisable que pour des matrices carrées
|
||
|
// Intéressant lorsque l'on veut les plus petites
|
||
|
// valeurs propres, en nombre restreind car seule les premières valeurs
|
||
|
// sont calculées avec une précision convenable. On obtiend également
|
||
|
// les vecteurs propres correspondant.
|
||
|
// résolution de : ((*this) - lambda KG) X = 0
|
||
|
// en entrée : KG, VP dont la dimension est défini et fourni le nombre
|
||
|
// de valeurs propres que l'on veut calculer
|
||
|
// On considère que les conditions limites sont déjà appliquées à (*this) et KG.
|
||
|
// c'est à dire des 1 sur la diagonale pour (*this) et des 0 sur la diagonale pour KG
|
||
|
// en sortie : VP contiend les valeurs propres et vecteurs propres
|
||
|
|
||
|
Tableau <VeurPropre> * Mat_abstraite::V_Propres(Mat_abstraite& KG,Tableau <VeurPropre> & VP )
|
||
|
{ // la méthode est décrite dans Touzot/Dhatt seconde édition p 393-395
|
||
|
#ifdef MISE_AU_POINT
|
||
|
// vérification des entrées
|
||
|
// 1) (*this) et KG sont carrées et identiques en taille
|
||
|
if ( (Nb_ligne() != KG.Nb_ligne()) || (Nb_colonne() != KG.Nb_colonne()) ||
|
||
|
(Nb_ligne() != Nb_colonne()))
|
||
|
{ cout << "\n ***** Erreur : la taille des matrices a traiter n\'est pas correcte !\n";
|
||
|
cout << "\n les matrices doivent être carrés !! \n";
|
||
|
cout << "Mat_abstraite::V_Propres(... \n";
|
||
|
cout << " KG CxL " << KG.Nb_colonne() << " x " << KG.Nb_ligne();
|
||
|
cout << " (*this) CxL : " << (Nb_colonne()) << " x " << (Nb_ligne()) << "\n";
|
||
|
Sortie(1);
|
||
|
};
|
||
|
#endif
|
||
|
// stockage inter
|
||
|
Vecteur Vinter(Nb_colonne());
|
||
|
|
||
|
bool sorIter ; // gestion de la sortie de la boucle sur les valeurs propres
|
||
|
// on boucle sur le nombre de valeur propre demandé
|
||
|
for (int il=1; il<= VP.Taille(); il++)
|
||
|
{ sorIter = true; // tout va bien à priori
|
||
|
// choix d'un vecteur initial
|
||
|
Vecteur V(Nb_colonne(),1.);
|
||
|
// calcul d'un décalage éventuelle du aux vecteurs déjà calculés
|
||
|
Vecteur Ybarre = KG.Prod_mat_vec(V);
|
||
|
for (int ill=1; ill< il; ill++)
|
||
|
V = V - (VP(ill).Pv() * Ybarre) * VP(ill).Pv();
|
||
|
// calcul initial de la sollicitation
|
||
|
Vecteur F = KG.Prod_mat_vec(V);
|
||
|
// initialisation en taille (uniquement) de la sollicitation intermédiaire
|
||
|
Vecteur Fbarre = F;
|
||
|
// des scalaires intermédiaires
|
||
|
double d,lambda = 0.;
|
||
|
double lambdaPrec = ConstMath::grand; // initialisation à une valeur grande
|
||
|
int maxiBoucle = 500; // maxi de boucle d'itération inverse
|
||
|
int nbBoucle = 0; // indice courant de nombre de boucle
|
||
|
|
||
|
while (Abs(lambda - lambdaPrec) > ConstMath::petit*MaX(Abs(lambda),Abs(lambdaPrec)))
|
||
|
{ // a chaque itération
|
||
|
nbBoucle++; // incrémentation du nombre de boucle
|
||
|
if (nbBoucle > maxiBoucle)
|
||
|
{cout << " \n PB dans le calcul de la valeur propre nb = "<< il;
|
||
|
cout << " Mat_abstraite::V_Propres(.. \n ";
|
||
|
cout << " lambda = "<< lambda;
|
||
|
sorIter = false; // pour l'arrêt de la boucle globale
|
||
|
break; // sortie des itérations
|
||
|
};
|
||
|
// sauvegarde de la raideur
|
||
|
Mat_abstraite * KSS = NouvelElement();
|
||
|
V = KSS->Resol_syst(F); // résolution
|
||
|
// calcul d'un décalage éventuelle du aux vecteurs déjà calculés
|
||
|
Ybarre = KG.Prod_mat_vec(V);
|
||
|
for (int ill=1; ill< il; ill++)
|
||
|
V = V - (VP(ill).Pv() * Ybarre) * VP(ill).Pv();
|
||
|
Fbarre = KG.Prod_mat_vec(V); // sollicitation intermédiaire
|
||
|
d = V * Fbarre; // facteur d
|
||
|
lambdaPrec = lambda; // sauvegarde
|
||
|
lambda = (V * F) / d; // approximation de lambda
|
||
|
F = Fbarre / sqrt(d); // nouvelle sollicitation
|
||
|
};
|
||
|
if (!sorIter) break; // sortie au cas ou l'on n'a pas convergé
|
||
|
// calcul du vecteur propre normalisé
|
||
|
Vinter = V / sqrt(d);
|
||
|
VP(il) = VeurPropre(lambda,Vinter); // sauvegarde
|
||
|
};
|
||
|
|
||
|
// retour du tableau
|
||
|
return &VP;
|
||
|
};
|
||
|
|
||
|
// définie la surcharge de multiplication d'une matrice par un MV_Vector
|
||
|
MV_Vector<double> Mat_abstraite::operator * (const MV_Vector<double> & vec) const
|
||
|
{ // tout d'abord on construit un vecteur en place du MV_Vector
|
||
|
const MV_Vecteur vecte(vec);
|
||
|
const Vecteur & vecv = (Vecteur &) vecte;
|
||
|
// multiplication et retour
|
||
|
// MV_Vecteur resulta = (Prod_mat_vec(vecv)).MV_vecteur_double();
|
||
|
|
||
|
//// MV_Vector<double> resulta = (Prod_mat_vec(vecv)).MV_vecteur_double();
|
||
|
|
||
|
// autre solution
|
||
|
MV_Vecteur resulta(vec);
|
||
|
Vecteur & vecretour = (Vecteur &) resulta;
|
||
|
Prod_mat_vec(vecv,vecretour);
|
||
|
|
||
|
return resulta;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
// multiplication matrice transposée fois vecteur ce qui est équivalent à
|
||
|
// la transposée du résultat de : multiplication vecteur transposé fois matrice
|
||
|
MV_Vector<double> Mat_abstraite::trans_mult(const MV_Vector<double> &vec) const
|
||
|
{ // tout d'abord on construit un vecteur en place du MV_Vector
|
||
|
const MV_Vecteur vecte(vec);
|
||
|
const Vecteur & vecv = (Vecteur &) vecte;
|
||
|
// multiplication et retour
|
||
|
// MV_Vecteur resulta = (Prod_vec_mat (vecv)).MV_vecteur_double();
|
||
|
MV_Vector<double> resulta = (Prod_vec_mat (vecv)).MV_vecteur_double();
|
||
|
return resulta;
|
||
|
};
|
||
|
|
||
|
// -------------------------- Méthodes protégées : ----------------------------
|
||
|
|
||
|
// Resolution du systeme Ax=b , méthodes générales pouvant être appelées par les classes dérivée
|
||
|
// en entrée : b comme second membre
|
||
|
// en sortie : sol de même dimension que sol
|
||
|
void Mat_abstraite::Resolution_syst
|
||
|
(const Vecteur &b, Vecteur &sol,const double &tole, const int maxi, const int rest) const
|
||
|
{ // récup de l'homologue en vecteur_double
|
||
|
// const VECTOR_double bb_double(b.MV_vecteur_double());
|
||
|
const VECTOR_double * bb_double_pt = b.Nouveau_MV_Vector_double_const();
|
||
|
const VECTOR_double& bb_double = (*bb_double_pt);
|
||
|
// const VECTOR_double bb_double(b.Pointeur_vect(),b.Taille(),MV_Vector_::ref_type(1));
|
||
|
// MV_Vector<TYPE>::MV_Vector(TYPE* d, int n, MV_Vector_::ref_type i) : // modif GR
|
||
|
// idem pour la solution
|
||
|
// VECTOR_double sol_double (sol.MV_vecteur_double());
|
||
|
VECTOR_double* sol_double_pt = sol.Nouveau_MV_Vector_double();
|
||
|
VECTOR_double& sol_double = (*sol_double_pt);
|
||
|
int result,maxit = maxi,restart = rest; // Maximum iterations
|
||
|
double tol = tole;
|
||
|
|
||
|
// choix du préconditionnement
|
||
|
Pre_cond_double * D = NULL; // pointeur non affecté avec le choix
|
||
|
switch (type_preconditionnement)
|
||
|
{ case DIAGONAL :
|
||
|
// cas diagonal
|
||
|
D = new DiagPreconditioner_double (*this);
|
||
|
break;
|
||
|
case ICP :
|
||
|
// cas de la factorisation de cholesky incomplete
|
||
|
D = new ICPreconditioner_double (*this);
|
||
|
break;
|
||
|
case ILU :
|
||
|
// cas de la factorisation LU
|
||
|
D = new ILUPreconditioner_double (*this);
|
||
|
break;
|
||
|
default :
|
||
|
cout << "\nErreur : valeur incorrecte du type de preconditionnement !\n"
|
||
|
<< " = " << type_preconditionnement ;
|
||
|
cout << "\n Mat_abstraite::Resolution_syst (... ) \n";
|
||
|
Sortie(1);
|
||
|
};
|
||
|
|
||
|
if (ParaGlob::NiveauImpression() > 2) cout << "\n Resolution ";
|
||
|
// choix du type de résolution
|
||
|
switch (type_resolution)
|
||
|
{ case BI_CONJUG :
|
||
|
// biconjugué
|
||
|
{result = BiCG(*this, sol_double,bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "BiCG flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case BI_CONJUG_STAB:
|
||
|
// biconjugué stabilisé
|
||
|
{result = BiCGSTAB( *this, sol_double, bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "BiCGSTAB flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case CONJUG_GRAD :
|
||
|
// conjugué gradient
|
||
|
{result = CG(*this, sol_double, bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "CG flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case CONJUG_GRAD_SQUARE :
|
||
|
// conjugué square method
|
||
|
{result = CGS(*this, sol_double, bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "CGS flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case CHEBYSHEV :
|
||
|
// itération de chebyshev
|
||
|
{if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "\n attention utilisation de bornes bidon pour le rayon spectrale"
|
||
|
<< " dans les itération de chebyshev (résolution de système matricielle)";
|
||
|
double mineig = .01; // n'importe quoi
|
||
|
double maxeig = 3; // devra être modifié pour avoir un résultat correcte
|
||
|
result = CHEBY(*this, sol_double, bb_double, *D, maxit, tol, mineig, maxeig);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "CHEBY flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case GENE_MINI_RESIDUAL :
|
||
|
// résidu minimal généralisé
|
||
|
{MATRIX_double Htt(restart+1, restart, 0.0); // storage for upper Hessenberg H
|
||
|
result = GMRES(*this, sol_double, bb_double, *D, Htt,restart, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "GMRES flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case ITERATION_RICHARSON :
|
||
|
// itération de richarson
|
||
|
{result = IR( *this, sol_double, bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "IR flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case QUASI_MINI_RESIDUAL :
|
||
|
// résidu quasi minimal
|
||
|
{result = QMR( *this, sol_double, bb_double, *D, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "QMR flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
default :
|
||
|
cout << "\nErreur : valeur incorrecte du type de résolution !\n"
|
||
|
<< " = " << type_resolution ;
|
||
|
cout << "\n Mat_abstraite::Resolution_syst (... ) \n";
|
||
|
Sortie(1);
|
||
|
};
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
{ cout << "iterations performed: " << maxit << endl;
|
||
|
cout << "tolerance achieved : " << tol << endl;
|
||
|
};
|
||
|
|
||
|
// on recopie le résultat
|
||
|
sol = sol_double;
|
||
|
// on efface le préconditionnement
|
||
|
if (D != NULL) delete D;
|
||
|
// on efface les vecteurs de travail
|
||
|
delete bb_double_pt; delete sol_double_pt;
|
||
|
};
|
||
|
|
||
|
// idem avec en entrée un tableau de vecteur second membre et
|
||
|
// en sortie un tableau de vecteurs solution
|
||
|
void Mat_abstraite::Resolution_syst
|
||
|
(const Tableau <Vecteur>& b, Tableau <Vecteur> &sol,const double &tole
|
||
|
, const int maxi, const int rest) const
|
||
|
{
|
||
|
// choix du préconditionnement
|
||
|
Pre_cond_double * D = NULL; // pointeur non affecté avec le choix
|
||
|
switch (type_preconditionnement)
|
||
|
{ case DIAGONAL :
|
||
|
// cas diagonal
|
||
|
D = new DiagPreconditioner_double (*this);
|
||
|
break;
|
||
|
case ICP :
|
||
|
// cas de la factorisation de cholesky incomplete
|
||
|
D = new ICPreconditioner_double (*this);
|
||
|
break;
|
||
|
case ILU :
|
||
|
// cas de la factorisation LU
|
||
|
D = new ILUPreconditioner_double (*this);
|
||
|
break;
|
||
|
default :
|
||
|
cout << "\nErreur : valeur incorrecte du type de preconditionnement !\n"
|
||
|
<< " = " << type_preconditionnement ;
|
||
|
cout << "\n Mat_abstraite::Resolution_syst (... ) \n";
|
||
|
Sortie(1);
|
||
|
};
|
||
|
|
||
|
// on boucle sur le nombre de second membre
|
||
|
int nbsecondmembre = b.Taille();
|
||
|
for (int ise=1; ise<= nbsecondmembre;ise++)
|
||
|
{
|
||
|
// récup de l'homologue en vecteur_double
|
||
|
const VECTOR_double bb_double ((b(ise)).MV_vecteur_double());
|
||
|
// idem pour la solution
|
||
|
VECTOR_double sol_double ((sol(ise)).MV_vecteur_double());
|
||
|
|
||
|
int result,maxit = maxi,restart = rest; // Maximum iterations
|
||
|
double tol = tole;
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "\n resolution du second membre nb = " << ise << " ";
|
||
|
// choix du type de résolution
|
||
|
switch (type_resolution)
|
||
|
{ case BI_CONJUG :
|
||
|
// biconjugué
|
||
|
{result = BiCG(*this, sol_double,bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "BiCG flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case BI_CONJUG_STAB:
|
||
|
// biconjugué stabilisé
|
||
|
{result = BiCGSTAB( *this, sol_double, bb_double, *D, maxit, tol);
|
||
|
cout << "BiCGSTAB flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case CONJUG_GRAD :
|
||
|
// conjugué gradient
|
||
|
{result = CG(*this, sol_double, bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "CG flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case CONJUG_GRAD_SQUARE :
|
||
|
// conjugué square method
|
||
|
{result = CGS(*this, sol_double, bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "CGS flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case CHEBYSHEV :
|
||
|
// itération de chebyshev
|
||
|
{if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "\n attention utilisation de bornes bidon pour le rayon spectrale"
|
||
|
<< " dans les iteration de chebyshev (resolution de systeme matricielle)";
|
||
|
double mineig = .01; // n'importe quoi
|
||
|
double maxeig = 3; // devra être modifié pour avoir un résultat correcte
|
||
|
result = CHEBY(*this, sol_double, bb_double, *D, maxit, tol, mineig, maxeig);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "CHEBY flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case GENE_MINI_RESIDUAL :
|
||
|
// résidu minimal généralisé
|
||
|
{MATRIX_double Htt(restart+1, restart, 0.0); // storage for upper Hessenberg H
|
||
|
result = GMRES(*this, sol_double, bb_double, *D, Htt,restart, maxit, tol);
|
||
|
cout << "GMRES flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case ITERATION_RICHARSON :
|
||
|
// itération de richarson
|
||
|
{result = IR( *this, sol_double, bb_double, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "IR flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
case QUASI_MINI_RESIDUAL :
|
||
|
// résidu quasi minimal
|
||
|
{result = QMR( *this, sol_double, bb_double, *D, *D, maxit, tol);
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
cout << "QMR flag = " << result << endl;
|
||
|
break;
|
||
|
}
|
||
|
default :
|
||
|
cout << "\nErreur : valeur incorrecte du type de résolution !\n"
|
||
|
<< " = " << type_resolution ;
|
||
|
cout << "\n Mat_abstraite::Resolution_syst (... ) \n";
|
||
|
Sortie(1);
|
||
|
};
|
||
|
if (ParaGlob::NiveauImpression() > 2)
|
||
|
{cout << "iterations performed: " << maxit << endl;
|
||
|
cout << "tolerance achieved : " << tol << endl;
|
||
|
};
|
||
|
// on recopie le résultat
|
||
|
sol(ise) = sol_double;
|
||
|
|
||
|
};
|
||
|
// on efface le préconditionnement
|
||
|
if (D != NULL) delete D;
|
||
|
|
||
|
};
|
||
|
|
||
|
// 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_abstraite::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 " << '\n';
|
||
|
int i,j;
|
||
|
cout << " ";
|
||
|
for (j=min_j;j<=max_j;j+=pas_j) cout << "col " << setw(5) << 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_abstraite::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 " << '\n';
|
||
|
if (nd < 7)
|
||
|
{ cout << " dimension des colonnes trop faible (<7 ! ) " << endl;
|
||
|
return;
|
||
|
};
|
||
|
int i,j;
|
||
|
SortBlanc(16);
|
||
|
|
||
|
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;
|
||
|
};
|
||
|
|
||
|
// affichage à l'écran après une demande interactive de la matrice
|
||
|
// entete: une chaine explicative, a afficher en entête
|
||
|
void Mat_abstraite::Affichage_ecran(string entete) const
|
||
|
{// affichage éventuelle de la matrice
|
||
|
cout << "\n --- " << entete << " -----";
|
||
|
string rep;
|
||
|
cout << "\n voulez-vous afficher la matrice ? (o ou n) ";
|
||
|
rep = lect_return_defaut(false,"n");
|
||
|
if (rep == "o")
|
||
|
{cout << "\n parametre d'affichage par defaut (toute la matrice) ? (o ou n) " ;
|
||
|
rep = lect_return_defaut(false,"n");
|
||
|
int min_i,max_i,pas_i,min_j,max_j,pas_j,nd;
|
||
|
if (rep =="o")
|
||
|
{ min_i=1; max_i=this->Nb_ligne(); min_j=1; max_j=this->Nb_ligne();
|
||
|
pas_i=1;pas_j=1; nd=14;
|
||
|
}
|
||
|
else
|
||
|
{try
|
||
|
{ cout << "\n a partir de quel numero de ligne ? (1) "; min_i=(int)lect_double();
|
||
|
cout << " jusqu'a quel numero de ligne ? ("<<this->Nb_ligne()<<") "; max_i=(int)lect_double();
|
||
|
cout << " par pas de ? (1) "; pas_i=(int)lect_double();
|
||
|
cout << "\n a partir de quel numero de colonne ? (1) "; min_j=(int)lect_double();
|
||
|
cout << " jusqu'a quel numero de colonne ? ("<<this->Nb_ligne()<<") "; max_j=(int)lect_double();
|
||
|
cout << " par pas de ? (1) "; pas_j=(int)lect_double();
|
||
|
cout << "\n nombre de diggit ? (14) "; nd=(int)lect_double();
|
||
|
}
|
||
|
catch (ErrSortieFinale)
|
||
|
// cas d'une direction voulue vers la sortie
|
||
|
// on relance l'interuption pour le niveau supérieur
|
||
|
{ ErrSortieFinale toto;
|
||
|
throw (toto);
|
||
|
}
|
||
|
catch (...)
|
||
|
{ cout << "\n Erreur sur l'entree des donnee !!, on prend les valeurs par defaut ";
|
||
|
min_i=1; max_i=this->Nb_ligne(); min_j=1; max_j=this->Nb_ligne();
|
||
|
pas_i=1;pas_j=1; nd=14;
|
||
|
}
|
||
|
};
|
||
|
this->Affiche2(min_i,max_i,pas_i,min_j,max_j,pas_j,nd);
|
||
|
cout << "\n entrez une lettre pour continuer ? ";
|
||
|
rep = lect_chaine();
|
||
|
}; //-- fin du choix visu ou pas de la matrice
|
||
|
};
|
||
|
|
||
|
|
||
|
// calcul, récupération et affichage éventuelle
|
||
|
// des mini, maxi, et en valeur absolue la moyenne de la diagonale de la matrice
|
||
|
// en retour: le min, le max et la moyenne en valeur absolue
|
||
|
Coordonnee3 Mat_abstraite::MinMaxMoy(bool affiche) const
|
||
|
{ Coordonnee3 retour;
|
||
|
// calcul des grandeurs
|
||
|
double min=ConstMath::tresgrand,max=-ConstMath::tresgrand,moy=0.;
|
||
|
int nbl = this->Nb_ligne();
|
||
|
if (affiche)
|
||
|
{for (int i=1;i<=nbl;i++)
|
||
|
{double dia = (*this)(i,i);
|
||
|
min = MiN(min, dia);
|
||
|
max = MaX(max, dia);
|
||
|
moy += Dabs(dia);
|
||
|
};
|
||
|
moy /= nbl;
|
||
|
// affichage
|
||
|
cout << "\n matrice masse: valeurs diagonales: min= "<<min <<", max= "<<max<<", moy des |(i,i)| "<<moy<<flush;
|
||
|
}
|
||
|
else
|
||
|
{for (int i=1;i<=nbl;i++)
|
||
|
{double dia = (*this)(i,i);
|
||
|
min = MiN(min, dia);
|
||
|
max = MaX(max, dia);
|
||
|
moy += Dabs(dia);
|
||
|
};
|
||
|
moy /= nbl;
|
||
|
};
|
||
|
retour(1) = min; retour(2) = max; retour(3)=moy;
|
||
|
return retour;
|
||
|
};
|
||
|
|
||
|
|
||
|
// limite la valeur mini de la diagonale: si un terme de la diagonale
|
||
|
// est inférieure à la limite passée en argument (seuil_bas), d'une manière arbitraire
|
||
|
// le terme à mis à une valeur égale au paramètre passé en paramètre val_a_imposer
|
||
|
// s'il y a eu changement retour de true
|
||
|
bool Mat_abstraite::Limitation_min_diag(double seuil_bas, double val_a_imposer)
|
||
|
{bool modif = false;
|
||
|
int nbl = this->Nb_ligne();
|
||
|
for (int i=1;i<=nbl;i++)
|
||
|
{double dia = (*this)(i,i);
|
||
|
if (dia < seuil_bas)
|
||
|
{ modif = true;
|
||
|
(*this)(i,i) = val_a_imposer;
|
||
|
};
|
||
|
};
|
||
|
return modif;
|
||
|
};
|
||
|
|
||
|
|
||
|
|