// FICHIER : Hypo_ortho3D_entrainee.cc
// CLASSE : Hypo_ortho3D_entrainee


// 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-2022 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 <math.h>
#include <stdlib.h>
#include "Sortie.h"
#include "TypeConsTens.h"
#include "ConstMath.h"
#include "Hypo_ortho3D_entrainee.h"
#include "NevezTenseur.h"
#include "MathUtil.h"
#include "Util.h"

#include "Enum_TypeQuelconque.h"
#include "TypeQuelconqueParticulier.h"
#include "TenseurQ3gene.h"
#include "MathUtil.h"
#include "MathUtil2.h"
#include "CharUtil.h"


// ========== fonctions pour la classe de sauvegarde des résultats =========

// constructeur par défaut
Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee(const int type_transport):
     O_B(NULL), O_H(NULL),Op_H(3,3),Op_H_t(3,3)
     ,eps_loc_HH(NULL),sig_loc_HH(NULL),delta_eps_loc_HH(NULL),delta_sig_loc_HH(NULL)
     ,para_loi(NULL)
{
// non on ne fait pas de définition par défaut
//  if (type_transport == 0)
//   {O_H = new BaseH(); sig_loc_HH = NevezTenseurHH(3);  }
//  else
//   {O_B = new BaseB(); eps_loc_HH = NevezTenseurHH(3);  };
};

// constructeur de copie
Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee(const SaveResulHypo_ortho3D_entrainee& sav):
   O_B(NULL), O_H(NULL),Op_H(3,3),Op_H_t(3,3)
   ,eps_loc_HH(NULL),sig_loc_HH(NULL),delta_eps_loc_HH(NULL),delta_sig_loc_HH(NULL)
   ,para_loi(NULL)
 {
   // partie repère d'orthotropie
   if (sav.O_B != NULL)
     O_B = new BaseB(*sav.O_B);
   if (sav.O_H != NULL)
     O_H = new BaseH(*sav.O_H);
   if (sav.eps_loc_HH != NULL)
     eps_loc_HH = NevezTenseurHH(*sav.eps_loc_HH);
   if (sav.sig_loc_HH != NULL)
     sig_loc_HH = NevezTenseurHH(*sav.sig_loc_HH);
   if (sav.delta_eps_loc_HH != NULL)
     delta_eps_loc_HH = NevezTenseurHH(*sav.delta_eps_loc_HH);
   if (sav.delta_sig_loc_HH != NULL)
     delta_sig_loc_HH = NevezTenseurHH(*sav.delta_sig_loc_HH);
   if (sav.para_loi != NULL)
     para_loi = new Vecteur (*sav.para_loi);
 };

// destructeur
Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::~SaveResulHypo_ortho3D_entrainee()
   {
    // partie repère d'orthotropie
    if (O_B != NULL)
      delete O_B;
    if (O_H != NULL)
      delete O_H;
    if (eps_loc_HH != NULL)
      delete eps_loc_HH;
    if (sig_loc_HH != NULL)
      delete sig_loc_HH;
    if (delta_eps_loc_HH != NULL)
      delete delta_eps_loc_HH;
    if (delta_sig_loc_HH != NULL)
      delete delta_sig_loc_HH;
    if (para_loi != NULL)
      delete para_loi;
   };

// affectation
Loi_comp_abstraite::SaveResul & Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee& sav = *((Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee*) &a);
    // partie repère d'orthotropie
    if (sav.O_B != NULL)
     {if (O_B == NULL) {O_B = new BaseB(*sav.O_B);}
      else {*O_B = *sav.O_B;};
     }
    else // sinon cas NULL
    {if (O_B != NULL) {delete O_B;O_B=NULL;}} ;
   
    if (sav.O_H != NULL)
     {if (O_H == NULL) {O_H = new BaseH(*sav.O_H);}
      else {*O_H = *sav.O_H;};
     }
    else // sinon cas NULL
    {if (O_H != NULL) {delete O_H;O_H=NULL;}} ;
   
    if (sav.eps_loc_HH != NULL)
     {if (eps_loc_HH == NULL) {eps_loc_HH = NevezTenseurHH(*sav.eps_loc_HH);}
      else {*eps_loc_HH = *sav.eps_loc_HH;};
     }
    else // sinon cas NULL
    {if (eps_loc_HH != NULL) {delete eps_loc_HH;eps_loc_HH=NULL;}} ;
   
    if (sav.sig_loc_HH != NULL)
     {if (sig_loc_HH == NULL) {sig_loc_HH = NevezTenseurHH(*sav.sig_loc_HH);}
      else {*sig_loc_HH = *sav.sig_loc_HH;};
     }
    else // sinon cas NULL
    {if (sig_loc_HH != NULL) {delete sig_loc_HH; sig_loc_HH= NULL;};
    } ;
   
    if (sav.delta_eps_loc_HH != NULL)
     {if (delta_eps_loc_HH == NULL) {delta_eps_loc_HH = NevezTenseurHH(*sav.delta_eps_loc_HH);}
      else {*delta_eps_loc_HH = *sav.delta_eps_loc_HH;};
     }
    else // sinon cas NULL
    {if (delta_eps_loc_HH != NULL) {delete delta_eps_loc_HH;delta_eps_loc_HH=NULL;}} ;
   
    if (sav.delta_sig_loc_HH != NULL)
     {if (delta_sig_loc_HH == NULL) {delta_sig_loc_HH = NevezTenseurHH(*sav.delta_sig_loc_HH);}
      else {*delta_sig_loc_HH = *sav.delta_sig_loc_HH;};
     }
    else // sinon cas NULL
    {if (delta_sig_loc_HH != NULL) {delete delta_sig_loc_HH; delta_sig_loc_HH= NULL;};
    } ;

    if (sav.para_loi != NULL)
     {if (para_loi == NULL) para_loi = new Vecteur (*sav.para_loi);
      else {*para_loi = *sav.para_loi; };
     }
    else // sinon cas NULL
    {if (para_loi != NULL) {delete para_loi;para_loi=NULL;}} ;
    // et la base
    Op_H = sav.Op_H;
    Op_H_t = sav.Op_H_t;

    return *this;
  };


//------- lecture écriture dans base info -------
   // cas donne le niveau de la récupération
   // = 1 : on récupère tout
   // = 2 : on récupère uniquement les données variables (supposées comme telles)
void Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::Lecture_base_info(istream& ent,const int cas)
   {  string nom;
      ent >>  nom ;

      #ifdef MISE_AU_POINT
      if (nom != "S_Ortho_3D")
          { cout << "\nErreur : on attendait le mot cle: S_Ortho_3D "
                 << " et on a lue "<<nom;
            cout << " Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::Lecture_base_info\n";
            Sortie(1);
          };
      #endif
      // on lit que ce qui est à 0 et à t, ce qui est à tdt est considéré une zone de travail
      switch (cas)
       { case 1 :
          {
           // la base initiale
           if (O_B != NULL)
            { ent >> nom >> *O_B;}
           else if (O_H != NULL)
            { ent >> nom >> *O_H;}
           // la base convectée
           ent >> nom >> Op_H_t ;
           Op_H = Op_H_t;
           // les stockages conditionnels
           int test;
           ent >> nom >> test;
           if (test == 0)
            { if (eps_loc_HH != NULL)
                {delete eps_loc_HH;eps_loc_HH=NULL;}
              if (sig_loc_HH != NULL)
                {delete sig_loc_HH;sig_loc_HH=NULL;}
              if (delta_eps_loc_HH != NULL)
                {delete delta_eps_loc_HH;delta_eps_loc_HH=NULL;}
              if (delta_sig_loc_HH != NULL)
                {delete delta_sig_loc_HH;delta_sig_loc_HH=NULL;}
              if (para_loi != NULL)
                {delete para_loi;para_loi=NULL;}
            }
           else // sinon cas où on a des données additionnelles
            { if (eps_loc_HH == NULL) eps_loc_HH = NevezTenseurHH(3);
              ent >> nom ; eps_loc_HH->Lecture(ent);
              if (sig_loc_HH == NULL) sig_loc_HH = NevezTenseurHH(3);
              ent >> nom ; sig_loc_HH->Lecture(ent);
              if (delta_eps_loc_HH == NULL) delta_eps_loc_HH = NevezTenseurHH(3);
              ent >> nom ; delta_eps_loc_HH->Lecture(ent);
              if (delta_sig_loc_HH == NULL) delta_sig_loc_HH = NevezTenseurHH(3);
              ent >> nom ; delta_sig_loc_HH->Lecture(ent);
              if (para_loi == NULL) para_loi = new Vecteur (9);
              ent >> *para_loi;
            };
           break;
          }
         case 2 :
          {
           // la base convectée
           ent >> nom >> Op_H_t ;
           // les stockages conditionnels
           int test;
           ent >> nom >> test;
           if (test == 0)
            { if (eps_loc_HH != NULL)
                {delete eps_loc_HH;eps_loc_HH=NULL;}
              if (sig_loc_HH != NULL)
                {delete sig_loc_HH;sig_loc_HH=NULL;}
              if (delta_eps_loc_HH != NULL)
                {delete delta_eps_loc_HH;delta_eps_loc_HH=NULL;}
              if (delta_sig_loc_HH != NULL)
                {delete delta_sig_loc_HH;delta_sig_loc_HH=NULL;}
              if (para_loi != NULL)
                {delete para_loi;para_loi=NULL;}
            }
           else // sinon cas où on a des données additionnelles
            { if (eps_loc_HH == NULL) eps_loc_HH = NevezTenseurHH(3);
              ent >> nom ; eps_loc_HH->Lecture(ent);
              if (sig_loc_HH == NULL) sig_loc_HH = NevezTenseurHH(3);
              ent >> nom ; sig_loc_HH->Lecture(ent);
              if (delta_eps_loc_HH == NULL) delta_eps_loc_HH = NevezTenseurHH(3);
              ent >> nom ; delta_eps_loc_HH->Lecture(ent);
              if (delta_sig_loc_HH == NULL) delta_sig_loc_HH = NevezTenseurHH(3);
              ent >> nom ; delta_sig_loc_HH->Lecture(ent);
              if (para_loi == NULL) para_loi = new Vecteur(9);
              ent >> nom  >> *para_loi;
            };
           break;
          }
         default:
            cout << "\n cas non considere !!: cas= " << cas
                 << "\n   Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::Ecriture_base_info(...";
            Sortie(1);
       };
  };

// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables
//(supposées comme telles)
void Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::Ecriture_base_info(ostream& sort,const int cas )
   {  sort << "\n S_Ortho_3D  ";
      // on ne sauvegarde que ce qui est à 0 et à t, ce qui est à tdt est considéré une zone de travail
      switch (cas)
       { case 1 :
          {
           // la base initiale
           if (O_B != NULL)
            { sort << " O_B: "<< *O_B;}
           else if (O_H != NULL)
            { sort << " O_H: "<< *O_H;}
           // la base convectée
           sort << " Op_H_t: "<< Op_H_t << " ";
           // les stockages conditionnels
           if (eps_loc_HH != NULL)
            { sort << " addi: 1 " << "\n eps_loc_HH: ";
              eps_loc_HH->Ecriture(sort);
              sort << " sig_loc_HH: ";
              sig_loc_HH->Ecriture(sort);
              sort << "\n delta_eps_loc_HH: ";
              delta_eps_loc_HH->Ecriture(sort);
              sort << " delta_sig_loc_HH: ";
              delta_sig_loc_HH->Ecriture(sort);
              sort << "\n para_loi: " << *para_loi << " ";
            }
           else
            { sort << " addi: 0 ";};
           break;
          }
         case 2 :
          {
           // la base convectée
           sort << " Op_H_t: "<< Op_H_t << " ";
           // les stockages conditionnels
           if (eps_loc_HH != NULL)
            { sort << "\n addi: 1 "<< "\n eps_loc_HH: " ;
              eps_loc_HH->Ecriture(sort);
              sort << " sig_loc_HH: " ;
              sig_loc_HH->Ecriture(sort);
              sort << "\n delta_eps_loc_HH: ";
              delta_eps_loc_HH->Ecriture(sort);
              sort << " delta_sig_loc_HH: ";
              delta_sig_loc_HH->Ecriture(sort);
              sort << "\n para_loi: " << *para_loi << " ";
            }
           else
            { sort << "\n addi: 0 ";};
           break;
          }
         default:
            cout << "\n cas non considere !!: cas= " << cas
                 << "\n   Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::Ecriture_base_info(...";
            Sortie(1);
       };
  };

// mise à jour des informations transitoires
void Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::TdtversT()
   { Op_H_t = Op_H;
   };

void Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::TversTdt()
   { Op_H = Op_H_t;
   };

// affichage à l'écran des infos
void Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::Affiche() const
{ cout << "\n SaveResulHypo_ortho3D_entrainee: " ;
  if (O_B != NULL)
    {cout << "\n O_B= "; O_B->Affiche();
    };
  if (O_H != NULL)
    {cout << "\n O_H= "; O_H->Affiche();
    };
  cout << "\n Op_H= ";Op_H.Affiche();

  // les tenseurs intermédiaires
  if (eps_loc_HH != NULL)
   { cout << "\n eps_loc_HH= "; eps_loc_HH->Ecriture(cout);
   };
  if (sig_loc_HH != NULL)
   { cout << "\n sig_loc_HH= "; sig_loc_HH->Ecriture(cout);
   };
  if (delta_eps_loc_HH != NULL)
   { cout << "\n delta_eps_loc_HH= "; delta_eps_loc_HH->Ecriture(cout);
   };
  if (delta_sig_loc_HH != NULL)
   { cout << "\n delta_sig_loc_HH= "; delta_sig_loc_HH->Ecriture(cout);
   };
  // paramètre variables éventuelles de la loi
  if (para_loi != NULL)
   { cout << "\n para_loi: ";
     for (int i=1; i< 10;i++)
       cout << " coef("<<i<<")= "<< (*para_loi)(i);
     cout << " ";
   };


  cout  << "\n .. fin SaveResulHypo_ortho3D_entrainee ... ";
};

//changement de base de toutes les grandeurs internes tensorielles stockées
// b(i,j) represente les coordonnees de la nouvelle base naturelle gpB dans l'ancienne gB
// gpB(i) = beta(i,j) * gB(j), i indice de ligne, j indice de colonne
// gpH(i) = gamma(i,j) * gH(j)
void Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::ChBase_des_grandeurs(const Mat_pleine& beta,const Mat_pleine& gamma)
{ // on ne s'intéresse qu'aux grandeurs tensorielles
  // il faut que l'on exprime le repère d'orthotropie dans le nouveau repère
  if (O_B != NULL)
   {for (int i=1;i<4;i++)
     { CoordonneeB Ap_B(3); // inter
       MathUtil2::ChBase(O_B->CoordoB(i),beta,Ap_B);
       O_B->CoordoB(i)=Ap_B;
     }
   };
  if (O_H != NULL)
   {for (int i=1;i<4;i++)
     { CoordonneeH Ap_H(3); // inter
       MathUtil2::ChBase(O_H->CoordoH(i),gamma,Ap_H);
       O_H->CoordoH(i)=Ap_H;
     }
   };
  // les autres grandeurs sont issues du calcul
  // normalement elles sont calculées en même temps que les contraintes
  // mais on les change de repère néanmoins, au cas on on ferait une sortie
  // d'info sans calcul (c'est pénalisant pour le cas avec calcul, mais cela
  //  évite peut-être des pb potentiels ??)
  // Op_H est toujours calculé
  {for (int i=1;i<4;i++)
     { CoordonneeH Ap_H(3); // inter
       MathUtil2::ChBase(Op_H_t.CoordoH(i),gamma,Ap_H);
       Op_H_t.CoordoH(i)=Ap_H;
     }
   };
  // cas des grandeurs locales si elles sont sauvegardées
  if (eps_loc_HH != NULL)
   { eps_loc_HH->ChBase(gamma);};
  if (sig_loc_HH != NULL)
   { sig_loc_HH->ChBase(gamma);};
  // cas des grandeurs locales si elles sont sauvegardées
  if (delta_eps_loc_HH != NULL)
   { delta_eps_loc_HH->ChBase(gamma);};
  if (delta_sig_loc_HH != NULL)
   { delta_sig_loc_HH->ChBase(gamma);};

};

// procedure permettant de completer éventuellement les données particulières
// de la loi stockées
// au niveau du point d'intégration par exemple: exemple: un repère d'anisotropie
// completer est appelé apres sa creation avec les donnees du bloc transmis
// peut etre appeler plusieurs fois
Loi_comp_abstraite::SaveResul* Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee
         ::Complete_SaveResul(const BlocGen & bloc, const Tableau <Coordonnee>& tab_coor
                              ,const Loi_comp_abstraite* loi)
  {// on regarde  s'il s'agit d'un repère d'orthotropie
   if (bloc.Nom(1) == "repere_anisotropie_")
    {// ensuite on vérifie le nom de l'identificateur
     Hypo_ortho3D_entrainee* loiOrtho = (Hypo_ortho3D_entrainee*) loi;
     // dimensionnement des bases
     if (loiOrtho->Type_transport() == 0)
      {O_H = new BaseH(); sig_loc_HH = NevezTenseurHH(3); delta_sig_loc_HH = NevezTenseurHH(3); }
     else
      {O_B = new BaseB(); eps_loc_HH = NevezTenseurHH(3); delta_eps_loc_HH = NevezTenseurHH(3); };
     // récupération du repère
     if (bloc.Nom(2) == loiOrtho->NomRepere())
       {// c'est le bon, récupération du repère
        if (O_B != NULL)
         {for (int i=1;i<4;i++)
           O_B->CoordoB(i).Change_val(tab_coor(i));
         };
        if (O_H != NULL)
         {for (int i=1;i<4;i++)
           O_H->CoordoH(i).Change_val(tab_coor(i));
         };
       };
    };
   //
   return this;
  };

// initialise les informations de travail concernant le pas de temps en cours
void Hypo_ortho3D_entrainee::SaveResulHypo_ortho3D_entrainee::Init_debut_calcul()
   { };

// ========== fin des fonctions pour la classe de sauvegarde des résultats =========

Hypo_ortho3D_entrainee::Hypo_ortho3D_entrainee ()  : // Constructeur par defaut
  Loi_comp_abstraite(HYPO_ORTHO3D,CAT_MECANIQUE,3)
  ,E1(-ConstMath::trespetit),E2(-ConstMath::trespetit),E3(-ConstMath::trespetit)
  ,nu12(-ConstMath::trespetit),nu13(-ConstMath::trespetit),nu23(-ConstMath::trespetit)
  ,G12(-ConstMath::trespetit),G13(-ConstMath::trespetit),G23(-ConstMath::trespetit)
  ,fct_para(9),cas_calcul(0)
  ,type_transport(0),type_derive(-1)
  ,sortie_post(0)
  ,nom_repere("")
  ,inv_loi(3,3),Op_B(3,3),d_Op_B(3,3),d_Op_H(3,3),pO_B(3,3),pO_H(3,3)
  ,beta_inv(3,3),beta(3,3),gamma(3,3),beta_transpose(3,3),gamma_transpose(3,3)
  ,alpha_H(3,3)
  ,I_x_I_HHHH(),I_xbarre_I_HHHH(),I_x_eps_HHHH(),Ixbarre_eps_HHHH()

    {for (int i=1;i<=9;i++)
       fct_para(i) = NULL;
     null_fct_para=1; // pour l'instant pas de fonction
    };

		// Contructeur fonction de tous les paramètres constants de la loi
Hypo_ortho3D_entrainee::Hypo_ortho3D_entrainee(const double& EE1,const double& EE2,const double& EE3
                                   ,const double& nunu12,const double& nunu13,const double& nunu23
                                   ,const double& GG12,const double& GG13,const double& GG23
                                   ,const string& nom_rep):
   Loi_comp_abstraite(HYPO_ORTHO3D,CAT_THERMO_MECANIQUE,3)
   ,E1(EE1),E2(EE2),E3(EE3),nu12(nunu12),nu13(nunu13),nu23(nunu23)
   ,G12(GG12),G13(GG13),G23(GG23)
   ,fct_para(9),cas_calcul(0)
   ,type_transport(0),type_derive(-1)
   ,sortie_post(0)
   ,nom_repere(nom_rep)
   ,inv_loi(3,3),Op_B(3,3),d_Op_B(3,3),d_Op_H(3,3),pO_B(3,3),pO_H(3,3)
   ,beta_inv(3,3),beta(3,3),gamma(3,3),beta_transpose(3,3),gamma_transpose(3,3)
   ,alpha_H(3,3)
   ,I_x_I_HHHH(),I_xbarre_I_HHHH(),I_x_eps_HHHH(),Ixbarre_eps_HHHH()

    {for (int i=1;i<=9;i++)
       fct_para(i) = NULL;
     null_fct_para=1; // pour l'instant pas de fonction
    };

// Constructeur de copie
Hypo_ortho3D_entrainee::Hypo_ortho3D_entrainee (const Hypo_ortho3D_entrainee& loi) :
   Loi_comp_abstraite(loi)
   ,E1(loi.E1),E2(loi.E2),E3(loi.E3),nu12(loi.nu12),nu13(loi.nu13),nu23(loi.nu23)
   ,G12(loi.G12),G13(loi.G13),G23(loi.G23)
   ,fct_para(loi.fct_para),cas_calcul(loi.cas_calcul)
   ,inv_loi(loi.inv_loi),Op_B(3,3),d_Op_B(3,3),d_Op_H(3,3),pO_B(3,3),pO_H(3,3)
   ,beta_inv(3,3),beta(3,3),gamma(3,3),beta_transpose(3,3),gamma_transpose(3,3)
   ,alpha_H(3,3)
   ,type_derive(loi.type_derive),type_transport(loi.type_transport)
   ,sortie_post(loi.sortie_post)
   ,nom_repere(loi.nom_repere)
   ,I_x_I_HHHH(),I_xbarre_I_HHHH(),I_x_eps_HHHH(),Ixbarre_eps_HHHH()

	 {// on regarde s'il s'agit d'une courbe locale ou d'une courbe globale
   for (int i=1;i<=9;i++)
	   {if (fct_para(i) != NULL)
	     {null_fct_para=0; // dans tous les cas on indique qu'il y a des fonctions
       if (fct_para(i)->NomFonction() == "_")
        {// comme il s'agit d'une fonction locale on la redéfinie (sinon pb lors du destructeur de loi)
         string non_fonction("_");
         fct_para(i) = Fonction_nD::New_Fonction_nD(*fct_para(i));
        };
      };
    };
  };

Hypo_ortho3D_entrainee::~Hypo_ortho3D_entrainee ()
  // Destructeur
  { for (int i=1;i<=9;i++)
      {if (fct_para(i) != NULL)
         if (fct_para(i)->NomFonction() == "_") delete fct_para(i);
      };
  };

// Lecture des donnees de la classe sur fichier
void Hypo_ortho3D_entrainee::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  {
    // on lit les coefficients dans l'ordre
    string nom_class_methode("Hypo_ortho3D_entrainee::LectureDonneesParticulieres");
    double val_defaut=0.;
    double min = 0.; double max = -1; // max < min => la condition n'est pas prise en compte
   
    // pour faire une boucle de lecture on constitue un tableau de mots clés
    Tableau <string > tab_mot_cle(9);
    tab_mot_cle(1) = "E1";tab_mot_cle(2) = "E2";tab_mot_cle(3) = "E3";
    tab_mot_cle(4) = "nu12";tab_mot_cle(5) = "nu13";tab_mot_cle(6) = "nu23";
    tab_mot_cle(7) = "G12";tab_mot_cle(8) = "G13";tab_mot_cle(9) = "G23";
    // puis un tableau pour les valeurs
    Tableau < double * > coef(9);
    coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
    coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
    coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
   
    // on boucle sur les 9 coefficients
    for (int i=1;i<=9;i++)
     {string mot_cle1=tab_mot_cle(i)+"=";
      string mot_cle2=tab_mot_cle(i)+"_fonction_nD:";
      if(strstr(entreePrinc->tablcar,mot_cle2.c_str())==0)
       {// lecture du paramètre
        if (i<4) // dans le cas des Ei, il faut qu'ils soient tous non nulles
                 // sinon on ne peut pas calculer inv_loi
         { min = ConstMath::unpeupetit; max = ConstMath::grand; }
        else {min = 0.; max = -1; };// max < min => la condition n'est pas prise en compte
        if (!entreePrinc->Lecture_un_parametre_double(val_defaut,nom_class_methode
                                                        ,min,max,mot_cle1, *coef(i) ))
           { entreePrinc->MessageBuffer("**erreur en lecture**  "+mot_cle1);
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);
           };
       }
      else // on lit une fonction
       {// on passe le mot clé générique
        bool lec = entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle1);
        // on lit le nom de la fonction
        string nom_fonct;
        lec = lec && entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle2,nom_fonct);
        if (!lec )
           { entreePrinc->MessageBuffer("**erreur en lecture**  "+mot_cle2);
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);
           };
        null_fct_para=0; // on indique qu'il y a des fonctions
        // maintenant on définit la fonction
        if (lesFonctionsnD.Existe(nom_fonct))
         {fct_para(i) = lesFonctionsnD.Trouve(nom_fonct);
         }
        else
         {// sinon il faut la lire maintenant
          string non("_");
          fct_para(i) = Fonction_nD::New_Fonction_nD(non, Id_Nom_Fonction_nD(nom_fonct));
          // lecture de la courbe
          fct_para(i)->LectDonnParticulieres_Fonction_nD (non,entreePrinc);
          // maintenant on vérifie que la fonction est utilisable
          if (fct_para(i)->NbComposante() != 1 )
           { cout << "\n erreur en lecture, la fonction " << nom_fonct
                  << " est une fonction vectorielle a   " << fct_para(i)->NbComposante()
                  << " composante alors qu'elle devrait etre scalaire ! "
                  << " elle n'est donc pas utilisable !! ";
             string message("\n**erreur08** \n"+nom_class_methode+"(...");
             entreePrinc->MessageBuffer(message);
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);
           };
        };
        entreePrinc->NouvelleDonnee(); // on se positionne sur un nouvel enreg
       };
     }; // fin de la boucle for (int i=1;i<=9;i++)
     
    // lecture du repère d'orthotropie entraîné, associé
    string mot_cle("nom_repere_associe_");
    entreePrinc->NouvelleDonnee(); // on se positionne sur un nouvel enreg
    bool lec = entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle,nom_repere);
    if (!lec )
       { entreePrinc->MessageBuffer("**erreur en lecture**  "+mot_cle);
         throw (UtilLecture::ErrNouvelleDonnee(-1));
         Sortie(1);
       };
   
    // --- lecture éventuelle des paramètres de réglage ----
    cas_calcul = 0;   // par défaut
    if(strstr(entreePrinc->tablcar,"avec_parametres_de_reglage_")!=0)
     {string nom;
      entreePrinc->NouvelleDonnee(); // on se positionne sur un nouvel enreg
      // on lit tant que l'on ne rencontre pas la ligne contenant "fin_parametres_reglage_"
      // ou un nouveau mot clé global auquel cas il y a pb !!
      MotCle motCle; // ref aux mots cle
      while (strstr(entreePrinc->tablcar,"fin_parametres_reglage_")==0)
       {
        // si on a  un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur
        if ( motCle.SimotCle(entreePrinc->tablcar))
         { cout << "\n erreur de lecture des parametre de reglage : on n'a pas trouve le mot cle "
                << " fin_parametres_reglage_ et par contre la ligne courante contient un mot cle global  ";
           entreePrinc->MessageBuffer("** erreur5 des parametres de reglage de la loi de comportement de Hypo_ortho3D_entrainee **");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         };
        
        // lecture d'un mot clé
        *(entreePrinc->entree) >> nom;
        
        // type de transport
        if (nom == "type_transport_")
         { // lecture du type
           *(entreePrinc->entree) >> type_transport;
           if ((type_transport!=0)&&(type_transport!=1))
             { cout << "\n le type de transport lue pour la loi de Hypo_ortho3D_entrainee:  "<< type_transport
                    << " n'est pas acceptable (uniquement 0 ou 1), on utilise le type par defaut (0)"
                    << " qui correspond a un transport de type  contravariant ";
               type_transport = 0;
             };
         }
        // on regarde ensuite si le type de dérivée est indiqué
        else if (nom == "type_derivee")
         { // lecture du type
           string toto;
           *(entreePrinc->entree) >> toto >> type_derive;
           if ((type_derive!=0)&&(type_derive!=-1)&&(type_derive!=1))
             { cout << "\n le type de derivee indique pour la loi Hypo_ortho3D_entrainee:  "<< type_derive
                    << " n'est pas acceptable (uniquement -1 ou 0 ou 1), on utilise le type par defaut (-1 -> Jauman)"
                    << " qui correspond à la derivee mixte de Lie deux fois covariantes, deux fois contravariantes";
               type_derive = -1;
             };
         }
        // forcer un affichage particulier pour les méthodes
        else if (nom == "permet_affichage_")
         {Lecture_permet_affichage(entreePrinc,lesFonctionsnD);
         }
        // on regarde si le calcul est éventuellement uniquement déviatorique
        else if (nom == "seule_deviatorique")
         {if (cas_calcul == 2) {cas_calcul=0;} else {cas_calcul = 1;};}
        // idem pour la partie sphérique
        else if (nom == "seule_spherique")
         {if (cas_calcul == 1) {cas_calcul=0;} else {cas_calcul = 2;};}
        // forcer un stockage pour des sorties
        else if (nom == "sortie_post_")
         {*(entreePrinc->entree) >> sortie_post;
         }

        // sinon ce n'est pas un mot clé connu, on le signale
        else if (nom != "fin_parametres_reglage_")
         { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu "
                << " on a lu : " << nom << endl;
           if (ParaGlob::NiveauImpression()>3)
                cout << "\n Hypo_ortho3D_entrainee::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         }
         
        if ((entreePrinc->entree)->rdstate() == 0)
          {} // lecture normale
        #ifdef ENLINUX
        else  if ((entreePrinc->entree)->fail())
           // on a atteind la fin de la ligne et on appelle un nouvel enregistrement
          {   entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
              *(entreePrinc->entree) >>nom;
           }
        #else
        else  if ((entreePrinc->entree)->eof())
          // la lecture est bonne mais on a atteind la fin de la ligne
          { if(nom != "fin_parametres_reglage_")
              {entreePrinc->NouvelleDonnee(); };
          }
        #endif
        else // cas d'une erreur de lecture
         { cout << "\n erreur de lecture inconnue  ";
           entreePrinc->MessageBuffer("** erreur4 des parametres de reglage de la loi de comportement de Hypo_ortho3D_entrainee **");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         };

       }; //-- fin du while
      }; //-- fin de la lecture des paramètres de réglage

    // appel au niveau de la classe mère
    Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire
                 (*entreePrinc,lesFonctionsnD);
   
    // dans le cas particulier où il n'y a pas de fonction nD on peut calculer inv_loi
    if (null_fct_para)
     {// on commence par remplir la matrice
      inv_loi(1,1) = 1./E1;inv_loi(2,2) = 1./E2;inv_loi(3,3) = 1./E3;
      inv_loi(1,2) = inv_loi(2,1) = -nu12/E1;
      inv_loi(1,3) = inv_loi(3,1) = -nu13/E1;
      inv_loi(3,2) = inv_loi(2,3) = -nu23/E2;
      inv_loi = inv_loi.Inverse(); // on inverse la matrice
     };
   
   
  };
// affichage de la loi
void Hypo_ortho3D_entrainee::Affiche() const
  { // pour faire une boucle  on constitue un tableau de mots clés
    Tableau <string > tab_mot_cle(9);
    tab_mot_cle(1) = "E1";tab_mot_cle(2) = "E2";tab_mot_cle(3) = "E3";
    tab_mot_cle(4) = "nu12";tab_mot_cle(5) = "nu13";tab_mot_cle(6) = "nu23";
    tab_mot_cle(7) = "G12";tab_mot_cle(8) = "G13";tab_mot_cle(9) = "G23";
    // puis un tableau pour les valeurs
    Tableau < const double * > coef(9);
    coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
    coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
    coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
   
    // on boucle sur les 9 coefficients
    cout << "\n loi de comportement orthotrope elastique 3D ";
    for (int i=1;i<=9;i++)
     {string mot_cle1=tab_mot_cle(i)+"= ";
      string mot_cle2=tab_mot_cle(i)+"_fonction_nD:";
      cout <<  mot_cle1 ;
      if (fct_para(i) == NULL)
        cout << *coef(i) << " ";
      else
        {cout << mot_cle2 << " ";
         if (fct_para(i)->NomFonction() != "_")
           cout << fct_para(i)->NomFonction();
         else
           fct_para(i)->Affiche();
         cout << "\n";
        };
     };
    // le nom du repère associé
    cout << "\n nom_repere_associe " << nom_repere;

    // indicateur de cas de calcul
    if (cas_calcul != 0)
    	{ if (cas_calcul == 1)
    	   {cout << "\n calcul uniquement deviatorique ";}
    	  else if (cas_calcul == 2)
    	   {cout << " calcul uniquement spherique ";}
    	  else
    	   {cout << " cas de calcul mal defini !! ";}; 
    	};
    // affichage du type de transport
    cout << " type_transport: " << type_transport;
    // et du type de dérivée objective
    switch (type_derive)
     { case -1: cout << ", et derivee de jauman pour la contrainte" << endl;break;
       case  0: cout << ", et derivee de Lie deux fois covariantes (Rivlin) pour la contrainte" << endl; break;
       case  1: cout << ", et derivee de Lie deux fois contravariantes (Oldroyd) pour la contrainte" << endl; break;
     };
    // niveau d'affichage
    Affiche_niveau_affichage();
    cout << " sortie_post: "<< sortie_post;
    cout << endl;
    // appel de la classe mère
    Loi_comp_abstraite::Affiche_don_classe_abstraite();
  };
            
// affichage et definition interactive des commandes particulières à chaques lois
void Hypo_ortho3D_entrainee::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
 {ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
	 cout << "\n definition standart (rep o) ou exemples exhaustifs (rep n'importe quoi) ? ";
	 string rep = "_";
  // procédure de lecture avec prise en charge d'un retour chariot
  rep = lect_return_defaut(true,"o");

  // pour faire une boucle  on constitue un tableau de mots clés
  Tableau <string > tab_mot_cle(9);
  tab_mot_cle(1) = "E1";tab_mot_cle(2) = "E2";tab_mot_cle(3) = "E3";
  tab_mot_cle(4) = "nu12";tab_mot_cle(5) = "nu13";tab_mot_cle(6) = "nu23";
  tab_mot_cle(7) = "G12";tab_mot_cle(8) = "G13";tab_mot_cle(9) = "G23";
  // puis un tableau pour les valeurs
  Tableau < double * > coef(9);
  coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
  coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
  coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
  
  E1=100000; E2= 50000; E3= 20000;
  nu12= 0.2; nu13 = 0.3; nu23 = 0.1;
  G12 = 20000; G13 = 10000; G23 = 2000;
  

  sort << "\n# .......  loi de comportement hypo elastique orthotrope 3D ........"
       << "\n#    9 parametres materiau: 3 modules tangent de traction, 3 coef type Poisson"
       << "\n#  , 3 modules type cisaillement tangent "
       << "\n#  et un nom de repere associe  \n";
  for (int i=1;i<=9;i++)
   {string mot_cle1=tab_mot_cle(i)+"= ";
    string mot_cle2=tab_mot_cle(i)+"_fonction_nD:";
    if ((i==3)||(i==6)) sort << " \\ \n";
    sort << mot_cle1 << setprecision(6) << *coef(i) << " ";
   };
  sort << "\n nom_repere_associe_  repere1 ";
  sort << endl;

  // cas avec plus d'information
	 if ((rep != "o") && (rep != "O" ) && (rep != "0") )
      { // cas d'une loi thermo dépendante
        sort << "\n# .... infos complementaires ...."
             <<"\n# 1) Pour chaque parametre materiau, individuellement, il est possible "
             <<"\n#    d'utiliser une fonction nD a la place d'une valeur numerique. "
             <<"\n#    La fonction nD peut alors dependre de toutes les grandeurs disponibles "
             <<"\n#    localement, en particulier la position, les donnees imposees par l'utilisateur "
             <<"\n#    par exe: une temperature, ou tout ddl obtenu directement ou par interpolation "
             <<"\n#    suivant sa disponibilite, sachant que l'on regarde d'abord si la grandeur est "
             <<"\n#    directement disponible au point d'integration, sinon on regarde si elle est "
             <<"\n#    disponible par interpolation. "
             <<"\n#    "
             <<"\n#    Supposons que l'on veuille que E3 soit une fonction nD on ecrira: "
             <<"\n#     soit a: "
             <<"\n#        E3= E3_fonction_nD: un_nom_de_fonction_existant "
             <<"\n#     soit b: "
             <<"\n#        E3= E3_fonction_nD: un_nom_de_type_de_fonction_existant "
             <<"\n#      suivit sur la ligne suivante de la definition specifique de la fonction "
             <<"\n# "
             <<"\n#    exemple d'un cas a: "
             <<"\n#        E3= E3_fonction_nD: f1_temperature  "
             <<"\n#      fi_temperature doit alors avoir ete definie dans les fonctions nD"
             <<"\n# "
             <<"\n#    exemple d'un cas b: "
             <<"\n#        E3= E3_fonction_nD: FONCTION_EXPRESSION_LITTERALE_nD  "
             <<"\n#               deb_list_var_ TEMP  fin_list_var_  "
             <<"\n#               fct= (100726-101325)/50*TEMP + 101325  "
             <<"\n#               fin_parametres_fonction_expression_litterale_  "
             <<"\n# "
             <<"\n# Remarques: "
             <<"\n#    a) apres chaque definition d'une fonction nD on change de ligne "
             <<"\n#    b) pour les autres coefficients, on remplace E3 par E1, ou E2, ou"
             <<"\n#       nu12 ou nu13 ou n23 ou G12 ou G13 ou G23 "
             <<"\n# "
             <<"\n# 2) Par defaut, la base initiale d'orthotropie est transportee dans l'etat courant "
             <<"\n#    via une methode de type transport contravariant (cf. doc) "
             <<"\n#    Il est possible d'indiquer un transport de type covariant. Pour ce faire "
             <<"\n#    on utilise le mot cle: type_transport_ suivi de 0 ou 1 "
             <<"\n#    0 : pour un transport de type contravariant (valeur par defaut) "
             <<"\n#    1 : pour un transport de type covariant "
             <<"\n# "
             <<"\n# 3)  le type de derivee objective utilisee pour la contrainte, est optionnel: "
             << "\n# = -1 -> derivee de jauman (valeur par defaut), "
             << "\n# = 0 -> derivee deux fois covariantes (ou de Rivlin), "
             << "\n# = 1 -> derivee deux fois contravariantes (ou d'Oldroyd)"
             << "\n# dans le cas ou l'on veut une valeur differente de la valeur par defaut il faut mettre le mot cle"
             << "\n# type_derivee suivi de la valeur -1 ou 0 ou 1"
             <<"\n# "
             <<"\n# 4)"
             << "\n# -------------- affichage des erreurs et des warning ---------- "
             << "\n# - l'affichage normale est fonction du parametre global d'affichage gerer"
             << "\n# par le niveau d'affichage cependant pour des raisons par exemple de mise au point,"
             << "\n#  il est possible de permettre l'affichage  a un niveau particulier "
             << "\n#  (mot cle : permet_affichage_ suivi d'un nombre entier) en plus de l'affichage normal. "
             << "\n# l'affichage s'effectuera donc en fonction de l'affichage normale et de l'affichage particulier."
             << "\n# Le fonctionnement de l'affichage particulier suit les mêmes règles que l'affichage globale"
             << "\n# soit permet_affichage_ est nulle (cas par defaut), dans ce cas l'affichage est fonction du niveau global"
             << "\n# soit permet_affichage_ vaut n par exemple, dans ce cas l'affichage est fonction uniquement de n "
             << "\n# "
             << "\n# ex: permet_affichage_ 5  "
             << "\n#             "
             <<"\n# "
             <<"\n# 5) Il est possible de calculer que la partie spherique du tenseur de contrainte "
             <<"\n#    ou que la partie deviatorique "
             <<"\n#   Pour ce faire on indique a la suite des autres parametres:"
             <<"\n#    soit le mot clef : seule_deviatorique "
             <<"\n#    soit le mot clef : seule_spherique "
             <<"\n# "
             <<"\n# "
             << "\n# 6) --------------- acces en sortie a des grandeurs intermediaires de calcul  -------"
             << "\n#  A chaque resolution, il est possible de stocker:  "
             << "\n#  - le tenseur des contraintes exprime dans le repere d'anisotropie "
             << "\n#  - le tenseur des deformation exprime dans le repere d'anisotropie "
             << "\n#  - les parametres d'orthotropie entrainee: interessant s'ils varient  "
             << "\n#  le mot cle est sortie_post_ , par defaut il vaut 0, dans ce cas aucun indicateur n'est stoke"
             << "\n#  s'il est different de 0, on peut acceder aux grandeurs "
             << "\n#  seules les grandeurs en cours sont disponibles, il n'y a pas de stockage sur plusieurs increment "
             << "\n# "
             << "\n# ex: sortie_post_ 1 "
             << "\n# "
             <<"\n# "
             ;
      };

    // appel de la classe mère
    Loi_comp_abstraite::Info_commande_don_LoisDeComp(entreePrinc);     
  };  		  	  

// test si la loi est complete
int Hypo_ortho3D_entrainee::TestComplet()
    { int ret = LoiAbstraiteGeneral::TestComplet();
  
      // pour faire une boucle  on constitue un tableau de mots clés
      Tableau <string > tab_mot_cle(9);
      tab_mot_cle(1) = "E1";tab_mot_cle(2) = "E2";tab_mot_cle(3) = "E3";
      tab_mot_cle(4) = "nu12";tab_mot_cle(5) = "nu13";tab_mot_cle(6) = "nu23";
      tab_mot_cle(7) = "G12";tab_mot_cle(8) = "G13";tab_mot_cle(9) = "G23";
      // puis un tableau pour les valeurs
      Tableau < double * > coef(9);
      coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
      coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
      coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
      for (int i=1;i<=9;i++)
       if ((*coef(i) == -ConstMath::trespetit) && (fct_para(i) == NULL))
         {string mot_cle1=tab_mot_cle(i)+"= ";
          cout <<  mot_cle1  << " n'est pas defini \n " ;
          ret = 0;
         };
      // test du cas de calcul
      if ((cas_calcul < 0) || (cas_calcul > 2))
       { cout << "\n l'indicateur de calcul cas_calcul= " << cas_calcul << " n'est pas correcte "
              << "\n ceci pour la Hypo_ortho3D_entrainee";
         ret = 0;
       };
      // le nom du repère associé
      if (nom_repere.length() == 0)
       { cout << "\n le nom du repere assoce  n'est pas defini "
              << "\n ceci pour la Hypo_ortho3D_entrainee";
         ret = 0;
       };

      // info globale disponible actuellement
      if (!ret)
       { cout << "\n loi ortho elastique incomplete : ";
         Affiche();
       };
      // retour
      return ret;
    }; 



// récupération des grandeurs particulière (hors ddl )
// correspondant à liTQ
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Hypo_ortho3D_entrainee::Grandeur_particuliere
              (bool ,List_io<TypeQuelconque>& liTQ,Loi_comp_abstraite::SaveResul * saveDon,list<int>& decal) const
{  // ici on est en 3D et les grandeurs sont par principe en locale, donc la variable absolue ne sert pas
   // on passe en revue la liste
   List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
   list<int>::iterator idecal=decal.begin();
   for (itq=liTQ.begin();itq!=itqfin;itq++,idecal++)
     {TypeQuelconque& tipParticu = (*itq); // pour simplifier
      if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
       switch (tipParticu.EnuTypeQuelconque().EnumTQ())
       {  case REPERE_D_ANISOTROPIE:
           // a) ----- cas du repère d'anisotropie
            { SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveDon);
              Tab_Grandeur_BaseH& tyTQ= *((Tab_Grandeur_BaseH*) (*itq).Grandeur_pointee()); // pour simplifier
              tyTQ(1+(*idecal))=save_resul.Op_H;
             
//////----- debug
//cout << "\n debug Hypo_ortho3D_entrainee::Grandeur_particuliere(.. "
//     << "\n save_resul.Op_H: "<< save_resul.Op_H << "\n ";
//Signature_pti_encours(cout);
//
//////----- fin debug
                                     
              (*idecal)++; break;
            }
          case EPS_TRANSPORTEE_ANISO:
           //  ----- cas de la déformation transportée dans le repère d'orthotropie
            { SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveDon);

              Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
              if (sortie_post) {tyTQ(1+(*idecal))=  *(save_resul.eps_loc_HH);}
              else {tyTQ(1+(*idecal)).Inita(0.);};
              (*idecal)++; break;
            }
          case SIGMA_DANS_ANISO:
           //  ----- cas de la contrainte calculée dans le repère d'orthotropie
            { SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveDon);
              Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
              if (sortie_post) {tyTQ(1+(*idecal))=  *(save_resul.sig_loc_HH);}
              else {tyTQ(1+(*idecal)).Inita(0.);};
              (*idecal)++; break;
            }
          case DELTA_EPS_TRANSPORTEE_ANISO:
           //  ----- cas de la déformation transportée dans le repère d'orthotropie
            { SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveDon);

              Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
              if (sortie_post) {tyTQ(1+(*idecal))=  *(save_resul.delta_eps_loc_HH);}
              else {tyTQ(1+(*idecal)).Inita(0.);};
              (*idecal)++; break;
            }
          case DELTA_SIGMA_DANS_ANISO:
           //  ----- cas de la contrainte calculée dans le repère d'orthotropie
            { SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveDon);
              Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
              if (sortie_post) {tyTQ(1+(*idecal))=  *(save_resul.delta_sig_loc_HH);}
              else {tyTQ(1+(*idecal)).Inita(0.);};
              (*idecal)++; break;
            }
          case PARA_ORTHO:
           //  ----- cas des paramètres d'orthotropie
            { SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveDon);
              Tab_Grandeur_Vecteur& tyTQ= *((Tab_Grandeur_Vecteur*) (*itq).Grandeur_pointee()); // pour simplifier
              if (sortie_post) {tyTQ(1+(*idecal))=  *(save_resul.para_loi);}
              else {tyTQ(1+(*idecal)).Zero();};
              (*idecal)++; break;
            }

          default: ;// on ne fait rien
       };

     };
};

// récupération et création de la liste de tous les grandeurs particulières
// ces grandeurs sont ajoutées à la liste passées en paramètres
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Hypo_ortho3D_entrainee::ListeGrandeurs_particulieres(bool absolue,List_io<TypeQuelconque>& liTQ) const
 {
  
  //  $$$ cas du repère local d'orthotropie
  int dim_espace = 3;
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == REPERE_D_ANISOTROPIE)
      { Tab_Grandeur_BaseH& tyTQ= *((Tab_Grandeur_BaseH*) (*itq).Grandeur_pointee()); // pour simplifier
        int taille = tyTQ.Taille()+1;
        tyTQ.Change_taille(taille); nexistePas = false;
      };
   if (nexistePas)
     {Grandeur_BaseH v_rep(dim_espace,3);
      Tab_Grandeur_BaseH grand5(v_rep,1); // def d'une grandeur courante 
      TypeQuelconque typQ6(REPERE_D_ANISOTROPIE,EPS11,grand5);
      liTQ.push_back(typQ6);
     };
  };
  
  // ---- la suite dépend de l'indicateur : sortie_post
  if (sortie_post)
   {   // $$$ cas de la déformation transportée dans le repère d'orthotropie
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == EPS_TRANSPORTEE_ANISO)
        {Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TenseurHH* tens = NevezTenseurHH(3); // un tenseur typique
        Tab_Grandeur_TenseurHH eps_loc_HH(*tens,1);
        // def d'un type quelconque représentatif
        TypeQuelconque typQ(EPS_TRANSPORTEE_ANISO,EPS11,eps_loc_HH);
        liTQ.push_back(typQ);
        delete tens; // car on n'en a plus besoin
      };
    };
    // $$$ cas de la contrainte calculée dans le repère d'orthotropie
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == SIGMA_DANS_ANISO)
        {Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TenseurHH* tens = NevezTenseurHH(3); // un tenseur typique
        Tab_Grandeur_TenseurHH eps_loc_HH(*tens,1);
        // def d'un type quelconque représentatif
        TypeQuelconque typQ(SIGMA_DANS_ANISO,SIG11,eps_loc_HH);
        liTQ.push_back(typQ);
        delete tens; // car on n'en a plus besoin
      };
    };
   // $$$ cas de delta déformation transportée dans le repère d'orthotropie
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == DELTA_EPS_TRANSPORTEE_ANISO)
        {Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TenseurHH* tens = NevezTenseurHH(3); // un tenseur typique
        Tab_Grandeur_TenseurHH delta_eps_loc_HH(*tens,1);
        // def d'un type quelconque représentatif
        TypeQuelconque typQ(DELTA_EPS_TRANSPORTEE_ANISO,EPS11,delta_eps_loc_HH);
        liTQ.push_back(typQ);
        delete tens; // car on n'en a plus besoin
      };
    };
    // $$$ cas de la contrainte calculée dans le repère d'orthotropie
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == DELTA_SIGMA_DANS_ANISO)
        {Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TenseurHH* tens = NevezTenseurHH(3); // un tenseur typique
        Tab_Grandeur_TenseurHH delta_sig_loc_HH(*tens,1);
        // def d'un type quelconque représentatif
        TypeQuelconque typQ(DELTA_SIGMA_DANS_ANISO,SIG11,delta_sig_loc_HH);
        liTQ.push_back(typQ);
        delete tens; // car on n'en a plus besoin
      };
    };
    // $$$ cas des paramètres de la loi de comportement
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == PARA_ORTHO)
        {Tab_Grandeur_Vecteur& tyTQ= *((Tab_Grandeur_Vecteur*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {Vecteur  tens(9); // les 9 paramètres
        Tab_Grandeur_Vecteur gr_vec_para(tens,1);
        // def d'un type quelconque représentatif
        TypeQuelconque typQ(PARA_ORTHO,EPS11,gr_vec_para);
        liTQ.push_back(typQ);
      };
    };

   }; // fin du cas ou sortie_post est actif, c-a-d que l'on veut des infos sur les indicateurs
   // de résolution

 };


	   //----- lecture écriture de restart -----
	   // cas donne le niveau de la récupération
       // = 1 : on récupère tout
       // = 2 : on récupère uniquement les données variables (supposées comme telles)
void Hypo_ortho3D_entrainee::Lecture_base_info_loi(istream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
	{ string toto,nom;
   if (cas == 1)
    { ent >> nom ;
      if (nom != "ORTHOELAS3D")
       {cout <<"\n *** erreur en lecture du type de la loi de comportement, on attendait"
             << " la chaine de caracteres: ORTHOELAS3D et on a lu "
             << nom <<" !!! on ne peut pas continuer "
             << "\n Hypo_ortho3D_entrainee::Lecture_base_info_loi(.. "
             << flush;
        Sortie(1);
       };
      // pour faire une boucle  on constitue un tableau de mots clés
      Tableau <string > tab_mot_cle(9);
      tab_mot_cle(1) = "E1";tab_mot_cle(2) = "E2";tab_mot_cle(3) = "E3";
      tab_mot_cle(4) = "nu12";tab_mot_cle(5) = "nu13";tab_mot_cle(6) = "nu23";
      tab_mot_cle(7) = "G12";tab_mot_cle(8) = "G13";tab_mot_cle(9) = "G23";
      // puis un tableau pour les valeurs
      Tableau < double * > coef(9);
      coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
      coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
      coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
      // cela va permettre de choisir entre une valeur fixe et une fonction nD
      for (int i=1;i<10;i++)
        { ent >> toto >> nom;
          string mot_cle2=tab_mot_cle(i)+"_fonction_nD:";
          if (nom == mot_cle2)
            // cas d'une fonction nD
            {fct_para(i) = lesFonctionsnD.Lecture_pour_base_info(ent,cas,fct_para(i));
            }
          else // cas d'une valeur fixe
           {(*coef(i)) = ChangeReel(nom);};
        };
      // lecture du repère associé
      ent >> nom >> nom_repere;
      // indicateur pour les calculs partielles
      ent >> nom >> cas_calcul ;
      // le type de transport
      ent >> nom >> type_transport;
      // le type de dérivée objective
      ent >> nom >> type_derive;
      // le niveau d'affichage
      Lecture_permet_affichage(ent,cas,lesFonctionsnD);
      // sortie_post
      ent >> nom >> sortie_post;
    };

	  // appel de la classe mère
	  Loi_comp_abstraite::Lecture_don_base_info(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD); 	 
 };
       // cas donne le niveau de sauvegarde
       // = 1 : on sauvegarde tout
       // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)

void Hypo_ortho3D_entrainee::Ecriture_base_info_loi(ostream& sort,const int cas)
   { if (cas == 1)
       { sort << " ORTHOELAS3D " ;
         // pour faire une boucle  on constitue un tableau de mots clés
         Tableau <string > tab_mot_cle(9);
         tab_mot_cle(1) = "E1";tab_mot_cle(2) = "E2";tab_mot_cle(3) = "E3";
         tab_mot_cle(4) = "nu12";tab_mot_cle(5) = "nu13";tab_mot_cle(6) = "nu23";
         tab_mot_cle(7) = "G12";tab_mot_cle(8) = "G13";tab_mot_cle(9) = "G23";
         // puis un tableau pour les valeurs
         Tableau < const double * > coef(9);
         coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
         coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
         coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
        
         // on boucle sur les 9 coefficients
         sort << "\n loi de comportement orthotrope elastique 3D ";
         for (int i=1;i<10;i++)
          {string mot_cle1=tab_mot_cle(i)+"= ";
           string mot_cle2=tab_mot_cle(i)+"_fonction_nD:";
           sort <<  mot_cle1 ;
           if (fct_para(i) == NULL)
             sort << *coef(i) << " ";
           else
             {sort << mot_cle2 << " ";
              if (fct_para(i)->NomFonction() != "_")
                sort << fct_para(i)->NomFonction();
              else
                fct_para(i)->Affiche();
              sort << "\n";
             };
          };
         // le nom du repère associé
         sort << "\n nom_repere_associe_ "<< nom_repere;
         // indicateur de cas de calcul
         if (cas_calcul != 0)
          { if (cas_calcul == 1)
             {sort << "\n seul_deviatorique ";}
            else if (cas_calcul == 2)
             {sort << " seul_spherique ";}
            else
             {sort << " cas_de_calcul_mal_defini ";};
          };
         // affichage du type de transport
         sort << " type_transport: " << type_transport;
         // type de dérivée objective
         sort << " type_derive_objective: " << type_derive;
         // niveau d'affichage
         Affiche_niveau_affichage(sort,cas);
         sort << " sortie_post: "<<sortie_post;
         sort << endl;
       };
   // appel de la classe mère
	  Loi_comp_abstraite::Ecriture_don_base_info(sort,cas);
	};
// calcul d'un module d'young équivalent à la loi pour un chargement nul
double Hypo_ortho3D_entrainee::Module_young_equivalent(Enum_dure temps,const Deformation & def,SaveResul * )
    { /*if (!thermo_dependant)
	       { return E;}
	     else
	       { temperature_tdt = def.DonneeInterpoleeScalaire(TEMP,temps);
          return E_temperature->Valeur(temperature_tdt);
        };
*/
     cout << "\n *** attention, methode non implante: "
          << "\n Hypo_ortho3D_entrainee::Module_young_equivalent(...";
     Sortie(1);
    };
	  
// récupération d'un module de compressibilité équivalent à la loi pour un chargement nul
// il s'agit ici de la relation -pression = sigma_trace/3. = module de compressibilité * I_eps
double Hypo_ortho3D_entrainee::Module_compressibilite_equivalent(Enum_dure temps,const Deformation & def,SaveResul * )
    {
     if (null_fct_para)
      {double unsurKs1 = 1./E1 - nu12/E1 -nu13/E1;
       double unsurKs2 = -nu12/E1+1./E2-nu23/E2;
       double unsurKs3 = -nu13/E1-nu23/E2+1./E3;
       double module_compressibilite = 1./9.*(1./unsurKs1+1./unsurKs2+1./unsurKs3);
       return module_compressibilite;
      }
     else
      {
        cout << "\n *** attention, methode non implante: "
             << "\n Hypo_ortho3D_entrainee::Module_compressibilite_equivalent(...";
        Sortie(1);
      };

    
    /* if (!thermo_dependant)
	       { return E/(3.*(1.-2.*nu));}
	      else
	       { temperature_tdt = def.DonneeInterpoleeScalaire(TEMP,temps);
          return E_temperature->Valeur(temperature_tdt)/(3.*(1.-2.*nu));
        };
*/	   };

 // ========== codage des METHODES VIRTUELLES  protegees:================
//  virtual void Calcul_SigmaHH
//     (TenseurHH & sigHH_t,TenseurBB& DepsBB,DdlElement & tab_ddl
//      ,TenseurBB & gijBB_t,TenseurHH & gijHH_t,BaseB& giB,BaseH& gi_H,TenseurBB & epsBB
//      ,TenseurBB & delta_epsBB,TenseurBB & gijBB,TenseurHH & gijHH,Tableau <TenseurBB *>& d_gijBB
//      ,double& jacobien_0,double& jacobien,TenseurHH & sigHH
//      ,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double&  module_cisaillement
//      ,const Met_abstraite::Expli_t_tdt& ex) = 0;        // calcul des contraintes a t+dt
void Hypo_ortho3D_entrainee::Calcul_SigmaHH (TenseurHH& sigHH_t,TenseurBB& ,DdlElement & tab_ddl
             ,TenseurBB & gijBB_t,TenseurHH & ,BaseB& ,BaseH& ,TenseurBB&  epsBB_
             ,TenseurBB&  delta_epsBB_,TenseurBB& gijBB_
             ,TenseurHH & gijHH_,Tableau <TenseurBB *>& d_gijBB_,double& ,double&
             ,TenseurHH & sigHH_,EnergieMeca & energ,const EnergieMeca & energ_t
             ,double& module_compressibilite,double&  module_cisaillement
             ,const Met_abstraite::Expli_t_tdt& ex)
 {   
    #ifdef MISE_AU_POINT
    if (epsBB_.Dimension() != 3)
       { cout << "\nErreur : la dimension devrait etre 3 !\n";
      cout << " Hypo_ortho3D_entrainee::Calcul_SigmaHH\n";
      Sortie(1);
    };
    #endif

    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_); // passage en dim 3
    const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_); // passage en dim 3
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_); //   "      "  "  "
    const Tenseur3BB & gijBB = *((Tenseur3BB*) &gijBB_); //   "      "  "  "
    Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_);  //   "      "  "  "
    Tenseur3HH & sigHH_nn = *((Tenseur3HH*) &sigHH_t);  //   "      "  "  "

 // --- opération de transport du tenseur sigma(t), de t à tdt
    // tenseur intermédiaires utilisées selon les cas (par forcément dans tous les cas !!)
    Tenseur3BH sigBH_n;Tenseur3HH sigHH_n; Tenseur3BB sigBB_n;Tenseur3BB sig_interBB_n;
    switch (type_derive) //case 1: cas d'une dérivée de Lie deux fois contravariante : cas par défaut
     {case -1: // cas d'une dérivée de jauman: 1/2 deux fois covariant + deux fois contra
        {sig_interBB_n = gijBB_t * sigHH_nn * gijBB_t;
         sigBH_n = 0.5*( sig_interBB_n * gijHH + gijBB * sigHH_nn) ;
         sigHH_n = gijHH * sigBH_n ;
         sigBB_n = sigBH_n * gijBB; break;}
      case 0: // cas d'une dérivée de Lie deux fois covariantes
        {sigBB_n = gijBB_t * sigHH_nn * gijBB_t;
         sigBH_n = sigBB_n * gijHH ;
         sigHH_n = gijHH * sigBH_n ; break;}
      case 1: // cas d'une dérivée de Lie deux fois contravariantes
        {sigHH_n = sigHH_nn;
         sigBH_n = gijBB * sigHH_n;
         sigBB_n = sigBH_n * gijBB;
         break;}
     };
 // ---- calcul relatif à l'incrément de contrainte  -----

    Tenseur3BH  epsBH = epsBB * gijHH;  // deformation en mixte
  
    //----  le repère d'anisotropie
    // récup du conteneur spécifique
    SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveResul);
    // on commence par calculer le repère d'orthotropie transporté
    // Op_H_i sont les coordonnées contravariantes de la nouvelle base
    // donc par rapport à g_i,
    BaseH& Op_H = save_resul.Op_H;
    Tableau <double> tab_norme(3);
    if (type_transport == 0)
      // transport de type contravariant
     { // on calcule les coordonnées de la base O' dans la base naturelle
      #ifdef MISE_AU_POINT
      if (save_resul.O_H == NULL)
        {cout << "\n  *** erreur, le repere d'anisotropie n'est pas defini "
              <<"on ne peut pas continuer " << flush ;
         cout << " Hypo_ortho3D_entrainee::Calcul_SigmaHH\n";
         Sortie(1);
        };
      #endif
      BaseH& O_H = (*save_resul.O_H); // coordonnées en absolu de la base d'orthotropie
      // calcul des coordonnées alpha_a^{.i} = O_H(a) * g^i  à t= 0
      for (int a = 1;a < 4; a++)
        {CoordonneeH& inter = alpha_H.CoordoH(a);
         for (int i=1;i < 4;i++)
           inter(i)= O_H(a).ScalHH((*ex.giH_0)(i));
        };

      // calcule des beta_a^{.i} tel que O'_a = beta_a^{.i} \hat{g}_i   donc au temps t+dt
      for (int a=1; a<4;a++)
       { // tout d'abord la base non normalisée
         // Op_H(a) non normé a les mêmes coordonnées alpha_a^{.j}
         // mais exprimés dans le repère actuel \hat \vec g_j
         CoordonneeH& Op_H_a = Op_H.CoordoH(a);
         Op_H_a = alpha_H(a);
         // calcul de la norme du vecteur Op_H_a
         double norme = sqrt(Op_H_a * gijBB * Op_H_a);
         tab_norme(a) = norme;
         // coordonnées finales
         Op_H_a /= norme;
//cout << "\n  Op_H("<<a<<"): ";
//Op_H_a.Affiche();
//cout << "\n  alpha_H("<<a<<"): ";
//alpha_H(a).Affiche();
//cout << "\n giB_tdt"; (*ex.giB_tdt)(a).Affiche();
       };
     }
    else
      // transport de type covariant
     { // on calcule les coordonnées de la base O' dans la base duale
      #ifdef MISE_AU_POINT
      if (save_resul.O_B == NULL)
        {cout << "\n  *** erreur, le repere d'anisotropie n'est pas defini "
              <<"on ne peut pas continuer " << flush ;
         cout << " Hypo_ortho3D_entrainee::Calcul_SigmaHH\n";
         Sortie(1);
        };
      #endif
      BaseB& O_B = (*save_resul.O_B); // pour simplifier
      for (int a=1; a<4;a++)
       { // tout d'abord la base non normalisée
         CoordonneeB& Op_B_a = Op_B.CoordoB(a);
         // calcul de la norme du vecteur Op_B_a
         double norme = sqrt(Op_B_a * gijHH * Op_B_a);
         // coordonnées finales
         Op_B_a /= norme;
       };
      // maintenant on calcule la base Op_H correspondante
      for (int i=1; i<4;i++)
         Op_H.CoordoH(i) = Op_B.CoordoB(i) * gijHH;
     };
    // on calcul la matrice de passage de la base g_i vers la base O'_i
    // O'_i = beta_i^{.j} * g_j
    // et on a également \hat{\vec g}^i = {\beta}_{a}^{.i}~\hat{\vec O'}^a
    // comme O'_i est déjà exprimé dans g_j, ses coordonnées sont directement béta
    for (int i=1; i<4;i++)
      for (int j=1; j<4;j++)
         { beta(i,j) = Op_H(i)(j);};
    // puis on calcul les coordonnées de la base duale
    beta_transpose = beta.Transpose();
    gamma = beta_transpose.Inverse();
    gamma_transpose = gamma.Transpose();
//cout << "\n beta: ";beta.Affiche();
//cout << "\n beta_transpose: ";beta_transpose.Affiche();
//cout << "\n gamma: ";gamma.Affiche();
//cout << "\n gamma_transpose: ";gamma_transpose.Affiche();

    // changement de base (cf. théorie) : la matrice beta est telle que:
    // gpB(i) = beta(i,j) * gB(j) <==> gp_i = beta_i^j * g_j

    // calcul des coordonnées de l'incrément de déformation dans le repère O'^i
    // c-a-d les coordonnées dans le dual de O'_i
//    Tenseur3BB  delta_eps_p_BB(delta_epsBB);
//cout <<"\n delta_eps_p_BB: "; delta_eps_p_BB.Ecriture(cout);
    // il faut passer en 2 fois contravariant
    Tenseur3HH delta_eps_p_HH = gijHH * delta_epsBB * gijHH;
    delta_eps_p_HH.ChBase(gamma); // res = (gamma * res) * gamma.Transpose();
//cout <<"\n delta_eps_p_HH: "; delta_eps_p_HH.Ecriture(cout);
//Tenseur3HH  toto(delta_eps_p_HH);
//toto.ChBase(beta_transpose);
//cout << "\n retour dans la base g^i de eps^{ij} :";toto.Ecriture(cout);
//Tenseur3BB  titi(gijBB * toto * gijBB);
//cout << "\n delta def eps_ij :";titi.Ecriture(cout);

    double untiers = 1./3.;

    // dans le cas de fonctions nD récupération des valeurs
    if (!null_fct_para)
//  Tableau <Fonction_nD* > fct_para; // fonction nD éventuelle d'évolution des paramètres
     {// un tableau de travail pour les valeurs sous forme indicée
      Tableau < double * > coef(9);
      coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
      coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
      coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
      // opération de transmission de la métrique
      const Met_abstraite::Impli* ex_impli = NULL;
      const Met_abstraite::Expli_t_tdt* ex_expli_tdt = &ex;
      const Met_abstraite::Umat_cont* ex_expli = NULL;

      // on passe en revue les fonctions nD
      for (int i=1;i<10;i++)
       {if (fct_para(i) != NULL)
         { Fonction_nD* pt_fonct = fct_para(i); // pour simplifier
         
           // on utilise la méthode générique de loi abstraite
           Tableau <double> & tab_val = Loi_comp_abstraite::Loi_comp_Valeur_FnD_Evoluee
               (pt_fonct,1 // une seule valeur attendue en retour
                ,ex_impli,ex_expli_tdt,ex_expli
                ,NULL
                ,NULL
                ,NULL
               );

/*           // ici on utilise les variables connues aux pti, ou calculées à partir de
           // on commence par récupérer les conteneurs des grandeurs à fournir
           List_io <Ddl_enum_etendu>& li_enu_scal = pt_fonct->Li_enu_etendu_scalaire();
           List_io <TypeQuelconque >& li_quelc = pt_fonct->Li_equi_Quel_evolue();
           bool absolue = true; // on se place systématiquement en absolu
           // on va utiliser la méhode Valeur_multi_interpoler_ou_calculer
           // pour les grandeurs strictement scalaire
            Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
                        (absolue,TEMPS_tdt,li_enu_scal,ex_impli,ex_expli_tdt,ex_expli,NULL)
                                          );
           // on utilise la méthode Valeurs_Tensorielles_interpoler_ou_calculer
           // pour les Coordonnees et Tenseur
           Valeurs_Tensorielles_interpoler_ou_calculer
                         (absolue,TEMPS_tdt,li_quelc,ex_impli,ex_expli_tdt,ex_expli,NULL);
           // calcul de la valeur et retour dans tab_ret
           Tableau <double> & tab_val = pt_fonct->Valeur_FnD_Evoluee(&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
           #ifdef MISE_AU_POINT
           if (tab_val.Taille() != 1)
              { cout << "\nErreur : la fonction nD relative au parametre materiau " << i
                     << " doit calculer un scalaire or le tableau de retour est de taille "
                     << tab_val.Taille() << " ce n'est pas normal !\n";
                cout << " Hypo_ortho3D_entrainee::Calcul_SigmaHH\n";
                Sortie(1);
              };
           #endif
*/
           // on récupère le premier élément du tableau uniquement
           (*coef(i)) = tab_val(1);
         };
       };
     };
    // puis fabrication de la matrice inv_loi
    {// on commence par remplir la matrice
     inv_loi(1,1) = 1./E1;inv_loi(2,2) = 1./E2;inv_loi(3,3) = 1./E3;
     inv_loi(1,2) = inv_loi(2,1) = -nu12/E1;
     inv_loi(1,3) = inv_loi(3,1) = -nu13/E1;
     inv_loi(3,2) = inv_loi(2,3) = -nu23/E2;
     inv_loi = inv_loi.Inverse(); // on inverse la matrice
    };
    // calcul de l'accroissement des contraintes dans le repère O_p
    Vecteur delta_eps_ii(3);Vecteur delta_sig_ii(3);
    for (int i=1; i<4;i++)
      delta_eps_ii(i) = delta_eps_p_HH(i,i);
    delta_sig_ii = inv_loi * delta_eps_ii;
//    Tenseur3HH sig_HH;
    // l'accroissement est stocké momentanément dans sigHH
    // ensuite on ajoutera la contrainte à t transportée de t à tdt
    for (int i=1; i<4;i++)
      {sigHH.Coor(i,i) = delta_sig_ii(i);
      };
    sigHH.Coor(1,2) = 2.* G12 * delta_eps_p_HH(1,2);
    sigHH.Coor(1,3) = 2.* G13 * delta_eps_p_HH(1,3);
    sigHH.Coor(2,3) = 2.* G23 * delta_eps_p_HH(2,3);
  
     // dans le cas où on veut une sortie des grandeurs on sauvegarde
    if (sortie_post)
     { if (save_resul.delta_eps_loc_HH == NULL)
         {save_resul.delta_eps_loc_HH = NevezTenseurHH(3);
          save_resul.delta_sig_loc_HH = NevezTenseurHH(3);
          save_resul.para_loi = new Vecteur (9);
          save_resul.eps_loc_HH = NevezTenseurHH(3);
          save_resul.sig_loc_HH = NevezTenseurHH(3);
         };
       (*save_resul.delta_eps_loc_HH) = delta_eps_p_HH;
       (*save_resul.delta_sig_loc_HH) = sigHH;
       // paramètres de la loi
       (*save_resul.para_loi)(1) = E1; (*save_resul.para_loi)(2) =  E2;
       (*save_resul.para_loi)(3) = E3;
       (*save_resul.para_loi)(4) =  nu12; (*save_resul.para_loi)(5) =  nu13;
       (*save_resul.para_loi)(6) =  nu23;
       (*save_resul.para_loi)(7) =  G12; (*save_resul.para_loi)(8) =  G13;
       (*save_resul.para_loi)(9) =  G23;
     };

    // calcul de l'acroissement des contraintes dans le repère g_i
    // l'inverse de gamma c'est beta transposée
    sigHH.ChBase(beta_transpose);
    // maintenant on ajoute les contraintes à t, transportées
    sigHH += sigHH_n;
  
    // dans le cas où on veut une sortie des grandeurs locale on sauvegarde
    if (sortie_post)
     { Tenseur3HH eps_p_HH = gijHH * epsBB * gijHH;
       eps_p_HH.ChBase(gamma);
       Tenseur3HH sig_p_HH(sigHH);
       sig_p_HH.ChBase(gamma);
       (*save_resul.eps_loc_HH) = eps_p_HH;
       (*save_resul.sig_loc_HH) = sig_p_HH;
     };
  
//    beta_inv = beta.Inverse();
//    sig_BB.ChBase(beta_inv);
    // passage dans la bonne variance
    Tenseur3BH sigBH = gijBB * sigHH ;
    switch (cas_calcul)
     { case 0: // calcul normal (tous les termes)
        { // on ne fait rien de spécial
          break;
        }
       case 1: // calcul de la partie déviatorique seule
        { double trace_sig = sigBH.Trace();
          sigBH -= (untiers * trace_sig) * IdBH3;
          sigHH -= (untiers * trace_sig) * gijHH;
          break;
        }
       case 2: // calcul de la partie sphérique seule
        { double trace_sig = sigBH.Trace();
          sigBH = (untiers * trace_sig) * IdBH3;
          sigHH = (untiers * trace_sig) * gijHH;
          break;
        }
       default:
        { cout << "\n erreur l'indicateur cas_calcul= " << cas_calcul << " n'a pas une valeur correcte !! "
               << "\n Hypo_ortho3D_entrainee::Calcul_SigmaHH (.... ";
          Sortie(1);
        }
     };
//----------------- debug
//    const Tenseur3BB & gijBB = *((Tenseur3BB*) &gijBB_tdt); // passage en dim 3
//cout << "\n epsBB="<<epsBB << " gijBB_tdt= " << gijBB << " gijHH_tdt= " << gijHH<<" ";
//cout << "\n sighh="<<sigHH<<" "<< endl ;
//----------- fin debug

    // traitement des énergies
    // arbitrairement, on considère qu'il s'agit d'un accroissement d'énergie élastique
    energ.Inita(0.); 
    energ.ChangeEnergieElastique(energ_t.EnergieElastique() + 0.5 * (sigHH && delta_epsBB));
    // -- calcul des modules
    // on n'utilise plus la forme linéaire, mais à la place la variation relative de volume
    // constaté, au sens d'une mesure logarithmique, sauf dans le cas où cette variation est trop petite
    //module_compressibilite = E/(3.*(1.-2.*nu));
    //  calcul de la valeur de la variation relative de volume en log
    double log_var_vol = log((*(ex.jacobien_tdt))/(*(ex.jacobien_0)));
    // pour le module de compressibilité, choix entre les différents cas
    if ((cas_calcul == 0) || (cas_calcul == 2))
     {if (Dabs(log_var_vol) > ConstMath::petit)
        {module_compressibilite = untiers * sigBH.Trace() / (log_var_vol);}
      else // si la variation de volume est trop faible on passe par la moyenne
           // des compressibilités dans les 3 directions d'orthotropie (cf. théorie)
        {double unsurKs1 = 1./E1 - nu12/E1 -nu13/E1;
         double unsurKs2 = -nu12/E1+1./E2-nu23/E2;
         double unsurKs3 = -nu13/E1-nu23/E2+1./E3;
         module_compressibilite = untiers*untiers*(1./unsurKs1+1./unsurKs2+1./unsurKs3);
        };
     }
    else
     // dans le cas d'une loi purement déviatorique, le module de compressibilité = 0 (approximativement)
     {module_compressibilite = 0.;};
    // pour la partie cisaillement on garde la forme associée à la loi
    // on prend la moyenne des 3
    if ((cas_calcul == 0) || (cas_calcul == 1))
      {module_cisaillement = untiers * 2. * (G12+G13+G23);}
    else
      // en purement sphérique, le module est supposé nul
      {module_cisaillement = 0.; };

    LibereTenseur();   
 };
        
        // calcul des contraintes a t+dt et de ses variations  
// void Calcul_DsigmaHH_tdt (TenseurHH & sigHH_t,TenseurBB& DepsBB,DdlElement & tab_ddl
//     ,BaseB& giB_t,TenseurBB & gijBB_t,TenseurHH & gijHH_t
//     ,BaseB& giB_tdt,Tableau <BaseB> & d_giB_tdt,BaseH& giH_tdt,Tableau <BaseH> & d_giH_tdt
//     ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *>& d_epsBB
//     ,TenseurBB & delta_epsBB,TenseurBB & gijBB_tdt,TenseurHH & gijHH_tdt
//     ,Tableau <TenseurBB *>& d_gijBB_tdt
//     ,Tableau <TenseurHH *>& d_gijHH_tdt,double& jacobien_0,double& jacobien
//     ,Vecteur& d_jacobien_tdt,TenseurHH& sigHH,Tableau <TenseurHH *>& d_sigHH
//     ,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double&  module_cisaillement
//     ,const Met_abstraite::Impli& ex);
void Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt (TenseurHH& sigHH_t,TenseurBB& ,DdlElement & tab_ddl
         ,BaseB& ,TenseurBB & gijBB_t_,TenseurHH &
         ,BaseB& ,Tableau <BaseB> & ,BaseH& ,Tableau <BaseH> &
         ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *>& d_epsBB
         ,TenseurBB & delta_epsBB_,TenseurBB & gijBB_tdt,TenseurHH & gijHH_tdt
		       ,Tableau <TenseurBB *>& d_gijBB_tdt
		  	    ,Tableau <TenseurHH *>& d_gijHH_tdt,double& ,double&
		  	    ,Vecteur& ,TenseurHH& sigHH_tdt,Tableau <TenseurHH *>& d_sigHH
		  	    ,EnergieMeca & energ,const EnergieMeca & energ_t
		  	    ,double& module_compressibilite,double&  module_cisaillement
		  	    ,const Met_abstraite::Impli& ex)
 {
    #ifdef MISE_AU_POINT
    if (epsBB_tdt.Dimension() != 3)
      { cout << "\nErreur : la dimension devrait etre 3 !\n";
        cout << " Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt\n";
        Sortie(1);
      };
    if (tab_ddl.NbDdl() != d_gijBB_tdt.Taille())
      { cout << "\nErreur : le nb de ddl est != de la taille de d_gijBB_tdt  !\n";
        cout << " Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt\n";
        Sortie(1);
      };
    #endif
    
    bool affichage = (Permet_affichage() > 5);
    const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_); // passage en dim 3
    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_tdt); //   "      "  "  "
    Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_tdt);  //   "      "  "  "
    Tenseur3HH & sigHH_nn = *((Tenseur3HH*) &sigHH_t);  //   "      "  "  "
    const Tenseur3BB & gijBB = *((Tenseur3BB*) &gijBB_tdt); //   "      "  "  "
    const Tenseur3BB & gijBB_t = *((Tenseur3BB*) &gijBB_t_); //   "      "  "  "


 // --- opération de transport du tenseur sigma(t), de t à tdt
    // tenseur intermédiaires utilisées selon les cas (par forcément dans tous les cas !!)
    Tenseur3BH sigBH_n;Tenseur3HH sigHH_n; Tenseur3BB sigBB_n;Tenseur3BB sig_interBB_n;
    switch (type_derive) //case 1: cas d'une dérivée de Lie deux fois contravariante : cas par défaut
     {case -1: // cas d'une dérivée de jauman: 1/2 deux fois covariant + deux fois contra
        {sig_interBB_n = gijBB_t * sigHH_nn * gijBB_t;
         sigBH_n = 0.5*( sig_interBB_n * gijHH + gijBB * sigHH_nn) ;
         sigHH_n = gijHH * sigBH_n ;
         sigBB_n = sigBH_n * gijBB; break;}
      case 0: // cas d'une dérivée de Lie deux fois covariantes
        {sigBB_n = gijBB_t * sigHH_nn * gijBB_t;
         sigBH_n = sigBB_n * gijHH ;
         sigHH_n = gijHH * sigBH_n ; break;}
      case 1: // cas d'une dérivée de Lie deux fois contravariantes
        {sigHH_n = sigHH_nn;
         sigBH_n = gijBB * sigHH_n;
         sigBB_n = sigBH_n * gijBB;
         break;}
      };
  
   //----  le repère d'anisotropie
    // récup du conteneur spécifique
    SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveResul);
    // on commence par calculer le repère d'orthotropie transporté
    // Op_H_i sont les coordonnées contravariantes de la nouvelle base
    // donc par rapport à g_i,
    BaseH& Op_H = save_resul.Op_H;
    Tableau <double> tab_norme(3);
    if (type_transport == 0)
      // transport de type contravariant
     { // on calcule les coordonnées de la base O' dans la base naturelle
      #ifdef MISE_AU_POINT
      if (save_resul.O_H == NULL)
        {cout << "\n  *** erreur, le repere d'anisotropie n'est pas defini "
              <<"on ne peut pas continuer " << flush ;
         cout << " Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt\n";
         Sortie(1);
        };
      #endif
      BaseH& O_H = (*save_resul.O_H); // coordonnées en absolu de la base d'orthotropie
      // calcul des coordonnées alpha_a^{.i} = O_H(a) * g^i  à t= 0
      for (int a = 1;a < 4; a++)
        {CoordonneeH& inter = alpha_H.CoordoH(a);
         for (int i=1;i < 4;i++)
           inter(i)= O_H(a).ScalHH((*ex.giH_0)(i));
        };

      // calcule des beta_a^{.i} tel que O'_a = beta_a^{.i} \hat{g}_i   donc au temps t+dt
      for (int a=1; a<4;a++)
       { // tout d'abord la base non normalisée
         // Op_H(a) non normé a les mêmes coordonnées alpha_a^{.j}
         // mais exprimés dans le repère actuel \hat \vec g_j
         CoordonneeH& Op_H_a = Op_H.CoordoH(a); // pour simplifier
         Op_H_a = alpha_H(a);
         // calcul de la norme du vecteur Op_H_a
         double norme = sqrt(Op_H_a * gijBB * Op_H_a);
         tab_norme(a) = norme;
         // coordonnées finales
         Op_H_a /= norme;
         #ifdef MISE_AU_POINT
         if (affichage)
           {cout << "\n  Op_H("<<a<<"): ";
            Op_H_a.Affiche();
            cout << "\n  alpha_H("<<a<<"): ";
            alpha_H(a).Affiche();
            cout << "\n giB_tdt"; (*ex.giB_tdt)(a).Affiche();
            // affichage du repère tournée
            Coordonnee3B V;
            for (int j=1;j<4;j++) V += Op_H_a(j) * (*ex.giB_tdt)(a)(j);
            cout << "\n op_H("<<a<<"):  en absolu " << V ;
           };
         #endif
       };
     }
    else
      // transport de type covariant
     { // on calcule les coordonnées de la base O' dans la base duale
      #ifdef MISE_AU_POINT
      if (save_resul.O_B == NULL)
        {cout << "\n  *** erreur, le repere d'anisotropie n'est pas defini "
              <<"on ne peut pas continuer " << flush ;
         cout << " Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt\n";
         Sortie(1);
        };
      #endif
      BaseB& O_B = (*save_resul.O_B); // pour simplifier
      for (int a=1; a<4;a++)
       { // tout d'abord la base non normalisée
         CoordonneeB& Op_B_a = Op_B.CoordoB(a);
         // calcul de la norme du vecteur Op_B_a
         double norme = sqrt(Op_B_a * gijHH * Op_B_a);
         tab_norme(a) = norme;
         // coordonnées finales
         Op_B_a /= norme;
       };
      // maintenant on calcule la base Op_H correspondante
      for (int i=1; i<4;i++)
         Op_H.CoordoH(i) = Op_B.CoordoB(i) * gijHH;
     };
    // on calcul la matrice de passage de la base g_i vers la base O'_i
    // O'_i = beta_i^{.j} * g_j
    // et on a également \hat{\vec g}^i = {\beta}_{a}^{.i}~\hat{\vec O'}^a
    // comme O'_i est déjà exprimé dans g_j, ses coordonnées sont directement béta
    for (int i=1; i<4;i++)
      for (int j=1; j<4;j++)
         { beta(i,j) = Op_H(i)(j);};
    // puis on calcul les coordonnées de la base duale
    beta_transpose = beta.Transpose();
    gamma = beta_transpose.Inverse();
    gamma_transpose = gamma.Transpose();
    #ifdef MISE_AU_POINT
    if (affichage)
      {cout << "\n beta: ";beta.Affiche();
       cout << "\n beta_transpose: ";beta_transpose.Affiche();
       cout << "\n gamma: ";gamma.Affiche();
       cout << "\n gamma_transpose: ";gamma_transpose.Affiche();
      };
    #endif

    // changement de base (cf. théorie) : la matrice beta est telle que:
    // gpB(i) = beta(i,j) * gB(j) <==> gp_i = beta_i^j * g_j

    // ------- partie déformation
  
    Tenseur3BH  delta_epsBH = delta_epsBB * gijHH;  // accroissement de deformation en mixte
    Tenseur3HH  delta_epsHH = gijHH * delta_epsBH; // en deuxfois contra
    // calcul des coordonnées de l'incrément de déformation dans le repère O'^i
    #ifdef MISE_AU_POINT
    if (affichage)
      { cout <<"\n delta_eps_BB en g^i: "; delta_epsBB.Ecriture(cout);
      };
    #endif

    // c-a-d les coordonnées dans le dual de O'_i
    // il faut passer en 2 fois contravariant
    Tenseur3HH delta_eps_p_HH(delta_epsHH);
    delta_eps_p_HH.ChBase(gamma); // res = (gamma * res) * gamma.Transpose();
    #ifdef MISE_AU_POINT
    if (affichage)
      { cout <<"\n delta_eps_p_HH: "; delta_eps_p_HH.Ecriture(cout);
        Tenseur3HH  toto(delta_eps_p_HH);
        toto.ChBase(beta_transpose);
        cout << "\n retour dans la base g^i de eps^{ij} :";toto.Ecriture(cout);
        Tenseur3BB  titi = gijBB * toto * gijBB;
        cout << "\n def eps_ij :";titi.Ecriture(cout);
      };
    #endif

    static const double untiers = 1./3.;

    // dans le cas de fonctions nD récupération des valeurs
    if (!null_fct_para)
//  Tableau <Fonction_nD* > fct_para; // fonction nD éventuelle d'évolution des paramètres
     {// un tableau de travail pour les valeurs sous forme indicée
      Tableau < double * > coef(9);
      coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
      coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
      coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
      // opération de transmission de la métrique
      const Met_abstraite::Impli* ex_impli = &ex;
      const Met_abstraite::Expli_t_tdt* ex_expli_tdt = NULL;
      const Met_abstraite::Umat_cont* ex_expli = NULL;

      // on passe en revue les fonctions nD
      for (int i=1;i<10;i++)
       {if (fct_para(i) != NULL)
         { Fonction_nD* pt_fonct = fct_para(i); // pour simplifier
           
           // on utilise la méthode générique de loi abstraite
           Tableau <double> & tab_val = Loi_comp_abstraite::Loi_comp_Valeur_FnD_Evoluee
               (pt_fonct,1 // une seule valeur attendue en retour
                ,ex_impli,ex_expli_tdt,ex_expli
                ,NULL
                ,NULL
                ,NULL
               );
         
/*           // ici on utilise les variables connues aux pti, ou calculées à partir de
           // on commence par récupérer les conteneurs des grandeurs à fournir
           List_io <Ddl_enum_etendu>& li_enu_scal = pt_fonct->Li_enu_etendu_scalaire();
           List_io <TypeQuelconque >& li_quelc = pt_fonct->Li_equi_Quel_evolue();
           bool absolue = true; // on se place systématiquement en absolu
           // on va utiliser la méhode Valeur_multi_interpoler_ou_calculer
           // pour les grandeurs strictement scalaire
            Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
                        (absolue,TEMPS_tdt,li_enu_scal,ex_impli,ex_expli_tdt,ex_expli,NULL)
                                          );
           // on utilise la méthode Valeurs_Tensorielles_interpoler_ou_calculer
           // pour les Coordonnees et Tenseur
           Valeurs_Tensorielles_interpoler_ou_calculer
                         (absolue,TEMPS_tdt,li_quelc,ex_impli,ex_expli_tdt,ex_expli,NULL);
           // calcul de la valeur et retour dans tab_ret
           Tableau <double> & tab_val = pt_fonct->Valeur_FnD_Evoluee(&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
           #ifdef MISE_AU_POINT
           if (tab_val.Taille() != 1)
              { cout << "\nErreur : la fonction nD relative au parametre materiau " << i
                     << " doit calculer un scalaire or le tableau de retour est de taille "
                     << tab_val.Taille() << " ce n'est pas normal !\n";
                cout << " Hypo_ortho3D_entrainee::Calcul_SigmaHH\n";
                Sortie(1);
              };
           #endif
*/
           // on récupère le premier élément du tableau uniquement
           (*coef(i)) = tab_val(1);
         };
       };
     };
    // puis fabrication de la matrice inv_loi
    {// on commence par remplir la matrice
     inv_loi(1,1) = 1./E1;inv_loi(2,2) = 1./E2;inv_loi(3,3) = 1./E3;
     inv_loi(1,2) = inv_loi(2,1) = -nu12/E1;
     inv_loi(1,3) = inv_loi(3,1) = -nu13/E1;
     inv_loi(3,2) = inv_loi(2,3) = -nu23/E2;
     inv_loi = inv_loi.Inverse(); // on inverse la matrice
    };
  
    // calcul de l'accroissement des contraintes dans le repère O_p
    Tenseur3HH delta_sig_abij_HH; // au début c'est ab puis après chgt de base devient en ij
    Vecteur delta_eps_ii(3);Vecteur delta_sig_ii(3);
    for (int i=1; i<4;i++)
      delta_eps_ii(i) = delta_eps_p_HH(i,i);
    delta_sig_ii = inv_loi * delta_eps_ii;

    // l'accroissement est stocké dans delta_sig_abij_HH: on en a besoin pour l'opérateur tangent
    // ensuite on ajoutera la contrainte à t transportée de t à tdt
    for (int i=1; i<4;i++)
      delta_sig_abij_HH.Coor(i,i) = delta_sig_ii(i);

    delta_sig_abij_HH.Coor(1,2) = 2.* G12 * delta_eps_p_HH(1,2);
    delta_sig_abij_HH.Coor(1,3) = 2.* G13 * delta_eps_p_HH(1,3);
    delta_sig_abij_HH.Coor(2,3) = 2.* G23 * delta_eps_p_HH(2,3);


    // dans le cas où on veut une sortie des grandeurs on sauvegarde
    if (sortie_post)
     { if (save_resul.eps_loc_HH == NULL)
         {save_resul.eps_loc_HH = NevezTenseurHH(3);
          save_resul.sig_loc_HH = NevezTenseurHH(3);
          save_resul.para_loi = new Vecteur (9);
          save_resul.delta_eps_loc_HH = NevezTenseurHH(3);
          save_resul.delta_sig_loc_HH = NevezTenseurHH(3);
         };
       (*save_resul.delta_eps_loc_HH) = delta_eps_p_HH;
       (*save_resul.delta_sig_loc_HH) = delta_sig_abij_HH;
       // paramètres de la loi
       (*save_resul.para_loi)(1) = E1; (*save_resul.para_loi)(2) =  E2;
       (*save_resul.para_loi)(3) = E3;
       (*save_resul.para_loi)(4) =  nu12; (*save_resul.para_loi)(5) =  nu13;
       (*save_resul.para_loi)(6) =  nu23;
       (*save_resul.para_loi)(7) =  G12; (*save_resul.para_loi)(8) =  G13;
       (*save_resul.para_loi)(9) =  G23;
      };
  
    // calcul de l'acroissement des contraintes dans le repère g_i
    // l'inverse de gamma c'est beta transposée
    delta_sig_abij_HH.ChBase(beta_transpose);
    // maintenant on ajoute les contraintes à t, transportées
    sigHH = delta_sig_abij_HH + sigHH_n;

    // dans le cas où on veut une sortie des grandeurs locale on sauvegarde
    if (sortie_post)
     { Tenseur3HH eps_p_HH = gijHH * epsBB * gijHH;
       eps_p_HH.ChBase(gamma);
       Tenseur3HH sig_p_HH(sigHH);
       sig_p_HH.ChBase(gamma);
       (*save_resul.eps_loc_HH) = eps_p_HH;
       (*save_resul.sig_loc_HH) = sig_p_HH;
     };

    // passage dans la bonne variance
    Tenseur3BH sigBH = gijBB * sigHH ;
    switch (cas_calcul)
     { case 0: // calcul normal (tous les termes)
        { // on ne fait rien de spécial
          break;
        }
       case 1: // calcul de la partie déviatorique seule
        { double trace_sig = sigBH.Trace();
          sigBH -= (untiers * trace_sig) * IdBH3;
          sigHH -= (untiers * trace_sig) * gijHH;
          break;
        }
       case 2: // calcul de la partie sphérique seule
        { double trace_sig = sigBH.Trace();
          sigBH = (untiers * trace_sig) * IdBH3;
          sigHH = (untiers * trace_sig) * gijHH;
          break;
        }
       default:
        { cout << "\n erreur l'indicateur cas_calcul= " << cas_calcul << " n'a pas une valeur correcte !! "
               << "\n Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt (.... ";
          Sortie(1);
        }
     };
//----------------- debug
    #ifdef MISE_AU_POINT
    if (affichage)
       { cout << "\n epsBB="<<epsBB << " gijBB_tdt= " << gijBB << " gijHH_tdt= " << gijHH<<" ";
         cout << "\n sighh="<<sigHH<<" "<< endl ;
       };
    #endif
//----------- fin debug

    // traitement des énergies
    // arbitrairement, on considère qu'il s'agit d'un accroissement d'énergie élastique
    energ.Inita(0.);
    energ.ChangeEnergieElastique(energ_t.EnergieElastique() + 0.5 * (sigHH && delta_epsBB));
    // -- calcul des modules
    // on n'utilise plus la forme linéaire, mais à la place la variation relative de volume
    // constaté, au sens d'une mesure logarithmique, sauf dans le cas où cette variation est trop petite
    //module_compressibilite = E/(3.*(1.-2.*nu));
    //  calcul de la valeur de la variation relative de volume en log
    double log_var_vol = log((*(ex.jacobien_tdt))/(*(ex.jacobien_0)));
    // pour le module de compressibilité, choix entre les différents cas
    if ((cas_calcul == 0) || (cas_calcul == 2))
     {if (Dabs(log_var_vol) > ConstMath::petit)
        {module_compressibilite = untiers * sigBH.Trace() / (log_var_vol);}
      else // si la variation de volume est trop faible on passe par la moyenne
           // des compressibilités dans les 3 directions d'orthotropie (cf. théorie)
        {double unsurKs1 = 1./E1 - nu12/E1 -nu13/E1;
         double unsurKs2 = -nu12/E1+1./E2-nu23/E2;
         double unsurKs3 = -nu13/E1-nu23/E2+1./E3;
         module_compressibilite = untiers *untiers*(1./unsurKs1+1./unsurKs2+1./unsurKs3);
        };
     }
    else
     // dans le cas d'une loi purement déviatorique, le module de compressibilité = 0 (approximativement)
     {module_compressibilite = 0.;};
    // pour la partie cisaillement on garde la forme associée à la loi
    // on prend la moyenne des 3
    if ((cas_calcul == 0) || (cas_calcul == 1))
      {module_cisaillement = untiers * 2. * (G12+G13+G23);}
    else
      // en purement sphérique, le module est supposé nul
      {module_cisaillement = 0.; };
  
    // -------- cas le la variation du tenseur des contraintes par rapport aux ddl ---------
  
    int nbddl = d_gijBB_tdt.Taille();
  
    // des tenseurs de travail
    Tenseur3BH dsigBH_n,d_SBH_n; // tenseurs de travail
    Tenseur3BH d_sigBH; Tenseur3HH d_sig_HH,dsigHH_n;
//    Tenseur3HH  d_epsHH;Mat_pleine mat_d_epsHH(3,3);
    Tenseur3HH  d_delta_epsHH;Mat_pleine mat_d_delta_epsHH(3,3);
    Vecteur d_delta_eps_ii(3);Vecteur d_delta_sig_ii(3);
    Mat_pleine  d_beta(3,3);Mat_pleine  d_beta_inv(3,3);
    Mat_pleine  d_beta_transpose(3,3);
    Mat_pleine d_gamma(3,3);
    Mat_pleine mat_d_delta_eps_p_HH(3,3);
    // on récupère la matrice des composantes de déformation dans O_p_a
    Mat_pleine mat_delta_epsHH(3,3);delta_epsHH.Matrice_composante(mat_delta_epsHH);
//cout << "\n mat_epsHH: ";mat_epsHH.Affiche();
    for (int i = 1; i<= nbddl; i++)
     { // on fait uniquement une égalité d'adresse et de ne pas utiliser
       // le constructeur d'ou la profusion d'* et de ()
       Tenseur3HH & dsigHH = *((Tenseur3HH*) (d_sigHH(i)));  // passage en dim 3
       const Tenseur3HH & dgijHH = *((Tenseur3HH*)(d_gijHH_tdt(i))) ; // pour simplifier l'ecriture
       const Tenseur3BB & dgijBB = *((Tenseur3BB*)(d_gijBB_tdt(i))) ; // pour simplifier l'ecriture
       const Tenseur3BB & depsBB = *((Tenseur3BB *) (d_epsBB(i))); //    "
      
       //Tableau <BaseB> * d_giB_tdt
       BaseB & d_giB = (*ex.d_giB_tdt)(i);
       BaseH & d_giH = (*ex.d_giH_tdt)(i);

       // pour chacun des ddl on calcul les tenseurs derivees
       Tenseur3BH depsBH =  epsBB * dgijHH  + depsBB * gijHH ;
//cout <<"\n depsBH: "; depsBH.Ecriture(cout);
       double dIeps = depsBH.Trace();
      

       // -- variation de sigma_n
       switch (type_derive)
        { case -1: // // cas d'une dérivée de jauman: 1/2 deux fois covariant + deux fois contra
           {// pour info sigBH_n = 0.5*(gijBB * sigHH_n + (gijBB_t * sigHH_n * gijBB_t) * gijHH)
            dsigBH_n = 0.5*(sig_interBB_n * dgijHH + dgijBB * sigHH_nn );
            break;}
          case 0: // cas d'une dérivée de Lie deux fois covariantes
           {// pour info sigBH_n = (gijBB_t * sigHH_n * gijBB_t) * gijHH
            dsigBH_n = sigBB_n * dgijHH;
            break;}
          case 1: // cas d'une dérivée de Lie deux fois contravariantes
           {// pour info sigBH_n = gijBB * sigHH_n
            dsigBH_n = dgijBB * sigHH_n; break;}
        };
       // variation de la trace de sigma_n du au transport
       double dIsig_n = dsigBH_n.Trace();
       // variation du déviateur due au transport
       d_SBH_n = dsigBH_n - (untiers * dIsig_n) * IdBH3;

       //--- prise en compte de la variation du repère d'anisotropie
      
/*       // calcul des variations du repère O'_i
       // en fait il s'agit des variations des beta_a^{.j}
       if (type_transport == 0)
         // transport de type contravariant
        { // on calcule les coordonnées de la base O' dans la base naturelle
         BaseH& O_H = (*save_resul.O_H); // pour simplifier
         for (int a=1; a<4;a++)
          { // calcul des variations du vecteur non normé
            CoordonneeH d_pO_H_i(3);
            d_pO_H_i.Zero();
            // on a: Op_H(a) non normé = alpha_a^{.k} * \hat \vec g_k
            // d'où : d_Op_H(a) non normé = alpha_a^{.k} * d(\hat \vec g_k)
            for (int k=1; k<4;k++)
              {const CoordonneeB& d_giB_k = d_giB(k);
               // on change la variance car, celle-ci en fait dépend de la base
               // et non de gi_B, mais ici on utilise la base sous forme d'un scalaire
               // O_H(a)(k) et la variance est donnée par d_inter...
               CoordonneeH d_inter(3);
               d_inter.ConstructionAPartirDe_B(d_giB_k);
               d_pO_H_i += O_H(a)(k) * d_inter;
              };
            // calcul de la variation du vecteur unitaire connaissant la variation du
            // vecteur non unitaire et la norme
//            d_Op_H.CoordoH(a) = Util::VarUnVect_coorH(pO_B.CoordoB(a),d_pO_H_i,tab_norme(a));
          };
        }
       else
         // transport de type covariant
        { // on calcule les coordonnées de la base O' dans la base duale
         BaseB& O_B = (*save_resul.O_B); // pour simplifier
         for (int iloc=1; iloc<4;iloc++)
          { // tout d'abord la base non normalisée
            CoordonneeH& d_pO_H_i = d_Op_H.CoordoH(iloc);
            d_pO_H_i.Zero();
            for (int k=1; k<4;k++)
              {CoordonneeH d_giH_k = d_giH(k);
               d_pO_H_i += O_B(i)(k) * d_giH_k;
              };
            // calcul de la variation du vecteur unitaire connaissant la variation du
            // vecteur non unitaire et la norme
            CoordonneeH interH = Util::VarUnVect_coorH(pO_H.CoordoH(iloc),d_pO_H_i,tab_norme(iloc));
          };
         // maintenant on calcule la base d_Op_B correspondante
         for (int i=1; i<4;i++)
            d_Op_B.CoordoB(i) = d_Op_H.CoordoH(i) * gijBB + Op_H.CoordoH(i) * dgijBB;
        };
*/

       // on calcul la variation de matrice de passage de la base g_i vers la base O'_a
       // O'_a = beta_a^{.i} * g_i
       if (type_transport == 0)
        // transport de type contravariant
         {for (int a=1; a<4;a++)
           {const CoordonneeH& alpha_H_a = alpha_H.CoordoH(a);
            // on calcul d'abord le produit alpha_a^l * alpha_a^m * d_g_ij(l,m)
            double inter = 0.;
            for (int l =1;l<4;l++)
             for (int m =1;m<4;m++)
               inter += alpha_H_a(l) * alpha_H_a(m) * dgijBB(l,m);
            for (int i=1; i<4;i++)
             {double & d_beta_ai = d_beta(a,i); // pour simplifier
              // ajout des termes or boucle
              d_beta_ai *= - 0.5 * alpha_H_a(i) * inter / PUISSN(tab_norme(a), 3);
             };
           };
        // on calcule ensuite la variation de gamma
        d_beta_transpose = d_beta.Transpose();
//cout << "\n gamma: ";gamma.Affiche();
//        d_gamma = (gamma * d_beta_transpose);
        d_gamma = - gamma * d_beta_transpose * gamma;
        #ifdef MISE_AU_POINT
        if (affichage)
         {cout << "\n d_beta: ";d_beta.Affiche();
          cout << "\n d_beta_transpose: ";d_beta_transpose.Affiche();
          cout << "\n d_gamma: ";d_gamma.Affiche();
          d_gamma = -d_gamma;
          cout << "\n d_gamma: ";d_gamma.Affiche();
         };
        #endif
        }
       else
        {cout << "\n **** cas en attente "
              << "\n Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt (.... "<< endl;
         Sortie(1);
        };
      
       // calcul des coordonnées de la variation de déformation dans le repère O'_i
       // -- 1) en coordonnees contravariantes tout d'abord variations dans g_i
       // delta_epsHH =  gijHH * delta_epsBB * gijHH dans g_i
       // de d_delta_epsBB/d_ddl = d_epsBB/d_ddl
       d_delta_epsHH  = dgijHH * delta_epsBB * gijHH + gijHH * depsBB * gijHH
                     + gijHH * delta_epsBB * dgijHH;
//cout <<"\n d_delta_epsHH: "; d_delta_epsHH.Ecriture(cout);

       // -- maintenant on s'occupe du changement de base
       // les beta et gamma sont des matrices et non des tenseurs ... on transforme localement
       // en matrice
       d_delta_epsHH.Matrice_composante(mat_d_delta_epsHH);
       // -- calcul final de la variation  de déformation dans le repère O'_i
       // rappel du changement de base : res = (gamma * res) * gamma.Transpose();
//cout << "\n d_gamma: ";d_gamma.Affiche();

       mat_d_delta_eps_p_HH = (d_gamma * mat_delta_epsHH * gamma_transpose)
                        + (gamma * mat_d_delta_epsHH * gamma_transpose)
                        + gamma * mat_delta_epsHH * d_gamma.Transpose();
//cout << "\n mat_d_eps_p_HH: ";mat_d_eps_p_HH.Affiche();


       // -- 2) calcul de la variation de l'accroissement des contraintes dans le repère O_p
       for (int i=1; i<4;i++)
         d_delta_eps_ii(i) = mat_d_delta_eps_p_HH(i,i); // les delta def de la diagonale
       d_delta_sig_ii = inv_loi * d_delta_eps_ii; // les delta contraintes en ii
      
       // on se sert du conteneur dsigHH
       for (int i=1; i<4;i++)
         {dsigHH.Coor(i,i) = d_delta_sig_ii(i); // affectation des delta contraintes en ii
         };
       // puis les contraintes en cisaillement
       dsigHH.Coor(1,2) = 2.* G12 * mat_d_delta_eps_p_HH(1,2);
       dsigHH.Coor(1,3) = 2.* G13 * mat_d_delta_eps_p_HH(1,3);
       dsigHH.Coor(2,3) = 2.* G23 * mat_d_delta_eps_p_HH(2,3);
//cout <<"\n dsigHH en O_p : "; dsigHH.Ecriture(cout);

       // -- 3) calcul de la variation des delta contraintes dans le repère g_i
       // c'est l'opération inverse et beta_transpose joue le rôle de gamma dans l'autre sens
       delta_sig_abij_HH.Var_tenseur_dans_nouvelle_base(beta_transpose,dsigHH,d_beta_transpose);
//cout <<"\n dsigHH en gi : "; dsigHH.Ecriture(cout);

       // assemblage final en tenant compte des contraintes à t transportées
       // sachant que dsigHH contient les variations de delta sigHH
       switch (cas_calcul)
        { case 0: // calcul normal (tous les termes)
           { // sigHH_n = gijHH * sigBH_n  d'où
             dsigHH_n = dgijHH * sigBH_n + gijHH * dsigBH_n;
             dsigHH += dsigHH_n; // assemblage
             break;
           }
          case 1: // calcul de la partie déviatorique seule
           { // -- la partie delta sigma
             // passage en mixte pour le calcul de la trace
             d_sigBH = dgijBB * delta_sig_abij_HH + gijBB * dsigHH;
             double d_trace_sig = d_sigBH.Trace();
             d_sigBH -= (untiers * d_trace_sig) * IdBH3;
             // -- ajout de la partie transportée en déviateur
             // ( somme de 2 déviateurs = un déviateur)
             d_sigBH += d_SBH_n;
             // -- passage en deux fois contravariant
             dsigHH = dgijHH * sigBH + gijHH * d_sigBH;
             break;
           }
          case 2: // calcul de la partie sphérique seule
           { // -- la partie delta sigma
             // passage en mixte pour le calcul de la trace
             d_sigBH = dgijBB * delta_sig_abij_HH + gijBB * dsigHH;
             double d_trace_sig = d_sigBH.Trace();
             // -- ajout de la partie transportée en sphérique
             // ( somme de 2 sphériques = un sphérique)
             d_sigBH = (untiers * d_trace_sig + dIsig_n) * IdBH3;
             // passage en deux fois contravariant
             dsigHH = dgijHH * sigBH + gijHH * d_sigBH;
             break;
           }
          default: break;//l'erreur a déjà été traitée dans le calcul de la contrainte
        };
////----------------- debug
//  if ((i==2) || (i==5))
//    {cout << "\n dsighh("<<i<<")="<<dsigHH<<" "
//	       << " dgijHH= " << dgijHH << " depsBB= " << depsBB ;
//	  };
//----------- fin debug        
      };
////----------------- debug
//cout << "\n\n\n"<<endl;Sortie(1);
//----------- fin debug

////debug
//cout << "\n Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt ";
//cout << "\n sigHH: "; sigHH.Ecriture(cout);
//cout << "\n epsBB: "; epsBB.Ecriture(cout);
//     << " epsBH.Trace()= " << Ieps
//     << " sigBH.Trace()= " << sigBH.Trace() << " module_compressibilite= " << module_compressibilite;
////fin debug

    LibereTenseur();        
 };

// void Calcul_dsigma_deps (bool en_base_orthonormee, TenseurHH & sigHH_t,TenseurBB& DepsBB
//     ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB,double& jacobien_0,double& jacobien
//     ,TenseurHH& sigHH,TenseurHHHH& d_sigma_deps
//     ,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double&  module_cisaillement
//     ,const Met_abstraite::Umat_cont& ex) ; //= 0;
// calcul des contraintes et ses variations  par rapport aux déformations a t+dt
// en_base_orthonormee:
//   si true:  le tenseur de contrainte en entrée est  en orthonormee
//                  le tenseur de déformation et son incrémentsont également en orthonormees
//   si = false: les bases transmises sont utilisées, sinon il s'agit de la base orthonormeee fixe
// ex: contient les éléments de métrique relativement au paramétrage matériel = X_(0)^a
void Hypo_ortho3D_entrainee::Calcul_dsigma_deps (bool en_base_orthonormee, TenseurHH & sigHH_t,TenseurBB&
            ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB_,double& ,double&
		  	       ,TenseurHH& sigHH_tdt,TenseurHHHH& d_sigma_deps_
		  	       ,EnergieMeca & energ,const EnergieMeca & energ_t
		  	       ,double& module_compressibilite,double&  module_cisaillement
		  	       ,const Met_abstraite::Umat_cont& ex)
 {
   #ifdef MISE_AU_POINT	 	 
   if (epsBB_tdt.Dimension() != 3)
      { cout << "\nErreur : la dimension devrait etre 3 !\n";
        cout << " Hypo_ortho3D_entrainee::Calcul_dsigma_deps\n";
        Sortie(1);
      };
   #endif
   bool affichage = (Permet_affichage() > 5);
   #ifdef MISE_AU_POINT
   if (affichage)
    {cout << "\n  --- loi de comportement orthotrope entrainee --- ";
    };
   #endif
    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
    const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_);
    Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_tdt);  //   "      "  "  "
    Tenseur3HH & sigHH_nn = *((Tenseur3HH*) &sigHH_t);  //   "      "  "  "
    Tenseur3HHHH& d_sigma_deps = *((Tenseur3HHHH*) &d_sigma_deps_);

    const Tenseur3HH & gijHH = *((Tenseur3HH*) ex.gijHH_tdt); //   "      "  "  "
    const Tenseur3BB & gijBB = *((Tenseur3BB*) ex.gijBB_tdt); //   "      "  "  "
    const Tenseur3HH & gijHH_t = *((Tenseur3HH*) ex.gijHH_t); //   "      "  "  "
    const Tenseur3BB & gijBB_t = *((Tenseur3BB*) ex.gijBB_t); //   "      "  "  "


 // --- opération de transport du tenseur sigma(t), de t à tdt
    // tenseur intermédiaires utilisées selon les cas (par forcément dans tous les cas !!)
    Tenseur3BH sigBH_n;Tenseur3HH sigHH_n; Tenseur3BB sigBB_n;Tenseur3BB sig_interBB_n;
    if (en_base_orthonormee)
      {// pour l'instant le transport s'effectue dans la base orthonormee!! ce qui est peut-être
       // mauvais dans le cas de grandes transformations !!
       sigBH_n = IdBB3 * sigHH_nn;
      }  // deformation en mixte
    else
      { switch (type_derive) //case 1: cas d'une dérivée de Lie deux fois contravariante : cas par défaut
         {case -1: // cas d'une dérivée de jauman: 1/2 deux fois covariant + deux fois contra
            {sig_interBB_n = gijBB_t * sigHH_nn * gijBB_t;
             sigBH_n = 0.5*( sig_interBB_n * gijHH + gijBB * sigHH_nn) ;
             sigHH_n = gijHH * sigBH_n ;
             sigBB_n = sigBH_n * gijBB; break;}
          case 0: // cas d'une dérivée de Lie deux fois covariantes
            {sigBB_n = gijBB_t * sigHH_nn * gijBB_t;
             sigBH_n = sigBB_n * gijHH ;
             sigHH_n = gijHH * sigBH_n ; break;}
          case 1: // cas d'une dérivée de Lie deux fois contravariantes
            {sigHH_n = sigHH_nn;
             sigBH_n = gijBB * sigHH_n;
             sigBB_n = sigBH_n * gijBB;
             break;}
          };
      };
  
   //----  le repère d'anisotropie
    // récup du conteneur spécifique
    SaveResulHypo_ortho3D_entrainee & save_resul = *((SaveResulHypo_ortho3D_entrainee*) saveResul);
    // on commence par calculer le repère d'orthotropie transporté
    // Op_H_i sont les coordonnées contravariantes de la nouvelle base
    // donc par rapport à g_i,
    BaseH& Op_H = save_resul.Op_H;
    Tableau <double> tab_norme(3);
    if (type_transport == 0)
      // transport de type contravariant
     { // on calcule les coordonnées de la base O' dans la base naturelle
      #ifdef MISE_AU_POINT
      if (save_resul.O_H == NULL)
        {cout << "\n  *** erreur, le repere d'anisotropie n'est pas defini "
              <<"on ne peut pas continuer " << flush ;
         cout << " Hypo_ortho3D_entrainee::Calcul_dsigma_deps\n";
         Sortie(1);
        };
      #endif
      BaseH& O_H = (*save_resul.O_H); // coordonnées en absolu de la base d'orthotropie
      // calcul des coordonnées alpha_a^{.i} = O_H(a) * g^i  à t= 0
      for (int a = 1;a < 4; a++)
        {CoordonneeH& inter = alpha_H.CoordoH(a);
         for (int i=1;i < 4;i++)
           inter(i)= O_H(a).ScalHH((*ex.giH_0)(i));
           #ifdef MISE_AU_POINT
           if (affichage)
            {cout << "\n  O_H("<<a<<"): ";O_H(a).Affiche();
             cout << "\n giH_0("<<a<<"): "; (*ex.giH_0)(a).Affiche();
//if ((*ex.giH_0)(a).Norme() < ConstMath::petit)
//   cout << "\n debug lor_ortho pb ";
//             cout << "\n  alpha_H("<<a<<"): ";alpha_H(a).Affiche();
            };            
           #endif
        };

      // calcule des beta_a^{.i} tel que O'_a = beta_a^{.i} \hat{g}_i   donc au temps t+dt
      for (int a=1; a<4;a++)
       { // tout d'abord la base non normalisée
         // récup du conteneur et affectation des coordonnées initiales
         // Op_H(a) non normé a les mêmes coordonnées alpha_a^{.j}
         // que O_H(a), mais exprimés dans le repère actuel \hat \vec g_j
         CoordonneeH& Op_H_a = Op_H.CoordoH(a); // pour simplifier
         Op_H_a = alpha_H(a);
         // calcul de la norme du vecteur Op_H_a
         double norme = sqrt(Op_H_a * gijBB * Op_H_a);
         tab_norme(a) = norme;
         // coordonnées finales
         Op_H_a /= norme;
         #ifdef MISE_AU_POINT
         if (affichage)
          { cout << "\n  Op_H("<<a<<"): ";
            Op_H_a.Affiche();
            cout << "\n giB_tdt("<<a<<"): "; (*ex.giB_tdt)(a).Affiche();
            cout << "\n giH_tdt("<<a<<"): "; (*ex.giH_tdt)(a).Affiche();
            // affichage du repère tournée
            CoordonneeB V(3);
            for (int j=1;j<4;j++) V += (*ex.giB_tdt)(j) * Op_H_a(j);
            cout << "\n op_H("<<a<<"):  en absolu " << V ;
          };
         #endif
       };
     }
    else
      // transport de type covariant
     { // on calcule les coordonnées de la base O' dans la base duale
      #ifdef MISE_AU_POINT
      if (save_resul.O_B == NULL)
        {cout << "\n  *** erreur, le repere d'anisotropie n'est pas defini "
              <<"on ne peut pas continuer " << flush ;
         cout << " Hypo_ortho3D_entrainee::Calcul_dsigma_deps\n";
         Sortie(1);
        };
      #endif
      BaseB& O_B = (*save_resul.O_B); // pour simplifier
      for (int a=1; a<4;a++)
       { // tout d'abord la base non normalisée
         CoordonneeB& Op_B_a = Op_B.CoordoB(a);
         // calcul de la norme du vecteur Op_B_a
         double norme = sqrt(Op_B_a * gijHH * Op_B_a);
         // coordonnées finales
         Op_B_a /= norme;
       };
      // maintenant on calcule la base Op_H correspondante
      for (int i=1; i<4;i++)
         Op_H.CoordoH(i) = Op_B.CoordoB(i) * gijHH;
     };
    // on calcul la matrice de passage de la base g_i vers la base O'_i
    // O'_i = beta_i^{.j} * g_j
    // et on a également \hat{\vec g}^i = {\beta}_{a}^{.i}~\hat{\vec O'}^a
    // comme O'_i est déjà exprimé dans g_j, ses coordonnées sont directement béta
    for (int i=1; i<4;i++)
      for (int j=1; j<4;j++)
         { beta(i,j) = Op_H(i)(j);};
    // puis on calcul les coordonnées de la base duale
    beta_transpose = beta.Transpose();
    gamma = beta_transpose.Inverse();
    gamma_transpose = gamma.Transpose();
    #ifdef MISE_AU_POINT
    if (affichage)
     {cout << "\n beta: ";beta.Affiche();
      cout << "\n beta_transpose: ";beta_transpose.Affiche();
      cout << "\n gamma: ";gamma.Affiche();
      cout << "\n gamma_transpose: ";gamma_transpose.Affiche();
     };
    #endif

    // changement de base (cf. théorie) : la matrice beta est telle que:
    // gpB(i) = beta(i,j) * gB(j) <==> gp_i = beta_i^j * g_j

    // ------- partie déformation
  
    Tenseur3BH  delta_epsBH = delta_epsBB * gijHH;  // accroissement de deformation en mixte
    Tenseur3HH  delta_epsHH = gijHH * delta_epsBH; // en deuxfois contra
    // calcul des coordonnées de l'incrément de déformation dans le repère O'^i
    // calcul des coordonnées de la déformation dans le repère O'_i
    #ifdef MISE_AU_POINT
    if (affichage)
     {cout <<"\n delta_eps_BB en g^i: "; delta_epsBB.Ecriture(cout);
      Tenseur3BB tiutiu;
      delta_epsBB.BaseAbsolue(tiutiu,*(ex.giH_tdt));
      cout << "\n delta_eps en absolu :";tiutiu.Ecriture(cout);
     };
    #endif

    // il faut passer en 2 fois contravariant
    Tenseur3HH delta_eps_p_HH(delta_epsHH);
    delta_eps_p_HH.ChBase(gamma); // res = (gamma * res) * gamma.Transpose();
    #ifdef MISE_AU_POINT
    if (affichage)
      { cout <<"\n delta_eps_p_HH: "; delta_eps_p_HH.Ecriture(cout);
        Tenseur3HH  toto(delta_eps_p_HH);
        toto.ChBase(beta_transpose);
        cout << "\n retour dans la base g^i de eps^{ij} :";toto.Ecriture(cout);
        Tenseur3BB  titi = gijBB * toto * gijBB;
        cout << "\n def eps_ij :";titi.Ecriture(cout);
      };
    #endif


    double untiers = 1./3.;

    // dans le cas de fonctions nD récupération des valeurs
    if (!null_fct_para)
//rappel:  Tableau <Fonction_nD* > fct_para; // fonction nD éventuelle d'évolution des paramètres
     {// un tableau de travail pour les valeurs sous forme indicée
      Tableau < double * > coef(9);
      coef(1) = &E1; coef(2) = & E2; coef(3) = &E3;
      coef(4) = & nu12; coef(5) = & nu13; coef(6) = & nu23;
      coef(7) = & G12; coef(8) = & G13; coef(9) = & G23;
      // opération de transmission de la métrique
      const Met_abstraite::Impli* ex_impli = NULL;
      const Met_abstraite::Expli_t_tdt* ex_expli_tdt = NULL;
      const Met_abstraite::Umat_cont* ex_expli = &ex;

      // on passe en revue les fonctions nD
      for (int i=1;i<10;i++)
       {if (fct_para(i) != NULL)
         { Fonction_nD* pt_fonct = fct_para(i); // pour simplifier
           
           // on utilise la méthode générique de loi abstraite
           Tableau <double> & tab_val = Loi_comp_abstraite::Loi_comp_Valeur_FnD_Evoluee
               (pt_fonct,1 // une seule valeur attendue en retour
                ,ex_impli,ex_expli_tdt,ex_expli
                ,NULL
                ,NULL
                ,NULL
               );

/*           // ici on utilise les variables connues aux pti, ou calculées à partir de
           // on commence par récupérer les conteneurs des grandeurs à fournir
           List_io <Ddl_enum_etendu>& li_enu_scal = pt_fonct->Li_enu_etendu_scalaire();
           List_io <TypeQuelconque >& li_quelc = pt_fonct->Li_equi_Quel_evolue();
           bool absolue = true; // on se place systématiquement en absolu
           // on va utiliser la méhode Valeur_multi_interpoler_ou_calculer
           // pour les grandeurs strictement scalaire
            Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
                        (absolue,TEMPS_tdt,li_enu_scal,ex_impli,ex_expli_tdt,ex_expli,NULL)
                                          );
           // on utilise la méthode Valeurs_Tensorielles_interpoler_ou_calculer
           // pour les Coordonnees et Tenseur
           Valeurs_Tensorielles_interpoler_ou_calculer
                         (absolue,TEMPS_tdt,li_quelc,ex_impli,ex_expli_tdt,ex_expli,NULL);
           // calcul de la valeur et retour dans tab_ret
           Tableau <double> & tab_val = pt_fonct->Valeur_FnD_Evoluee(&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
           #ifdef MISE_AU_POINT
           if (tab_val.Taille() != 1)
              { cout << "\nErreur : la fonction nD relative au parametre materiau " << i
                     << " doit calculer un scalaire or le tableau de retour est de taille "
                     << tab_val.Taille() << " ce n'est pas normal !\n";
                cout << " Hypo_ortho3D_entrainee::Calcul_SigmaHH\n";
                Sortie(1);
              };
           #endif
*/
           // on récupère le premier élément du tableau uniquement
           (*coef(i)) = tab_val(1);
         };
       };
     };
    // puis fabrication de la matrice inv_loi
    {// on commence par remplir la matrice
     inv_loi(1,1) = 1./E1;inv_loi(2,2) = 1./E2;inv_loi(3,3) = 1./E3;
     inv_loi(1,2) = inv_loi(2,1) = -nu12/E1;
     inv_loi(1,3) = inv_loi(3,1) = -nu13/E1;
     inv_loi(3,2) = inv_loi(2,3) = -nu23/E2;
     inv_loi = inv_loi.Inverse(); // on inverse la matrice
    };
  
    // calcul de l'accroissement des contraintes dans le repère O_p
    Tenseur3HH delta_sig_ab_HH; // au début c'est ab puis après chgt de base devient en ij
    Vecteur delta_eps_ii(3);Vecteur delta_sig_ii(3);
    for (int i=1; i<4;i++)
      delta_eps_ii(i) = delta_eps_p_HH(i,i);
    delta_sig_ii = inv_loi * delta_eps_ii;

    // l'accroissement est stocké dans delta_sig_abij_HH: on en a besoin pour l'opérateur tangent
    // ensuite on ajoutera la contrainte à t transportée de t à tdt
    for (int i=1; i<4;i++)
      delta_sig_ab_HH.Coor(i,i) = delta_sig_ii(i);

    delta_sig_ab_HH.Coor(1,2) = 2.* G12 * delta_eps_p_HH(1,2);
    delta_sig_ab_HH.Coor(1,3) = 2.* G13 * delta_eps_p_HH(1,3);
    delta_sig_ab_HH.Coor(2,3) = 2.* G23 * delta_eps_p_HH(2,3);
    #ifdef MISE_AU_POINT
    if (affichage)
     {cout << "\n delta_sig_ab_HH :";delta_sig_ab_HH.Ecriture(cout);
     };
    #endif

    // dans le cas où on veut une sortie des grandeurs on sauvegarde
    if (sortie_post)
     { if (save_resul.eps_loc_HH == NULL)
         {save_resul.eps_loc_HH = NevezTenseurHH(3);
          save_resul.sig_loc_HH = NevezTenseurHH(3);
          save_resul.para_loi = new Vecteur (9);
          save_resul.delta_eps_loc_HH = NevezTenseurHH(3);
          save_resul.delta_sig_loc_HH = NevezTenseurHH(3);
         };
       (*save_resul.delta_eps_loc_HH) = delta_eps_p_HH;
       (*save_resul.delta_sig_loc_HH) = delta_sig_ab_HH;
       // paramètres de la loi
       (*save_resul.para_loi)(1) = E1; (*save_resul.para_loi)(2) =  E2;
       (*save_resul.para_loi)(3) = E3;
       (*save_resul.para_loi)(4) =  nu12; (*save_resul.para_loi)(5) =  nu13;
       (*save_resul.para_loi)(6) =  nu23;
       (*save_resul.para_loi)(7) =  G12; (*save_resul.para_loi)(8) =  G13;
       (*save_resul.para_loi)(9) =  G23;
      };
  
    // calcul de l'acroissement des contraintes dans le repère g_i
    // l'inverse de gamma c'est beta transposée
    Tenseur3HH delta_sig_ij_HH(delta_sig_ab_HH);
    delta_sig_ij_HH.ChBase(beta_transpose);
    // maintenant on ajoute les contraintes à t, transportées
    sigHH = delta_sig_ij_HH + sigHH_n;
    #ifdef MISE_AU_POINT
    if (affichage)
     {cout << "\n sig_ijHH :";sigHH.Ecriture(cout);
      Tenseur3HH tutu;
      sigHH.BaseAbsolue(tutu,*(ex.giB_tdt));
      cout << "\n sig en absolu :";tutu.Ecriture(cout);
     };
    #endif
  
    // dans le cas où on veut une sortie des grandeurs locale on sauvegarde
    if (sortie_post)
     { Tenseur3HH eps_p_HH = gijHH * epsBB * gijHH;
       eps_p_HH.ChBase(gamma);
       Tenseur3HH sig_p_HH(sigHH);
       sig_p_HH.ChBase(gamma);
       (*save_resul.eps_loc_HH) = eps_p_HH;
       (*save_resul.sig_loc_HH) = sig_p_HH;
     };


    // passage dans la variance mixte
    Tenseur3BH sigBH = gijBB * sigHH ;
    switch (cas_calcul)
     { case 0: // calcul normal (tous les termes)
        { // on ne fait rien de spécial
          break;
        }
       case 1: // calcul de la partie déviatorique seule
        { double trace_sig = sigBH.Trace();
          sigBH -= (untiers * trace_sig) * IdBH3;
          sigHH -= (untiers * trace_sig) * gijHH;
          break;
        }
       case 2: // calcul de la partie sphérique seule
        { double trace_sig = sigBH.Trace();
          sigBH = (untiers * trace_sig) * IdBH3;
          sigHH = (untiers * trace_sig) * gijHH;
          break;
        }
       default:
        { cout << "\n erreur l'indicateur cas_calcul= " << cas_calcul << " n'a pas une valeur correcte !! "
               << "\n Hypo_ortho3D_entrainee::Calcul_DsigmaHH_tdt (.... ";
          Sortie(1);
        }
     };
//----------------- debug
    #ifdef MISE_AU_POINT
    if (affichage)
       { cout << "\n epsBB="<<epsBB << " gijBB_tdt= " << gijBB << " gijHH_tdt= " << gijHH<<" ";
         cout << "\n sighh="<<sigHH<<" "<< endl ;
       };
    #endif
//----------- fin debug

    // traitement des énergies
    // arbitrairement, on considère qu'il s'agit d'un accroissement d'énergie élastique
    energ.Inita(0.);
    energ.ChangeEnergieElastique(energ_t.EnergieElastique() + 0.5 * (sigHH && delta_epsBB));
    // -- calcul des modules
    // on n'utilise plus la forme linéaire, mais à la place la variation relative de volume
    // constaté, au sens d'une mesure logarithmique, sauf dans le cas où cette variation est trop petite
    //module_compressibilite = E/(3.*(1.-2.*nu));
    //  calcul de la valeur de la variation relative de volume en log
    double log_var_vol = log((*(ex.jacobien_tdt))/(*(ex.jacobien_0)));
    // pour le module de compressibilité, choix entre les différents cas
    if ((cas_calcul == 0) || (cas_calcul == 2))
     {if (Dabs(log_var_vol) > ConstMath::petit)
        {module_compressibilite = untiers * sigBH.Trace() / (log_var_vol);}
      else // si la variation de volume est trop faible on passe par la moyenne
           // des compressibilités dans les 3 directions d'orthotropie (cf. théorie)
        {double unsurKs1 = 1./E1 - nu12/E1 -nu13/E1;
         double unsurKs2 = -nu12/E1+1./E2-nu23/E2;
         double unsurKs3 = -nu13/E1-nu23/E2+1./E3;
         module_compressibilite = untiers * untiers*(1./unsurKs1+1./unsurKs2+1./unsurKs3);
        };
      #ifdef MISE_AU_POINT
      if  (Permet_affichage() > 4)
         cout << "\n module_compressibilite= " << module_compressibilite;
      if  (Permet_affichage() > 5) cout << "\n cas_calcul= " << cas_calcul;
      #endif
     }
    else
     // dans le cas d'une loi purement déviatorique, le module de compressibilité = 0 (approximativement)
     {module_compressibilite = 0.;
      #ifdef MISE_AU_POINT
      if  (Permet_affichage() > 4)
         cout << "\n module_compressibilite= " << module_compressibilite;
      if  (Permet_affichage() > 5) cout << "\n cas_calcul= " << cas_calcul;
      #endif
     };
    // pour la partie cisaillement on garde la forme associée à la loi
    // on prend la moyenne des 3
    if ((cas_calcul == 0) || (cas_calcul == 1))
      {module_cisaillement = untiers * 2. * (G12+G13+G23);}
    else
      // en purement sphérique, le module est supposé nul
      {module_cisaillement = 0.; };
  
    // ----- calcul de l'opérateur tangent -----------
  
    // calcul des variations de sigma / eps dans le repère transporté
    Tenseur3HHBB var_sig_ab_cd_HHBB;
    for (int i=1; i<4;i++)
     for (int j=1; j<4;j++)
       var_sig_ab_cd_HHBB.Change(i,i,j,j,inv_loi(i,j));
    var_sig_ab_cd_HHBB.Change(1,2,1,2,G12); // du coup = (1,2,2,1) = (2,1,1,2) = (2,1,2,1)
    var_sig_ab_cd_HHBB.Change(1,3,1,3,G13); // "
    var_sig_ab_cd_HHBB.Change(2,3,2,3,G23); // *
  
    #ifdef MISE_AU_POINT
    if (affichage)
     {cout << "\n var_sig_ab_cd_HHBB= ";
      var_sig_ab_cd_HHBB.Affiche_bidim(cout);
     };
    #endif

    // cas de la variation des beta_a^{.i} par rapport aux eps_kl
    // on va les stocker dans un tableau d_beta(a,i) de tenseur HH
    Tableau2 <Tenseur3HH> d_beta_HH(3,3);
    Tableau2 <Tenseur3HH> d_beta_transpose_HH(3,3);
    if (type_transport == 0)
      // transport de type contravariant
     { // on calcule les coordonnées de la base O' dans la base naturelle
      BaseH& O_H = (*save_resul.O_H); // pour simplifier
      for (int a=1;a<4;a++)
       {// calcul de la norme  du vecteur O'_a
        CoordonneeH alpha_H_a = alpha_H(a);
        double n_O_a = tab_norme(a);
        for (int i=1;i<4;i++)
          {d_beta_transpose_HH(i,a)
                     = d_beta_HH(a,i)
                     = -(alpha_H_a(i)
                       /(n_O_a*n_O_a*n_O_a))*Tenseur3HH::Prod_tensoriel(alpha_H_a,alpha_H_a);
          };
       };
     }; // fin du transport 0
     //**** à faire le second transport
  
// vérif d_beta OK
/*{// vérif en différence finie de d_beta
for (int a=1;a<4;a++)
 { CoordonneeH alpha_H_a = alpha_H(a);
//Tenseur3HH toto(Tenseur3HH::Prod_tensoriel(alpha_H_a,alpha_H_a));
//cout << "\n Prod_tensoriel(alpha_H_a,alpha_H_a)= ";
//toto.Ecriture(cout);
//Tenseur3HH titi;
//for (int j=1;j<4;j++)
//  for (int i=1;i<4;i++)
//    titi.Coor(i,j) = alpha_H_a(i) * alpha_H_a(j);
//cout << "\n Prod_tensoriel(alpha_H_a,alpha_H_a) numerique = ";
//titi.Ecriture(cout);
  // calcul de la norme  du vecteur O'_a
  double d_beta_num=0.;
  double n_O_a = tab_norme(a);
  for (int i=1;i<4;i++)
   {d_beta_num = d_beta_HH(a,i) && epsBB;
    cout << "\n delta_beta("<<a<<","<<i<<")= "
         << (beta(a,i)-alpha_H_a(i))<< " num: "<<d_beta_num
         << " beta(a,i)= " << beta(a,i) << " alpha_H_a(i)= " << alpha_H_a(i) ;
   }
}
};
Sortie(1);
*/
  
    // on calcule maintenant la variation de gamma
    Tableau2 <Tenseur3HH> d_gamma_HH(3,3);
    for (int b=1;b<4;b++)
      for (int j=1;j<4;j++)
       {for (int a=1;a<4;a++)
         for (int i=1;i<4;i++)
           d_gamma_HH(b,j) -= (gamma(a,j) * gamma(b,i)) * d_beta_HH(a,i);
       };
  
/*
// vérification numérique de d_gamma
// on a \hat{\vec g}_j =  {\gamma}_{.j}^{b}~\hat{\vec O'}_b
{Mat_pleine gamma_0(3,3);
 Mat_pleine O_p_0_ij(3,3);Mat_pleine O_p_tdt_ij(3,3);
 
for (int a=1;a<4;a++)
 {
 
 CoordonneeH alpha_H_a = alpha_H(a);
//Tenseur3HH toto(Tenseur3HH::Prod_tensoriel(alpha_H_a,alpha_H_a));
//cout << "\n Prod_tensoriel(alpha_H_a,alpha_H_a)= ";
//toto.Ecriture(cout);
//Tenseur3HH titi;
//for (int j=1;j<4;j++)
//  for (int i=1;i<4;i++)
//    titi.Coor(i,j) = alpha_H_a(i) * alpha_H_a(j);
//cout << "\n Prod_tensoriel(alpha_H_a,alpha_H_a) numerique = ";
//titi.Ecriture(cout);
  // calcul de la norme  du vecteur O'_a
  double d_beta_num=0.;
  double n_O_a = tab_norme(a);
  for (int i=1;i<4;i++)
   {d_beta_num = d_beta_HH(a,i) && epsBB;
    cout << "\n delta_beta("<<a<<","<<i<<")= "
         << (beta(a,i)-alpha_H_a(i))<< " num: "<<d_beta_num
         << " beta(a,i)= " << beta(a,i) << " alpha_H_a(i)= " << alpha_H_a(i) ;
   }
}
};
*/

  
    //variation des déformations epsHH / eps_ij dans le repère initial gi
//    Tenseur3HHHH var_eps_nm_kl_HHHH(Tenseur3HHHH::Prod_tensoriel_barre(gijHH,gijHH));
//--//    Tenseur3HHHH var_eps_nm_kl_HHHH(Tenseur3HHHH::Prod_tensoriel_croise(gijHH,gijHH));
//cout << "\n (1) var_eps_nm_kl_HHHH= ";
//var_eps_nm_kl_HHHH.Affiche_bidim(cout);
//{// pour vérification on va calculer par composante
// Tenseur3HHHH deps_nmkl;
// for (int n=1;n<4;n++) for (int m=1;m<4;m++) for (int k=1;k<4;k++) for (int l=1;l<4;l++)
//  { double inter=  gijHH(n,k) * gijHH(l,m);
//    deps_nmkl.Change(n,m,k,l,inter);
//  };
// cout << "\n (1) deps_nmkl= calcul en composantes";
// deps_nmkl.Affiche_bidim(cout);
//}
//    Tenseur3HHHH interHHHH1(Tenseur3HHHH::Prod_tensoriel_barre(gijHH,eps_p_HH));
//    Tenseur3HHHH interHHHH2(Tenseur3HHHH::Prod_tensoriel_barre(eps_p_HH,gijHH));
//--//    Tenseur3HHHH interHHHH1(Tenseur3HHHH::Prod_tensoriel_croise(gijHH,eps_HH));
//--//    Tenseur3HHHH interHHHH2(Tenseur3HHHH::Prod_tensoriel_croise(eps_HH,gijHH));
//Tenseur3HHHH interHHHH3(interHHHH1+interHHHH2);
//cout << "\n interHHHH3= ";
//interHHHH3.Affiche_bidim(cout);
//cout << "\n interHHHH1= ";
//interHHHH1.Affiche_bidim(cout);
//cout << "\n interHHHH2= ";
//interHHHH2.Affiche_bidim(cout);
//{Tenseur3HHHH A(interHHHH3);
//A += interHHHH3;
//cout << "\n A= ";A.Affiche_bidim(cout);
//Tenseur3HHHH B(var_eps_nm_kl_HHHH);
//cout << "\n (1) B= ";B.Affiche_bidim(cout);
//B -= 2. * interHHHH3;
//cout << "\n B= ";B.Affiche_bidim(cout);
//
//}
//--//    var_eps_nm_kl_HHHH -= 2. * (interHHHH1+interHHHH2);
    //Tenseur3HHHH::Prod_tensoriel_barre(gijHH,eps_p_HH);
    //(interHHHH1+interHHHH2);
//--//cout << "\n var_eps_nm_kl_HHHH: ";
//--//var_eps_nm_kl_HHHH.Affiche_bidim(cout);

/*
// vérif numérique de la variation
{Tenseur3HH delta_eps = var_eps_nm_kl_HHHH && epsBB;
 cout << "\n delta_eps= "; delta_eps.Ecriture(cout);
Tenseur3HH eps_p_HH(gijHH * epsBB * gijHH);
cout <<"\n eps_p_HH en g_i: "; eps_p_HH.Ecriture(cout);
// vérif var de g^ij
Tenseur3HHHH d_gijHH(Tenseur3HHHH::Prod_tensoriel_croise(gijHH,gijHH));
d_gijHH *= -2.;
Tenseur3HH delta_gijHH(gijHH-(*ex.gijHH_0));
Tenseur3HH delta_gijHH_num = d_gijHH && epsBB;
cout << "\n delta_gijHH= "; delta_gijHH.Ecriture(cout);
cout << "\n delta_gijHH_num (1) "; delta_gijHH_num.Ecriture(cout);
for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 {delta_gijHH_num.Coor(n,m)=0;
  for (int i=1;i<4;i++) for (int j=1;j<4;j++)
    delta_gijHH_num.Coor(n,m) += d_gijHH(n,m,i,j)  * epsBB(i,j);
 }
cout << "\n delta_gijHH_num (2)) = "; delta_gijHH_num.Ecriture(cout);
for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 {delta_gijHH_num.Coor(n,m)=0;
  for (int i=1;i<4;i++) for (int j=1;j<4;j++)
    delta_gijHH_num.Coor(n,m) += -2.* gijHH(n,i) * gijHH(j,m)  * epsBB(i,j);
 }
cout << "\n delta_gijHH_num (3)) = "; delta_gijHH_num.Ecriture(cout);

Tenseur3HHHH d_gijHH_num;
for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 for (int i=1;i<4;i++) for (int j=1;j<4;j++)
     d_gijHH_num.Change(n,m,i,j,(-2.* gijHH(n,i) * gijHH(j,m))) ;


for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 for (int i=1;i<4;i++) for (int j=1;j<4;j++)
   { cout << "\n d_gijHH("<<n <<","<<m<<","<<i<<","<<j<<") et "
          << " -2.* gijHH("<<n<<","<<i<<") * gijHH("<<j<<","<<m<<")= et d_gijHH_num "
          << d_gijHH(n,m,i,j) << " "
          << (-2.* gijHH(n,i) * gijHH(j,m))<< " "
          << d_gijHH_num(n,m,i,j) ;
    }

}
*/

//{Tenseur3HH A(1,2,3,0.,0.,0.);
// Tenseur3HH B(4,5,6,0.,0.,0.);
// Tenseur3HHHH C(Tenseur3HHHH::Prod_tensoriel(A,B));
//cout << "\n C= ";C.Affiche_bidim(cout);
// Tenseur3HHHH C1(Tenseur3HHHH::Prod_tensoriel_barre(A,B));
//cout << "\n Prod_tensoriel_barre(A,B)= ";C1.Affiche_bidim(cout);
// Tenseur3HHHH C2(Tenseur3HHHH::Prod_tensoriel_croise(A,B));
//cout << "\n Prod_tensoriel_croise(A,B)= ";C2.Affiche_bidim(cout);
// Tenseur3HHHH C3(Tenseur3HHHH::Prod_tensoriel_croise_croise(A,B));
//cout << "\n Prod_tensoriel_croise_croise(A,B)= ";C3.Affiche_bidim(cout);
//}

//--//    var_delta_eps_nm_kl_HHHH -= 2. * (interHHHH1+interHHHH2);

    // on calcul par composante car il y a des pb de symétrie qui sont difficiles à maîtriser
    // en tensoriel avec un stockage symétrique (il faudra peut-être essayer d'améliorer via les tenseurs
    // généraux) mais cela doit-être cependant assez efficace !
    // d_Delta_epsilon^{nm} / d_epsilon_{kl} = -2 ( g^{nk} . Delta_epsilon^{lm} +  Delta_epsilon^{nk} . g^{ml} ) + g^{nk} . g^{lm}

    TenseurQ3geneHHHH d_delta_eps_nmkl_HHHH;
    {for (int n=1;n<4;n++) for (int m=1;m<4;m++) for (int k=1;k<4;k++) for (int l=1;l<4;l++)
       { double inter=  gijHH(n,k) * gijHH(l,m)
                             -2.*(gijHH(n,k) * delta_epsHH(l,m) + delta_epsHH(n,l) * gijHH(m,k));
         d_delta_eps_nmkl_HHHH.Change(n,m,k,l,inter);
       };
////  vérification du stockage
//cout << "\n deps_nmkl= calcul en composantes";
//for (int n=1;n<4;n++) for (int m=1;m<4;m++) for (int k=1;k<4;k++) for (int l=1;l<4;l++)
//   { double inter=  gijHH(n,k) * gijHH(l,m)
//                             -2.*(gijHH(n,k) * epsHH(l,m) + epsHH(n,l) * gijHH(m,k));
//     cout << "\n deps_nmkl("<<n <<","<<m<<","<<k<<","<<l<<") =  et formule directe "
//          << inter <<" " << deps_nmkl_HHHH(n,m,k,l);
//  };
    };

// OK  vérif variation deps_nmkl_HHHH
/*{
Tenseur3HH delta_epsHH_num;
for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 {delta_epsHH_num.Coor(n,m)=0;
  for (int i=1;i<4;i++) for (int j=1;j<4;j++)
    delta_epsHH_num.Coor(n,m) += deps_nmkl_HHHH(n,m,i,j)  * epsBB(i,j);
 }
cout << "\n delta_epsHH_num = "; delta_epsHH_num.Ecriture(cout);
cout << "\n epsHH = "; epsHH.Ecriture(cout);
}
Sortie(1);
*/
    //variation des delta déformations delta_epsHH / eps_ij dans le repère transporté / au eps_kl
    // c'est à dire la variation de delta_eps^ab / eps_kl
  
    // d_delta_epsilon^{ab} / d_epsilon_{kl} = d_gamma^a_{.n} / d_epsilon_{kl} . Delta_epsilon^{nm} . gamma^b_{.m}
    //                                        + gamma^a_{.n} . d_Delta_epsilon^{nm} / d_epsilon_{kl} . gamma^b_{.m}
    //                                        + gamma^a_{.n} . Delta_epsilon^{nm} . d_gamma^b_{.m} / d_epsilon_{kl}

    // on calcul par composante car il y a des pb de symétrie qui sont difficiles à maîtriser
    // en tensoriel avec un stockage symétrique (il faudra peut-être essayer d'améliorer via les tenseurs
    // généraux) mais cela doit-être cependant assez efficace !
    TenseurQ3geneHHHH d_delta_eps_abkl_HHHH;
    {for (int a=1;a<4;a++) for (int b=1;b<4;b++) for (int k=1;k<4;k++) for (int l=1;l<4;l++)
      { double inter= 0.;
        for (int n=1;n<4;n++) for (int m=1;m<4;m++)
          inter += d_gamma_HH(a,n)(k,l) *  delta_epsHH(n,m) * gamma(b,m)
                   + gamma(a,n) * d_delta_eps_nmkl_HHHH(n,m,k,l) * gamma(b,m)
                   + gamma(a,n) * delta_epsHH(n,m) * d_gamma_HH(b,m)(k,l);
        d_delta_eps_abkl_HHHH.Change(a,b,k,l,inter);
      };
//cout << "\n d_delta_eps_abkl_HHHH= calcul en composantes";
//d_delta_eps_abkl_HHHH.Affiche_bidim(cout);
    };

// OK  vérif numérique de la variation
/*{
Tenseur3HH delta_eps_ab_HH_num;
for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 {delta_eps_ab_HH_num.Coor(n,m)=0;
  for (int i=1;i<4;i++) for (int j=1;j<4;j++)
    delta_eps_ab_HH_num.Coor(n,m) += deps_abkl_HHHH(n,m,i,j)  * epsBB(i,j);
 }
cout << "\n delta_eps_ab_HH_num = "; delta_eps_ab_HH_num.Ecriture(cout);
cout << "\n eps_p_HH = "; eps_p_HH.Ecriture(cout);
Sortie(1);
}
*/
    // variation des contraintes (composantes dans le repère transporté) / au eps_kl
//--//    Tenseur3HHHH var_sig_ab_kl_HHHH = var_sig_ab_cd_HHBB && var_eps_ab_kl_HHHH;
  
    TenseurQ3geneHHHH d_delta_sig_abkl_HHHH;
    {// pour vérification on va calculer par composante
     for (int a=1;a<4;a++) for (int b=1;b<4;b++) for (int k=1;k<4;k++) for (int l=1;l<4;l++)
      { double inter= 0.;
        for (int n=1;n<4;n++) for (int m=1;m<4;m++)
           inter += var_sig_ab_cd_HHBB(a,b,n,m) * d_delta_eps_abkl_HHHH(m,n,k,l);
        d_delta_sig_abkl_HHHH.Change(a,b,k,l,inter);
      };
//    cout << "\n d_delta_sig_abkl_HHHH= calcul en composantes";
//    d_delta_sig_abkl_HHHH.Affiche_bidim(cout);
    };

//cout << "\n var_sig_ab_kl_HHHH= ";
//var_sig_ab_kl_HHHH.Affiche_bidim(cout);

// OK  vérif numérique de la variation
/*{
Tenseur3HH delta_sigma_ab_HH_num;
for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 {delta_sigma_ab_HH_num.Coor(n,m)=0;
  for (int i=1;i<4;i++) for (int j=1;j<4;j++)
    delta_sigma_ab_HH_num.Coor(n,m) += dsig_abkl_HHHH(n,m,i,j)  * epsBB(i,j);
 }
cout << "\n delta_sigma_ab_HH_num = "; delta_sigma_ab_HH_num.Ecriture(cout);
cout << "\n sigma_ab_HH = "; sig_sauveHH.Ecriture(cout);
Sortie(1);
}
*/

    // variation des contraintes (composantes dans le repère g_i ) / au eps_kl
    // on peut maintenant calculer la variation de sig_ij / eps_kl
//--//    d_sigma_deps  = Tenseur3HHHH::Var_tenseur_dans_nouvelle_base
//--//                                  (beta_transpose,var_sig_ab_kl_HHHH,d_beta_transpose_HH,sigHH);
    // on calcul par composante car il y a des pb de symétrie qui sont difficiles à maîtriser
    // en tensoriel avec un stockage symétrique (il faudra peut-être essayer d'améliorer via les tenseurs
    // généraux) mais cela doit-être cependant assez efficace !
  
    // d_delta_sigma^{ij} / d_epsilon_{kl} = d_beta^{.i}_{a} / d_epsilon_{kl} . delta_sigma^{ab} . beta^{.j}_{b}
    //                                       + beta^{.i}_{a} .  d_delta_sigma^{ab} \ d_epsilon_{kl} . beta^{.j}_{b}
    //                                       + beta^{.i}_{a} . delta_sigma^{ab} . d_beta^{.j}_{b} \ d_epsilon_{kl}
    TenseurQ3geneHHHH dsig_ijkl_HHHH;
    {for (int i=1;i<4;i++) for (int j=1;j<4;j++) for (int k=1;k<4;k++) for (int l=1;l<4;l++)
      { double inter= 0.;
        for (int a=1;a<4;a++) for (int b=1;b<4;b++)
          inter += d_beta_HH(a,i)(k,l) *  delta_sig_ab_HH(a,b) * beta(b,j)
                   + beta(a,i) * d_delta_sig_abkl_HHHH(a,b,k,l) * beta(b,j)
                   + beta(a,i) * delta_sig_ab_HH(a,b) * d_beta_HH(b,j)(k,l);
        dsig_ijkl_HHHH.Change(i,j,k,l,inter);
      };
//cout << "\n deps_abkl= calcul en composantes";
//deps_abkl.Affiche_bidim(cout);
    };

// vérif numérique de la variation
/*{
Tenseur3HH delta_sigma_ij_HH_num;
for (int n=1;n<4;n++) for (int m=1;m<4;m++)
 {delta_sigma_ij_HH_num.Coor(n,m)=0;
  for (int i=1;i<4;i++) for (int j=1;j<4;j++)
    delta_sigma_ij_HH_num.Coor(n,m) += dsig_ijkl_HHHH(n,m,i,j)  * epsBB(i,j);
 }
cout << "\n delta_sigma_ij_HH_num = "; delta_sigma_ij_HH_num.Ecriture(cout);
cout << "\n sigma_ij_HH = "; sigHH.Ecriture(cout);
Sortie(1);
}
*/


    // on passe au tenseur de retour
    d_sigma_deps.TransfertDunTenseurGeneral(dsig_ijkl_HHHH.Symetrise1et2_3et4());

//cout << "\n d_sigma_deps= ";
//d_sigma_deps.Affiche_bidim(cout);
//
//    d_sigma_deps  = Tenseur3HHHH::Var_tenseur_dans_nouvelle_base
//                                  (beta,var_sig_ab_kl_HHHH,d_beta_HH,sigHH);
//
//cout << "\n (2) d_sigma_deps= ";
//d_sigma_deps.Affiche_bidim(cout);

// Sortie(1);

/*    // 1) la variation de d eps_ij / d eps_kl (dans le repère natuelle
    // ici on utilise le fait que IdBB3(i,j) représente le kronecker et idem pour IdHH3(i,j)
    // donc on met la variance qui va bien mais elle n'est pas utilisée
    // var_eps_ab_BBHH(i,j,k,l) = delta_i^k * delta_j^l : puis avec les symétries
    // car on peut changer i et j d'une part et k et l d'autre part
    Tenseur3BBHH var_eps_ij_kl_BBHH(Tenseur3BBHH::Prod_tensoriel_barre(IdBB3,IdHH3));
  
    // 2) la variation d eps_ab / d eps_ij
    Tenseur3BBHH var_eps_ab_kl_BBHH = Tenseur3BBHH::Var_tenseur_dans_nouvelle_base
                                         (beta,var_eps_ij_kl_BBHH,d_beta_HH,eps_p_BB);
  
    // maintenant on calcul la variation de sigma_ab / d epsilon_kl
    Tenseur3BBHH var_sig_ab_kl_BBHH =  var_sig_ab_cd_BBHH && var_eps_ab_kl_BBHH;
  
 
    // calcul de la variation de l'inverse de beta
//    beta_inv = beta.Inverse();
    Tableau2 <Tenseur3HH> d_beta_inv_HH(3,3);
    for (int b=1;b<4;b++)
     for (int j=1;j<4;j++)
       {Tenseur3HH& resHH = d_beta_inv_HH(j,b);
        for (int a=1;a<4;a++)
         for (int i=1;i<4;i++)
           resHH -= (beta_inv(j,a) * beta_inv(i,b)) * d_beta_HH(a,i);
       };

    // on peut maintenant calculer la variation de sig_ij / eps_kl
    Tenseur3BBHH var_sig_ij_kl_BBHH = Tenseur3BBHH::Var_tenseur_dans_nouvelle_base
                                         (beta_inv,var_sig_ab_kl_BBHH,d_beta_inv_HH,sig_BB);
  
    // calcul de la variation de \hat g^ij
    Tenseur3HHHH gijkl_HHHH(Tenseur3HHHH::Prod_tensoriel_barre(gijHH,gijHH));
    Tenseur3HHHH d_gij_kl_HHHH(-2.*Tenseur3HHHH::Prod_tensoriel_barre(gijHH,gijHH));
    Tenseur3HHBB interHHBB(Tenseur3HHBB::Prod_tensoriel_barre(gijHH,sig_BB));
  
    // puis on calcul  l'opérateur tangent dans la la bonne variance
    d_sigma_deps =  (gijkl_HHHH && var_sig_ij_kl_BBHH)
                   + (d_gij_kl_HHHH && (Tenseur3BBHH::Prod_tensoriel_barre(sig_BB,gijHH)))
                   + (interHHBB && d_gij_kl_HHHH);
  
*/

 
    LibereTenseur();
    LibereTenseurQ();       
 };