1315 lines
50 KiB
C++
1315 lines
50 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 "Debug.h"
|
|
#include "Util.h"
|
|
#include "Coordonnee3.h"
|
|
#include "Coordonnee2.h"
|
|
#include "Coordonnee1.h"
|
|
#include "ConstMath.h"
|
|
#include "MathUtil.h"
|
|
|
|
#ifndef Util_H_deja_inclus
|
|
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//// PRODUIT VECTORIEL DE DEUX VECTEURS EN COORDONNEES ASBOLUS
|
|
//Vecteur Util::ProdVec( const Vecteur & v1, const Vecteur & v2)
|
|
// {
|
|
// #ifdef MISE_AU_POINT
|
|
// if (v1.Taille() != v2.Taille())
|
|
// { cout << "\nErreur : la taille des deux vecteur n'est pas identiques !\n";
|
|
// cout << "Util::ProdVec(Vecteur & v1,Vecteur & v2) \n";
|
|
// Sortie(1);
|
|
// };
|
|
// if (v1.Taille() != 3)
|
|
// { cout << "\nErreur : la taille des deux vecteur est differente de trois !\n";
|
|
// cout << "Util::ProdVec(Vecteur & v1,Vecteur & v2) \n";
|
|
// Sortie(1);
|
|
// };
|
|
// #endif
|
|
// Vecteur v(3);
|
|
// v(1) = v1(2) * v2(3) - v1(3) * v2(2);
|
|
// v(2) = v1(3) * v2(1) - v1(1) * v2(3);
|
|
// v(3) = v1(1) * v2(2) - v1(2) * v2(1);
|
|
// return v;
|
|
// };
|
|
//
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// idem en coordonnées absolues avec le type Coordonnee
|
|
Coordonnee Util::ProdVec_coor( const Coordonnee & v1, const Coordonnee & v2)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (v1.Dimension() != v2.Dimension())
|
|
{ cout << "\nErreur : la taille des deux Coordonnees n'est pas identiques !\n";
|
|
cout << "Util::ProdVec(const Coordonnee & v1, const Coordonnee & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
if (v1.Dimension() != 3)
|
|
{ cout << "\nErreur : la taille des deux vecteur est differente de trois !\n";
|
|
cout << "Util::ProdVec(Vecteur & v1,Vecteur & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
Coordonnee v(3);
|
|
v(1) = v1(2) * v2(3) - v1(3) * v2(2);
|
|
v(2) = v1(3) * v2(1) - v1(1) * v2(3);
|
|
v(3) = v1(1) * v2(2) - v1(2) * v2(1);
|
|
return v;
|
|
};
|
|
|
|
// idem en coordonnées contravariantes avec le type CoordonneeH
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
CoordonneeH Util::ProdVec_coorH( const CoordonneeH & v1, const CoordonneeH & v2)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (v1.Dimension() != v2.Dimension())
|
|
{ cout << "\nErreur : la taille des deux CoordonneesH n'est pas identiques !\n";
|
|
cout << "Util::ProdVec_coorH( const CoordonneeH & v1, const CoordonneeH & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
if (v1.Dimension() != 3)
|
|
{ cout << "\nErreur : la taille des deux CoordonneesH est differente de trois !\n";
|
|
cout << "Util::ProdVec_coorH( const CoordonneeH & v1, const CoordonneeH & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
CoordonneeH v(3);
|
|
v(1) = v1(2) * v2(3) - v1(3) * v2(2);
|
|
v(2) = v1(3) * v2(1) - v1(1) * v2(3);
|
|
v(3) = v1(1) * v2(2) - v1(2) * v2(1);
|
|
return v;
|
|
};
|
|
|
|
// idem en coordonnées covariantes avec le type CoordonneeB
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
CoordonneeB Util::ProdVec_coorB( const CoordonneeB & v1, const CoordonneeB & v2)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (v1.Dimension() != v2.Dimension())
|
|
{ cout << "\nErreur : la taille des deux CoordonneesB n'est pas identiques !\n";
|
|
cout << "Util::ProdVec_coorB( const CoordonneeB & v1, const CoordonneeB & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
if (v1.Dimension() != 3)
|
|
{ cout << "\nErreur : la taille des deux CoordonneesB est differente de trois !\n";
|
|
cout << "Util::ProdVec_coorB( const CoordonneeB & v1, const CoordonneeB & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
CoordonneeB v(3);
|
|
v(1) = v1(2) * v2(3) - v1(3) * v2(2);
|
|
v(2) = v1(3) * v2(1) - v1(1) * v2(3);
|
|
v(3) = v1(1) * v2(2) - v1(2) * v2(1);
|
|
return v;
|
|
};
|
|
|
|
// idem en coordonnées covariantes avec le type CoordonneeB, et en retour un coordonnee normal
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Coordonnee Util::ProdVec_coorBN( const CoordonneeB & v1, const CoordonneeB & v2)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (v1.Dimension() != v2.Dimension())
|
|
{ cout << "\nErreur : la taille des deux CoordonneesB n'est pas identiques !\n";
|
|
cout << "Util::ProdVec_coorBN( const CoordonneeB & v1, const CoordonneeB & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
if (v1.Dimension() != 3)
|
|
{ cout << "\nErreur : la taille des deux CoordonneesB est differente de trois !\n";
|
|
cout << "Util::ProdVec_coorBN( const CoordonneeB & v1, const CoordonneeB & v2) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
Coordonnee v(3);
|
|
v(1) = v1(2) * v2(3) - v1(3) * v2(2);
|
|
v(2) = v1(3) * v2(1) - v1(1) * v2(3);
|
|
v(3) = v1(1) * v2(2) - v1(2) * v2(1);
|
|
return v;
|
|
};
|
|
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//// CALCUL DU DETERMINANT DE TROIS VECTEURS
|
|
//double Util::Determinant( const Vecteur & v1, const Vecteur & v2, const Vecteur & v3)
|
|
// {
|
|
// #ifdef MISE_AU_POINT
|
|
// if ((v1.Taille() != 3) || (v2.Taille() != 3) || (v3.Taille() != 3))
|
|
// { cout << "\nErreur : la taille des trois vecteur est differente de trois !\n";
|
|
// cout << "Util::Determinant(Vecteur & v1,Vecteur & v2,Vecteur & v3)\n";
|
|
// Sortie(1);
|
|
// }
|
|
// #endif
|
|
// return (ProdVec(v1,v2) * v3);
|
|
// };
|
|
|
|
// CALCUL DU DETERMINANT DE TROIS VECTEURS en coordonnées covariantes
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Util::DeterminantB( const CoordonneeB & v1, const CoordonneeB & v2, const CoordonneeB & v3)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != 3) || (v2.Dimension() != 3) || (v3.Dimension() != 3))
|
|
{ cout << "\nErreur : la taille des trois Coordonee est differente de trois !\n";
|
|
cout << "Util::DeterminantB(CoordonneeB & v1,CoordonneeB & v2,CoordonneeB & v3)\n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
return ((ProdVec_coorB(v1,v2)).ScalBB(v3));
|
|
};
|
|
|
|
// CALCUL DU DETERMINANT DE TROIS VECTEURS en coordonnées absolues avec le type Coordonnee
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Util::Determinant( const Coordonnee & v1, const Coordonnee & v2, const Coordonnee & v3)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != 3) || (v2.Dimension() != 3) || (v3.Dimension() != 3))
|
|
{ cout << "\nErreur : la taille des trois Coordonee est differente de trois !\n";
|
|
cout << "Util::Determinant(Coordonnee & v1,Coordonnee & v2,Coordonnee & v3)\n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
return (ProdVec_coor(v1,v2) * v3);
|
|
};
|
|
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//// CALCUL DU DETERMINANT DE DEUX VECTEURS
|
|
//double Util::Determinant( const Vecteur & v1, const Vecteur & v2)
|
|
// {
|
|
// #ifdef MISE_AU_POINT
|
|
// if (((v1.Taille() != 3) && (v1.Taille() != 2))
|
|
// || ((v2.Taille() != 3) && (v2.Taille() != 2)) )
|
|
// { cout << "\nErreur : la dimension des deux vecteur est differente de trois et deux !\n";
|
|
// cout << "Util::Determinant(Vecteur & v1,Vecteur & v2)\n";
|
|
// Sortie(1);
|
|
// }
|
|
// #endif
|
|
// double res;
|
|
// switch (v1.Taille())
|
|
// { case 2 : res = v1(1) * v2(2) - v1(2) * v2(1); break;
|
|
// case 3 : res = !(ProdVec(v1,v2)); break;
|
|
// default : cout << "erreur Determinant(Vecteur & v1,Vecteur & v2)\n";
|
|
// Sortie(1);
|
|
// }
|
|
// return res;
|
|
// };
|
|
//
|
|
|
|
// CALCUL DU DETERMINANT DE DEUX VECTEURS en coordonnées covariantes
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Util::DeterminantB( const CoordonneeB & v1, const CoordonneeB & v2)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (((v1.Dimension() != 3) && (v1.Dimension() != 2))
|
|
|| ((v2.Dimension() != 3) && (v2.Dimension() != 2)) )
|
|
{ cout << "\nErreur : la dimension des deux Coordonnees est differente de trois et deux !\n";
|
|
cout << "Util::DeterminantB(CoordonneeB & v1,CoordonneeB & v2)\n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
double res;
|
|
switch (v1.Dimension())
|
|
{ case 2 : res = v1(1) * v2(2) - v1(2) * v2(1); break;
|
|
case 3 : res = (ProdVec_coorB(v1,v2)).Norme(); break;
|
|
default : cout << "erreur DeterminantB(CoordonneeB & v1,CoordonneeB & v2)\n";
|
|
Sortie(1);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
// CALCUL DU DETERMINANT DE DEUX VECTEURS en coordonnées absolues avec le type Coordonnee
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Util::Determinant( const Coordonnee & v1, const Coordonnee & v2)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (((v1.Dimension() != 3) && (v1.Dimension() != 2))
|
|
|| ((v2.Dimension() != 3) && (v2.Dimension() != 2)) )
|
|
{ cout << "\nErreur : la dimension des deux Coordonnees est differente de trois et deux !\n";
|
|
cout << "Util::Determinant(Coordonnee & v1,Coordonnee & v2)\n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
double res;
|
|
switch (v1.Dimension())
|
|
{ case 2 : res = v1(1) * v2(2) - v1(2) * v2(1); break;
|
|
case 3 : res = (ProdVec_coor(v1,v2)).Norme(); break;
|
|
default : cout << "erreur Determinant(Coordonnee & v1,Coordonnee & v2)\n";
|
|
Sortie(1);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//// CALCUL DU DETERMINANT DE UN VECTEUR
|
|
//double Util::Determinant( const Vecteur & v1)
|
|
// {
|
|
// return v1.Norme(); //v1 * v1;
|
|
// };
|
|
//
|
|
|
|
// CALCUL DU DETERMINANT DE UN VECTEUR en coordonnée covariante
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Util::DeterminantB( const CoordonneeB & v1)
|
|
{
|
|
return v1.Norme(); //v1 * v1;
|
|
};
|
|
|
|
// CALCUL DU DETERMINANT DE UN VECTEUR en coordonnées absolues avec le type Coordonnee
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Util::Determinant( const Coordonnee & v1)
|
|
{
|
|
return v1.Norme(); //v1 * v1;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// calcul de la variation d'un vecteur unitaire connaissant la variation du
|
|
// vecteur non norme
|
|
// v : le vecteur non norme, Dv : la variation de v, nor : la norme de v
|
|
// en retour : la variation de vecteur
|
|
Vecteur Util::VarUnVect( const Vecteur & v, const Vecteur & Dv, double nor)
|
|
{ double nor3 = nor * nor * nor;
|
|
Vecteur De = Dv / nor - v * ( (v * Dv) / nor3);
|
|
return De;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// idem avec coordonnee en retour
|
|
Coordonnee Util::VarUnVect_coor( const Coordonnee & v, const Coordonnee & Dv, double nor)
|
|
{ double nor3 = nor * nor * nor;
|
|
Coordonnee De = Dv / nor - v * ( (v * Dv) / nor3);
|
|
return De;
|
|
};
|
|
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// idem avec coordonneeB en in-out
|
|
//!!!!!!!!!!!!! très important: il doit s'agir de vecteur exprimé dans un repère orthonormé
|
|
// ceci est vrai quelque soit la variance affichée: car ici on ne prend pas en compte la variation
|
|
// d'une métrique associée à un repère non orthonormé
|
|
// ex: les variations des gi sont ok car en fait les gi représentent les coorddonées dans un repère absolu
|
|
CoordonneeB Util::VarUnVect_coorB( const CoordonneeB & v, const CoordonneeB & Dv, double nor)
|
|
{ double nor3 = nor * nor * nor;
|
|
CoordonneeB De = Dv / nor - v * ( (v.ScalBB(Dv)) / nor3);
|
|
return De;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// idem avec coordonneeH en in-out
|
|
//!!!!!!!!!!!!! très important: il doit s'agir de vecteur exprimé dans un repère orthonormé
|
|
// ceci est vrai quelque soit la variance affichée: car ici on ne prend pas en compte la variation
|
|
// d'une métrique associée à un repère non orthonormé
|
|
// ex: les variations des gi sont ok car en fait les gi représentent les coorddonées dans un repère absolu
|
|
CoordonneeH Util::VarUnVect_coorH( const CoordonneeH & v, const CoordonneeH & Dv, double nor)
|
|
{ double nor3 = nor * nor * nor;
|
|
CoordonneeH De = Dv / nor - v * ( (v.ScalHH(Dv)) / nor3);
|
|
return De;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// calcul du tableau de variation d'un vecteur unitaire connaissant le tableau de variation du
|
|
// vecteur non norme
|
|
// v : le vecteur non norme, Dv : la variation de v, nor : la norme de v
|
|
// en retour : le tableau de variation
|
|
Tableau <Vecteur> Util::VarUnVect( const Vecteur & v, const Tableau <Vecteur>& Dv, double nor)
|
|
{ Tableau <Vecteur> De(Dv.Taille());
|
|
double nor3 = nor * nor * nor;
|
|
int DvTaille=Dv.Taille();
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ De(i) = Dv(i) / nor - v * ( (v * Dv(i)) / nor3);
|
|
}
|
|
return De;
|
|
};
|
|
// idem avec des coordonnees
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee> Util::VarUnVect_coor( const Coordonnee & v, const Tableau <Coordonnee>& Dv, double nor)
|
|
{ Tableau <Coordonnee> De(Dv.Taille());
|
|
double nor3 = nor * nor * nor;
|
|
int DvTaille=Dv.Taille();
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ De(i) = Dv(i) / nor - v * ( (v * Dv(i)) / nor3);
|
|
}
|
|
return De;
|
|
};
|
|
// idem avec des coordonneesB
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
//!!!!!!!!!!!!! très important: il doit s'agir de vecteur exprimé dans un repère orthonormé
|
|
// ceci est vrai quelque soit la variance affichée: car ici on ne prend pas en compte la variation
|
|
// d'une métrique associée à un repère non orthonormé
|
|
// ex: les variations des gi sont ok car en fait les gi représentent les coorddonées dans un repère absolu
|
|
Tableau <CoordonneeB> Util::VarUnVect_coorB( const CoordonneeB & v, const Tableau <CoordonneeB>& Dv, double nor)
|
|
{ Tableau <CoordonneeB> De(Dv.Taille());
|
|
double nor3 = nor * nor * nor;
|
|
int DvTaille=Dv.Taille();
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ De(i) = Dv(i) / nor - v * ( ( v.ScalBB(Dv(i)) ) / nor3);
|
|
}
|
|
return De;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// idem et le tableau de retour passé en paramètre
|
|
// calcul du tableau de variation d'un vecteur unitaire connaissant le tableau de variation du
|
|
// vecteur non norme
|
|
// v : le vecteur non norme, Dv : la variation de v, nor : la norme de v
|
|
// en retour : le tableau de variation
|
|
Tableau <Vecteur>& Util::VarUnVect( const Vecteur & v, const Tableau <Vecteur>& Dv, double nor, Tableau <Vecteur>& retour)
|
|
{ retour.Change_taille(Dv.Taille());
|
|
double nor3 = nor * nor * nor;
|
|
int DvTaille=Dv.Taille();
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ retour(i) = Dv(i) / nor - v * ( (v * Dv(i)) / nor3);
|
|
}
|
|
return retour;
|
|
};
|
|
// idem avec des coordonnees
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee>& Util::VarUnVect_coor( const Coordonnee & v, const Tableau <Coordonnee>& Dv, double nor, Tableau <Coordonnee>& retour )
|
|
{ retour.Change_taille(Dv.Taille());
|
|
double nor3 = nor * nor * nor;
|
|
int DvTaille=Dv.Taille();
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ retour(i) = Dv(i) / nor - v * ( (v * Dv(i)) / nor3);
|
|
}
|
|
return retour;
|
|
};
|
|
// idem avec des coordonneesB
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
//!!!!!!!!!!!!! très important: il doit s'agir de vecteur exprimé dans un repère orthonormé
|
|
// ceci est vrai quelque soit la variance affichée: car ici on ne prend pas en compte la variation
|
|
// d'une métrique associée à un repère non orthonormé
|
|
// ex: les variations des gi sont ok car en fait les gi représentent les coorddonées dans un repère absolu
|
|
Tableau <CoordonneeB>& Util::VarUnVect_coorB( const CoordonneeB & v, const Tableau <CoordonneeB>& Dv, double nor,Tableau <CoordonneeB>& retour)
|
|
{ retour.Change_taille(Dv.Taille());
|
|
double nor3 = nor * nor * nor;
|
|
int DvTaille=Dv.Taille();
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ retour(i) = Dv(i) / nor - v * ( ( v.ScalBB(Dv(i)) ) / nor3);
|
|
}
|
|
return retour;
|
|
};
|
|
// idem avec des coordonnees
|
|
// la variation du vecteur est supposé se trouver dans le premier vecteur de la base
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
//!!!!!!!!!!!!! très important: il doit s'agir de vecteur exprimé dans un repère orthonormé
|
|
// ceci est vrai quelque soit la variance affichée: car ici on ne prend pas en compte la variation
|
|
// d'une métrique associée à un repère non orthonormé
|
|
// ex: les variations des gi sont ok car en fait les gi représentent les coorddonées dans un repère absolu
|
|
Tableau <Coordonnee>& Util::VarUnVect_coorBN( const CoordonneeB & v, const Tableau <BaseB>& Dv, double nor,Tableau <Coordonnee>& retour)
|
|
{ retour.Change_taille(Dv.Taille());
|
|
double nor3 = nor * nor * nor;
|
|
int DvTaille=Dv.Taille();
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ //retour(i) = (Dv(i) / nor - v * ( ( v.ScalBB(Dv(i)(1)) ) / nor3)).Coor_const();
|
|
const Coordonnee & dv = Dv(i).Coordo(1); // pour simplifier
|
|
retour(i) = (dv / nor - v.Coor_const() * ( v.Coor_const() * dv) / nor3);
|
|
|
|
}
|
|
return retour;
|
|
};
|
|
|
|
|
|
|
|
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//// calcul de la variation d'un produit vectoriel
|
|
//// vi et Dvi les vecteurs du produit vectoriel et leurs variations
|
|
//Tableau <Vecteur> Util::VarProdVect( const Vecteur & v1, const Vecteur & v2,
|
|
// const Tableau <Vecteur >& Dv1, const Tableau <Vecteur >& Dv2)
|
|
// {
|
|
// #ifdef MISE_AU_POINT
|
|
// if ((v1.Taille() != v2.Taille()) || (Dv1.Taille() != Dv2.Taille())
|
|
// || (Dv1.Taille() == 0)
|
|
// || (v1.Taille() != Dv1(1).Taille()) || (Dv1(1).Taille() != Dv1(2).Taille()) )
|
|
// { cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
// cout << "Util::VarProdVect(Vecteur & v1,Vecteur & v2," <<
|
|
// "Tableau <Vecteur >& Dv1,Tableau <Vecteur >& Dv2)\n";
|
|
// Sortie(1);
|
|
// }
|
|
// #endif
|
|
// int Dv1Taille = Dv1.Taille();
|
|
// Tableau <Vecteur> De(Dv1Taille);
|
|
// for (int i=1;i<= Dv1Taille;i++)
|
|
// { De(i) = ProdVec(Dv1(i),v2) + ProdVec(v1,Dv2(i));
|
|
// }
|
|
// return De;
|
|
// };
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee> Util::VarProdVect_coor( const Coordonnee & v1, const Coordonnee & v2,
|
|
const Tableau <Coordonnee >& Dv1, const Tableau <Coordonnee >& Dv2)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != v2.Dimension()) || (Dv1.Taille() != Dv2.Taille())
|
|
|| (Dv1.Taille() == 0)
|
|
|| (v1.Dimension() != Dv1(1).Dimension()) || (Dv1(1).Dimension() != Dv1(2).Dimension()) )
|
|
{ cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
cout << "Util::VarProdVect_coor(Coordonnee & v1,Coordonnee & v2," <<
|
|
"Tableau <Coordonnee >& Dv1,Tableau <Coordonnee >& Dv2)\n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int Dv1taille=Dv1.Taille();
|
|
Tableau <Coordonnee> De(Dv1taille);
|
|
for (int i=1;i<= Dv1taille;i++)
|
|
{ De(i) = ProdVec_coor(Dv1(i),v2) + ProdVec_coor(v1,Dv2(i));
|
|
}
|
|
return De;
|
|
};
|
|
|
|
// idem que le précédent module mais avec un retour en coordonnée, et un tableau de BaseB
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee> Util::VarProdVect_coor(const Coordonnee & v1, const Coordonnee & v2,
|
|
const Tableau <BaseB >& Dv)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != v2.Dimension()) || (Dv(1)(1).Dimension() != v1.Dimension())
|
|
|| (Dv.Taille() == 0))
|
|
{ cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
cout << "Util::VarProdVect( int toto, const Vecteur & v1, const Vecteur & v2,"
|
|
<< " const Tableau <BaseB >& Dv) \n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int DvTaille = Dv.Taille();
|
|
Tableau <Coordonnee> De(DvTaille);
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ De(i) = ProdVec_coor(Dv(i).Coordo(1),v2) + ProdVec_coor(v1,Dv(i).Coordo(2));
|
|
}
|
|
return De;
|
|
};
|
|
|
|
// idem que le précédent module mais avec un in-out en coordonnéeB, et un tableau de BaseB
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <CoordonneeB> Util::VarProdVect_coorB(const CoordonneeB & v1, const CoordonneeB & v2,
|
|
const Tableau <BaseB >& Dv)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != v2.Dimension()) || (Dv(1)(1).Dimension() != v1.Dimension())
|
|
|| (Dv.Taille() == 0))
|
|
{ cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
cout << "Util::VarProdVect( int toto, const Vecteur & v1, const Vecteur & v2,"
|
|
<< " const Tableau <BaseB >& Dv) \n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int DvTaille = Dv.Taille();
|
|
Tableau <CoordonneeB> De(DvTaille);
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ De(i) = ProdVec_coorB(Dv(i)(1),v2) + ProdVec_coorB(v1,Dv(i)(2));
|
|
}
|
|
return De;
|
|
};
|
|
|
|
|
|
// idem mais avec le retour passé en paramètre
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee>& Util::VarProdVect_coor( const Coordonnee & v1, const Coordonnee & v2,
|
|
const Tableau <Coordonnee >& Dv1, const Tableau <Coordonnee >& Dv2,Tableau <Coordonnee>& retour)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != v2.Dimension()) || (Dv1.Taille() != Dv2.Taille())
|
|
|| (Dv1.Taille() == 0)
|
|
|| (v1.Dimension() != Dv1(1).Dimension()) || (Dv1(1).Dimension() != Dv1(2).Dimension()) )
|
|
{ cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
cout << "Util::VarProdVect_coor(Coordonnee & v1,Coordonnee & v2," <<
|
|
"Tableau <Coordonnee >& Dv1,Tableau <Coordonnee >& Dv2)\n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int Dv1taille=Dv1.Taille();
|
|
retour.Change_taille(Dv1taille);
|
|
for (int i=1;i<= Dv1taille;i++)
|
|
{ retour(i) = ProdVec_coor(Dv1(i),v2) + ProdVec_coor(v1,Dv2(i));
|
|
}
|
|
return retour;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee>& Util::VarProdVect_coor(const Coordonnee & v1, const Coordonnee & v2,
|
|
const Tableau <BaseB >& Dv,Tableau <Coordonnee>& retour)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != v2.Dimension()) || (Dv(1)(1).Dimension() != v1.Dimension())
|
|
|| (Dv.Taille() == 0))
|
|
{ cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
cout << "Util::VarProdVect( int toto, const Vecteur & v1, const Vecteur & v2,"
|
|
<< " const Tableau <BaseB >& Dv) \n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int DvTaille = Dv.Taille();
|
|
retour.Change_taille(DvTaille);
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ retour(i) = ProdVec_coor(Dv(i).Coordo(1),v2) + ProdVec_coor(v1,Dv(i).Coordo(2));
|
|
}
|
|
return retour;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <CoordonneeB>& Util::VarProdVect_coorB(const CoordonneeB & v1, const CoordonneeB & v2,
|
|
const Tableau <BaseB >& Dv,Tableau <CoordonneeB>& retour)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != v2.Dimension()) || (Dv(1)(1).Dimension() != v1.Dimension())
|
|
|| (Dv.Taille() == 0))
|
|
{ cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
cout << "Util::VarProdVect( int toto, const Vecteur & v1, const Vecteur & v2,"
|
|
<< " const Tableau <BaseB >& Dv) \n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int DvTaille = Dv.Taille();
|
|
retour.Change_taille(DvTaille);
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ retour(i) = ProdVec_coorB(Dv(i)(1),v2) + ProdVec_coorB(v1,Dv(i)(2));
|
|
}
|
|
return retour;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee>& Util::VarProdVect_coorBN(const CoordonneeB & v1, const CoordonneeB & v2,
|
|
const Tableau <BaseB >& Dv,Tableau <Coordonnee>& retour)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((v1.Dimension() != v2.Dimension()) || (Dv(1)(1).Dimension() != v1.Dimension())
|
|
|| (Dv.Taille() == 0))
|
|
{ cout << "\nErreur : dans le calcul de la variation du produit vectoriel de 2 vecteurs";
|
|
cout << "Util::VarProdVect( int toto, const Vecteur & v1, const Vecteur & v2,"
|
|
<< " const Tableau <BaseB >& Dv) \n";
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int DvTaille = Dv.Taille();
|
|
retour.Change_taille(DvTaille);
|
|
for (int i=1;i<= DvTaille;i++)
|
|
{ retour(i) = ProdVec_coorBN(Dv(i)(1),v2) + ProdVec_coorBN(v1,Dv(i)(2));
|
|
}
|
|
return retour;
|
|
};
|
|
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// retourne le numero du ddl recherche identifie par en, dans le tableau passé en paramètre
|
|
// s'il existe sinon 0
|
|
int Util::Existe(const Tableau<Ddl >& tab_ddl,Enum_ddl en)
|
|
{ static int posiddl; // initialisée par le système à zéro
|
|
int tab_ddl_Taille = tab_ddl.Taille();
|
|
// on commence par tester a partir de la derniere position sauvegardee
|
|
for (int i=posiddl+1;i<= tab_ddl_Taille;i++)
|
|
if (en == tab_ddl(i).Id_nom())
|
|
{ posiddl=i; return i; }
|
|
// on continue la recherche a partir du debut
|
|
for (int i=1;i<= posiddl;i++)
|
|
if (en == tab_ddl(i).Id_nom())
|
|
{ posiddl=i; return i; }
|
|
// sinon retour 0
|
|
return 0;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// calcul du produit mixte des vecteurs d'une base naturelle en coordonnée covariante
|
|
double Util::ProduitMixte(const BaseB & tab_v )
|
|
{ int nbvecteur= tab_v.NbVecteur(); // le nombre de vecteur
|
|
// on utilise le fait que les vecteurs de la base sont uniquement 1D 2D ou 3D pour optimiser
|
|
switch (nbvecteur)
|
|
{ case 1: // on calcul la norme du vecteur qui est donc toujours positive
|
|
return DeterminantB(tab_v(1));
|
|
break;
|
|
case 2: // cas de deux vecteurs, on ramène la norme du produit vectoriel
|
|
return DeterminantB(tab_v(1),tab_v(2));
|
|
break;
|
|
case 3: // produit mixte normal qui peut-être négatif
|
|
return DeterminantB(tab_v(1),tab_v(2),tab_v(3));
|
|
break;
|
|
default:
|
|
cout << "\n nombre de vecteur de la base non correcte : " << nbvecteur
|
|
<< "\n double Util::ProduitMixte(const BaseB & tab_v )";
|
|
Sortie(1);
|
|
}
|
|
// pour le compilo
|
|
Sortie(1);
|
|
return 0.; // ne doit jamais passer ici
|
|
};
|
|
|
|
// calcul de la variation de la norme d'un vecteur, connaissant la variation du vecteur,
|
|
// le vecteur, et sa norme
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <double> Util::VarNorme( const Tableau <Coordonnee >& Dv,const Coordonnee& V,const double& norme)
|
|
{ int nbddl = Dv.Taille();
|
|
Tableau <double> tab_Nv(nbddl);
|
|
if (norme < ConstMath::trespetit) {return tab_Nv;}; // retour dans le cas où la vitesse est nulle
|
|
double unsurnorme = 1./norme;
|
|
for (int i=1;i<=nbddl;i++)
|
|
{ tab_Nv(i) = (V*Dv(i))*unsurnorme;};
|
|
return tab_Nv;
|
|
};
|
|
|
|
// idem mais avec le type vecteur
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <double> Util::VarNorme( const Tableau <Vecteur >& Dv,const Vecteur& V,const double& norme)
|
|
{ int nbddl = Dv.Taille();
|
|
Tableau <double> tab_Nv(nbddl);
|
|
if (norme < ConstMath::trespetit) {return tab_Nv;}; // retour dans le cas où la vitesse est nulle
|
|
double unsurnorme = 1./norme;
|
|
for (int i=1;i<=nbddl;i++)
|
|
{ tab_Nv(i) = (V*Dv(i))*unsurnorme;};
|
|
return tab_Nv;
|
|
};
|
|
|
|
// calcul de l'inverse d'une matrice 3x3 donnée par ces coordonnées, en retour la matrice
|
|
// d'entrée est remplacée par la matrice inverse
|
|
// 1) cas d'une matrice non symétrique (quelconque), rangement des valeurs:
|
|
// (1,1) ; (1,2) ; (1,3) ; (2,1) ; (2,2) ; (2,3) ; (3,1) ; (3,2) ; (3,3)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Util::Inverse_mat3x3(listdouble9Iter & i9Iter)
|
|
|
|
// le codage est très basique, pour essayer d'avoir un calcul très efficace !!
|
|
|
|
{ // on commence par créer une matrice qui contient une copie de la matrice a inverser
|
|
double t[9];
|
|
double * tex = (i9Iter)->donnees; // idem pour la matrice passée en paramètre
|
|
for ( int i=0; i< 9; i++)
|
|
t[i] = tex[i]; // recopie des valeurs
|
|
// pour plus de clarté on va définir des identifiants explicites
|
|
double* M11 =&t[0];
|
|
double* M12 =&t[1];
|
|
double* M13 =&t[2];
|
|
double* M21 =&t[3];
|
|
double* M22 =&t[4];
|
|
double* M23 =&t[5];
|
|
double* M31 =&t[6];
|
|
double* M32 =&t[7];
|
|
double* M33 =&t[8];
|
|
// on calcul un vecteur d'équilibrage V
|
|
double V[3];
|
|
V[0] = DabsMaX(*M11,DabsMaX(*M12, *M13));
|
|
V[1] = DabsMaX(*M21,DabsMaX(*M22, *M23));
|
|
V[2] = DabsMaX(*M31,DabsMaX(*M32, *M33));
|
|
if ( (V[0] < ConstMath::trespetit ) || (V[1] < ConstMath::trespetit ) || (V[2] < ConstMath::trespetit ))
|
|
{ cout << "\n erreur *** la matrice 3x3 est singuliere et ne peut pas etre inversee"
|
|
<< "\n m11= "<< *M11 <<" m12= "<< *M12 <<" m13= "<< *M13
|
|
<< "\n m21= "<< *M21 <<" m22= "<< *M22 <<" m23= "<< *M23
|
|
<< "\n m31= "<< *M31 <<" m32= "<< *M32 <<" m33= "<< *M33 ;
|
|
if (ParaGlob::NiveauImpression() > 5)
|
|
cout << "\n Util::Inverse_mat3x3(listdouble9Iter & i9Iter)";
|
|
Sortie(1);
|
|
};
|
|
V[0] = 1./V[0]; V[1] = 1./V[1];V[2] = 1./V[2];
|
|
// def d'un vecteur de permutation
|
|
short int indi[3]; // par exemple indi[1]+1 = indique pour la 2ième ligne de la nouvelle matrice alph_beta,
|
|
// à quelle ligne de l'ancienne matrice cela correspond
|
|
short int jdi[3]; // par exemple jdi[1]+1 = indique pour la 2ième ligne de l'ancienne matrice,
|
|
// à quelle ligne de la nouvelle matrice alpha_beta cela correspond
|
|
// permet de faire le retour inverse de la permutation
|
|
|
|
//-----------------------------------------------------------------------
|
|
// --- A triangulation de la matrice avec équilibrage suivant les lignes
|
|
//-----------------------------------------------------------------------
|
|
// Beta11 beta12 beta13
|
|
// alpha21 beta22 beta23
|
|
// alpha31 alpha32 beta33
|
|
|
|
// 1) == cas de la première nouvelle colonne
|
|
// on commence par chercher la ligne telle que |Mi1|*Vi est maxi
|
|
double mvi1 = Dabs(*M11) * V[0];
|
|
double mvi2 = Dabs(*M21) * V[1]; double mvi3 = Dabs(*M31) * V[2];
|
|
|
|
if (mvi1 >= mvi2) { if (mvi1 >= mvi3) { indi[0]=0;jdi[0]=0;} // mvi1 est le plus grand
|
|
else { indi[0]=2;jdi[2]=0;}; // mvi3 est le plus grand
|
|
}
|
|
else { if (mvi2 >= mvi3) { indi[0]=1;jdi[1]=0;} // mvi2 est le plus grand
|
|
else { indi[0]=2;jdi[2]=0;}; // mvi3 est le plus grand
|
|
};
|
|
// on permutte les lignes 1 et indi[0]+1 si indi[0] n'est pas égal à 0
|
|
double inter = 0.;
|
|
switch (indi[0])
|
|
{ case 1: // permutation des lignes 1 et 2
|
|
{inter = *M11; *M11 = *M21; *M21 = inter;
|
|
inter = *M12; *M12 = *M22; *M22 = inter;
|
|
inter = *M13; *M13 = *M23; *M23 = inter;
|
|
inter = V[0]; V[0] = V[1]; V[1] = inter;
|
|
}
|
|
break;
|
|
case 2: // permutation des lignes 1 et 3
|
|
{inter = *M11; *M11 = *M31; *M31 = inter;
|
|
inter = *M12; *M12 = *M32; *M32 = inter;
|
|
inter = *M13; *M13 = *M33; *M33 = inter;
|
|
inter = V[0]; V[0] = V[2]; V[2] = inter;
|
|
}
|
|
break;
|
|
};
|
|
// calcule de la première colonne
|
|
// beta11 = M11 donc rien n'a faire pour le premier terme
|
|
*M21 /= *M11; // alpha21 = M21 / beta11
|
|
*M31 /= *M11; // alpha31 = M31 / beta11
|
|
|
|
// 2) == cas de la deuxième nouvelle colonne
|
|
//Beta12 = M12 : donc rien n'a faire pour Beta12
|
|
|
|
// choix entre la 2ième et 3ième ligne
|
|
double p22 = *M22 - *M21 * *M12;
|
|
double p32 = *M32 - *M31 * *M12;
|
|
if(V[1]*Dabs(p22) < V[2]*Dabs(p32))
|
|
{ // cas ou l'on inverse les lignes 2 et 3
|
|
indi[1] = 2;jdi[2]=1;indi[2] = 1;jdi[1]=2;
|
|
inter = *M21; *M21 = *M31; *M31 = inter;
|
|
inter = *M22; *M22 = *M32; *M32 = inter;
|
|
inter = *M23; *M23 = *M33; *M33 = inter;
|
|
inter = p22; p22 = p32; p32 = inter;
|
|
}
|
|
else // sinon c'est ok
|
|
{ indi[1] = 1;jdi[1]=1;indi[2] = 2;jdi[2]=2;};
|
|
|
|
// calcul de la deuxième colonne
|
|
// beta12 = M12 donc rien n'a faire pour ce premier terme
|
|
*M22 = p22; // beta22 = M22 - alpha21 * beta12
|
|
*M32 = p32 / *M22; // alpha32 = 1/beta22 * (M32 - alpha31*beta12)
|
|
|
|
// 3) == cas de la troisième colonne
|
|
// beta13 = M13 donc rien n'a faire avec ce terme
|
|
*M23 -= *M21 * *M13 ; // beta23 = M23 - alpha21*beta13
|
|
*M33 -= *M31 * *M13 - *M32 * *M23 ; // beta33 = M33 - alpha31*beta13 - alpha32*beta23
|
|
//-----------------------------------------------------------------------
|
|
// --- B calcul de l'inverse de la matrice en résolvant 3 problèmes
|
|
//-----------------------------------------------------------------------
|
|
// on a les formules suivantes:
|
|
// [alpha](Z)=(Y) sachant que alphaii=1
|
|
// -> Z1=Y1; Z2=Y2-alpha21*Z1; Z3=Y3-alpha31*Z1-alpha32*Z2
|
|
//
|
|
// ensuite [beta](X)=(Z) d'où
|
|
// -> X3=Z3/beta33; X2=1/beta22 * (Z2-beta23*X3);
|
|
// X1=1./beta11 * (Z1-beta12*X2-beta13*X3)
|
|
//
|
|
// il faut tenir compte des permutations éventuelles Yi -> Y_i
|
|
// du coup on ne sait pas exactement quelles sont les grandeurs nulles ou pas
|
|
|
|
//1) première colonne
|
|
// Y1=1.,Y2=0.,Y3=0.; et sans permutation on a X1=tex[0], X2 = tex[3] et X3 = tex[6]
|
|
double Y[3];double * pt[3];
|
|
{Y[0]=1.;Y[1]=0.;Y[2]=0.;
|
|
double Z1 = Y[indi[0]]; // Z1 = Y_1
|
|
double Y_2 = Y[indi[1]];double Y_3 = Y[indi[2]];
|
|
double Z2= Y_2- *M21 * Z1; double Z3=Y_3- *M31 * Z1- *M32 * Z2;
|
|
pt[0] = &tex[0]; pt[1] = &tex[3]; pt[2] = &tex[6];
|
|
*(pt[jdi[2]]) = Z3/ *M33; *(pt[jdi[1]]) = (Z2 - *M23 * (*(pt[jdi[2]])) )/ *M22;
|
|
*(pt[jdi[0]]) = (Z1 - *M12 * (*(pt[jdi[1]])) - *M13 * (*(pt[jdi[2]])) )/ *M11;
|
|
}
|
|
//2) deuxième colonne
|
|
// Y1=0.,Y2=1.,Y3=0.; et sans permutation on a X1=tex[1], X2 = tex[4] et X3 = tex[7]
|
|
{Y[0]=0.;Y[1]=1.;Y[2]=0.;
|
|
double Z1 = Y[indi[0]]; // Z1 = Y_1
|
|
double Y_2 = Y[indi[1]];double Y_3 = Y[indi[2]];
|
|
double Z2= Y_2- *M21 * Z1; double Z3=Y_3- *M31 * Z1- *M32 * Z2;
|
|
pt[0] = &tex[1]; pt[1] = &tex[4]; pt[2] = &tex[7];
|
|
*(pt[jdi[2]]) = Z3/ *M33; *(pt[jdi[1]]) = (Z2 - *M23 * (*(pt[jdi[2]])) )/ *M22;
|
|
*(pt[jdi[0]]) = (Z1 - *M12 * (*(pt[jdi[1]])) - *M13 * (*(pt[jdi[2]])) )/ *M11;
|
|
}
|
|
//2) troisième colonne
|
|
// Y1=0.,Y2=0.,Y3=1.; et sans permutation on a X1=tex[2], X2 = tex[5] et X3 = tex[8]
|
|
{Y[0]=0.;Y[1]=0.;Y[2]=1.;
|
|
double Z1 = Y[indi[0]]; // Z1 = Y_1
|
|
double Y_2 = Y[indi[1]];double Y_3 = Y[indi[2]];
|
|
double Z2= Y_2- *M21 * Z1; double Z3=Y_3- *M31 * Z1- *M32 * Z2;
|
|
pt[0] = &tex[2]; pt[1] = &tex[5]; pt[2] = &tex[8];
|
|
*(pt[jdi[2]]) = Z3/ *M33; *(pt[jdi[1]]) = (Z2 - *M23 * (*(pt[jdi[2]])) )/ *M22;
|
|
*(pt[jdi[0]]) = (Z1 - *M12 * (*(pt[jdi[1]])) - *M13 * (*(pt[jdi[2]])) )/ *M11;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
// calcul de l'inverse d'une matrice 3x3 donnée par ces coordonnées, en retour la matrice
|
|
// d'entrée est remplacée par la matrice inverse
|
|
// 2) cas d'une matrice symétrique , rangement des valeurs:
|
|
// (1,1) ; (2,2) ; (3,3) ; (2,1) = (1,2) ; (3,2) = (2,3) ; (3,1) = (1,3) ;
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Util::Inverse_mat3x3(listdouble6Iter & i6Iter)
|
|
// le codage est très basique, pour essayer d'avoir un calcul très efficace !!
|
|
|
|
{ // on commence par créer une matrice qui contient une copie de la matrice a inverser
|
|
double t[9];
|
|
double * tex = (i6Iter)->donnees; // idem pour la matrice passée en paramètre
|
|
// recopie des valeurs
|
|
t[0] = tex[0]; t[4] = tex[1]; t[8] = tex[2];
|
|
t[1] = t[3] = tex[3]; t[5] = t[7]= tex[4]; t[6] = t[2] = tex[5];
|
|
// pour plus de clarté on va définir des identifiants explicites
|
|
double* A11 = &t[0];
|
|
double* A12 = &t[1];
|
|
double* A13 = &t[2];
|
|
double* A21 = &t[3];
|
|
double* A22 = &t[4];
|
|
double* A23 = &t[5];
|
|
double* A31 = &t[6];
|
|
double* A32 = &t[7];
|
|
double* A33 = &t[8];
|
|
//cout << "\n " << *A11 <<" "<< *A12 <<" "<< *A13 <<" "<< *A21 <<" "<< *A22 <<" "<< *A23 <<" "<< *A31 <<" "<< *A32 <<" "<< *A33 <<endl;
|
|
// on calcul un vecteur d'équilibrage V
|
|
double V[3];
|
|
V[0] = DabsMaX(*A11,DabsMaX(*A12, *A13));
|
|
V[1] = DabsMaX(*A21,DabsMaX(*A22, *A23));
|
|
V[2] = DabsMaX(*A31,DabsMaX(*A32, *A33));
|
|
if ( (V[0] < ConstMath::trespetit ) || (V[1] < ConstMath::trespetit ) || (V[2] < ConstMath::trespetit ))
|
|
{ cout << "\n erreur *** la matrice 3x3 est singuliere et ne peut pas etre inversee"
|
|
<< "\n m11= "<< *A11 <<" m12= "<< *A12 <<" m13= "<< *A13
|
|
<< "\n m21= "<< *A21 <<" m22= "<< *A22 <<" m23= "<< *A23
|
|
<< "\n m31= "<< *A31 <<" m32= "<< *A32 <<" m33= "<< *A33 ;
|
|
if (ParaGlob::NiveauImpression() > 5)
|
|
cout << "\n Util::Inverse_mat3x3(listdouble9Iter & i9Iter)";
|
|
Sortie(1);
|
|
};
|
|
V[0] = 1./V[0]; V[1] = 1./V[1];V[2] = 1./V[2];
|
|
// def d'un vecteur de permutation
|
|
short int indi[3]; // par exemple indi[1]+1 = indique pour la 2ième ligne de la nouvelle matrice alph_beta,
|
|
// à quelle ligne de l'ancienne matrice cela correspond
|
|
short int jdi[3]; // par exemple jdi[1]+1 = indique pour la 2ième ligne de l'ancienne matrice,
|
|
// à quelle ligne de la nouvelle matrice alpha_beta cela correspond
|
|
// permet de faire le retour inverse de la permutation
|
|
|
|
//-----------------------------------------------------------------------
|
|
// --- A triangulation de la matrice avec équilibrage suivant les lignes
|
|
//-----------------------------------------------------------------------
|
|
// Beta11 beta12 beta13
|
|
// alpha21 beta22 beta23
|
|
// alpha31 alpha32 beta33
|
|
|
|
// 1) == cas de la première nouvelle colonne
|
|
// on commence par chercher la ligne telle que |Mi1|*Vi est maxi
|
|
double mvi1 = Dabs(*A11) * V[0];
|
|
double mvi2 = Dabs(*A21) * V[1]; double mvi3 = Dabs(*A31) * V[2];
|
|
|
|
if (mvi1 >= mvi2) { if (mvi1 >= mvi3) { indi[0]=0;jdi[0]=0;} // mvi1 est le plus grand
|
|
else { indi[0]=2;jdi[2]=0;}; // mvi3 est le plus grand
|
|
}
|
|
else {if (mvi2 >= mvi3) { indi[0]=1;jdi[1]=0;} // mvi2 est le plus grand
|
|
else { indi[0]=2;jdi[2]=0;}; // mvi3 est le plus grand
|
|
};
|
|
// on permutte les lignes 1 et indi[0] si indi[0] n'est pas égal à 1
|
|
double inter = 0.;
|
|
switch (indi[0])
|
|
{ case 1: // permutation des lignes 1 et 2
|
|
{inter = *A11; *A11 = *A21; *A21 = inter;
|
|
inter = *A12; *A12 = *A22; *A22 = inter;
|
|
inter = *A13; *A13 = *A23; *A23 = inter;
|
|
inter = V[0]; V[0] = V[1]; V[1] = inter;
|
|
}
|
|
break;
|
|
case 2: // permutation des lignes 1 et 3
|
|
{inter = *A11; *A11 = *A31; *A31 = inter;
|
|
inter = *A12; *A12 = *A32; *A32 = inter;
|
|
inter = *A13; *A13 = *A33; *A33 = inter;
|
|
inter = V[0]; V[0] = V[2]; V[2] = inter;
|
|
}
|
|
break;
|
|
};
|
|
// calcule de la première colonne
|
|
// beta11 = A11 donc rien n'a faire pour le premier terme
|
|
*A21 /= *A11; // alpha21 = A21 / beta11
|
|
*A31 /= *A11; // alpha31 = A31 / beta11
|
|
|
|
// 2) == cas de la deuxième nouvelle colonne
|
|
//Beta12 = A12 : donc rien n'a faire pour Beta12
|
|
|
|
// choix entre la 2ième et 3ième ligne
|
|
double p22 = *A22 - *A21 * *A12;
|
|
double p32 = *A32 - *A31 * *A12;
|
|
if(V[1]*Dabs(p22) < V[2]*Dabs(p32))
|
|
{ // cas ou l'on inverse les lignes 2 et 3
|
|
indi[1] = 2;jdi[2]=1;indi[2] = 1;jdi[1]=2;
|
|
inter = *A21; *A21 = *A31; *A31 = inter;
|
|
inter = *A22; *A22 = *A32; *A32 = inter;
|
|
inter = *A23; *A23 = *A33; *A33 = inter;
|
|
inter = p22; p22 = p32; p32 = inter;
|
|
}
|
|
else // sinon c'est ok
|
|
{ indi[1] = 1;jdi[1]=1;indi[2] = 2;jdi[2]=2;};
|
|
|
|
// calcul de la deuxième colonne
|
|
// beta12 = A12 donc rien n'a faire pour ce premier terme
|
|
*A22 = p22; // beta22 = A22 - alpha21 * beta12
|
|
*A32 = p32 / *A22; // alpha32 = 1/beta22 * (A32 - alpha31*beta12)
|
|
|
|
// 3) == cas de la troisième colonne
|
|
// beta13 = A13 donc rien n'a faire avec ce terme
|
|
*A23 -= *A21 * *A13 ; // beta23 = A23 - alpha21*beta13
|
|
*A33 -= *A31 * *A13 - *A32 * *A23 ; // beta33 = A33 - alpha31*beta13 - alpha32*beta23
|
|
//-----------------------------------------------------------------------
|
|
// --- B calcul de l'inverse de la matrice en résolvant 3 problèmes
|
|
//-----------------------------------------------------------------------
|
|
// on a les formules suivantes:
|
|
// [alpha](Z)=(Y) sachant que alphaii=1
|
|
// -> Z1=Y1; Z2=Y2-alpha21*Z1; Z3=Y3-alpha31*Z1-alpha32*Z2
|
|
//
|
|
// ensuite [beta](X)=(Z) d'où
|
|
// -> X3=Z3/beta33; X2=1/beta22 * (Z2-beta23*X3);
|
|
// X1=1./beta11 * (Z1-beta12*X2-beta13*X3)
|
|
//
|
|
// il faut tenir compte des permutations éventuelles Yi -> Y_i
|
|
// du coup on ne sait pas exactement quelles sont les grandeurs nulles ou pas
|
|
|
|
|
|
//1) première colonne
|
|
// Y1=1.,Y2=0.,Y3=0.; et sans permutation on a X1=tex[0], X2 = tex[3] et X3 = tex[5]
|
|
double Y[3];double * pt[3];
|
|
{Y[0]=1.;Y[1]=0.;Y[2]=0.;
|
|
double Z1 = Y[indi[0]]; // Z1 = Y_1
|
|
double Y_2 = Y[indi[1]];double Y_3 = Y[indi[2]];
|
|
double Z2= Y_2- *A21 * Z1; double Z3=Y_3- *A31 * Z1- *A32 * Z2;
|
|
pt[0] = &tex[0]; pt[1] = &tex[3]; pt[2] = &tex[5];
|
|
*(pt[jdi[2]]) = Z3/ *A33; *(pt[jdi[1]]) = (Z2 - *A23 * (*(pt[jdi[2]])) )/ *A22;
|
|
*(pt[jdi[0]]) = (Z1 - *A12 * (*(pt[jdi[1]])) - *A13 * (*(pt[jdi[2]])) )/ *A11;
|
|
}
|
|
//2) deuxième colonne
|
|
// Y1=0.,Y2=1.,Y3=0.; et sans permutation on a X1=tex[3] déjà calculé, X2 = tex[1] et X3 = tex[4]
|
|
// on pourrait sans doute faire des éconnomies due à la symétrie, cependant due aux permutations
|
|
// ce n'est pas évident d'utiliser correctement les symétries, donc on recalcul tout
|
|
{Y[0]=0.;Y[1]=1.;Y[2]=0.;
|
|
double Z1 = Y[indi[0]]; // Z1 = Y_1
|
|
double Y_2 = Y[indi[1]];double Y_3 = Y[indi[2]];
|
|
double Z2= Y_2- *A21 * Z1; double Z3=Y_3- *A31 * Z1- *A32 * Z2;
|
|
pt[0] = &tex[3]; pt[1] = &tex[1]; pt[2] = &tex[4];
|
|
*(pt[jdi[2]]) = Z3/ *A33; *(pt[jdi[1]]) = (Z2 - *A23 * (*(pt[jdi[2]])) )/ *A22;
|
|
*(pt[jdi[0]]) = (Z1 - *A12 * (*(pt[jdi[1]])) - *A13 * (*(pt[jdi[2]])) )/ *A11;
|
|
}
|
|
//2) troisième colonne
|
|
// Y1=0.,Y2=0.,Y3=1.; et sans permutation on a X1=tex[5] déjà calculé, X2 = tex[4] déjà calculé et X3 = tex[2]
|
|
{Y[0]=0.;Y[1]=0.;Y[2]=1.;
|
|
double Z1 = Y[indi[0]]; // Z1 = Y_1
|
|
double Y_2 = Y[indi[1]];double Y_3 = Y[indi[2]];
|
|
double Z2= Y_2- *A21 * Z1; double Z3=Y_3- *A31 * Z1- *A32 * Z2;
|
|
pt[0] = &tex[5]; pt[1] = &tex[4]; pt[2] = &tex[2];
|
|
*(pt[jdi[2]]) = Z3/ *A33; *(pt[jdi[1]]) = (Z2 - *A23 * (*(pt[jdi[2]])) )/ *A22;
|
|
*(pt[jdi[0]]) = (Z1 - *A12 * (*(pt[jdi[1]])) - *A13 * (*(pt[jdi[2]])) )/ *A11;
|
|
}
|
|
|
|
|
|
};
|
|
// calcul de l'inverse d'une matrice 2x2 donnée par ces coordonnées, en retour la matrice
|
|
// d'entrée est remplacée par la matrice inverse
|
|
// 1) cas d'une matrice non symétrique (quelconque), rangement des valeurs:
|
|
// (1,1) ; (2,2) ; (2,1) ; (1,2) ;
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Util::Inverse_mat2x2(listdouble4Iter & i4Iter)
|
|
|
|
// le codage est très basique, pour essayer d'avoir un calcul très efficace !!
|
|
|
|
{ // on commence par créer une matrice qui contient une copie de la matrice a inverser
|
|
double t[4];
|
|
double * tex = (i4Iter)->donnees; // idem pour la matrice passée en paramètre
|
|
// recopie des valeurs
|
|
t[0] = tex[0]; t[3] = tex[1]; t[2] = tex[2]; t[1] = tex[4];
|
|
// pour plus de clarté on va définir des identifiants explicites
|
|
// *** finalement on n'utilise pas de define car cela donne une grandeur définie pour tous Herezh
|
|
// et dans certaine méthodes on utilise des variables qui ont ce nom là !!
|
|
// #define B11 t[0]
|
|
// #define B12 t[1]
|
|
// #define B21 t[2]
|
|
// #define B22 t[3]
|
|
double* B11 = &t[0];
|
|
double* B12 = &t[1];
|
|
double* B21 = &t[2];
|
|
double* B22 = &t[3];
|
|
|
|
//cout << "\n " << *B11 <<" "<< *B12 <<" "<< *B21 <<" "<< *B22 << endl;
|
|
// on calcul un vecteur d'équilibrage V
|
|
double V[2];
|
|
V[0] = DabsMaX(*B11,*B12);
|
|
V[1] = DabsMaX(*B21,*B22);
|
|
if ( (V[0] < ConstMath::trespetit ) || (V[1] < ConstMath::trespetit ) )
|
|
{ cout << "\n erreur *** la matrice 2x2 est singuliere et ne peut pas etre inversee"
|
|
<< "\n m11= "<< *B11 <<" m12= "<< *B12
|
|
<< "\n m21= "<< *B21 <<" m22= "<< *B22 ;
|
|
if (ParaGlob::NiveauImpression() > 5)
|
|
cout << "\n Util::Inverse_mat2x2(listdouble4Iter & i4Iter)";
|
|
Sortie(1);
|
|
};
|
|
V[0] = 1./V[0]; V[1] = 1./V[1];
|
|
// def d'un indicateur de permutation
|
|
bool permutation = false; // indique si oui ou non on permutte la première ligne avec la seconde
|
|
|
|
// 1) == cas de la première nouvelle colonne
|
|
// on commence par chercher la ligne telle que |Mi1|*Vi est maxi
|
|
double mvi1 = Dabs(*B11) * V[0];
|
|
double mvi2 = Dabs(*B21) * V[1];
|
|
|
|
double inter = 0.;
|
|
if (mvi1 < mvi2)
|
|
{ permutation = true; // mvi2 est le plus grand
|
|
// permutation des lignes 1 et 2
|
|
inter = *B11; *B11 = *B21; *B21 = inter;
|
|
inter = *B12; *B12 = *B22; *B22 = inter;
|
|
inter = V[0]; V[0] = V[1]; V[1] = inter;
|
|
};
|
|
|
|
// calcule de la première colonne
|
|
// beta11 = A11 donc rien n'a faire pour le premier terme
|
|
*B21 /= *B11; // alpha21 = B21 / beta11
|
|
|
|
// 2) == cas de la deuxième nouvelle colonne
|
|
//Beta12 = B12 : donc rien n'a faire pour Beta12
|
|
// calcul du deuxième terme de la deuxième colonne
|
|
*B22 = *B22 - *B21 * *B12; // beta22 = B22 - alpha21 * beta12
|
|
|
|
//-----------------------------------------------------------------------
|
|
// --- B calcul de l'inverse de la matrice en résolvant 2 problèmes
|
|
//-----------------------------------------------------------------------
|
|
// on a les formules suivantes:
|
|
// [alpha](Z)=(Y) sachant que alphaii=1
|
|
// -> Z1=Y1; Z2=Y2-alpha21*Z1;
|
|
//
|
|
// ensuite [beta](X)=(Z) d'où
|
|
// X2=Z2/beta22 ;
|
|
// X1=1./beta11 * (Z1-beta12*X2)
|
|
//
|
|
// il faut tenir compte d'une permutation éventuelle
|
|
|
|
if (!permutation)
|
|
{ //1) première colonne
|
|
// Y1=1.,Y2=0., et sans permutation on a X1=tex[0], X2 = tex[2]
|
|
double Y2=0.;
|
|
double Z1 = 1.;
|
|
double Z2 = Y2 - *B21 * Z1;
|
|
tex[2] = Z2 / *B22; tex[0] = (Z1 - *B12 * tex[2] )/ *B11;
|
|
//2) deuxième colonne
|
|
// Y1=0.,Y2=1.; et sans permutation on a X1=tex[3], X2 = tex[1]
|
|
// on pourrait faire des éconnomies due à la symétrie, cependant due aux permutations on recalcul tout
|
|
Y2=1.;
|
|
Z1 = 0.; // Z1 = Y_1
|
|
Z2 = Y2- *B21 * Z1;
|
|
tex[1] = Z2 / *B22; tex[3] = (Z1 - *B12 * tex[1] )/ *B11;
|
|
}
|
|
else
|
|
{ //avec permutation: 1) première colonne
|
|
// Y1=0.,Y2=1., et avec permutation on a X1=tex[2], X2 = tex[0]
|
|
double Y2=1.;
|
|
double Z1 = 0.;
|
|
double Z2 = Y2 - *B21 * Z1;
|
|
tex[0] = Z2 / *B22; tex[2] = (Z1 - *B12 * tex[0] )/ *B11;
|
|
//2) deuxième colonne
|
|
// Y1=1.,Y2=0.; et sans permutation on a X1=tex[1] , X2 = tex[3]
|
|
// on pourrait faire des éconnomies due à la symétrie, cependant due aux permutations on recalcul tout
|
|
Y2=0.;
|
|
Z1 = 1.; // Z1 = Y_1
|
|
Z2 = Y2- *B21 * Z1;
|
|
tex[3] = Z2 / *B22; tex[1] = (Z1 - *B12 * tex[3] )/ *B11;
|
|
};
|
|
|
|
};
|
|
|
|
// calcul de l'inverse d'une matrice 2x2 donnée par ces coordonnées, en retour la matrice
|
|
// d'entrée est remplacée par la matrice inverse
|
|
// 2) cas d'une matrice symétrique , rangement des valeurs:
|
|
// (1,1) ; (2,2) ; (2,1) = (1,2) ;
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Util::Inverse_mat2x2(listdouble3Iter & i3Iter)
|
|
// le codage est très basique, pour essayer d'avoir un calcul très efficace !!
|
|
|
|
{ // on commence par créer une matrice qui contient une copie de la matrice a inverser
|
|
double t[4];
|
|
double * tex = (i3Iter)->donnees; // idem pour la matrice passée en paramètre
|
|
// recopie des valeurs
|
|
t[0] = tex[0]; t[3] = tex[1]; t[1] = t[2] = tex[2];
|
|
// pour plus de clarté on va définir des identifiants explicites
|
|
double* C11 = &t[0];
|
|
double* C12 = &t[1];
|
|
double* C21 = &t[2];
|
|
double* C22 = &t[3];
|
|
//cout << "\n " << *C11 <<" "<< *C12 <<" "<< *C21 <<" "<< *C22 << endl;
|
|
// on calcul un vecteur d'équilibrage V
|
|
double V[2];
|
|
V[0] = DabsMaX(*C11,*C12);
|
|
V[1] = DabsMaX(*C21,*C22);
|
|
if ( (V[0] < ConstMath::trespetit ) || (V[1] < ConstMath::trespetit ) )
|
|
{ cout << "\n erreur *** la matrice 2x2 est singuliere et ne peut pas etre inversee"
|
|
<< "\n m11= "<< *C11 <<" m12= "<< *C12
|
|
<< "\n m21= "<< *C21 <<" m22= "<< *C22 ;
|
|
if (ParaGlob::NiveauImpression() > 5)
|
|
cout << "\n Util::Inverse_mat2x2(listdouble3Iter & i3Iter)";
|
|
Sortie(1);
|
|
};
|
|
V[0] = 1./V[0]; V[1] = 1./V[1];
|
|
// def d'un indicateur de permutation
|
|
bool permutation = false; // indique si oui ou non on permutte la première ligne avec la seconde
|
|
|
|
//-----------------------------------------------------------------------
|
|
// --- A triangulation de la matrice avec équilibrage suivant les lignes
|
|
//-----------------------------------------------------------------------
|
|
// Beta11 beta12
|
|
// alpha21 beta22
|
|
|
|
// 1) == cas de la première nouvelle colonne
|
|
// on commence par chercher la ligne telle que |Mi1|*Vi est maxi
|
|
double mvi1 = Dabs(*C11) * V[0];
|
|
double mvi2 = Dabs(*C21) * V[1];
|
|
|
|
double inter = 0.;
|
|
if (mvi1 < mvi2)
|
|
{ permutation = true; // mvi2 est le plus grand
|
|
// permutation des lignes 1 et 2
|
|
inter = *C11; *C11 = *C21; *C21 = inter;
|
|
inter = *C12; *C12 = *C22; *C22 = inter;
|
|
inter = V[0]; V[0] = V[1]; V[1] = inter;
|
|
};
|
|
// calcule de la première colonne
|
|
// beta11 = A11 donc rien n'a faire pour le premier terme
|
|
*C21 /= *C11; // alpha21 = C21 / beta11
|
|
|
|
// 2) == cas de la deuxième nouvelle colonne
|
|
//Beta12 = C12 : donc rien n'a faire pour Beta12
|
|
// calcul du deuxième terme de la deuxième colonne
|
|
*C22 = *C22 - *C21 * *C12; // beta22 = C22 - alpha21 * beta12
|
|
|
|
//-----------------------------------------------------------------------
|
|
// --- B calcul de l'inverse de la matrice en résolvant 2 problèmes
|
|
//-----------------------------------------------------------------------
|
|
// on a les formules suivantes:
|
|
// [alpha](Z)=(Y) sachant que alphaii=1
|
|
// -> Z1=Y1; Z2=Y2-alpha21*Z1;
|
|
//
|
|
// ensuite [beta](X)=(Z) d'où
|
|
// X2=Z2/beta22 ;
|
|
// X1=1./beta11 * (Z1-beta12*X2)
|
|
//
|
|
// il faut tenir compte d'une permutation éventuelle
|
|
|
|
if (!permutation)
|
|
{ //1) première colonne
|
|
// Y1=1.,Y2=0., et sans permutation on a X1=tex[0], X2 = tex[2]
|
|
double Y2=0.;
|
|
double Z1 = 1.;
|
|
double Z2 = Y2 - *C21 * Z1;
|
|
tex[2] = Z2 / *C22; tex[0] = (Z1 - *C12 * tex[2] )/ *C11;
|
|
//2) deuxième colonne
|
|
// Y1=0.,Y2=1.; et sans permutation on a X1=tex[2] déjà calculé, X2 = tex[1]
|
|
// on pourrait faire des éconnomies due à la symétrie, cependant due aux permutations on recalcul tout
|
|
Y2=1.;
|
|
Z1 = 0.; // Z1 = Y_1
|
|
Z2 = Y2- *C21 * Z1;
|
|
tex[1] = Z2 / *C22; tex[2] = (Z1 - *C12 * tex[1] )/ *C11;
|
|
}
|
|
else
|
|
{ //avec permutation: 1) première colonne
|
|
// Y1=0.,Y2=1., et avec permutation on a X1=tex[2], X2 = tex[0]
|
|
double Y2=1.;
|
|
double Z1 = 0.;
|
|
double Z2 = Y2 - *C21 * Z1;
|
|
tex[0] = Z2 / *C22; tex[2] = (Z1 - *C12 * tex[0] )/ *C11;
|
|
//2) deuxième colonne
|
|
// Y1=1.,Y2=0.; et sans permutation on a X1=tex[1] déjà calculé, X2 = tex[2]
|
|
// on pourrait faire des éconnomies due à la symétrie, cependant due aux permutations on recalcul tout
|
|
Y2=0.;
|
|
Z1 = 1.; // Z1 = Y_1
|
|
Z2 = Y2- *C21 * Z1;
|
|
tex[2] = Z2 / *C22; tex[1] = (Z1 - *C12 * tex[2] )/ *C11;
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|