// 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 "Tenseur2.h" #include "ConstMath.h" #include "MathUtil.h" #include "Util.h" #ifndef Tenseur2_H_deja_inclus // variables globales // initialisation dans EnteteTenseur.h , utilisé dans le progr principal //----------------------------------------------------------------------- // cas des composantes deux fois contravariantes non symetriques // pour les differencier la dimension = -2 //----------------------------------------------------------------------- // --- gestion de changement d'index ---- #ifndef MISE_AU_POINT inline #endif Tenseur_ns2HH::ChangementIndex::ChangementIndex() : idx_i(4),idx_j(4),odVect(2) { idx_i(1)=1;idx_i(2)=2; idx_j(1)=1;idx_j(2)=2; idx_i(3)=2;idx_i(4)=1; idx_j(3)=1;idx_j(4)=2; odVect(1,1)=1;odVect(1,2)=4; odVect(2,1)=3;odVect(2,2)=2; }; #ifndef MISE_AU_POINT inline #endif Tenseur_ns2HH::Tenseur_ns2HH() : ipointe() // par defaut { dimension = -2; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille t[0] = 0.; t[1] = 0.; t[2] = 0.;t[3] = 0.; }; // initialisation de toutes les composantes a une meme valeur #ifndef MISE_AU_POINT inline #endif Tenseur_ns2HH::Tenseur_ns2HH( const double val) : ipointe() { dimension = -2; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille t[0] =val; t[1] =val; t[2] =val; t[3] =val; }; // initialisation avec 4 valeurs differentes #ifndef MISE_AU_POINT inline #endif Tenseur_ns2HH::Tenseur_ns2HH ( const double val1, const double val2, const double val3, const double val4) : ipointe() { dimension = -2; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille t[0] =val1; t[1] =val2; t[2] =val3; t[3] = val4; }; // constructeur a partir d'une instance non differenciee #ifndef MISE_AU_POINT inline #endif Tenseur_ns2HH::Tenseur_ns2HH ( const TenseurHH & B) : ipointe() { this->dimension = -2 ; #ifdef MISE_AU_POINT if (Abs(B.dimension) != 2) { cout << "\n erreur de dimension, elle devrait etre = 2 ou -2 "; Message(2,"Tenseur_ns2HH::Tenseur_ns2HH( etc.."); } #endif listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille if (B.dimension == -2) // cas d'un tenseur non symétrique { this->t[0] = B.t[0]; this->t[1] = B.t[1]; this->t[2] = B.t[2]; this->t[3] = B.t[3]; } else // cas d'un tenseur symétrique { Tenseur2HH& C = *((Tenseur2HH*) & B); t[0] = C.t[0];t[1] = C.t[2]; t[2] = C.t[2];t[3] = C.t[1]; }; }; // constructeur de copie #ifndef MISE_AU_POINT inline #endif Tenseur_ns2HH::Tenseur_ns2HH ( const Tenseur_ns2HH & B): ipointe() { this->dimension = B.dimension; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille this->t[0] = B.t[0]; this->t[1] = B.t[1]; this->t[2] = B.t[2]; this->t[3] = B.t[3]; }; #ifndef MISE_AU_POINT inline #endif Tenseur_ns2HH::~Tenseur_ns2HH() {//if(listdouble4.end() != listdouble4.begin()) // si la liste n'est pas vide listdouble4.erase(ipointe);} ; // suppression de l'élément de la liste // initialise toutes les composantes à val #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2HH::Inita(double val) { t[0] =val; t[1] =val; t[2] =val;t[3] =val;}; // operations #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::operator + ( const TenseurHH & B) const { TenseurHH * ptr; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator + ( etc.."); #endif ptr = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon( ptr); // ajout d'un tenseur intermediaire for (int i = 0; i<=2; i++) (*ptr).t[i] = this->t[i] + B.t[i]; //somme des donnees (*ptr).t[3] = this->t[3] + B(1,2); //somme des donnees if (!diffpetit((*ptr).t[3],(*ptr).t[2],(*ptr).MaxiComposante())) // cas ou l'on est redevenue symetrique { TenseurHH * ptrr; ptrr = new Tenseur2HH; LesMaillonsHH::NouveauMaillon( ptrr); // ajout d'un tenseur intermediaire for (int i=0;i<=2;i++) ptrr->t[i] = ptr->t[i]; return (*ptrr); } else return (*ptr) ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2HH::operator += ( const TenseurHH & B) { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator += ( etc.."); #endif for (int i = 0; i<=2; i++) this->t[i] += B.t[i]; this->t[3] += B(1,2); }; #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::operator - () const { TenseurHH * ptr; ptr = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon( ptr); // ajout d'un tenseur intermediaire for (int i = 0; i<=3; i++) (*ptr).t[i] = - this->t[i]; return (*ptr) ;}; #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::operator - ( const TenseurHH & B) const { TenseurHH * ptr; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator + ( etc.."); #endif ptr = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon( ptr); // ajout d'un tenseur intermediaire for (int i = 0; i<=2; i++) (*ptr).t[i] = this->t[i] - B.t[i]; (*ptr).t[3] = this->t[3] - B(1,2); if (!diffpetit((*ptr).t[3],(*ptr).t[2],(*ptr).MaxiComposante())) // cas ou l'on est redevenue symetrique { TenseurHH * ptrr; ptrr = new Tenseur2HH; LesMaillonsHH::NouveauMaillon( ptrr); // ajout d'un tenseur intermediaire for (int i=0;i<=2;i++) ptrr->t[i] = ptr->t[i]; return (*ptrr); } else return (*ptr) ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2HH::operator -= ( const TenseurHH & B) { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator -= ( etc.."); #endif for (int i = 0; i<=2; i++) this->t[i] -= B.t[i]; this->t[3] -= B(1,2); }; #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::operator = ( const TenseurHH & B) { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator = ( etc.."); #endif for (int i = 0; i<=2; i++) this->t[i] = B.t[i]; this->t[3] = B(1,2); LesMaillonsHH::Libere(); // destruction des tenseurs intermediaires return *this; }; //affectation des donnees; #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::operator * ( const double & b) const { TenseurHH * res; res = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire for (int i = 0; i<=3; i++) res->t[i] = this->t[i] * b; //multiplication des donnees return *res ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2HH::operator *= ( const double & b) { for (int i = 0; i<=3; i++) this->t[i] *= b;}; //multiplication des donnees #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::operator / ( const double & b) const { TenseurHH * res; res = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire for (int i = 0; i<=3; i++) res->t[i] = this->t[i] / b; //division des donnees return *res ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2HH::operator /= ( const double & b) { for (int i = 0; i<=3; i++) this->t[i] /= b;}; //division des donnees #ifndef MISE_AU_POINT inline #endif // affectation de B dans this, les données en trop sont ignorées void Tenseur_ns2HH::Affectation_3D_a_2D(const Tenseur_ns3HH & B) { this->t[0] = B.t[0];this->t[1] = B.t[4];this->t[2] = B.t[3];this->t[3] = B.t[1]; }; #ifndef MISE_AU_POINT inline #endif // affectation de B dans this, plusZero = false: les données manquantes sont inchangées, // plusZero = true: les données manquantes sont mises à 0 // si au contraire la dimension de B est plus grande que *this, il y a uniquement affectation // des données possibles void Tenseur_ns2HH::Affectation_trans_dimension(const TenseurHH & B,bool plusZero) { switch (B.Dimension()) {case 2: case -2: *this = B; break; // affectation normale case -3: { const Tenseur_ns3HH & bn = *((Tenseur_ns3HH *) &B); this->Affectation_3D_a_2D(bn); break; } case 3: { const Tenseur_ns3HH bn = B; // on crée un nouveau tenseur transitoire this->Affectation_3D_a_2D(bn); // qui est tout de suite supprimé break; } case 1: { if (plusZero) this->Inita(0.); this->t[0] = B.t[0]; //on affecte le seul terme break; } default: cout << "\n this= " << *this << " B= "; B.Ecriture(cout); Message(3, "erreur d\'affectation, Tenseur2HH::Affectation_trans_dimension( const TenseurHH & B, .."); } }; // produit contracte avec un vecteur #ifndef MISE_AU_POINT inline #endif CoordonneeH Tenseur_ns2HH::operator * ( const CoordonneeB & B) const { #ifdef MISE_AU_POINT if (B.Dimension() != Dabs(dimension)) { cout << "\nErreur : dimensions vecteur tenseur non egales !\n"; cout << " Tenseur_ns2HH::operator *\n"; Sortie(1); }; #endif CoordonneeH v(dimension); v(1) = this->t[0] * B(1) + this->t[3] * B(2); v(2) = this->t[2] * B(1) + this->t[1] * B(2); return v; }; #ifndef MISE_AU_POINT inline #endif TenseurHB & Tenseur_ns2HH::operator * ( const TenseurBB & B) const // produit une fois contracte { TenseurHB * res; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator * ( etc.."); #endif res = new Tenseur2HB; LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0] * B.t[0] + this->t[3] * B.t[2]; res->t[1] = this->t[2] * B(1,2) + this->t[1] * B.t[1]; res->t[2] = this->t[2] * B.t[0] + this->t[1] * B.t[2]; res->t[3] = this->t[0] * B(1,2) + this->t[3] * B.t[1] ; return (*res); }; #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::operator * ( const TenseurBH & B) const // produit une fois contracte { TenseurHH * res; res = new Tenseur_ns2HH; #ifdef MISE_AU_POINT if (B.Dimension() != 2) Message(2,"Tenseur_ns2HH::operator * ( etc.."); #endif LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0] * B.t[0] + this->t[3] * B.t[2]; res->t[1] = this->t[2] * B.t[3] + this->t[1] * B.t[1]; res->t[2] = this->t[2] * B.t[0] + this->t[1] * B.t[2]; res->t[3] = this->t[0] * B.t[3] + this->t[3] * B.t[1]; if (!diffpetit(res->t[2],res->t[3],res->MaxiComposante())) // cas ou l'on retrouve un tenseur symetrique { TenseurHH * ress; ress = new Tenseur2HH; LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire for (int i=0;i<=2;i++) ress->t[i] = res->t[i]; return (*ress); } else return (*res); }; #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2HH::operator && ( const TenseurBB & B) const // produit deux fois contracte { double b; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator && ( etc.."); #endif b = (this->t[0] * B.t[0] + this->t[3] * B.t[2]) + (this->t[2] * B(1,2) + this->t[1] * B.t[1]); return b;}; #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2HH::Det() const // determinant de la matrice des coordonnees { double b; b = this->t[0] * this->t[1] - this->t[2] * this->t[3]; return b;}; // test #ifndef MISE_AU_POINT inline #endif int Tenseur_ns2HH::operator == ( const TenseurHH & B) const { int res = 1; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator == ( etc.."); #endif for (int i = 0; i<=2; i++) if (this->t[i] != B.t[i]) res = 0 ; if (this->t[3] != B(1,2)) res = 0 ; return res; }; #ifndef MISE_AU_POINT inline #endif int Tenseur_ns2HH::operator != ( const TenseurHH & B) const { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2HH::operator != ( etc.."); #endif if ((*this) == B) return 0; else return 1; }; // calcul du tenseur inverse par rapport au produit contracte #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2HH::Inverse() const {TenseurBB * res; res = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire // choix sur la méthode d'inversion switch (ParaGlob::param->ParaAlgoControleActifs().Type_calnum_inversion_metrique()) { case LU_EQUILIBRE: { // on recopie this dans le nouveau tenseur res->t[0] = t[0];res->t[1] = t[1];res->t[2] = t[2];res->t[3] = t[3]; // pour le débug //res->t[0]=3.; res->t[1]=2.;res->t[2]=1.;res->t[3]=1.; // appel de l'inversion Util::Inverse_mat2x2(((Tenseur_ns2BB*) res)->ipointe); } //cout << "\n comp \n "; // res->Ecriture(cout); cout << "\n"; // Sortie(1); break; case CRAMER : // méthode historique { // calcul du determinant double det = this->Det() ; #ifdef MISE_AU_POINT if (Dabs(det) <= ConstMath::trespetit) { cout << "\nErreur : le determinant du tenseur est nul !\n"; cout << "Tenseur_ns2HH::Inverse() \n"; Sortie(1); }; #endif // transposee de la matrice des cofacteurs res->t[0] = this->t[1] / det; res->t[2] = - this->t[2] / det; res->t[1] = this->t[0] / det; res->t[3] = - this->t[3] / det; break; } default: { cout << "\nErreur **** : la methode de resolution de l'inversion de tenseur " << ParaGlob::param->ParaAlgoControleActifs().Type_calnum_inversion_metrique() << " n'est pas implante \n"; cout << "Tenseur_ns2HH::Inverse() \n"; Sortie(1); }; }; // res->Ecriture(cout); // pour le debug return *res; }; #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2HH::Transpose() const { TenseurHH * res; res = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[3]; res->t[3] = this->t[2]; return *res;}; // ---- manipulation d'indice ---- -> création de nouveaux tenseurs #ifndef MISE_AU_POINT inline #endif TenseurBB& Tenseur_ns2HH::Baisse2Indices() const { TenseurBB * res; res = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[2]; res->t[3] = this->t[3]; return *res;}; #ifndef MISE_AU_POINT inline #endif TenseurBH& Tenseur_ns2HH::BaissePremierIndice() const { TenseurBH * res; res = new Tenseur2BH; LesMaillonsBH::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[2]; res->t[3] = this->t[3]; return *res;}; #ifndef MISE_AU_POINT inline #endif TenseurHB& Tenseur_ns2HH::BaisseDernierIndice() const { TenseurHB * res; res = new Tenseur2HB; LesMaillonsHB::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[2]; res->t[3] = this->t[3]; return *res;}; // calcul du maximum en valeur absolu des composantes du tenseur #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2HH::MaxiComposante() const { return DabsMaxiTab(t, 4) ; }; // retourne la composante i,j en lecture et écriture #ifndef MISE_AU_POINT inline #endif double& Tenseur_ns2HH::Coor( const int i, const int j) { #ifdef MISE_AU_POINT if ( ((i!=1)&&(i!=2)) || ((j!=1)&&(j!=2)) ) { cout << "\nErreur : composante inexistante !\n"; cout << " i = " << i << "j = " << j << '\n'; cout << "TenseurBH::Coor(int,int ) \n"; Sortie(1); }; #endif switch (i) { case 1 : { switch (j) { case 1 : return t[0]; break; case 2 : return t[3]; break; default : return t[0]; } break;} case 2 : { switch (j) { case 1 : return t[2]; break; case 2 : return t[1]; break; default : return t[0]; } break; } default : return t[0]; } }; // retourne la composante i,j en lecture uniquement #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2HH::operator () ( const int i, const int j) const { #ifdef MISE_AU_POINT if ( ((i!=1)&&(i!=2)) || ((j!=1)&&(j!=2)) ) { cout << "\nErreur : composante inexistante !\n"; cout << " i = " << i << "j = " << j << '\n'; cout << "TenseurBH::OPERATOR() (int,int ) \n"; Sortie(1); }; #endif switch (i) { case 1 : { switch (j) { case 1 : return t[0]; break; case 2 : return t[3]; break; default : return t[0]; } break;} case 2 : { switch (j) { case 1 : return t[2]; break; case 2 : return t[1]; break; default : return t[0]; } break; } default : return t[0]; } }; // lecture et écriture de données #ifndef MISE_AU_POINT inline #endif istream & Tenseur_ns2HH::Lecture(istream & entree) { // lecture et vérification du type string nom_type; entree >> nom_type; if (nom_type != "Tenseur_ns2HH") { Sortie(1); return entree; } // lecture des coordonnées for (int i = 0; i<= 3; i++) entree >> this->t[i]; return entree; }; #ifndef MISE_AU_POINT inline #endif ostream & Tenseur_ns2HH::Ecriture(ostream & sort) const { // écriture du type sort << "Tenseur_ns2HH "; // puis les datas for (int i = 0; i<= 3; i++) sort << setprecision(ParaGlob::NbdigdoCA()) << this->t[i] << " "; return sort; }; #ifndef MISE_AU_POINT inline #endif // surcharge de l'operator de lecture istream & operator >> (istream & entree, Tenseur_ns2HH & A) { int dim = A.Dimension(); #ifdef MISE_AU_POINT if (dim != -2) A.Message(-2,"operator >> (istream & entree, Tenseur_ns2HH & A)"); #endif // lecture et vérification du type string nom_type; entree >> nom_type; if (nom_type != "Tenseur_ns2HH") { Sortie(1); return entree; } // lecture des coordonnées for (int i = 0; i<=3; i++) entree >> A.t[i]; return entree; }; #ifndef MISE_AU_POINT inline #endif // surcharge de l'operator d'ecriture ostream & operator << (ostream & sort , const Tenseur_ns2HH & A) { //int dim = A.Dimension(); // écriture du type sort << "Tenseur_ns2HH "; // puis les datas for (int i = 0; i<= 3; i++) sort << setprecision(ParaGlob::NbdigdoCA()) << A.t[i] << " "; return sort; }; //-------------------------------------------------------------------- // cas des composantes deux fois covariantes non symetriques // pour les differencier la dimension = -2 //-------------------------------------------------------------------- // --- gestion de changement d'index ---- #ifndef MISE_AU_POINT inline #endif Tenseur_ns2BB::ChangementIndex::ChangementIndex() : idx_i(4),idx_j(4),odVect(2) { idx_i(1)=1;idx_i(2)=2; idx_j(1)=1;idx_j(2)=2; idx_i(3)=2;idx_i(4)=1; idx_j(3)=1;idx_j(4)=2; odVect(1,1)=1;odVect(1,2)=4; odVect(2,1)=3;odVect(2,2)=2; }; #ifndef MISE_AU_POINT inline #endif Tenseur_ns2BB::Tenseur_ns2BB(): ipointe() // par defaut { dimension = -2; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille t[0] = 0.; t[1] = 0.; t[2] = 0.;t[3] = 0.; }; // initialisation de toutes les composantes a une meme valeur #ifndef MISE_AU_POINT inline #endif Tenseur_ns2BB::Tenseur_ns2BB( const double val): ipointe() { dimension = -2; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille t[0] =val; t[1] =val; t[2] =val; t[3] =val; }; // initialisation avec 4 valeurs differentes #ifndef MISE_AU_POINT inline #endif Tenseur_ns2BB::Tenseur_ns2BB ( const double val1, const double val2, const double val3, const double val4) : ipointe() { dimension = -2; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille t[0] =val1; t[1] =val2; t[2] =val3; t[3] = val4; }; // constructeur a partir d'une instance non differenciee #ifndef MISE_AU_POINT inline #endif Tenseur_ns2BB::Tenseur_ns2BB ( const TenseurBB & B): ipointe() { this->dimension = -2 ; #ifdef MISE_AU_POINT if (Abs(B.dimension) != 2) { cout << "\n erreur de dimension, elle devrait etre = 2 ou -2 "; Message(2,"Tenseur_ns2BB::Tenseur_ns2BB( etc.."); } #endif listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille if (B.dimension == -2) // cas d'un tenseur non symétrique { this->t[0] = B.t[0]; this->t[1] = B.t[1]; this->t[2] = B.t[2]; this->t[3] = B.t[3]; } else // cas d'un tenseur symétrique { Tenseur2BB& C = *((Tenseur2BB*) & B); t[0] = C.t[0];t[1] = C.t[2]; t[2] = C.t[2];t[3] = C.t[1]; }; }; // constructeur de copie #ifndef MISE_AU_POINT inline #endif Tenseur_ns2BB::Tenseur_ns2BB ( const Tenseur_ns2BB & B): ipointe() { this->dimension = B.dimension; listdouble4.push_front(Reels4()); // allocation ipointe = listdouble4.begin(); // recup de la position de la maille dans la liste t = (ipointe)->donnees; // recup de la position des datas dans la maille this->t[0] = B.t[0]; this->t[1] = B.t[1]; this->t[2] = B.t[2]; this->t[3] = B.t[3]; }; #ifndef MISE_AU_POINT inline #endif Tenseur_ns2BB::~Tenseur_ns2BB() {//if(listdouble4.end() != listdouble4.begin()) // si la liste n'est pas vide listdouble4.erase(ipointe);} ; // suppression de l'élément de la liste // initialise toutes les composantes à val #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2BB::Inita(double val) { t[0] =val; t[1] =val; t[2] =val;t[3] =val;}; // operations #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::operator + ( const TenseurBB & B) const { TenseurBB * ptr; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator + ( etc.."); #endif ptr = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon( ptr); // ajout d'un tenseur intermediaire for (int i = 0; i<=2; i++) (*ptr).t[i] = this->t[i] + B.t[i]; //somme des donnees (*ptr).t[3] = this->t[3] + B(1,2); //somme des donnees if (!diffpetit((*ptr).t[3],(*ptr).t[2],(*ptr).MaxiComposante())) // cas ou l'on est redevenue symetrique { TenseurBB * ptrr; ptrr = new Tenseur2BB; LesMaillonsBB::NouveauMaillon( ptrr); // ajout d'un tenseur intermediaire for (int i=0;i<=2;i++) ptrr->t[i] = ptr->t[i]; return (*ptrr); } else return (*ptr) ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2BB::operator += ( const TenseurBB & B) { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator += ( etc.."); #endif for (int i = 0; i<=2; i++) this->t[i] += B.t[i]; this->t[3] += B(1,2); }; #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::operator - () const { TenseurBB * ptr; ptr = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon( ptr); // ajout d'un tenseur intermediaire for (int i = 0; i<=3; i++) (*ptr).t[i] = - this->t[i]; return (*ptr) ;}; #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::operator - ( const TenseurBB & B) const { TenseurBB * ptr; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator + ( etc.."); #endif ptr = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon( ptr); // ajout d'un tenseur intermediaire for (int i = 0; i<=2; i++) (*ptr).t[i] = this->t[i] - B.t[i]; (*ptr).t[3] = this->t[3] - B(1,2); if (!diffpetit((*ptr).t[3],(*ptr).t[2],(*ptr).MaxiComposante())) // cas ou l'on est redevenue symetrique { TenseurBB * ptrr; ptrr = new Tenseur2BB; LesMaillonsBB::NouveauMaillon( ptrr); // ajout d'un tenseur intermediaire for (int i=0;i<=2;i++) ptrr->t[i] = ptr->t[i]; return (*ptrr); } else return (*ptr) ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2BB::operator -= ( const TenseurBB & B) { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator -= ( etc.."); #endif for (int i = 0; i<=2; i++) this->t[i] -= B.t[i]; this->t[3] -= B(1,2); }; #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::operator = ( const TenseurBB & B) { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator = ( etc.."); #endif for (int i = 0; i<=2; i++) this->t[i] = B.t[i]; this->t[3] = B(1,2); LesMaillonsBB::Libere(); // destruction des tenseurs intermediaires return *this; }; //affectation des donnees; #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::operator * ( const double & b) const { TenseurBB * res; res = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire for (int i = 0; i<=3; i++) res->t[i] = this->t[i] * b; //multiplication des donnees return *res ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2BB::operator *= ( const double & b) { for (int i = 0; i<=3; i++) this->t[i] *= b;}; //multiplication des donnees #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::operator / ( const double & b) const { TenseurBB * res; res = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire for (int i = 0; i<=3; i++) res->t[i] = this->t[i] / b; //division des donnees return *res ;}; #ifndef MISE_AU_POINT inline #endif void Tenseur_ns2BB::operator /= ( const double & b) { for (int i = 0; i<=3; i++) this->t[i] /= b;}; //division des donnees #ifndef MISE_AU_POINT inline #endif // affectation de B dans this, les données en trop sont ignorées void Tenseur_ns2BB::Affectation_3D_a_2D(const Tenseur_ns3BB & B) { this->t[0] = B.t[0];this->t[1] = B.t[4];this->t[2] = B.t[3];this->t[3] = B.t[1]; }; #ifndef MISE_AU_POINT inline #endif // affectation de B dans this, plusZero = false: les données manquantes sont inchangées, // plusZero = true: les données manquantes sont mises à 0 // si au contraire la dimension de B est plus grande que *this, il y a uniquement affectation // des données possibles void Tenseur_ns2BB::Affectation_trans_dimension(const TenseurBB & B,bool plusZero) { switch (B.Dimension()) {case 2: case -2: *this = B; break; // affectation normale case -3: { const Tenseur_ns3BB & bn = *((Tenseur_ns3BB *) &B); this->Affectation_3D_a_2D(bn); break; } case 3: { const Tenseur_ns3BB bn = B; // on crée un nouveau tenseur transitoire this->Affectation_3D_a_2D(bn); // qui est tout de suite supprimé break; } case 1: { if (plusZero) this->Inita(0.); this->t[0] = B.t[0]; //on affecte le seul terme break; } default: cout << "\n this= " << *this << " B= "; B.Ecriture(cout); Message(3, "erreur d\'affectation, Tenseur2BB::Affectation_trans_dimension( const TenseurBB & B, .."); } }; // produit contracte avec un vecteur #ifndef MISE_AU_POINT inline #endif CoordonneeB Tenseur_ns2BB::operator * ( const CoordonneeH & B) const { #ifdef MISE_AU_POINT if (B.Dimension() != Dabs(dimension)) { cout << "\nErreur : dimensions vecteur tenseur non egales !\n"; cout << " Tenseur_ns2BB::operator *\n"; Sortie(1); }; #endif CoordonneeB v(dimension); v(1) = this->t[0] * B(1) + this->t[3] * B(2); v(2) = this->t[2] * B(1) + this->t[1] * B(2); return v; }; #ifndef MISE_AU_POINT inline #endif TenseurBH & Tenseur_ns2BB::operator * ( const TenseurHH & B) const // produit une fois contracte { TenseurBH * res; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator * ( etc.."); #endif res = new Tenseur2BH; LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0] * B.t[0] + this->t[3] * B.t[2]; res->t[1] = this->t[2] * B(1,2) + this->t[1] * B.t[1]; res->t[2] = this->t[2] * B.t[0] + this->t[1] * B.t[2]; res->t[3] = this->t[0] * B(1,2) + this->t[3] * B.t[1] ; return (*res); }; #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::operator * ( const TenseurHB & B) const // produit une fois contracte { TenseurBB * res; res = new Tenseur_ns2BB; #ifdef MISE_AU_POINT if (B.Dimension() != 2) Message(2,"Tenseur_ns2BB::operator * ( etc.."); #endif LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0] * B.t[0] + this->t[3] * B.t[2]; res->t[1] = this->t[2] * B.t[3] + this->t[1] * B.t[1]; res->t[2] = this->t[2] * B.t[0] + this->t[1] * B.t[2]; res->t[3] = this->t[0] * B.t[3] + this->t[3] * B.t[1]; if (!diffpetit(res->t[2],res->t[3],res->MaxiComposante())) // cas ou l'on retrouve un tenseur symetrique { TenseurBB * ress; ress = new Tenseur2BB; LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire for (int i=0;i<=2;i++) ress->t[i] = res->t[i]; return (*ress); } else return (*res); }; #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2BB::operator && ( const TenseurHH & B) const // produit deux fois contracte { double b; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator && ( etc.."); #endif b = (this->t[0] * B.t[0] + this->t[3] * B.t[2]) + (this->t[2] * B(1,2) + this->t[1] * B.t[1]); return b;}; #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2BB::Det() const // determinant de la matrice des coordonnees { double b; b = this->t[0] * this->t[1] - this->t[2] * this->t[3]; return b;}; // test #ifndef MISE_AU_POINT inline #endif int Tenseur_ns2BB::operator == ( const TenseurBB & B) const { int res = 1; #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator == ( etc.."); #endif for (int i = 0; i<=2; i++) if (this->t[i] != B.t[i]) res = 0 ; if (this->t[3] != B(1,2)) res = 0 ; return res; }; #ifndef MISE_AU_POINT inline #endif int Tenseur_ns2BB::operator != ( const TenseurBB & B) const { #ifdef MISE_AU_POINT if (Dabs(B.Dimension()) != 2) Message(2,"Tenseur_ns2BB::operator != ( etc.."); #endif if ((*this) == B) return 0; else return 1; }; // calcul du tenseur inverse par rapport au produit contracte #ifndef MISE_AU_POINT inline #endif TenseurHH & Tenseur_ns2BB::Inverse() const {TenseurHH * res; res = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire // choix sur la méthode d'inversion switch (ParaGlob::param->ParaAlgoControleActifs().Type_calnum_inversion_metrique()) { case LU_EQUILIBRE: { // on recopie this dans le nouveau tenseur res->t[0] = t[0];res->t[1] = t[1];res->t[2] = t[2];res->t[3] = t[3]; // pour le débug //res->t[0]=3.; res->t[1]=2.;res->t[2]=1.;res->t[3]=1.; // appel de l'inversion Util::Inverse_mat2x2(((Tenseur_ns2HH*) res)->ipointe); } //cout << "\n comp \n "; // res->Ecriture(cout); cout << "\n"; // Sortie(1); break; case CRAMER : // méthode historique { // calcul du determinant double det = this->Det() ; #ifdef MISE_AU_POINT if (Dabs(det) <= ConstMath::trespetit) { cout << "\nErreur : le determinant du tenseur est nul !\n"; cout << "Tenseur_ns2BB::Inverse() \n"; Sortie(1); }; #endif // transposee de la matrice des cofacteurs res->t[0] = this->t[1] / det; res->t[2] = - this->t[2] / det; res->t[1] = this->t[0] / det; res->t[3] = - this->t[3] / det; break; } default: { cout << "\nErreur **** : la methode de resolution de l'inversion de tenseur " << ParaGlob::param->ParaAlgoControleActifs().Type_calnum_inversion_metrique() << " n'est pas implante \n"; cout << "Tenseur_ns2BB::Inverse() \n"; Sortie(1); }; }; // res->Ecriture(cout); // pour le debug return *res; }; #ifndef MISE_AU_POINT inline #endif TenseurBB & Tenseur_ns2BB::Transpose() const { TenseurBB * res; res = new Tenseur_ns2BB; LesMaillonsBB::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[3]; res->t[3] = this->t[2]; return *res;}; // ---- manipulation d'indice ---- -> création de nouveaux tenseurs #ifndef MISE_AU_POINT inline #endif TenseurHH& Tenseur_ns2BB::Monte2Indices() const { TenseurHH * res; res = new Tenseur_ns2HH; LesMaillonsHH::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[2]; res->t[3] = this->t[3]; return *res;}; #ifndef MISE_AU_POINT inline #endif TenseurBH& Tenseur_ns2BB::MonteDernierIndice() const { TenseurBH * res; res = new Tenseur2BH; LesMaillonsBH::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[2]; res->t[3] = this->t[3]; return *res;}; #ifndef MISE_AU_POINT inline #endif TenseurHB& Tenseur_ns2BB::MontePremierIndice() const { TenseurHB * res; res = new Tenseur2HB; LesMaillonsHB::NouveauMaillon(res); // ajout d'un tenseur intermediaire res->t[0] = this->t[0]; res->t[1] = this->t[1]; res->t[2] = this->t[2]; res->t[3] = this->t[3]; return *res;}; // calcul du maximum en valeur absolu des composantes du tenseur #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2BB::MaxiComposante() const { return DabsMaxiTab(t, 4) ; }; // retourne la composante i,j en lecture et écriture #ifndef MISE_AU_POINT inline #endif double& Tenseur_ns2BB::Coor( const int i, const int j) { #ifdef MISE_AU_POINT if ( ((i!=1)&&(i!=2)) || ((j!=1)&&(j!=2)) ) { cout << "\nErreur : composante inexistante !\n"; cout << " i = " << i << "j = " << j << '\n'; cout << "TenseurBH::Coor(int,int ) \n"; Sortie(1); }; #endif switch (i) { case 1 : { switch (j) { case 1 : return t[0]; break; case 2 : return t[3]; break; default : return t[0]; } break;} case 2 : { switch (j) { case 1 : return t[2]; break; case 2 : return t[1]; break; default : return t[0]; } break; } default : return t[0]; } }; // retourne la composante i,j en lecture uniquement #ifndef MISE_AU_POINT inline #endif double Tenseur_ns2BB::operator () ( const int i, const int j) const { #ifdef MISE_AU_POINT if ( ((i!=1)&&(i!=2)) || ((j!=1)&&(j!=2)) ) { cout << "\nErreur : composante inexistante !\n"; cout << " i = " << i << "j = " << j << '\n'; cout << "TenseurBH::OPERATOR() (int,int ) \n"; Sortie(1); }; #endif switch (i) { case 1 : { switch (j) { case 1 : return t[0]; break; case 2 : return t[3]; break; default : return t[0]; } break;} case 2 : { switch (j) { case 1 : return t[2]; break; case 2 : return t[1]; break; default : return t[0]; } break; } default : return t[0]; } }; // lecture et écriture de données #ifndef MISE_AU_POINT inline #endif istream & Tenseur_ns2BB::Lecture(istream & entree) { // lecture et vérification du type string nom_type; entree >> nom_type; if (nom_type != "Tenseur_ns2BB") { Sortie(1); return entree; } // lecture des coordonnées for (int i = 0; i<= 3; i++) entree >> this->t[i]; return entree; }; #ifndef MISE_AU_POINT inline #endif ostream & Tenseur_ns2BB::Ecriture(ostream & sort) const { // écriture du type sort << "Tenseur_ns2BB "; // puis les datas for (int i = 0; i<= 3; i++) sort << setprecision(ParaGlob::NbdigdoCA()) << this->t[i] << " "; return sort; }; #ifndef MISE_AU_POINT inline #endif // surcharge de l'operator de lecture istream & operator >> (istream & entree, Tenseur_ns2BB & A) { int dim = A.Dimension(); #ifdef MISE_AU_POINT if (dim != -2) A.Message(-2,"operator >> (istream & entree, Tenseur_ns2BB & A)"); #endif // lecture et vérification du type string nom_type; entree >> nom_type; if (nom_type != "Tenseur_ns2BB") { Sortie(1); return entree; } // lecture des coordonnées for (int i = 0; i<= 3; i++) entree >> A.t[i]; return entree; }; #ifndef MISE_AU_POINT inline #endif // surcharge de l'operator d'ecriture ostream & operator << (ostream & sort , const Tenseur_ns2BB & A) { //int dim = A.Dimension(); // écriture du type sort << "Tenseur_ns2BB "; // puis les datas for (int i = 0; i<= 3; i++) sort << setprecision(ParaGlob::NbdigdoCA()) << A.t[i] << " "; return sort; }; #endif