931 lines
32 KiB
C++
931 lines
32 KiB
C++
|
|
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
//#include "debug.h"
|
|
#include "Base.h"
|
|
#include "Util.h"
|
|
|
|
#ifndef BASE_HetB_deja_inclus
|
|
|
|
//===============================================================
|
|
// Les base covariantes et absolus
|
|
//===============================================================
|
|
|
|
|
|
// CONSTRUCTEURS :
|
|
// par defaut, defini la Base absolu en dimension 3
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::BaseB () :
|
|
dimension(3), nb_vecteur(3), v(3), v_sans(3)
|
|
{ v(1).Change_dim(3); v(1)(1) = 1.;
|
|
v(2).Change_dim(3); v(2)(2) = 1.;
|
|
v(3).Change_dim(3); v(3)(3) = 1.;
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// defini la Base absolu en dimension dim
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::BaseB (int dim) :
|
|
dimension(dim) , nb_vecteur(dim), v(dim), v_sans(dim)
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(dimension); v(3)(3) = 1.;
|
|
case 2: v(2).Change_dim(dimension); v(2)(2) = 1.;
|
|
case 1: v(1).Change_dim(dimension); v(1)(1) = 1.;
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseB::BaseB (int dim)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// defini une Base relative v1(dim)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::BaseB (int dim,const Tableau<CoordonneeB > & v1) :
|
|
dimension(dim) ,nb_vecteur(v1.Taille()), v(v1.Taille()), v_sans(v1.Taille())
|
|
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(v1(3).Dimension()); v(3) = v1(3);
|
|
case 2: v(2).Change_dim(v1(2).Dimension()); v(2) = v1(2);
|
|
case 1: v(1).Change_dim(v1(1).Dimension()); v(1) = v1(1);
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseB::BaseB (int dim,const Tableau<CoordonneeB > & v1)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// defini une Base locale absolu en dimension dim de n vecteurs
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::BaseB (int dim,int n) :
|
|
dimension(dim) , nb_vecteur(n), v(n), v_sans(n)
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(dimension); v(3)(3) = 1.;
|
|
case 2: v(2).Change_dim(dimension); v(2)(2) = 1.;
|
|
case 1: v(1).Change_dim(dimension); v(1)(1) = 1.;
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseB::BaseB (int dim,int n)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// idem dessus mais avec toutes les composantes = s
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::BaseB (int dim,int n,double s) :
|
|
dimension(dim) , nb_vecteur(n), v(n) , v_sans(n)
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(dimension);
|
|
case 2: v(2).Change_dim(dimension);
|
|
case 1: v(1).Change_dim(dimension);
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseB::BaseB (int dim,int n,double s)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
if (s != 0.)
|
|
for (int i=1; i<=nb_vecteur;i++)
|
|
for (int j =1; j<= dimension; j++)
|
|
v(i)(j) = s;
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// DESTRUCTEUR :
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::~BaseB ()
|
|
{ };
|
|
|
|
// constructeur de copie
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::BaseB (const BaseB & b) :
|
|
dimension(b.dimension) , nb_vecteur(b.nb_vecteur), v(b.v), v_sans(b.v_sans)
|
|
{ // on va définir les v_sans associé, stocké au même endroit
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
} ;
|
|
|
|
// defini une Base relative v1(dim) de n vecteurs
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB::BaseB (int dim,int n,const Tableau<CoordonneeB> & v1) :
|
|
dimension(dim) , nb_vecteur(n), v(n), v_sans(n)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (nb_vecteur > v1.Taille())
|
|
{ cout << "\nErreur : la taille relative est > a la taille du tableau !\n";
|
|
cout << " nb_vevteur = " << nb_vecteur
|
|
<< " v1.Taille = " << v1.Taille() << '\n';
|
|
cout << "BaseB::BaseB (int dim,int n,Tableau<CoordonneeB > v1) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(v1(3).Dimension()); v(3) = v1(3);
|
|
case 2: v(2).Change_dim(v1(2).Dimension()); v(2) = v1(2);
|
|
case 1: v(1).Change_dim(v1(1).Dimension()); v(1) = v1(1);
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseB::BaseB (int dim,int n)";
|
|
Sortie(1);
|
|
};
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// surcharge de l'affectation
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseB & BaseB::operator = (const BaseB & aB)
|
|
{ dimension = aB.dimension;
|
|
nb_vecteur = aB.nb_vecteur;
|
|
// on affecte directement
|
|
v = aB.v; // il y aura redimentionnement automatique
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
v_sans.Change_taille(aB.v_sans.Taille());
|
|
Meme_place_coordonnee();
|
|
return *this;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
const CoordonneeB & BaseB::operator () (int i) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((i < 1) || (i > dimension))
|
|
{ cout << "\nErreur : composante inexistante !\n";
|
|
cout << " i = " << i << '\n';
|
|
cout << "BaseB::OPERATOR() (int ) const \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
return v(i);
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
CoordonneeB& BaseB::CoordoB(int i) // retourne le i ieme vecteurs en I/O
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((i < 1) || (i > dimension))
|
|
{ cout << "\nErreur : composante inexistante !\n";
|
|
cout << " i = " << i << '\n';
|
|
cout << "BaseB::CoordoB(i) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
return v(i);
|
|
};
|
|
|
|
// acces contrôlé à des vecteurs sans variance: uniquement en lecture
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
const Coordonnee & BaseB::Coordo(int i) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((i < 1) || (i > dimension))
|
|
{ cout << "\nErreur : composante inexistante !\n";
|
|
cout << " i = " << i << '\n';
|
|
cout << "BaseB::Coordo(int i) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// on est obligé d'appliquer Meme_place, car comme on peut accèder directement à v,
|
|
// et que via les opérations sur v, on peut changer son pointeur!!
|
|
// dans le cas où c'est déjà à la même place, il n'y a aucune action (juste un test)
|
|
// donc normalement ce n'est pas "trop" couteux, en tout cas c'est moins que de créer
|
|
// un coordonnee intermédiaire.
|
|
v_sans(i).Meme_place(v(i));
|
|
return v_sans(i);
|
|
};
|
|
|
|
// affichage à l'écran des infos
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseB::Affiche() const
|
|
{ // écriture du type, de la dimension et du nombre de vecteur
|
|
cout << "\n BaseB dimension: " << dimension << " nombre de vecteurs : " << nb_vecteur << " ";
|
|
// les data
|
|
cout << "\n les vecteurs de la base: ";
|
|
v.Sortir_sansRet(cout);
|
|
|
|
};
|
|
|
|
// changement de base
|
|
// on suppose que this(i) correspond aux coordonnées dans un premier repère I_a
|
|
// IpH correspond aux coordonnées dans I_a d'un nouveau repère
|
|
// en sortie: apB(i) correspond aux coordonnées dans ipB de this(i)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseB::Change_repere(const BaseH& IpH, BaseB& apB)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dimension != IpH.Dimension())
|
|
{ cout << "\nErreur : dimension de this "<< dimension
|
|
<< " est differente de celle de la nouvelle base " << IpH.Dimension()
|
|
<< " !\n";
|
|
cout << "BaseB::Change_repere(... \n";
|
|
Sortie(1);
|
|
};
|
|
if (nb_vecteur != apB.NbVecteur())
|
|
{ cout << "\nErreur : le nombre de vecteur de this "<< nb_vecteur
|
|
<< " est different de celui de la base que l'on cherche a calculer " << apB.NbVecteur()
|
|
<< " !\n";
|
|
cout << "BaseB::Change_repere(... \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
for (int i=1;i<= nb_vecteur;i++)
|
|
for (int j=1;j<=dimension;j++)
|
|
apB.CoordoB(i)(j) = v(i) * IpH(j);
|
|
};
|
|
|
|
// affectation trans_variance: utile pour une recopie de mêmes valeurs
|
|
// mais ici l'appel est explicite donc a priori on sait ce que l'on fait
|
|
// il n'y a pas de redimensionnement, donc la dimension et le nombre des vecteurs
|
|
// doivent être identiques
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseB::Affectation_trans_variance(const BaseH& aH)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((dimension != aH.Dimension()) || (nb_vecteur != aH.NbVecteur()))
|
|
{ cout << "\nErreur : dimension de this "<< dimension
|
|
<< " difference de celle de la base a affecter: " << aH.Dimension()
|
|
<< " ou nombre de vecteur de this " << nb_vecteur
|
|
<< " different de celle de la base a affecter: " << aH.NbVecteur()
|
|
<< " !\n";
|
|
cout << "BaseB::Affectation_trans_variance(... \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// on affecte directement
|
|
for (int i=1;i<=nb_vecteur;i++)
|
|
v_sans(i) = aH.Coordo(i); // pas de redimensionnent car même dimension et même nombre
|
|
//return *this;
|
|
};
|
|
|
|
|
|
// la méthode qui suit a pour objectif de calcul les vecteurs de la base naturelle finale
|
|
// associée à un paramétrage cartésien initiale
|
|
// donc soit connue une base naturelle \hat g_i associée à un paramétrage theta^i
|
|
// \hat g_i est représenté par les vecteurs de this, et représente la situation déformée
|
|
// soit la base duale de g_i : gammaH^i = g^i c-à-d la base duale en situation non déformée
|
|
// maintenant: si on considère les coordonnées initiales X^i on cherche
|
|
// les vecteurs des bases naturelles associées à X^i avant g'_i et après déformation \hat g'_i
|
|
// on a (cf. annexe dans le document théorique d'Herezh)
|
|
// g'_i = I_i par définition et
|
|
// \hat g'_i = (\vec I_i . \vec g^j) ~\hat g_j c-a-d
|
|
// \hat g'_i = gammaH^j(i) * (*this)(j)
|
|
// c'est le résultat de la méthode qui suit
|
|
|
|
// si
|
|
|
|
// changement de base: retourne apB(a) = (*this)(j) . gamma^j_a
|
|
// il faut que le nombre de vecteur de apB soit identique à la dimension de gammaH
|
|
// et que le nombre de vecteur de gammaH soit identique au nombre de vecteur de this
|
|
// et que la dimension de apB soit identique à la dimension de this
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseB::ChangeBase_theta_vers_Xi(BaseB& apB, const BaseH& gammaH)
|
|
{ int apB_nbVecteur = apB.NbVecteur();
|
|
#ifdef MISE_AU_POINT
|
|
if (apB.Dimension()!= dimension)
|
|
{ cout << "\n erreur en changement de base , la dimension des vecteurs de la base resultante "
|
|
<< apB.Dimension() << " est differente de celle initiale " << dimension
|
|
<< "\n BaseB::ChangeBase_theta_vers_Xi(BaseB& apB, const BaseH& gammaH)";
|
|
Sortie(1);
|
|
};
|
|
if (gammaH.NbVecteur()!= nb_vecteur)
|
|
{ cout << "\n erreur en changement de base , le nombre de vecteur de this et gammaH est different"
|
|
<< "\n BaseB::ChangeBase_theta_vers_Xi(BaseB& apB, const BaseH& gammaH)";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
for (int a=1; a<= apB_nbVecteur; a++)
|
|
{apB.CoordoB(a).Zero();
|
|
for (int j=1;j<= nb_vecteur; j++)
|
|
apB.CoordoB(a) += gammaH(j)(a) * v(j);
|
|
};
|
|
};
|
|
|
|
|
|
// calcul des composantes de coordonnées locales dans la base absolue
|
|
// en argument : A -> une reference sur les coordonnées résultat qui peut avoir une dimension
|
|
// différente des coordonnées locale, retour d'une reference sur A
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Coordonnee & BaseB::BaseAbsolue(Coordonnee & A,const CoordonneeH & B) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (B.Dimension()!= nb_vecteur)
|
|
{ cout << "\n erreur, le nombre de vecteur de la base: " << nb_vecteur << ", est different du nombre de coordonnee "
|
|
<< " de B : "<< B.Dimension()
|
|
<< "\n BaseB::BaseAbsolue(Coordonnee & A,const CoordonneeH & B)";
|
|
Sortie(1);
|
|
};
|
|
if (A.Dimension()!= dimension )
|
|
{ cout << "\n erreur, la dimension de A : " << A.Dimension() << ", est differente de la dimension "
|
|
<< " des vecteurs de la base : "<< dimension
|
|
<< "\n BaseB::BaseAbsolue(Coordonnee & A,const CoordonneeH & B)";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
A.Zero();
|
|
for (int i=1; i<=nb_vecteur;i++)
|
|
A += B(i) * v_sans(i);
|
|
return A;
|
|
};
|
|
|
|
// une partie des vecteurs de B est affectée à this,
|
|
// si this contient plus de vecteur que B, les autres vecteurs sont mis à 0 ou non
|
|
// suivant la valeur de plusZero: = false: les autres vecteurs sont inchangées,
|
|
// plusZero = true: les autres vecteurs sont mis à 0
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseB::Affectation_partielle(int nb_vecteur_a_affecter, const BaseB & B,bool plusZero)
|
|
{ // on commence par vérifier si tout est ok (en débug)
|
|
#ifdef MISE_AU_POINT
|
|
if ((nb_vecteur_a_affecter > nb_vecteur) || (nb_vecteur_a_affecter > B.nb_vecteur))
|
|
{cout << "\n*** affectation partielle impossible: nb_vecteur_a_affecter = "<< nb_vecteur_a_affecter
|
|
<< " et nb_vecteur = " << nb_vecteur << " et B.nb_vecteur = " << B.nb_vecteur
|
|
<< "\n BaseB::Affectation_partielle(int nb_vecteur_a_affecter,... ";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
switch (nb_vecteur_a_affecter)
|
|
{ case 3: v(3) = B.v(3);
|
|
case 2: v(2) = B.v(2);
|
|
case 1: v(1) = B.v(1);
|
|
};
|
|
if ((plusZero) && (nb_vecteur_a_affecter < nb_vecteur))
|
|
{ switch (nb_vecteur)
|
|
{ case 3: {switch (nb_vecteur_a_affecter) { case 1: v(2).Zero(); case 2: v(3).Zero();}break;}
|
|
case 2: {switch (nb_vecteur_a_affecter) {case 1: v(2).Zero();} break;}
|
|
};
|
|
};
|
|
|
|
};
|
|
|
|
// surcharge de l'operateur de lecture
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
istream & operator >> ( istream & ent, BaseB & ba)
|
|
{ // lecture du type et vérification
|
|
string nomtype; ent >> nomtype;
|
|
if (nomtype != "BaseB")
|
|
{ Sortie(1);
|
|
return ent;
|
|
}
|
|
// lecture de la dimension et du nombre de vecteur
|
|
ent >> ba.dimension >> ba.nb_vecteur ;
|
|
// les data
|
|
ba.v.Entree(ent);
|
|
// on met à la même place les v_sans que les v
|
|
ba.v_sans.Change_taille(ba.v.Taille());
|
|
ba.Meme_place_coordonnee();
|
|
return ent;
|
|
};
|
|
|
|
// surcharge de l'operateur d'ecriture
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
ostream & operator << ( ostream & sort,const BaseB & ba)
|
|
{ // écriture du type, de la dimension et du nombre de vecteur
|
|
sort << "BaseB " << ba.dimension << " " << ba.nb_vecteur << " ";
|
|
// les data
|
|
ba.v.Sortir_sansRet(sort);
|
|
// sort << ba.v;
|
|
return sort;
|
|
};
|
|
|
|
//----------------------------- fonctions internes protégées ---------------
|
|
// on met à la même place les v_sans que les v
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseB::Meme_place_coordonnee()
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v_sans(3).Meme_place(v(3));
|
|
case 2: v_sans(2).Meme_place(v(2));
|
|
case 1: v_sans(1).Meme_place(v(1));
|
|
};
|
|
};
|
|
|
|
|
|
//===============================================================
|
|
// Les base duales
|
|
//===============================================================
|
|
|
|
|
|
// CONSTRUCTEURS :
|
|
// par defaut, defini la Base absolu en dimension 3
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::BaseH () :
|
|
dimension(3), nb_vecteur(3), v(3) , v_sans(3)
|
|
{ v(1).Change_dim(3); v(1)(1) = 1.;
|
|
v(2).Change_dim(3); v(2)(2) = 1.;
|
|
v(3).Change_dim(3); v(3)(3) = 1.;
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// defini la Base absolu en dimension dim
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::BaseH (int dim) :
|
|
dimension(dim) , nb_vecteur(dim), v(dim), v_sans(dim)
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(dimension); v(3)(3) = 1.;
|
|
case 2: v(2).Change_dim(dimension); v(2)(2) = 1.;
|
|
case 1: v(1).Change_dim(dimension); v(1)(1) = 1.;
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseH::BaseH (int dim)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// defini une Base relative v1(dim)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::BaseH (int dim,const Tableau<CoordonneeH >& v1) :
|
|
dimension(dim) ,nb_vecteur(v1.Taille()), v(v1.Taille()), v_sans(v1.Taille())
|
|
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(v1(3).Dimension()); v(3) = v1(3);
|
|
case 2: v(2).Change_dim(v1(2).Dimension()); v(2) = v1(2);
|
|
case 1: v(1).Change_dim(v1(1).Dimension()); v(1) = v1(1);
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseH::BaseH (int dim,const Tableau<CoordonneeH > & v1)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// defini une Base locale absolu en dimension dim de n vecteurs
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::BaseH (int dim,int n) :
|
|
dimension(dim) , nb_vecteur(n), v(n), v_sans(n)
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(dimension); v(3)(3) = 1.;
|
|
case 2: v(2).Change_dim(dimension); v(2)(2) = 1.;
|
|
case 1: v(1).Change_dim(dimension); v(1)(1) = 1.;
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseH::BaseH (int dim,int n)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// idem dessus mais avec toutes les composantes = s
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::BaseH (int dim,int n,double s) :
|
|
dimension(dim) , nb_vecteur(n), v(n) , v_sans(n)
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(dimension);
|
|
case 2: v(2).Change_dim(dimension);
|
|
case 1: v(1).Change_dim(dimension);
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseH::BaseH (int dim,int n,double s)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
if (s != 0.)
|
|
for (int i=1; i<=nb_vecteur;i++)
|
|
for (int j =1; j<= dimension; j++)
|
|
v(i)(j) = s;
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// DESTRUCTEUR :
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::~BaseH ()
|
|
{ };
|
|
|
|
// constructeur de copie
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::BaseH (const BaseH & b) :
|
|
dimension(b.dimension) , nb_vecteur(b.nb_vecteur), v(b.v), v_sans(b.v_sans)
|
|
{ // on va définir les v_sans associé, stocké au même endroit
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
} ;
|
|
|
|
// defini une Base relative v1(dim) de n vecteurs
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH::BaseH (int dim,int n,const Tableau<CoordonneeH > & v1) :
|
|
dimension(dim) , nb_vecteur(n), v(n), v_sans(n)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (nb_vecteur > v1.Taille())
|
|
{ cout << "\nErreur : la taille relative est > a la taille du tableau !\n";
|
|
cout << " nb_vevteur = " << nb_vecteur
|
|
<< " v1.Taille = " << v1.Taille() << '\n';
|
|
cout << "BaseH::BaseH (int dim,int n,Tableau<CoordonneeH > v1) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
switch (nb_vecteur)
|
|
{ case 3: v(3).Change_dim(v1(3).Dimension()); v(3) = v1(3);
|
|
case 2: v(2).Change_dim(v1(2).Dimension()); v(2) = v1(2);
|
|
case 1: v(1).Change_dim(v1(1).Dimension()); v(1) = v1(1);
|
|
break;
|
|
default:
|
|
{ cout << "\n ** erreur en dimensionnement d'une base, le nombre de vecteur = 0"
|
|
<< "\n BaseH::BaseH (int dim,int n)";
|
|
Sortie(1);
|
|
}
|
|
};
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
Meme_place_coordonnee();
|
|
};
|
|
|
|
// surcharge de l'affectation
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
BaseH & BaseH::operator = (const BaseH & aH)
|
|
{ dimension = aH.dimension;
|
|
nb_vecteur = aH.nb_vecteur;
|
|
// on affecte directement
|
|
v = aH.v; // il y aura redimentionnement automatique
|
|
// on va définir les v_sans associé, stocké au même endroit
|
|
v_sans.Change_taille(aH.v_sans.Taille());
|
|
Meme_place_coordonnee();
|
|
return *this;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
const CoordonneeH & BaseH::operator () (int i) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((i < 1) || (i > dimension))
|
|
{ cout << "\nErreur : composante inexistante !\n";
|
|
cout << " i = " << i << '\n';
|
|
cout << "BaseH::OPERATOR() (int i) const \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
return v(i);
|
|
};
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
CoordonneeH& BaseH::CoordoH(int i) // retourne le i ieme vecteurs en I/0
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((i < 1) || (i > dimension))
|
|
{ cout << "\nErreur : composante inexistante !\n";
|
|
cout << " i = " << i << '\n';
|
|
cout << "BaseH::CoordoH(i) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
return v(i);
|
|
};
|
|
|
|
// acces contrôlé à des vecteurs sans variance: uniquement en lecture
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
const Coordonnee & BaseH::Coordo(int i) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((i < 1) || (i > dimension))
|
|
{ cout << "\nErreur : composante inexistante !\n";
|
|
cout << " i = " << i << '\n';
|
|
cout << "BaseH::Coordo(int i) \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// on est obligé d'appliquer Meme_place, car comme on peut accèder directement à v,
|
|
// et que via les opérations sur v, on peut changer son pointeur!!
|
|
// dans le cas où c'est déjà à la même place, il n'y a aucune action (juste un test)
|
|
// donc normalement ce n'est pas "trop" couteux, en tout cas c'est moins que de créer
|
|
// un coordonnee intermédiaire.
|
|
v_sans(i).Meme_place(v(i));
|
|
return v_sans(i);
|
|
};
|
|
|
|
// affectation trans_variance: utile pour une recopie de mêmes valeurs
|
|
// mais ici l'appel est explicite donc a priori on sait ce que l'on fait
|
|
// il n'y a pas de redimensionnement, donc la dimension et le nombre des vecteurs
|
|
// doivent être identiques
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseH::Affectation_trans_variance(const BaseB& aB)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ((dimension != aB.Dimension()) || (nb_vecteur != aB.NbVecteur()))
|
|
{ cout << "\nErreur : dimension de this "<< dimension
|
|
<< " difference de celle de la base a affecter: " << aB.Dimension()
|
|
<< " ou nombre de vecteur de this " << nb_vecteur
|
|
<< " different de celle de la base a affecter: " << aB.NbVecteur()
|
|
<< " !\n";
|
|
cout << "BaseH::Affectation_trans_variance(... \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// on affecte directement
|
|
for (int i=1;i<=nb_vecteur;i++)
|
|
v_sans(i) = aB.Coordo(i); // pas de redimensionnent car même dimension et même nombre
|
|
//return *this;
|
|
};
|
|
|
|
|
|
// affichage à l'écran des infos
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseH::Affiche() const
|
|
{ // écriture du type, de la dimension et du nombre de vecteur
|
|
cout << "\n BaseH dimension: " << dimension << " nombre de vecteurs : " << nb_vecteur << " ";
|
|
// les data
|
|
cout << "\n les vecteurs de la base: ";
|
|
v.Sortir_sansRet(cout);
|
|
|
|
};
|
|
|
|
// changement de base
|
|
// on suppose que this(i) correspond aux coordonnées dans un premier repère I_a
|
|
// IpB correspond aux coordonnées dans I_a d'un nouveau repère
|
|
// en sortie: apH(i) correspond aux coordonnées dans ipH de this(i)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseH::Change_repere(const BaseB& IpB, BaseH& apH)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (dimension != IpB.Dimension())
|
|
{ cout << "\nErreur : dimension de this "<< dimension
|
|
<< " est differente de celle de la nouvelle base " << IpB.Dimension()
|
|
<< " !\n";
|
|
cout << "BaseH::Change_repere(... \n";
|
|
Sortie(1);
|
|
};
|
|
if (nb_vecteur != apH.NbVecteur())
|
|
{ cout << "\nErreur : le nombre de vecteur de this "<< nb_vecteur
|
|
<< " est different de celui de la base que l'on cherche a calculer " << apH.NbVecteur()
|
|
<< " !\n";
|
|
cout << "BaseH::Change_repere(... \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
for (int i=1;i<= nb_vecteur;i++)
|
|
for (int j=1;j<=dimension;j++)
|
|
apH.CoordoH(i)(j) = v(i) * IpB(j);
|
|
};
|
|
|
|
// la méthode qui suit a pour objectif de calcul les vecteurs de la base naturelle finale
|
|
// associée à un paramétrage cartésien initiale
|
|
// donc soit connue une base duale \hat g^i associée à un paramétrage theta^i
|
|
// \hat g^i est représenté par les vecteurs de this, et représente la situation déformée
|
|
// soit la base naturel de g_i : betaB_i = g_i c-à-d la base naturelle en situation non déformée
|
|
// maintenant: si on considère les coordonnées initiales X^i on cherche
|
|
// les vecteurs des bases duales associées à X^i avant g'^i et après déformation \hat g'^i
|
|
// on a (cf. annexe dans le document théorique d'Herezh)
|
|
// g'^i = g'_i = I_i = I^i par définition et
|
|
// \hat g'^i = (\vec I_i . \vec g_j) ~\hat g^j c-a-d
|
|
// \hat g'^i = betaB^j(i) * (*this)(j)
|
|
// c'est le résultat de la méthode qui suit
|
|
|
|
// changement de base: retourne apH(a) = (*this)(j) . beta_j^a
|
|
// il faut que le nombre de vecteur de apH soit identique à la dimension de betaB
|
|
// et que le nombre de vecteur de betaB soit identique au nombre de vecteur de this
|
|
// et que la dimension de apB soit identique à la dimension de this
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseH::ChangeBase_theta_vers_Xi(BaseH& apH, const BaseB& betaB)
|
|
{ int apH_nbVecteur = apH.NbVecteur();
|
|
#ifdef MISE_AU_POINT
|
|
if (apH.Dimension()!= dimension)
|
|
{ cout << "\n erreur en changement de base , la dimension des vecteurs de la base resultante "
|
|
<< apH.Dimension() << " est differente de celle initiale " << dimension
|
|
<< "\n BaseH::ChangeBase_theta_vers_Xi(BaseH& apH, const BaseB& gammaB)";
|
|
Sortie(1);
|
|
};
|
|
if (betaB.NbVecteur()!= nb_vecteur)
|
|
{ cout << "\n erreur en changement de base , le nombre de vecteur de this et betaB est different"
|
|
<< "\n BaseH::ChangeBase_theta_vers_Xi(BaseB& apH, const BaseH& betaB)";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
for (int a=1; a<= apH_nbVecteur; a++)
|
|
{apH.CoordoH(a).Zero();
|
|
for (int j=1;j<= nb_vecteur; j++)
|
|
apH.CoordoH(a) += betaB(j)(a) * v(j);
|
|
};
|
|
};
|
|
|
|
|
|
// calcul des composantes de coordonnées locales dans la base absolue
|
|
// en argument : A -> une reference sur les coordonnées résultat qui peut avoir une dimension
|
|
// différente des coordonnées locale, retour d'une reference sur A
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Coordonnee & BaseH::BaseAbsolue(Coordonnee & A,const CoordonneeB & B) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (B.Dimension()!= nb_vecteur)
|
|
{ cout << "\n erreur, le nombre de vecteur de la base: " << nb_vecteur << ", est different du nombre de coordonnee "
|
|
<< " de B : "<< B.Dimension()
|
|
<< "\n BaseH::BaseAbsolue(Coordonnee & A,const CoordonneeB & B)";
|
|
Sortie(1);
|
|
};
|
|
if (A.Dimension()!= dimension )
|
|
{ cout << "\n erreur, la dimension de A : " << A.Dimension() << ", est differente de la dimension "
|
|
<< " des vecteurs de la base : "<< dimension
|
|
<< "\n BaseH::BaseAbsolue(Coordonnee & A,const CoordonneeB & B)";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
A.Zero();
|
|
for (int i=1; i<=nb_vecteur;i++)
|
|
A += B(i) * v_sans(i);
|
|
return A;
|
|
};
|
|
|
|
// une partie des vecteurs de B est affectée à this,
|
|
// si this contient plus de vecteur que B, les autres vecteurs sont mis à 0 ou non
|
|
// suivant la valeur de plusZero: = false: les autres vecteurs sont inchangées,
|
|
// plusZero = true: les autres vecteurs sont mis à 0
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseH::Affectation_partielle(int nb_vecteur_a_affecter, const BaseH & B,bool plusZero)
|
|
{ // on commence par vérifier si tout est ok (en débug)
|
|
#ifdef MISE_AU_POINT
|
|
if ((nb_vecteur_a_affecter > nb_vecteur) || (nb_vecteur_a_affecter > B.nb_vecteur))
|
|
{cout << "\n*** affectation partielle impossible: nb_vecteur_a_affecter = "<< nb_vecteur_a_affecter
|
|
<< " et nb_vecteur = " << nb_vecteur << " et B.nb_vecteur = " << B.nb_vecteur
|
|
<< "\n BaseH::Affectation_partielle(int nb_vecteur_a_affecter,... ";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
switch (nb_vecteur_a_affecter)
|
|
{ case 3: v(3) = B.v(3);
|
|
case 2: v(2) = B.v(2);
|
|
case 1: v(1) = B.v(1);
|
|
};
|
|
if ((plusZero) && (nb_vecteur_a_affecter < nb_vecteur))
|
|
{ switch (nb_vecteur)
|
|
{ case 3: {switch (nb_vecteur_a_affecter) { case 1: v(2).Zero(); case 2: v(3).Zero();}break;}
|
|
case 2: {switch (nb_vecteur_a_affecter) {case 1: v(2).Zero();} break;}
|
|
};
|
|
};
|
|
|
|
};
|
|
|
|
// surcharge de l'operateur de lecture
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
istream & operator >> ( istream & ent, BaseH & ba)
|
|
{ // lecture du type et vérification
|
|
string nomtype; ent >> nomtype;
|
|
if (nomtype != "BaseH")
|
|
{ Sortie(1);
|
|
return ent;
|
|
}
|
|
// lecture de la dimension et du nombre de vecteur
|
|
ent >> ba.dimension >> ba.nb_vecteur ;
|
|
// on met à la même place les v_sans que les v
|
|
ba.v_sans.Change_taille(ba.v.Taille());
|
|
ba.Meme_place_coordonnee();
|
|
ent >> ba.v;
|
|
return ent;
|
|
};
|
|
|
|
// surcharge de l'operateur d'ecriture
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
ostream & operator << ( ostream & sort,const BaseH & ba)
|
|
{ // écriture du type, de la dimension et du nombre de vecteur
|
|
sort << "BaseH " << ba.dimension << " " << ba.nb_vecteur << " ";
|
|
// les data
|
|
// ba.v.Sortir_sansRet(sort);
|
|
sort << ba.v;
|
|
return sort;
|
|
};
|
|
|
|
//----------------------------- fonctions internes protégées ---------------
|
|
// on met à la même place les v_sans que les v
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void BaseH::Meme_place_coordonnee()
|
|
{ switch (nb_vecteur)
|
|
{ case 3: v_sans(3).Meme_place(v(3));
|
|
case 2: v_sans(2).Meme_place(v(2));
|
|
case 1: v_sans(1).Meme_place(v(1));
|
|
};
|
|
};
|
|
|
|
|
|
|
|
#endif
|