1090 lines
42 KiB
C++
1090 lines
42 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-2022 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 "MathUtil2.h"
|
|
#include "nrutil.h"
|
|
#include "jacobi.h"
|
|
#include "Util.h"
|
|
#include "ConstMath.h"
|
|
#include "MathUtil.h"
|
|
|
|
|
|
|
|
|
|
#ifndef MATHUTIL2_H_deja_inclus
|
|
|
|
//// vecteurs propre et valeurs propres d'une matrice nxn c-a-d : en particulier 3 3 ou 2 2 ou 1 1
|
|
//// avec une limitation sur n (< 50)
|
|
//// *** dans le cas où les matrices sont symétriques !! ***
|
|
//// la méthode est itérative, --> méthode de Jacobi
|
|
//// la matrice A est ecrasee, a la sortie chaque colonne represente un vecteur propre
|
|
//// le vecteur de retour contiend les valeurs propres
|
|
//// s'il y a une erreur dans le calcul : cas = -1
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//Vecteur MathUtil2::VectValPropre(Mat_pleine& A,int& cas)
|
|
// { // appel d'une routine jacobi
|
|
// int nbcol = A.Nb_colonne();
|
|
// #ifndef MISE_AU_POINT
|
|
// int nblign = A.Nb_ligne();
|
|
// if (nbcol != nblign)
|
|
// { cout << "\n erreur dans VectValPropre(Mat_pleine& A), la matrice n'est pas carré"
|
|
// << endl;
|
|
// Sortie(1);
|
|
// }
|
|
// #endif
|
|
//
|
|
// // 1) def de la matrice et du vecteur contenant les vecteurs propre et les valeurs propres
|
|
// Vecteur d(nbcol);
|
|
// Mat_pleine V(nbcol,nbcol);
|
|
// int nrot =0; // nombre de rotation dans jacobi
|
|
//
|
|
// // 3) appel du programme de la bibliothèque (fortement modifié)
|
|
// Jacobi jaco; // une instance par défaut
|
|
//
|
|
// jaco.jacobi(A,d,V,nrot);
|
|
// // traitement erreur
|
|
// if (nrot == -1) {cas = -1;} else {cas = 1;};
|
|
//
|
|
// // 4) mise en ordre des valeurs et vecteurs propres
|
|
// jaco.eigsrt(d,V);
|
|
// // 5) sauvegarde et retour
|
|
// A = V;
|
|
// return d;
|
|
// };
|
|
//
|
|
|
|
|
|
//calcul des vecteurs propres pour une matrice 3x3 réel uniquement, pas forcément symétrique
|
|
// dans le cas où on connait déjà les valeurs propres
|
|
// --> Utilisable que pour des matrices carrées
|
|
// en entrée : VP, de dimension 3, Vp contient les valeurs propres
|
|
// les 3 valeurs propres sont considérées classées: VP(1) >= VP(2) >= VP(3)
|
|
// cas : qui indique le type de valeurs propres
|
|
// , cas = 1 si 3 val propres différentes (= 3 composantes du vecteur de retour)
|
|
// , cas = 0 si les 3 sont identiques (= la première composantes du vecteur de retour),
|
|
// , cas = 2 si Vp(1)=Vp(2) ( Vp(1), et Vp(3) dans les 2 premières composantes du retour)
|
|
// , cas = 3 si Vp(2)=Vp(3) ( Vp(1), et Vp(2) dans les 2 premières composantes du retour)
|
|
// en sortie : le tableau des vecteurs propres, rangés selon l'ordre d'entrée
|
|
// cas = le cas de l'entrée, sauf s'il y a eu un pb, dans ce cas: cas = -1, et les vecteurs propres sont
|
|
// dans ce cas quelconques
|
|
//
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee> MathUtil2::V_Propres3x3(const Mat_pleine& A,const Coordonnee & VP, int & cas )
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((A.Nb_colonne() != 3)|| (A.Nb_ligne() != 3))
|
|
{cout << "\n erreur de dimension: Nb_colonne()= " << A.Nb_colonne() << ", Nb_ligne()= ";
|
|
cout << A.Nb_ligne() << " alors que cette methode ne s'applique qu'aux matrices 3x3 ! "
|
|
<< "\n V_Propres3x3(..." << endl;
|
|
Sortie(1);
|
|
};
|
|
if (VP.Dimension() != 3)
|
|
{cout << "\n erreur il n'y a pas 3 valeurs propres ! " << endl;
|
|
Sortie(1);
|
|
};
|
|
|
|
if ( (VP(1) < VP(2)) || (VP(2) < VP(3)) || (VP(1) < VP(3)) )
|
|
{cout << "\n erreur les trois valeurs propres ne sont pas dans le bon ordre (VP(1) >= VP(2) >= VP(3)) "
|
|
<< "\n VP(1)= " << VP(1) << ", VP(2)= " << VP(2) << ", VP(3)= " << VP(3)
|
|
<< "\n V_Propres3x3(..." << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// initialisation
|
|
Coordonnee3 zero(3);
|
|
Tableau <Coordonnee> Vpropre(3,zero); // les vecteurs propres
|
|
|
|
// on utilise une copie de la matrice d'entrée
|
|
Mat_pleine B(A);
|
|
// dans tous les cas il y a au moins une valeur propre, on démarre avec celle là
|
|
// on calcul la matrice B-lambda*Id qui normalement doit-être singulière
|
|
////---debug
|
|
//cout << "\n debug V_Propres3x3 ";
|
|
//cout <<"\n B: ";
|
|
//B.Affiche();
|
|
//// --- fin debug
|
|
|
|
for (int i=1;i<=3;i++)
|
|
B(i,i) -= VP(1);
|
|
|
|
////---debug
|
|
//cout << "\n debug V_Propres3x3 apres B(i,i) -= VP(1)";
|
|
//cout <<"\n B: ";
|
|
//B.Affiche();
|
|
//// --- fin debug
|
|
|
|
// on calcul le rang de la matrice
|
|
int rang_B = CalculRangMatrice3x3Singuliere(B);
|
|
//---debug
|
|
//cout << "\n debug V_Propres3x3 ";
|
|
//cout <<"\n rangB: "<<rang_B;
|
|
//// --- fin debug
|
|
switch (rang_B)
|
|
{ case 0: // si le rang = 0, la matrice B est uniformément nulle, et on peut choisir n'importe quel base
|
|
// on prend la base identité
|
|
// cela veut dire aussi que la matrice A initiale était sphérique !! donc que les trois valeurs propres sont identiques
|
|
{Vpropre(1)(1)=1.;Vpropre(2)(2)=1.;Vpropre(3)(3)=1.;
|
|
#ifdef MISE_AU_POINT
|
|
{// en débug on vérifie que le rang est également nulle pour les deux autres valeurs
|
|
Mat_pleine B2(A);
|
|
for (int i=1;i<=3;i++)
|
|
B2(i,i) -= VP(2);
|
|
Mat_pleine B3(A);
|
|
for (int i=1;i<=3;i++)
|
|
B3(i,i) -= VP(3);
|
|
if ((CalculRangMatrice3x3Singuliere(B2) != 0) || (CalculRangMatrice3x3Singuliere(B3) != 0))
|
|
{cout << "\n ** erreur au niveau des rangs de matrice: rang_B == 0,"
|
|
<< " mais rang_B2 = " << CalculRangMatrice3x3Singuliere(B2)
|
|
<< " et rang_B3= " << CalculRangMatrice3x3Singuliere(B3)
|
|
<< "\n V_Propres3x3(..." << endl;
|
|
cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
if (cas != 0)
|
|
{cout << "\n ** erreur au niveau des rangs de matrice: rang_B == 0,"
|
|
<< " normalement on devrait avoir cas = 0, et en fait on a : cas= " << cas
|
|
<< " (pour voir les matrices utiliser un niveau de commentaire > 7) "
|
|
<< "\n VP: ";
|
|
if (ParaGlob::NiveauImpression() > 7)
|
|
{ VP.Affiche();
|
|
cout <<"\n A: ";
|
|
A.Affiche();
|
|
cout <<"\n B: ";
|
|
B.Affiche();
|
|
cout <<"\n rangB: "<<rang_B ;
|
|
cout << "\n cas= "<< cas << " VP= "<<VP;
|
|
cout << "\n les val propres: " << VP ;
|
|
};
|
|
cout << "\n V_Propres3x3(..." << endl;
|
|
cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
};
|
|
#endif
|
|
// vérif pour le cas non débug
|
|
if (cas != 0)
|
|
{cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
break;
|
|
}
|
|
|
|
case 1: // on n'a qu'une seule direction de libre
|
|
// cela veut dire également que l'on a deux valeurs propres identiques
|
|
{ // on récupère la première ligne de la matrice qui est la direction libre
|
|
Coordonnee3 V(B(1).Coordo()); // c-a-d la première direction libre
|
|
// on définit les 2 vecteurs du plan normal
|
|
Def_vecteurs_plan(V, Vpropre(2), Vpropre(3));
|
|
// et le premier, qui correspond à la première valeur propre (celle qui a servi au calcul de B)
|
|
Vpropre(1) = Util::ProdVec_coor(Vpropre(2),Vpropre(3));
|
|
#ifdef MISE_AU_POINT
|
|
// en débug que l'on a bien deux valeurs propres identiques
|
|
if ((cas == 0) || (cas == 1))
|
|
{cout << "\n erreur au niveau du rang de matrice: rang_B == 1,"
|
|
<< " on devrait donc avoir deux valeurs propres identiques alors que cas = " << cas
|
|
<< " (pour voir les matrices utiliser un niveau de commentaire > 7) "
|
|
<< "\n VP: ";
|
|
if (ParaGlob::NiveauImpression() > 7)
|
|
{ VP.Affiche();
|
|
cout <<"\n A: ";
|
|
A.Affiche();
|
|
cout <<"\n B: ";
|
|
B.Affiche();
|
|
cout <<"\n rangB: "<<rang_B ;
|
|
cout << "\n cas= "<< cas << " VP= "<<VP;
|
|
cout << "\n les val propres: " << VP ;
|
|
};
|
|
cout << "\n V_Propres3x3(..." << endl;
|
|
cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
#endif
|
|
// vérif pour le cas non débug
|
|
if ((cas == 0) || (cas == 1))
|
|
{cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
break;
|
|
}
|
|
case 2:
|
|
{ // on récupère les deux première lignes de la matrice qui forme le plan normal à la direction principale
|
|
Coordonnee3 V1 = B(1).Coordo(); // premier vecteur
|
|
Coordonnee3 V2 = B(2).Coordo(); // second vecteur
|
|
// on définit le vecteur du plan normal
|
|
Vpropre(1) = Util::ProdVec_coor(V1,V2);
|
|
Vpropre(1).Normer();
|
|
|
|
// on s'occupe maintenant de la seconde valeur propre
|
|
Mat_pleine B2(A);
|
|
for (int i=1;i<=3;i++)
|
|
B2(i,i) -= VP(2);
|
|
int rang_B2 = CalculRangMatrice3x3Singuliere(B2);
|
|
#ifdef MISE_AU_POINT
|
|
// rang_B2 ne peut pas être nul
|
|
if (rang_B2 == 0)
|
|
{cout << "\n erreur au niveau du rang de matrice: rang_B == 2,"
|
|
<< " et on a trouve rang_B2= 0 !! "
|
|
<< " (pour voir les matrices utiliser un niveau de commentaire > 7) "
|
|
<< "\n VP: ";
|
|
if (ParaGlob::NiveauImpression() > 7)
|
|
{ VP.Affiche();
|
|
cout <<"\n A: ";
|
|
A.Affiche();
|
|
cout <<"\n B: ";
|
|
B.Affiche();
|
|
cout <<"\n rangB: "<<rang_B << ", rangB2= "<< rang_B2;
|
|
cout << "\n cas= "<< cas << " VP= "<<VP;
|
|
cout << "\n les val propres: " << VP ;
|
|
};
|
|
cout << "\n V_Propres3x3(..." << endl;
|
|
cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
#endif
|
|
// vérif pour le cas non débug
|
|
if (rang_B2 == 0)
|
|
{cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
if (rang_B2 == 1)
|
|
{// cela veut dire que les deux dernières valeurs propres sont identiques
|
|
// donc on peut choisir un plan normal au premier vecteur
|
|
// produit 2 vecteurs normés
|
|
Def_vecteurs_plan(Vpropre(1), Vpropre(2), Vpropre(3));
|
|
#ifdef MISE_AU_POINT
|
|
// en débug que l'on a bien deux valeurs propres identiques
|
|
if ((cas == 0) || (cas == 1))
|
|
{cout << "\n erreur au niveau du rang de matrice: rang_B1 == 2 et rang_B2 == 1,"
|
|
<< " on devrait donc avoir deux valeurs propres identiques alors que cas = " << cas
|
|
<< " (pour voir les matrices utiliser un niveau de commentaire > 7) "
|
|
<< "\n VP: ";
|
|
if (ParaGlob::NiveauImpression() > 7)
|
|
{ VP.Affiche();
|
|
cout <<"\n A: ";
|
|
A.Affiche();
|
|
cout <<"\n B: ";
|
|
B.Affiche();
|
|
cout <<"\n rangB: "<<rang_B << ", rangB2= "<< rang_B2;
|
|
cout << "\n cas= "<< cas << " VP= "<<VP;
|
|
cout << "\n les val propres: " << VP ;
|
|
};
|
|
cout << "\n V_Propres3x3(..." << endl;
|
|
cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
#endif
|
|
// vérif pour le cas non débug
|
|
if ((cas == 0) || (cas == 1))
|
|
{cas = -1; // on signale l'erreur
|
|
break; // et on arrête
|
|
};
|
|
}
|
|
else
|
|
{ // sinon rang_B2 == 2
|
|
Coordonnee3 W1 = B2(1).Coordo(); // premier vecteur
|
|
Coordonnee3 W2 = B2(2).Coordo(); // second vecteur
|
|
// on définit le vecteur du plan normal
|
|
Vpropre(2) = Util::ProdVec_coor(W1,W2);
|
|
Vpropre(2).Normer();
|
|
// puis le dernier vecteur propre: produit de deux vecteurs normés
|
|
// donc a priori est normé également par le produit vectoriel
|
|
Vpropre(3) = Util::ProdVec_coor(Vpropre(1),Vpropre(2));
|
|
#ifdef MISE_AU_POINT
|
|
if (cas == 0)
|
|
{cout << "\n warning au niveau du rang de matrice: rang_B == 2 et rang_B2 == 2,"
|
|
<< " bizarre les trois valeurs propres sont identiques cas = " << cas
|
|
<< "\n V_Propres3x3(..." << endl;
|
|
if (ParaGlob::NiveauImpression() > 7)
|
|
{cout << "\n matrice initiale: ";
|
|
A.Affiche();
|
|
cout << "\n B: ";
|
|
B.Affiche();
|
|
cout << "\n B2: ";
|
|
B2.Affiche();
|
|
cout <<"\n rangB: "<<rang_B << ", rangB2= "<< rang_B2;
|
|
cout << "\n cas= "<< cas << " VP= "<<VP;
|
|
cout << "\n les val propres: " << VP ;
|
|
};
|
|
};
|
|
#endif
|
|
// vérif pour le cas non débug
|
|
// if (cas == 0)
|
|
// {cas = -1; // on signale l'erreur
|
|
// break; // et on arrête
|
|
// };
|
|
};
|
|
break;
|
|
}
|
|
default:
|
|
{cout << "\n erreur au niveau du rang de matrice: rang_B doit etre compris entre 0 et 2 "
|
|
<< " ici = " << rang_B
|
|
<< "\n V_Propres3x3(..." << endl;
|
|
Sortie(1);
|
|
};
|
|
break;
|
|
};
|
|
|
|
#ifdef MISE_AU_POINT
|
|
// en débug que les valeurs propres fonctionnent correctement
|
|
// , cas = 1 si 3 val propres différentes (= 3 composantes du vecteur de retour)
|
|
// , cas = 0 si les 3 sont identiques (= la première composantes du vecteur de retour),
|
|
// , cas = 2 si Vp(1)=Vp(2) ( Vp(1), et Vp(3) dans les 2 premières composantes du retour)
|
|
// , cas = 3 si Vp(2)=Vp(3) ( Vp(1), et Vp(2) dans les 2 premières composantes du retour)
|
|
{ Vecteur Vp(3);
|
|
switch (cas)
|
|
{ case 0: Vp(1)=Vp(2)=Vp(3)=VP(1); break;
|
|
case 1: Vp = VP.Vect(); break;
|
|
case 2: Vp(1)=Vp(2)=VP(1); Vp(3)=VP(3); break;
|
|
case 3: Vp(2)=Vp(3)=VP(2); Vp(1)=VP(1); break;
|
|
};
|
|
for (int i=1;i<=3;i++)
|
|
{ Coordonnee3 W6 = A.Prod_mat_vec(Vpropre(i).Vect());
|
|
// normalement W6 = Vp(i)*Vpropre(i)
|
|
double diff = (W6 - (Vpropre(i) * Vp(i))).Norme();
|
|
if (Dabs(diff) > ConstMath::unpeupetit)
|
|
{cout << "\n erreur le vecteur (i= " << i <<") propre ";
|
|
Vpropre(i).Affiche();
|
|
cout << "\n n'est pas un vecteur propre pour la valeur propre: "
|
|
<< Vp(i) << " concernant la matrice: ";
|
|
A.Affiche();
|
|
cout << "\n A*V = "<<W6 << "(Vpropre(i) * Vp(i))= " << (Vpropre(i) * Vp(i))
|
|
<< " diff= "<<diff;
|
|
|
|
cout << "\n cas= "<< cas << " VP= "<<VP;
|
|
cout << "\n les val propres: " << Vp ;
|
|
|
|
cout << "\n V_Propres3x3(..." << endl;
|
|
};
|
|
};
|
|
};
|
|
|
|
#endif
|
|
// retour
|
|
return Vpropre;
|
|
|
|
};
|
|
|
|
|
|
// calcul du rang d'une matrice 3x3 singulière, qui peut être 0, 1 ou 2
|
|
// modifie la matrice en conséquence
|
|
// en sortie:
|
|
// rang : = le rang de la matrice
|
|
// rang = 0 ==> veut dire que c'est la matrice nulle (à ConstMath::pasmalpetit près)
|
|
// rang = 1 ==> la première ligne de la matrice contient la direction libre, génératrice
|
|
// rang = 2 ==> les deux premières ligne de la matrice contiennent les deux directions libres
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
int MathUtil2::CalculRangMatrice3x3Singuliere( Mat_pleine& A)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((A.Nb_colonne() != 3)|| (A.Nb_ligne() != 3))
|
|
{cout << "erreur de dimension: Nb_colonne()= " << A.Nb_colonne() << ", Nb_ligne()= ";
|
|
cout << A.Nb_ligne() << " alors que cette methode ne s'applique qu'aux matrices 3x3 ! "
|
|
<< "\n CalculRangMatrice(..." << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int rang = 0; // init par défaut
|
|
// on récupère la norme maxi de la matrice
|
|
int imax,jmax;
|
|
double maxMat = A.MaxiValAbs(imax,jmax);
|
|
// si maxMat == 0, la matrice est nulle -> rang = 0
|
|
if (maxMat <= ConstMath::pasmalpetit)
|
|
{ rang = 0; }
|
|
else
|
|
{// sinon le rang sera au moins égal à 1 et maxMat n'est pas trop petit
|
|
double unSurmaxMat = 1./maxMat;
|
|
// on permute la première ligne, pour qu'elle contienne le maxi
|
|
if (imax != 1)
|
|
{// sauvegarde de la ligne du maxi, avec normalisation à 1
|
|
Vecteur ligne_du_maxi = unSurmaxMat * A(imax);
|
|
A.Ligne_set(imax) = A(1); // permutation
|
|
A.Ligne_set(1) = ligne_du_maxi; // """"
|
|
};
|
|
// maintenant on fait une réduction, c-a-d on transforme la matrice pour qu'il n'y ait que (1,0,0) dans la colonne du maxi
|
|
Vecteur col_du_maxi = A(jmax); // récup de la colonne du maxi
|
|
A.Ligne_set(2) = A(2) - col_du_maxi(2)*A(1);
|
|
A.Ligne_set(3) = A(3) - col_du_maxi(3)*A(1);
|
|
// arrivé ici normalement on a A(imax,2) = A(imax,3) = 0.
|
|
// on calcul le maxi des composantes de la deuxième et troisième ligne de la matrice
|
|
// -- tout d'abord la deuxième ligne
|
|
int imax2=2; // init
|
|
int jmax2; double maxMat2 = A(2).Max_val_abs(jmax2);
|
|
// -- idem troisième ligne
|
|
int imax3=3; // init
|
|
int jmax3; double maxMat3 = A(3).Max_val_abs(jmax3);
|
|
// les maxi finaux sont avec les indices 2 (imax2, jmax2, maxMat2)
|
|
if (maxMat3 > maxMat2)
|
|
{imax2=imax3;jmax2=jmax3;maxMat2 = maxMat3;
|
|
};
|
|
// si le maxi est très petit, on n'a qu'une seule direction de libre
|
|
if (maxMat2 <= ConstMath::pasmalpetit)
|
|
{ rang = 1; }
|
|
else
|
|
{ // sinon on refait la même manip entre les lignes 2 et 3
|
|
double unSurmaxMat2 = 1./maxMat2;
|
|
// on permute la dernière ligne, si besoin, pour que la deuxième contienne le maxi
|
|
if (imax2 != 2)
|
|
{// sauvegarde de la ligne du maxi, avec normalisation à 1
|
|
Vecteur ligne_du_maxi = unSurmaxMat2 * A(imax2);
|
|
A.Ligne_set(imax2) = A(2); // permutation
|
|
A.Ligne_set(2) = ligne_du_maxi; // """"
|
|
};
|
|
// le rang est 2 et les 2 premières lignes contiennent deux vecteurs indépendants
|
|
rang = 2;
|
|
}
|
|
};
|
|
// retour
|
|
return rang;
|
|
};
|
|
|
|
|
|
// --- cas d'une dimension d'espace == 3
|
|
|
|
// calcul deux vecteurs perpendiculaires à un troisième, générateurs d'un plan, et orthonormée
|
|
// Les deux vecteurs résultats sont quelconques a priori
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::Def_vecteurs_plan(const Coordonnee& V1, Coordonnee& V2, Coordonnee& V3)
|
|
{ double norme_V1= V1.Norme();
|
|
#ifdef MISE_AU_POINT
|
|
if (norme_V1 < ConstMath::trespetit)
|
|
{cout << "erreur le vecteur V1 a une norme nulle (= " << norme_V1 << ") ";
|
|
cout << " le calcul du plan normal est impossible ! "
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
};
|
|
if ((V1.Dimension() != 3)|| (V2.Dimension() != 3) || (V3.Dimension() != 3))
|
|
{cout << "erreur de dimension dans les vecteurs, qui devraient etre de dimension 3: V1.Taille()= " << V1.Dimension()
|
|
<< ", V2.Dimension()= " << V2.Dimension() << ", V3.Dimension()= " << V3.Dimension()
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
Coordonnee V(V1/norme_V1); // on normalise
|
|
|
|
// on va chercher l'ordre des composantes de V
|
|
int un,deux,trois;
|
|
if (Dabs(V(2)) > Dabs(V(1)))
|
|
{ if (Dabs(V(2)) > Dabs(V(3)))
|
|
{un = 2;
|
|
if (Dabs(V(1)) > Dabs(V(3)))
|
|
{deux = 1; trois = 3;}
|
|
else
|
|
{deux = 3; trois = 1;}
|
|
}
|
|
else
|
|
{un = 3; deux= 2; trois = 1;}
|
|
}
|
|
else
|
|
{ if ((Dabs(V(3)) > Dabs(V(1))))
|
|
{un = 3; deux = 1; trois = 2; }
|
|
else
|
|
{if ((Dabs(V(3)) > Dabs(V(2))))
|
|
{un = 1; deux = 3; trois = 2;}
|
|
else
|
|
{un = 1; deux = 2; trois = 3;};
|
|
}
|
|
};
|
|
// on calcule les vecteurs en fonction
|
|
double unsurlongue = 1./sqrt(V(un)*V(un) + V(trois)*V(trois));
|
|
V2(un) = -V(trois) * unsurlongue;
|
|
V2(deux) = 0.;
|
|
V2(trois) = V(un) * unsurlongue;
|
|
|
|
V3(un) = V(deux) * V2(trois);
|
|
V3(deux) = V(trois) * V2(un) - V(un) * V2(trois);
|
|
V3(trois) = -V(deux) * V2(un);
|
|
|
|
#ifdef MISE_AU_POINT
|
|
if (ParaGlob::NiveauImpression() > 8)
|
|
{// on vérifie l'algo de tri
|
|
bool erreur = false;
|
|
if ((Dabs(V(deux)) > Dabs(V(un))) || (Dabs(V(trois)) > Dabs(V(un)))
|
|
|| (Dabs(V(trois)) > Dabs(V(deux)))
|
|
)
|
|
{cout << "\n *** erreur dans le tri des composantes de V: "
|
|
<< "un= "<< un << "deux= "<< deux <<" trois= "<< trois
|
|
<< " V= "<< V ;
|
|
erreur = true;
|
|
};
|
|
// on vérifie les normes et les produits scalaires
|
|
if ((V.Norme()-1.) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V a une norme " << V.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if ((V2.Norme()-1) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V2 a une norme " << V2.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if ((V3.Norme()-1) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 a une norme " << V3.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V * V2) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V2 n'est pas normal a V1 "
|
|
<< "\n V1= " << V1 << " V2= " << V2 ;
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V * V3) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 n'est pas normal a V1 "
|
|
<< "\n V1= " << V << " V3= " << V3 ;
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V2 * V3) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 n'est pas normal a V2 "
|
|
<< "\n V3= " << V3 << " V2= " << V2 ;
|
|
erreur = true;
|
|
}
|
|
if (erreur)
|
|
{ cout << "\n Def_vecteurs_plan(const Coordonnee& V1,..." << flush;
|
|
Sortie(1);
|
|
};
|
|
};
|
|
#endif
|
|
|
|
/* // calcul original, qui ne fonctionne pas pour le cas V(1) et V(3) nulle ensemble !!
|
|
|
|
|
|
//
|
|
if (Dabs(V(1)) >= Dabs(V(3)))
|
|
{ double unsurlongue = 1./sqrt(V(1)*V(1) + V(3)*V(3));
|
|
// si V(3) est nulle, alors V(1) est forcément non nulle ==>longue est non nul
|
|
// si (V(3) est non nulle, alors ==>longue est non nul
|
|
V2(1) = -V(3) * unsurlongue;
|
|
V2(2) = 0.;
|
|
V2(3) = V(1) * unsurlongue;
|
|
|
|
V3(1) = V(2) * V2(3);
|
|
V3(2) = V(3) * V2(1) - V(1) * V2(3);
|
|
V3(3) = -V(2) * V2(1);
|
|
}
|
|
else
|
|
{ double unsurlongue = 1./sqrt(V(2)*V(2) + V(3)*V(3));
|
|
// ici V(2) prend le rôle de V(1)
|
|
V2(1) = 0.;
|
|
V2(2) = V(3) * unsurlongue;
|
|
V2(3) = -V(2) * unsurlongue;
|
|
|
|
V3(1) = V(2) * V2(3) - V(3) * V2(2);
|
|
V3(2) = -V(1) * V2(3);
|
|
V3(3) = V(1) * V2(2);
|
|
};
|
|
*/
|
|
};
|
|
// calcul deux vecteurs perpendiculaires à un troisième, générateurs d'un plan, et orthonormée
|
|
// Les deux vecteurs résultats sont quelconques a priori
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::Def_vecteurs_plan(const CoordonneeB& V1, CoordonneeB& V2, CoordonneeB& V3)
|
|
{ double norme_V1= V1.Norme();
|
|
#ifdef MISE_AU_POINT
|
|
if (norme_V1 < ConstMath::trespetit)
|
|
{cout << "erreur le vecteur V1 a une norme nulle (= " << norme_V1 << ") ";
|
|
cout << " le calcul du plan normal est impossible ! "
|
|
<< "\n Def_vecteurs_plan(const CoordonneeB& V1,..." << endl;
|
|
Sortie(1);
|
|
};
|
|
if ((V1.Dimension() != 3)|| (V2.Dimension() != 3) || (V3.Dimension() != 3))
|
|
{cout << "erreur de dimension dans les vecteurs, qui devraient etre de dimension 3: V1.Taille()= " << V1.Dimension()
|
|
<< ", V2.Dimension()= " << V2.Dimension() << ", V3.Dimension()= " << V3.Dimension()
|
|
<< "\n Def_vecteurs_plan(const CoordonneeB& V1,..." << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
CoordonneeB V(V1/norme_V1); // on normalise
|
|
|
|
// on va chercher l'ordre des composantes de V
|
|
int un,deux,trois;
|
|
if (Dabs(V(2)) > Dabs(V(1)))
|
|
{ if (Dabs(V(2)) > Dabs(V(3)))
|
|
{un = 2;
|
|
if (Dabs(V(1)) > Dabs(V(3)))
|
|
{deux = 1; trois = 3;}
|
|
else
|
|
{deux = 3; trois = 1;}
|
|
}
|
|
else
|
|
{un = 3; deux= 2; trois = 1;}
|
|
}
|
|
else
|
|
{ if ((Dabs(V(3)) > Dabs(V(1))))
|
|
{un = 3; deux = 1; trois = 2; }
|
|
else
|
|
{if ((Dabs(V(3)) > Dabs(V(2))))
|
|
{un = 1; deux = 3; trois = 2;}
|
|
else
|
|
{un = 1; deux = 2; trois = 3;};
|
|
}
|
|
};
|
|
// on calcule les vecteurs en fonction
|
|
double unsurlongue = 1./sqrt(V(un)*V(un) + V(trois)*V(trois));
|
|
V2(un) = -V(trois) * unsurlongue;
|
|
V2(deux) = 0.;
|
|
V2(trois) = V(un) * unsurlongue;
|
|
|
|
V3(un) = V(deux) * V2(trois);
|
|
V3(deux) = V(trois) * V2(un) - V(un) * V2(trois);
|
|
V3(trois) = -V(deux) * V2(un);
|
|
|
|
#ifdef MISE_AU_POINT
|
|
if (ParaGlob::NiveauImpression() > 8)
|
|
{// on vérifie l'algo de tri
|
|
bool erreur = false;
|
|
if ((Dabs(V(deux)) > Dabs(V(un))) || (Dabs(V(trois)) > Dabs(V(un)))
|
|
|| (Dabs(V(trois)) > Dabs(V(deux)))
|
|
)
|
|
{cout << "\n *** erreur dans le tri des composantes de V: "
|
|
<< "un= "<< un << "deux= "<< deux <<" trois= "<< trois
|
|
<< " V= "<< V ;
|
|
erreur = true;
|
|
};
|
|
// on vérifie les normes et les produits scalaires
|
|
if ((V.Norme()-1.) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V a une norme " << V.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if ((V2.Norme()-1.) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V2 a une norme " << V2.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if ((V3.Norme()-1.) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 a une norme " << V3.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V.Coor() * V2.Coor()) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V2 n'est pas normal a V1 "
|
|
<< "\n V1= " << V1 << " V2= " << V2 ;
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V.Coor() * V3.Coor()) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 n'est pas normal a V1 "
|
|
<< "\n V1= " << V << " V3= " << V3 ;
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V2.Coor() * V3.Coor()) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 n'est pas normal a V2 "
|
|
<< "\n V3= " << V3 << " V2= " << V2 ;
|
|
erreur = true;
|
|
}
|
|
if (erreur)
|
|
{ cout << "\n Def_vecteurs_plan(const CoordonneeB& V1,..." << flush;
|
|
Sortie(1);
|
|
};
|
|
}
|
|
#endif
|
|
|
|
|
|
/* // calcul original, qui ne fonctionne pas pour le cas V(1) et V(3) nulle ensemble !!
|
|
if (Dabs(V(1)) >= Dabs(V(3)))
|
|
{ double unsurlongue = 1./sqrt(V(1)*V(1) + V(3)*V(3));
|
|
// si V(3) est nulle, alors V(1) est forcément non nulle ==>longue est non nul
|
|
// si (V(3) est non nulle, alors ==>longue est non nul
|
|
V2(1) = -V(3) * unsurlongue;
|
|
V2(2) = 0.;
|
|
V2(3) = V(1) * unsurlongue;
|
|
|
|
V3(1) = V(2) * V2(3);
|
|
V3(2) = V(3) * V2(1) - V(1) * V2(3);
|
|
V3(3) = -V(2) * V2(1);
|
|
}
|
|
else
|
|
{ double unsurlongue = 1./sqrt(V(2)*V(2) + V(3)*V(3));
|
|
// ici V(2) prend le rôle de V(1)
|
|
V2(1) = 0.;
|
|
V2(2) = V(3) * unsurlongue;
|
|
V2(3) = -V(2) * unsurlongue;
|
|
|
|
V3(1) = V(2) * V2(3) - V(3) * V2(2);
|
|
V3(2) = -V(1) * V2(3);
|
|
V3(3) = V(1) * V2(2);
|
|
};
|
|
*/
|
|
|
|
};
|
|
// calcul deux vecteurs perpendiculaires à un troisième, générateurs d'un plan, et orthonormée
|
|
// Les deux vecteurs résultats sont quelconques a priori
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::Def_vecteurs_plan(const CoordonneeH& V1, CoordonneeH& V2, CoordonneeH& V3)
|
|
{ double norme_V1= V1.Norme();
|
|
#ifdef MISE_AU_POINT
|
|
if (norme_V1 < ConstMath::trespetit)
|
|
{cout << "erreur le vecteur V1 a une norme nulle (= " << norme_V1 << ") ";
|
|
cout << " le calcul du plan normal est impossible ! "
|
|
<< "\n Def_vecteurs_plan(const CoordonneeH& V1,..." << endl;
|
|
Sortie(1);
|
|
};
|
|
if ((V1.Dimension() != 3)|| (V2.Dimension() != 3) || (V3.Dimension() != 3))
|
|
{cout << "erreur de dimension dans les vecteurs, qui devraient etre de dimension 3: V1.Taille()= " << V1.Dimension()
|
|
<< ", V2.Dimension()= " << V2.Dimension() << ", V3.Dimension()= " << V3.Dimension()
|
|
<< "\n Def_vecteurs_plan(const CoordonneeH& V1,..." << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
CoordonneeH V(V1/norme_V1); // on normalise
|
|
|
|
// on va chercher l'ordre des composantes de V
|
|
int un,deux,trois;
|
|
if (Dabs(V(2)) > Dabs(V(1)))
|
|
{ if (Dabs(V(2)) > Dabs(V(3)))
|
|
{un = 2;
|
|
if (Dabs(V(1)) > Dabs(V(3)))
|
|
{deux = 1; trois = 3;}
|
|
else
|
|
{deux = 3; trois = 1;}
|
|
}
|
|
else
|
|
{un = 3; deux= 2; trois = 1;}
|
|
}
|
|
else
|
|
{ if ((Dabs(V(3)) > Dabs(V(1))))
|
|
{un = 3; deux = 1; trois = 2; }
|
|
else
|
|
{if ((Dabs(V(3)) > Dabs(V(2))))
|
|
{un = 1; deux = 3; trois = 2;}
|
|
else
|
|
{un = 1; deux = 2; trois = 3;};
|
|
}
|
|
};
|
|
// on calcule les vecteurs en fonction
|
|
double unsurlongue = 1./sqrt(V(un)*V(un) + V(trois)*V(trois));
|
|
V2(un) = -V(trois) * unsurlongue;
|
|
V2(deux) = 0.;
|
|
V2(trois) = V(un) * unsurlongue;
|
|
|
|
V3(un) = V(deux) * V2(trois);
|
|
V3(deux) = V(trois) * V2(un) - V(un) * V2(trois);
|
|
V3(trois) = -V(deux) * V2(un);
|
|
|
|
#ifdef MISE_AU_POINT
|
|
if (ParaGlob::NiveauImpression() > 8)
|
|
{// on vérifie l'algo de tri
|
|
bool erreur = false;
|
|
if ((Dabs(V(deux)) > Dabs(V(un))) || (Dabs(V(trois)) > Dabs(V(un)))
|
|
|| (Dabs(V(trois)) > Dabs(V(deux)))
|
|
)
|
|
{cout << "\n *** erreur dans le tri des composantes de V: "
|
|
<< "un= "<< un << "deux= "<< deux <<" trois= "<< trois
|
|
<< " V= "<< V ;
|
|
erreur = true;
|
|
};
|
|
// on vérifie les normes et les produits scalaires
|
|
if ((V.Norme()-1.) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V a une norme " << V.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if ((V2.Norme()-1.) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V2 a une norme " << V2.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if ((V3.Norme()-1.) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 a une norme " << V3.Norme() << " diff de 1 ";
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V.Coor() * V2.Coor()) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V2 n'est pas normal a V1 "
|
|
<< "\n V1= " << V1 << " V2= " << V2 ;
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V.Coor() * V3.Coor()) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 n'est pas normal a V1 "
|
|
<< "\n V1= " << V << " V3= " << V3 ;
|
|
erreur = true;
|
|
}
|
|
if (Dabs(V2.Coor() * V3.Coor()) > ConstMath::petit)
|
|
{cout << "erreur le nouveau vecteur V3 n'est pas normal a V2 "
|
|
<< "\n V3= " << V3 << " V2= " << V2 ;
|
|
erreur = true;
|
|
}
|
|
if (erreur)
|
|
{ cout << "\n Def_vecteurs_plan(const CoordonneeH& V1,..." << flush;
|
|
Sortie(1);
|
|
};
|
|
}
|
|
#endif
|
|
|
|
|
|
/* // calcul original, qui ne fonctionne pas pour le cas V(1) et V(3) nulle ensemble !!
|
|
if (Dabs(V(1)) >= Dabs(V(3)))
|
|
{ double unsurlongue = 1./sqrt(V(1)*V(1) + V(3)*V(3));
|
|
// si V(3) est nulle, alors V(1) est forcément non nulle ==>longue est non nul
|
|
// si (V(3) est non nulle, alors ==>longue est non nul
|
|
V2(1) = -V(3) * unsurlongue;
|
|
V2(2) = 0.;
|
|
V2(3) = V(1) * unsurlongue;
|
|
|
|
V3(1) = V(2) * V2(3);
|
|
V3(2) = V(3) * V2(1) - V(1) * V2(3);
|
|
V3(3) = -V(2) * V2(1);
|
|
}
|
|
else
|
|
{ double unsurlongue = 1./sqrt(V(2)*V(2) + V(3)*V(3));
|
|
// ici V(2) prend le rôle de V(1)
|
|
V2(1) = 0.;
|
|
V2(2) = V(3) * unsurlongue;
|
|
V2(3) = -V(2) * unsurlongue;
|
|
|
|
V3(1) = V(2) * V2(3) - V(3) * V2(2);
|
|
V3(2) = -V(1) * V2(3);
|
|
V3(3) = V(1) * V2(2);
|
|
};
|
|
*/
|
|
|
|
};
|
|
|
|
// --- cas d'une dimension d'espace == 2
|
|
|
|
// calcul d'un vecteur perpendiculaire à un premier, et orthonormée
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::Def_vecteurs_plan(const Coordonnee& V1, Coordonnee& V2)
|
|
{ double norme_V1= V1.Norme();
|
|
#ifdef MISE_AU_POINT
|
|
if (norme_V1 < ConstMath::trespetit)
|
|
{cout << "erreur le vecteur V1 a une norme nulle (= " << norme_V1 << ") ";
|
|
cout << " le calcul du plan normal est impossible ! "
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
};
|
|
if ((V1.Dimension() != 2)|| (V2.Dimension() != 2) )
|
|
{cout << "erreur de dimension dans les vecteurs, qui devraient etre de dimension 2: V1.Taille()= " << V1.Dimension()
|
|
<< ", V2.Dimension()= " << V2.Dimension()
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
Coordonnee V(V1/norme_V1); // on normalise
|
|
|
|
// le vecteur V2 est normale à V
|
|
// et V,V2 -> sens direct (inverse de l'horloge)
|
|
V2(1) = - V1(2);
|
|
V2(2) = V1(1);
|
|
};
|
|
|
|
// calcul d'un vecteur perpendiculaire à un premier, et orthonormée
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::Def_vecteurs_plan(const CoordonneeB& V1, CoordonneeB& V2)
|
|
{ double norme_V1= V1.Norme();
|
|
#ifdef MISE_AU_POINT
|
|
if (norme_V1 < ConstMath::trespetit)
|
|
{cout << "erreur le vecteur V1 a une norme nulle (= " << norme_V1 << ") ";
|
|
cout << " le calcul du plan normal est impossible ! "
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
};
|
|
if ((V1.Dimension() != 2)|| (V2.Dimension() != 2) )
|
|
{cout << "erreur de dimension dans les vecteurs, qui devraient etre de dimension 2: V1.Taille()= " << V1.Dimension()
|
|
<< ", V2.Dimension()= " << V2.Dimension()
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
CoordonneeB V(V1/norme_V1); // on normalise
|
|
|
|
// le vecteur V2 est normale à V
|
|
// et V,V2 -> sens direct (inverse de l'horloge)
|
|
V2(1) = - V1(2);
|
|
V2(2) = V1(1);
|
|
};
|
|
|
|
// calcul d'un vecteur perpendiculaire à un premier, et orthonormée
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::Def_vecteurs_plan(const CoordonneeH& V1, CoordonneeH& V2)
|
|
{ double norme_V1= V1.Norme();
|
|
#ifdef MISE_AU_POINT
|
|
if (norme_V1 < ConstMath::trespetit)
|
|
{cout << "erreur le vecteur V1 a une norme nulle (= " << norme_V1 << ") ";
|
|
cout << " le calcul du plan normal est impossible ! "
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
};
|
|
if ((V1.Dimension() != 2)|| (V2.Dimension() != 2) )
|
|
{cout << "erreur de dimension dans les vecteurs, qui devraient etre de dimension 2: V1.Taille()= " << V1.Dimension()
|
|
<< ", V2.Dimension()= " << V2.Dimension()
|
|
<< "\n Def_vecteurs_plan(const Coordonnee& V1,..." << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
CoordonneeH V(V1/norme_V1); // on normalise
|
|
|
|
// le vecteur V2 est normale à V
|
|
// et V,V2 -> sens direct (inverse de l'horloge)
|
|
V2(1) = - V1(2);
|
|
V2(2) = V1(1);
|
|
};
|
|
|
|
|
|
//// calcul deux vecteurs perpendiculaires à un troisième, générateurs d'un plan, et orthonormées
|
|
//// Les deux vecteurs résultats sont quelconques a priori
|
|
//// calcul également la variation des vecteurs résultats
|
|
//// en entrée: V1 et d_Vi(1)(ddl) : vecteur donné et sa variation
|
|
//// en sortie: V2 et V3, d_Vi(2)(ddl) et d_Vi(3)(ddl) : vecteurs résultats et leurs variations
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//void Def_vecteurs_plan_et_variation(const CoordonneeB& V1, CoordonneeB& V2, CoordonneeB& V3
|
|
// ,Tableau <BaseB>& d_Vi)
|
|
// { double norme_V1= V1.Norme();
|
|
// #ifdef MISE_AU_POINT
|
|
// if (norme_V1 < ConstMath::trespetit)
|
|
// {cout << "erreur le vecteur V1 a une norme nulle (= " << norme_V1 << ") ";
|
|
// cout << " le calcul du plan normal est impossible ! "
|
|
// << "\n Def_vecteurs_plan_et_variation(const CoordonneeB& V1,..." << endl;
|
|
// Sortie(1);
|
|
// };
|
|
// if ((V1.Dimension() != 3)|| (V2.Dimension() != 3) || (V3.Dimension() != 3))
|
|
// {cout << "erreur de dimension dans les vecteurs, qui devraient etre de dimension 3: V1.Taille()= " << V1.Dimension()
|
|
// << ", V2.Dimension()= " << V2.Dimension() << ", V3.Dimension()= " << V3.Dimension()
|
|
// << "\n Def_vecteurs_plan_et_variation(const CoordonneeB& V1,..." << endl;
|
|
// Sortie(1);
|
|
// }
|
|
// #endif
|
|
// CoordonneeB V(V1/norme_V1); // on normalise
|
|
// //
|
|
// if (Dabs(V(1)) >= Dabs(V(3)))
|
|
// { double unsurlongue = 1./sqrt(V(1)*V(1) + V(3)*V(3));
|
|
// // si V(3) est nulle, alors V(1) est forcément non nulle ==>longue est non nul
|
|
// // si (V(3) est non nulle, alors ==>longue est non nul
|
|
// V2(1) = -V(3) * unsurlongue;
|
|
// V2(2) = 0.;
|
|
// V2(3) = V(1) * unsurlongue;
|
|
//
|
|
// V3(1) = V(2) * V2(3);
|
|
// V3(2) = V(3) * V2(1) - V(1) * V2(3);
|
|
// V3(3) = -V(2) * V2(1);
|
|
//
|
|
// // et les variations
|
|
// int taille = d_Vi.Taille();
|
|
// for (int i=1; i<= taille; i++)
|
|
// { BaseB & d_Vi_i = d_Vi(i); // pour simplifier
|
|
// CoordonneeB & d_V1 = d_Vi_i(1); // "
|
|
// double d_denom = 2. * (d_V1(1) * V(1) + d_V1(3) * V(3));
|
|
// double d_unsurlongue =
|
|
// 1./sqrt(V(1)*V(1) + V(3)*V(3));
|
|
//
|
|
// CoordonneeB & d_V2 = d_Vi_i(2); // "
|
|
//
|
|
//
|
|
// };
|
|
// }
|
|
// else
|
|
// { double unsurlongue = 1./sqrt(V(2)*V(2) + V(3)*V(3));
|
|
// // ici V(2) prend le rôle de V(1)
|
|
// V2(1) = 0.;
|
|
// V2(2) = V(3) * unsurlongue;
|
|
// V2(3) = -V(2) * unsurlongue;
|
|
//
|
|
// V3(1) = V(2) * V2(3) - V(3) * V2(2);
|
|
// V3(2) = -V(1) * V2(3);
|
|
// V3(3) = V(1) * V2(2);
|
|
// };
|
|
// };
|
|
//
|
|
|
|
// calcul d'un changement de base: ceci n'est pas fait dans la classe Coordonnee car il faut y adjoindre
|
|
// la classe Mat_pleine qui intègre beaucoup de chose, du coup la classe Coordonnee deviendrait une usine
|
|
// changement de base (cf. théorie) : la matrice beta est telle que:
|
|
// gpB(i) = beta(i,j) * gB(j) <==> gp_i = beta_i^j * g_j
|
|
// et la matrice gamma telle que:
|
|
// gamma(i,j) represente les coordonnees de la nouvelle base duale gpH dans l'ancienne gH
|
|
// gpH(i) = gamma(i,j) * gH(j), i indice de ligne, j indice de colonne
|
|
// c-a-d= gp^i = gamma^i_j * g^j
|
|
// rappel des différentes relations entre beta et gamma
|
|
// [beta]^{-1} = [gamma]^T ; [beta]^{-1T} = [gamma]
|
|
// [beta] = [gamma]^{-1T} ; [beta]^{T} = [gamma]^{-1}
|
|
// changement de base pour de une fois covariant:
|
|
// [Ap_k] = [beta] * [A_i]
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::ChBase(const CoordonneeB& A_B,const Mat_pleine& beta,CoordonneeB& Ap_B)
|
|
{ int dim = A_B.Dimension();
|
|
#ifdef MISE_AU_POINT
|
|
if ((beta.Nb_ligne() != dim) || (beta.Nb_colonne() != dim))
|
|
{ cout << "\nErreur : matrice beta n'a pas les memes dimensions beta.Nb_ligne(): "
|
|
<< beta.Nb_ligne() <<" et beta.Nb_colonne(): " << beta.Nb_colonne()
|
|
<< " que le vecteur de dim: "
|
|
<< dim << " ! le changement de base n'est pas possible ! \n";
|
|
cout << "ChBase(const CoordonneeB& A_B,const Mat_pleine& beta,CoordonneeB& Ap_B) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
Vecteur inter = beta.Prod_mat_vec(A_B.Vect());
|
|
for (int i=1; i<= dim;i++)
|
|
Ap_B(i) = inter(i);
|
|
};
|
|
|
|
|
|
// changement de base pour de une fois contravariant:
|
|
// [Ap^k] = [gamma] * [A^i]
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void MathUtil2::ChBase(const CoordonneeH& A_H,const Mat_pleine& gamma,CoordonneeH& Ap_H)
|
|
{ int dim = A_H.Dimension();
|
|
#ifdef MISE_AU_POINT
|
|
if ((gamma.Nb_ligne() != dim) || (gamma.Nb_colonne() != dim))
|
|
{ cout << "\nErreur : matrice gamma n'a pas les memes dimensions gamma.Nb_ligne(): "
|
|
<< gamma.Nb_ligne() <<" et gamma.Nb_colonne(): " << gamma.Nb_colonne()
|
|
<< " que le vecteur de dim: "
|
|
<< dim << " ! le changement de base n'est pas possible ! \n";
|
|
cout << "ChBase(const CoordonneeH& A_H,const Mat_pleine& gamma,CoordonneeH& Ap_H) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
|
|
Vecteur inter = gamma.Prod_mat_vec(A_H.Vect());
|
|
////-------- debug -------
|
|
//cout << "\n debug MathUtil2::ChBase( ...";
|
|
//cout << "\n A_H initiale: "<< A_H;
|
|
//cout << "\n gamma: "; gamma.Affiche();
|
|
//cout << "\n gamma * A_H " << inter << flush;
|
|
////-------- fin debug ---------
|
|
for (int i=1; i<= dim;i++)
|
|
Ap_H(i) = inter(i);
|
|
};
|
|
|
|
|
|
|
|
#endif
|