// 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) . // // 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 . // // For more information, please consult: . //#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 & 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 & 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 & 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 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& 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 & 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 & 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 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