Herezh_dev/tenseurs_mai99/Reperes_bases/Base.cc

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