

// 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 <iostream>
using namespace std;  //introduces namespace std
#include "Tenseur1.h"
#include "MathUtil.h"
#include "ConstMath.h"
 
#ifndef  Tenseur1_H_deja_inclus
//================================================================  
//  mixtes HB a une dimension
//================================================================
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HB::Tenseur1HB():  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.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.; };
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HB::Tenseur1HB( const double val):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *t = val; };

#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HB::~Tenseur1HB()
  {  listdouble1.erase(ipointe); // suppression de l'élément de la liste
  //  cout << " appel du destructeur de 1HB \n";
    }; 
// constructeur a partir d'une instance non differenciee  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HB::Tenseur1HB ( const  TenseurHB & B):  
 ipointe()
  { dimension = 1;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::Tenseur1HB  ( etc..");
     #endif
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.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) = *(B.t);
  };     
 
// constructeur de copie  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1HB::Tenseur1HB ( const  Tenseur1HB & B):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.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) = *(B.t);
  };     
// initialise toutes les composantes à val
#ifndef MISE_AU_POINT
  inline 
#endif
void Tenseur1HB::Inita(double val)
  {*(this->t) =val;};   
// operations 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::operator + ( const TenseurHB & B) const 
  {  TenseurHB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator + ( etc..");
     #endif
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) + *(B.t); //somme des données
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HB::operator += ( const TenseurHB & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator += ( etc..");
     #endif
     *(this->t) += *(B.t);}; //somme des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::operator - () const 
  {  TenseurHB * res;
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = - *(this->t); //oppose
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::operator - ( const TenseurHB & B) const 
  {  TenseurHB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator - ( etc..");
     #endif
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) - *(B.t); //soustraction des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HB::operator -= ( const TenseurHB & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator -= ( etc..");
     #endif
    *(this->t) -= *(B.t);}; //soustraction des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::operator = ( const TenseurHB & B) 
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator = ( etc..");
     #endif
    *(this->t) = *(B.t); //affectation des données
    LesMaillonsHB::Libere(); // destruction des tenseurs intermediaires
    return *this; };
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::operator * ( const double & b) const 
  {  TenseurHB * res;
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) * b; //multiplication des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HB::operator *= ( const double & b)
  { *(this->t) *= b;}; //multiplication des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::operator / ( const double & b) const 
  {  TenseurHB * res;
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) / b; //division des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1HB::operator /= ( const double & b)
  { *(this->t) /= b;}; //division des données
  // produit contracte avec un vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
CoordonneeH Tenseur1HB::operator * ( const CoordonneeH & B) const 
  { 
    #ifdef MISE_AU_POINT	 	 
	 if (B.Dimension() != dimension)
	    { cout << "\nErreur : dimensions vecteur tenseur non egales !\n";
		  cout << " Tenseur1HB::operator *\n";
		  Sortie(1);
		};
    #endif
    CoordonneeH v(dimension);
    v(1) = *(this->t) * B(1);
    return v;
  }; 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHH & Tenseur1HB::operator * ( const TenseurHH & B) const 
  {  TenseurHH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator * ( etc..");
     #endif
     res =  new Tenseur1HH;
     LesMaillonsHH::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  }; 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::operator * ( const TenseurHB & B) const 
  {  TenseurHB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator * ( etc..");
     #endif
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  };  
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1HB::operator && ( const TenseurHB & B) const 
  { double result;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator && ( etc..");
     #endif
    result =  (*(this->t)) * (*(B.t)); // contraction
    return result;};
// test
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1HB::operator == ( const TenseurHB & B) const 
  {  
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator == ( etc..");
     #endif
     if (*(this->t) != *(B.t))
         return 0 ;
      else
         return 1;};   
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1HB::operator != ( const TenseurHB & B) const 
  {  
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1HB::operator != ( etc..");
     #endif
     if (*(this->t) == *(B.t))
         return 0 ;
      else
         return 1;};   
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::Inverse() const 
  { TenseurHB * res;
    res =  new Tenseur1HB;
    LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
    #ifdef MISE_AU_POINT
     if  (Dabs(*(this->t)) <= ConstMath::trespetit)
       { cout << "\nErreur : la coordonnee du tenseur est nulle !\n";
         cout << "Tenseur1HB::Inverse() \n";
         Sortie(1);
       };
    #endif    
    *(res->t) = 1./ (*(this->t));
    return *res;
  };                
             
#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 Tenseur1HB::Affectation_trans_dimension(const TenseurHB & B,bool plusZero)
  { // dans tous les cas il suffit de récupérer le premier élément et de l'affecter
    this->t[0] = B.t[0]; //on affecte le seul terme disponible
  };

#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1HB::Trace() const 
  { double result = *(this->t);
    return result; };
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1HB::II() const 
  { double result = (*(this->t)) * (*(this->t)) ;
    return result; };
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1HB::III() const 
  { double result = (*(this->t)) * (*(this->t)) * (*(this->t));
    return result; };
                
    // valeurs propre  dans le vecteur  de retour, classée par ordres "décroissants"
    // cas indique le cas de valeur propre: 
    // quelque soit la dimension: cas = -1, si l'extraction des valeurs propres n'a pas pu se faire
    //                            dans ce cas les valeurs propres de retour sont nulles par défaut
    // dim = 1, cas=1 pour une valeur propre; 
#ifndef MISE_AU_POINT
  inline 
#endif
Coordonnee Tenseur1HB::ValPropre(int& cas) const 
  { Coordonnee ret(1); ret(1)=(*(this->t)); cas = 1;
    return ret;
   };
   
    // idem met en retour la matrice mat contiend par colonne les vecteurs propre
    // elle doit avoir la dimension du tenseur
    // les vecteurs propre sont exprime dans le repere naturel  
#ifndef MISE_AU_POINT
  inline 
#endif
Coordonnee Tenseur1HB::ValPropre(int& cas, Mat_pleine& mat) const 
  { Coordonnee ret(1); ret(1)=(*(this->t)); 
    #ifdef MISE_AU_POINT	 	 
	  if  ((mat.Nb_ligne() != 1) || (mat.Nb_colonne() != 1))
			{ cout << "\nErreur : la matrice en parametre doit etre de dimension " 
			       << 1 << " !\n";
			  cout << "Tenseur1HB::ValPropre( Mat_pleine& mat)  \n";
			  Sortie(1);
			};
    #endif
    mat(1,1)=1.; // vecteur unitaire de l'axe
    cas = 1;
    return ret;
   };

    // ici il s'agit uniquement de calculer les vecteurs propres, les valeurs propres
    // étant déjà connues
    // en retour VP les vecteurs propre : doivent avoir la dimension du tenseur
    // les vecteurs propre sont exprime dans le repere naturel (pour les tenseurs dim 3
    // pour dim=2:le premier vecteur propre est exprime dans le repere naturel 
    //            le second vecteur propre est exprimé dans le repère dual
    // pour dim=1 le vecteur est dans la base naturelle (mais ça importe pas)
    //   en sortie cas = -1 s'il y a eu un problème, dans ce cas, V_P est quelconque
    //             sinon si tout est ok, cas est identique en sortie avec l'entrée
#ifndef MISE_AU_POINT
  inline 
#endif
void Tenseur1HB::VecteursPropres(const Coordonnee& valPropre,int& cas, Tableau <Coordonnee>& V_P) const
  { // on dimensionne en conséquence
    Coordonnee toto(1); // un vecteur nul
    V_P.Change_taille(1,toto); // tableau initialisé à 0
    // ici dans tous les cas il s'agit du vecteur unitaire
    V_P(1)(1)=1.;
    cas = 1;
    return;
   };

#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1HB::Det() const 
  { double result = *(this->t);
    return result; };
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1HB::Transpose() const 
   { TenseurBH * res;
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           
		
//fonctions static définissant le produit tensoriel de deux vecteurs
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::Prod_tensoriel(const CoordonneeB & aB, const CoordonneeH & bH)
  {  TenseurBH * res;
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = aB(1)*bH(1); 
     return *res;}; 
	 
	 // lecture et écriture de données
#ifndef MISE_AU_POINT
  inline 
#endif
istream & Tenseur1BH::Lecture(istream & entree)
  { // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1BH")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*(this->t));
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
ostream & Tenseur1BH::Ecriture(ostream & sort) const 
  { // écriture du type
    sort << "Tenseur1BH ";
    // puis les datas
    sort  << setprecision (ParaGlob::NbdigdoCA()) <<   (*(this->t)) << " ";
     return sort;      
  };

#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator de lecture
istream & operator >> (istream & entree, Tenseur1HB & A)
  { int dim = A.Dimension();
     #ifdef MISE_AU_POINT
       if (dim != 1) A.Message(1,"operator >> (istream & entree, Tenseur1HB & A)");
    #endif
    // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1HB")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*A.t);
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort , const Tenseur1HB & A)
  { // écriture du type
    sort << "Tenseur1HB ";
    // puis les datas
    sort  << setprecision(ParaGlob::NbdigdoCA()) <<   (*A.t) << " ";
     return sort;      
  };
            
//================================================================  
//  mixtes BH a une dimension
//================================================================
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BH::Tenseur1BH():  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.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.; };
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BH::Tenseur1BH( const double val):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.begin(); // recup de la position de la maille dans la liste
    t = &((ipointe)->donnees);    // recup de la position des datas dans la maille
    *t = val; };

#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BH::~Tenseur1BH()
  {  listdouble1.erase(ipointe); // suppression de l'élément de la liste
 //   cout << " appel du destructeur de 1BH \n";
 }; 
// constructeur a partir d'une instance non differenciee  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BH::Tenseur1BH (  const TenseurBH & B) :  
 ipointe()
  { dimension = 1;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::Tenseur1BH ( etc..");
     #endif
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.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) = *(B.t);
  };     
// constructeur de copie  
#ifndef MISE_AU_POINT
  inline 
#endif
Tenseur1BH::Tenseur1BH ( const  Tenseur1BH & B):  
 ipointe()
  { dimension = 1;
    listdouble1.push_front(Reels1());  // allocation
    ipointe = listdouble1.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) = *(B.t);
  };     
// initialise toutes les composantes à val
#ifndef MISE_AU_POINT
  inline 
#endif
void Tenseur1BH::Inita(double val)
  {*(this->t) =val;};   
// operations 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::operator + ( const TenseurBH & B) const 
  {  TenseurBH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator + ( etc..");
     #endif
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) + *(B.t); //somme des données
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BH::operator += ( const TenseurBH & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator += ( etc..");
     #endif
     *(this->t) += *(B.t);}; //somme des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::operator - () const 
  {  TenseurBH * res;
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = - *(this->t); //oppose
    return *res;};
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::operator - ( const TenseurBH & B) const 
  {  TenseurBH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator + ( etc..");
     #endif
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) - *(B.t); //soustraction des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BH::operator -= ( const TenseurBH & B)
  { 
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator -= ( etc..");
     #endif
    *(this->t) -= *(B.t);}; //soustraction des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::operator = ( const TenseurBH & B)
  { *(this->t) = *(B.t); //affectation des données
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) 
          Message(1,"Tenseur1BH::operator = ( etc..");
     #endif
    LesMaillonsBH::Libere(); // destruction des tenseurs intermediaires
    return *this; };
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::operator * ( const double & b) const 
  {  TenseurBH * res;
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) * b; //multiplication des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BH::operator *= ( const double & b)
  { *(this->t) *= b;}; //multiplication des données
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::operator / ( const double & b) const 
  {  TenseurBH * res;
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t) / b; //division des données
    return *res;}; 
#ifndef MISE_AU_POINT
  inline 
#endif
void  Tenseur1BH::operator /= ( const double & b)
  { *(this->t) /= b;}; //division des données        

//#ifndef MISE_AU_POINT
//  inline 
//#endif
//// affectation de B dans this, les données en trop sont ignorées
//void Tenseur1BH::Affectation_3D_a_1D(const Tenseur3BH & B)
//{ this->t[0] = B.t[0];};

// produit contracte avec un vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
CoordonneeB Tenseur1BH::operator * ( const CoordonneeB & B) const 
  { 
    #ifdef MISE_AU_POINT	 	 
	 if (B.Dimension() != dimension)
	    { cout << "\nErreur : dimensions vecteur tenseur non egales !\n";
		  cout << " Tenseur1BH::operator *\n";
		  Sortie(1);
		};
    #endif
    CoordonneeB v(dimension);
    v(1) = *(this->t) * B(1);
    return v;
  }; 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBB & Tenseur1BH::operator * ( const TenseurBB & B) const 
  {  TenseurBB * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator * ( etc..");
     #endif
     res =  new Tenseur1BB;
     LesMaillonsBB::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  }; 
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::operator * ( const TenseurBH & B) const 
  {  TenseurBH * res;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator * ( etc..");
     #endif
     res =  new Tenseur1BH;
     LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire 
    *(res->t) = (*(this->t)) * (*(B.t)); //affectation des données
  return *res ;
  };  
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1BH::operator && ( const TenseurBH & B) const 
  { double result;
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator && ( etc..");
     #endif
    result =  (*(this->t)) * (*(B.t)); // contraction
    return result;};
// test
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1BH::operator == ( const TenseurBH & B) const 
  {   
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator == ( etc..");
     #endif
     if (*(this->t) != *(B.t))
         return 0 ;
      else
         return 1;};   
#ifndef MISE_AU_POINT
  inline 
#endif
int Tenseur1BH::operator != ( const TenseurBH & B) const 
  {   
     #ifdef MISE_AU_POINT
       if (B.Dimension() != 1) Message(1,"Tenseur1BH::operator != ( etc..");
     #endif
     if (*(this->t) == *(B.t))
         return 0 ;
      else
         return 1;};   
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurBH & Tenseur1BH::Inverse() const 
  { TenseurBH * res;
    res =  new Tenseur1BH;
    LesMaillonsBH::NouveauMaillon( res); // ajout d'un tenseur intermediaire
    #ifdef MISE_AU_POINT
     if  (Dabs(*(this->t)) <= ConstMath::trespetit)
       { cout << "\nErreur : la coordonnee du tenseur est nulle !\n";
         cout << "Tenseur1BH::Inverse() \n";
         Sortie(1);
       };
    #endif    
    *(res->t) = 1./ (*(this->t));
    return *res;
  };                
             
#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 Tenseur1BH::Affectation_trans_dimension(const TenseurBH & B,bool plusZero)
  { // dans tous les cas il suffit de récupérer le premier élément et de l'affecter
    this->t[0] = B.t[0]; //on affecte le seul terme disponible
  };

#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1BH::Trace() const 
  { double result = *(this->t);
    return result; };
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1BH::II() const 
  { double result = (*(this->t)) * (*(this->t)) ;
    return result; };
#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1BH::III() const 
  { double result = (*(this->t)) * (*(this->t)) * (*(this->t));
    return result; };            
                
    // valeurs propre  dans le vecteur  de retour, classée par ordres "décroissants"
    // cas indique le cas de valeur propre: 
    // quelque soit la dimension: cas = -1, si l'extraction des valeurs propres n'a pas pu se faire
    //                            dans ce cas les valeurs propres de retour sont nulles par défaut
    // dim = 1, cas=1 pour une valeur propre; 
#ifndef MISE_AU_POINT
  inline 
#endif
Coordonnee Tenseur1BH::ValPropre(int& cas) const 
  { Coordonnee ret(1); ret(1)=(*(this->t)); cas =1;
    return ret;
   };
   
    // idem met en retour la matrice mat contiend par colonne les vecteurs propre
    // elle doit avoir la dimension du tenseur
    // les vecteurs propre sont exprime dans le repere naturel  
#ifndef MISE_AU_POINT
  inline 
#endif
Coordonnee Tenseur1BH::ValPropre(int& cas, Mat_pleine& mat) const 
  { Coordonnee ret(1); ret(1)=(*(this->t)); 
    #ifdef MISE_AU_POINT	 	 
	  if  ((mat.Nb_ligne() != 1) || (mat.Nb_colonne() != 1))
			{ cout << "\nErreur : la matrice en parametre doit etre de dimension " 
			       << 1 << " !\n";
			  cout << "Tenseur1BH::ValPropre( Mat_pleine& mat)  \n";
			  Sortie(1);
			};
    #endif
    mat(1,1)=1.; // vecteur unitaire de l'axe
    cas = 1;
    return ret;
   };

    // ici il s'agit uniquement de calculer les vecteurs propres, les valeurs propres
    // étant déjà connues
    // en retour VP les vecteurs propre : doivent avoir la dimension du tenseur
    // les vecteurs propre sont exprime dans le repere naturel (pour les tenseurs dim 3
    // pour dim=2:le premier vecteur propre est exprime dans le repere naturel 
    //            le second vecteur propre est exprimé dans le repère dual
    // pour dim=1 le vecteur est dans la base naturelle (mais ça importe pas)
    //   en sortie cas = -1 s'il y a eu un problème, dans ce cas, V_P est quelconque
    //             sinon si tout est ok, cas est identique en sortie avec l'entrée
#ifndef MISE_AU_POINT
  inline 
#endif
void Tenseur1BH::VecteursPropres(const Coordonnee& valPropre,int& cas, Tableau <Coordonnee>& V_P) const
  { // on dimensionne en conséquence
    Coordonnee toto(1); // un vecteur nul
    V_P.Change_taille(1,toto); // tableau initialisé à 0
    // ici dans tous les cas il s'agit du vecteur unitaire
    V_P(1)(1)=1.;
    cas = 1;
    return;
   };

#ifndef MISE_AU_POINT
  inline 
#endif
double  Tenseur1BH::Det() const 
  { double result = *(this->t);
    return result; };  
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1BH::Transpose() const 
   { TenseurHB * res;
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon(res); // ajout d'un tenseur intermediaire
     *(res->t) = *(this->t); 
    return *res;};           
		
//fonctions static définissant le produit tensoriel de deux vecteurs
#ifndef MISE_AU_POINT
  inline 
#endif
TenseurHB & Tenseur1HB::Prod_tensoriel(const CoordonneeH & aH, const CoordonneeB & bB)
  {  TenseurHB * res;
     res =  new Tenseur1HB;
     LesMaillonsHB::NouveauMaillon( res); // ajout d'un tenseur intermediaire
     *(res->t) = aH(1)*bB(1); 
     return *res;}; 
	 
	 // lecture et écriture de données
#ifndef MISE_AU_POINT
  inline 
#endif
istream & Tenseur1HB::Lecture(istream & entree)
  { // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1HB")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*(this->t));
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
ostream & Tenseur1HB::Ecriture(ostream & sort) const 
  { // écriture du type
    sort << "Tenseur1HB ";
    // puis les datas
    sort  << setprecision (ParaGlob::NbdigdoCA()) <<   (*(this->t)) << " ";
     return sort;      
  };

#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator de lecture
istream & operator >> (istream & entree, Tenseur1BH & A)
  { int dim = A.Dimension();
     #ifdef MISE_AU_POINT
       if (dim != 1) A.Message(1,"operator >> (istream & entree, Tenseur1BH & A)");
    #endif
    // lecture et vérification du type
    string nom_type;
    entree >> nom_type;
    if (nom_type != "Tenseur1BH")
      { Sortie(1);
        return entree;
       }
    // lecture des coordonnées    
    entree >> (*A.t);
    return entree;      
  };
#ifndef MISE_AU_POINT
  inline 
#endif
 // surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort , const Tenseur1BH & A)
  { // écriture du type
    sort << "Tenseur1BH ";
    // puis les datas
    sort  << setprecision(ParaGlob::NbdigdoCA()) <<   (*A.t) << " ";
     return sort;      
  };


#endif    
  
