
// 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 "Deformation.h"
#include "ConstMath.h"
#include "ParaGlob.h"
#include "MathUtil.h"
#include "Tenseur3.h"
#include "Tenseur2.h"
#include "Tenseur1.h"
# include "TypeConsTens.h"
#include "Util.h"
#include "MathUtil2.h"


//================== initialisation des variables static ======================
// change 2 mai 2020: int Deformation::numInteg = 0;
// indicateur utilisé par VerifCal_deflog  
int Deformation::indic_VerifCal_implicit = 0;        
// def de deux tableaux d'indices pour avoir la suite: 12  21  13  31  23  32  à partir de 6 nombres
const Deformation::UtilIndexDeformation  Deformation::ccdex;
//  partie statique ou sont stocké tous les cas différents des variables de travail
list <Tableau <TenseurBH * > > Deformation::list_var_tens_BH;
list <Tableau <Tableau <TenseurBH* > > > Deformation::list_var_var_tens_BH;
list <Tableau <Coordonnee > > Deformation::list_tab_coor;
int Deformation::nombre_d_instance_deformation=0;

//================== fin d'initialisation des variables static ================

// def du constructeur par défaut de UtilIndexDeformation 
Deformation::UtilIndexDeformation::UtilIndexDeformation() :
  iii(6),jjj(6)
  { iii(6);  iii(1)=1; iii(2)=2;iii(3)=1;iii(4)=3;iii(5)=2;iii(6)=3;
    jjj(6); jjj(1)=2; jjj(2)=1;jjj(3)=3;jjj(4)=1;jjj(5)=3;jjj(6)=2;
  };

// ---------- constructeur----------------------------------------
Deformation::Deformation ()   // constructeur ne devant pas etre utilise
//#ifndef ENLINUX
  : tabnoeud((new Tableau <Noeud *> ))  // dans le cas de linux on ne déclare pas le tableau
    ,saveDefResul(NULL),numInteg(0),sauve_numInteg(0)
//#endif

// : tabnoeud()
 {
   #ifdef MISE_AU_POINT	 	 
		  { cout << "\nErreur : le constructeur par defaut ne doit pa etre utilise !\n";
			   cout << "Deformation::Deformation () \n";
			   Sortie(1);
    };
   #endif
 };

// constructeur normal dans le cas d'un ou de plusieurs pt d'integration             	  
Deformation::Deformation (Met_abstraite & a,Tableau<Noeud *>&  b,     
           Tableau <Mat_pleine> const  & tabdphi,Tableau <Vecteur> const & tabphi 
           ,Enum_type_deformation type_de_deformation) :
       tabnoeud(&b),type_deformation(type_de_deformation)
       ,type_gradient_vitesse(GRADVITESSE_VCONST) // pour l'instant ********* en test 
       ,saveDefResul(NULL) 
       // variables de travail pour log
       ,B_BH_tr(NULL),d_B_BH_tr(NULL),ki(),d_ki(NULL),Palpha_BH_tr(NULL),d_Palpha_BH_tr(NULL)
       ,dimensionnement_tableaux(0),numInteg(0)
       ,sauve_numInteg(0)
   { metrique = &a;
     tabDphi = &tabdphi;
     tabPhi = &tabphi;
     nbNoeud = (*tabPhi)(1).Taille();  // par defaut
     numInteg = 1; // 1 pt d'integ par defaut
     nombre_d_instance_deformation++;
   };

// constructeur de copie
Deformation::Deformation (const  Deformation& a) :
  tabnoeud(a.tabnoeud), type_deformation(a.type_deformation)
  ,type_gradient_vitesse(a.type_gradient_vitesse),saveDefResul(NULL)
  // variables de travail pour log
  ,B_BH_tr(a.B_BH_tr),d_B_BH_tr(a.d_B_BH_tr),ki(a.ki),d_ki(a.d_ki)
  ,Palpha_BH_tr(a.Palpha_BH_tr),d_Palpha_BH_tr(a.d_Palpha_BH_tr)
  ,dimensionnement_tableaux(a.dimensionnement_tableaux)
  ,numInteg(a.numInteg),sauve_numInteg(a.sauve_numInteg)
   { metrique = a.metrique;
     tabDphi = a.tabDphi;
     tabPhi = a.tabPhi;
     nbNoeud = a.nbNoeud;  
     nombre_d_instance_deformation++;
   };
     
Deformation::~Deformation () 
   { LibereTenseur() ; nombre_d_instance_deformation--;
     if (nombre_d_instance_deformation==0)
      {// cas de la dernière instance
       // ---- cas de list_var_tens_BH ----
       list <Tableau <TenseurBH * > >::iterator ilv,ilvend= list_var_tens_BH.end();
       for (ilv=list_var_tens_BH.begin();ilv!=ilvend;ilv++)
        { int tailletab=(*ilv).Taille();
          for (int i=1;i<=tailletab;i++) delete (*ilv)(i);
        };     
       list_var_tens_BH.erase(list_var_tens_BH.begin(),ilvend);
       // ---- cas de list_var_var_tens_BH ----
       list <Tableau <Tableau <TenseurBH* > > > ::iterator ilv1,ilvend1= list_var_var_tens_BH.end();
       for (ilv1=list_var_var_tens_BH.begin();ilv1!=ilvend1;ilv1++)
        { int tailletab=(*ilv1).Taille();
          for (int i=1;i<=tailletab;i++) 
            { int tailletab2=(*ilv1)(i).Taille();
              for (int j=1;j<=tailletab2;j++) delete (*ilv1)(i)(j);
            };
        };
       list_var_var_tens_BH.erase(list_var_var_tens_BH.begin(),ilvend1);
       // ---- cas de list_tab_coor ----
       list_tab_coor.erase(list_tab_coor.begin(),list_tab_coor.end());      
      };
   }; 
    
// réafectation du pointeur de tableau de noeuds interne
// il faut que le nouveau tableau ait la même taille que l'ancien (sert pour créer de nouveau éléments
// de même type, sinon ce n'est pas la bonne solution, 
// il vaut mieux creer une nouvelle def
void Deformation::PointeurTableauNoeud(Tableau <Noeud *> & tabN)
	{ // on vérifie la cohérence
	  if (tabN.Taille() != tabnoeud->Taille())
	  	{ cout << "\n erreur de re-affectation de tableau de noeud dans la deformation ! "
	  	       << " ancien nombre de noeud: " << tabnoeud->Taille() << " nouveau nombre: " << tabN.Taille()
	  	       << "\n  Deformation::PointeurTableauNoeud(..";
	  	  Sortie(1);     
	  	};
	  // sinon c'est ok
	  tabnoeud = &tabN;	
	};
    
// surcharge de l'opérateur d'affectation   
Deformation& Deformation::operator= (const Deformation& def)
{   metrique = def.metrique;
    tabnoeud = def.tabnoeud;
    tabDphi = def.tabDphi;
    tabPhi = def.tabPhi;
    nbNoeud = def.nbNoeud;type_deformation=def.type_deformation;
    numInteg = def.numInteg;
    saveDefResul = def.saveDefResul; 
    // variables de travail pour log
    B_BH_tr=def.B_BH_tr;d_B_BH_tr=def.d_B_BH_tr;ki=def.ki;d_ki=def.d_ki;
    Palpha_BH_tr=def.Palpha_BH_tr;d_Palpha_BH_tr=def.d_Palpha_BH_tr;
    
	   return (*this);	
};
    
// change le type de déformation 
void Deformation::Change_type_de_deformation(Enum_type_deformation type_de_def)
 { // le changement de déformation doit-être cohérent avec la déformation actuelle d'où les 
   // différents choix restreinds
   if ((type_de_def==DEFORMATION_STANDART) ||
	   (type_de_def==DEFORMATION_LOGARITHMIQUE) ||
	   (type_de_def==DEFORMATION_CUMU_LOGARITHMIQUE) ||
	   (type_de_def==DEF_CUMUL_CORROTATIONNEL) ||
	   (type_de_def==DEF_CUMUL_ROTATION_PROPRE) )
	     { if ((type_deformation==DEFORMATION_STANDART) ||
	           (type_deformation==DEFORMATION_LOGARITHMIQUE) ||
	           (type_deformation==DEFORMATION_CUMU_LOGARITHMIQUE) ||
	           (type_deformation==DEF_CUMUL_CORROTATIONNEL) ||
	           (type_deformation==DEF_CUMUL_ROTATION_PROPRE) )
	             type_deformation = type_de_def; // ok cohérent
      }     
   // sinon le type n'est pas pris en compte dans cette méthode donc erreur	    
	  else
      { cout << "\nErreur : valeur incorrecte du nouvrau type Enum_type_deformation !"
			          << "\n type actuelle: " << Nom_type_deformation(type_deformation)
			          << " type demande: " << Nom_type_deformation(type_de_def);
		      cout << "Deformation::Change_type_de_deformation(...) \n";
		      Sortie(1);
	     };
 };
 
// affichage des informations
void Deformation::Affiche() const
 { cout << "\n -- deformation: --- "
        << "\n nb noeud concerne = "<< nbNoeud
        << " numInteg= "<< numInteg;
   if (tabnoeud != NULL)
    {cout << "\n -- information concernant les noeuds: \n";
     for (int i = 1;i<= tabnoeud->Taille();i++)
       (*tabnoeud)(i)->Affiche();
    };
   if (metrique != NULL)
    {cout << "\n -- information concernant la metrique actuelle au pti --";
     metrique->Affiche();
    };
   cout << flush;
 };

   
//  ============      METHODES PUBLIQUES :  ==================
// ---------------- calcul des variables primaires pour la mécanique --------    
     // calcul explicit à t :tous les parametres sont des resultats
const Met_abstraite::Expli&  Deformation::Cal_explicit_t
//         ( bool gradV_instantane,TenseurBB & epsBB_t,Tableau <TenseurBB *> & d_epsBB
//           ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul)
                      // def_equi_t: est la def equi au debut du pas, et def_equi est la def finale
         ( const Tableau <double>& def_equi_t,TenseurBB & epsBB_t,Tableau <TenseurBB *> & d_epsBB
           ,Tableau <double>& def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul)
{bool gradV_instantane = false; // ************ pour l'instant figé
 // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc
 // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt
 // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes
 const Met_abstraite::Expli& ex = 
     metrique->Cal_explicit_t(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg),
                          nbNoeud,(*tabPhi)(numInteg),premier_calcul);
 
 // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange ..
	switch (type_deformation)
	  { case  DEFORMATION_STANDART :  
	     {Cal_explicit_Almansi
	            (gradV_instantane,epsBB_t,d_epsBB,DepsBB,delta_epsBB,premier_calcul,ex);
	      break;
      }
	    case DEFORMATION_LOGARITHMIQUE:
	     {Cal_explicit_Logarithmique
	            (gradV_instantane,epsBB_t,d_epsBB,DepsBB,delta_epsBB,premier_calcul,ex);
	      break;
      }
	      
//		case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE :
//		 {Cal_explicit_def_cumule
//		        (gradV_instantane,epsBB_t,d_epsBB,DepsBB,delta_epsBB,premier_calcul,ex);
//		  break;
//		  }
		   default :
			    cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation)
			         << " ) non traite !\n";
			    cout << "Deformation::Cal_explicit(... \n";
			    Sortie(1);
	  };

    // --- on calcul la déformation cumulée
	 
	{TenseurBH * delta_epsBH = NevezTenseurBH(delta_epsBB.Dimension(), 0.);
	 *delta_epsBH = delta_epsBB * (*ex.gijHH_t);
	 double delta_eps_equi = sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. ));
	 def_equi(1) = def_equi_t(1) + delta_eps_equi;
	 def_equi(4) = delta_eps_equi;
	 delete delta_epsBH;
	 };
	{TenseurBH * epsBH = NevezTenseurBH(epsBB_t.Dimension(), 0.);
	 *epsBH = epsBB_t * (*ex.gijHH_t);
	 def_equi(2) = sqrt(2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. ));
	 delete epsBH;
	 if (def_equi(2) > def_equi_t(3))
	    def_equi(3) = def_equi(2);
 };

	// sauvegarde des infos à 0 éventuellement et init par recopie des grandeurs sur t
 if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique);
	 // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici
//	 const Met_abstraite::Expli& toto = * (new Met_abstraite::Expli()); return toto; 
     return ex;
};
  
     // calcul explicit à tdt :tous les parametres sont des resultats
const Met_abstraite::Expli_t_tdt&  Deformation::Cal_explicit_tdt
//         ( bool gradV_instantane,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB,TenseurBB& DepsBB
//           ,TenseurBB& delta_epsBB_tdt,bool premier_calcul)
         ( const Tableau <double>& def_equi_t,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB
           ,Tableau <double>& def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB_tdt,bool premier_calcul)
{ bool gradV_instantane = false; // ************ pour l'instant figé  
  // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc
  // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt
  // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes
  const Met_abstraite::Expli_t_tdt& ex = 
                  metrique->Cal_explicit_tdt(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg),
                                             nbNoeud,(*tabPhi)(numInteg),premier_calcul);
  
  // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange ..
	 switch (type_deformation)
	  { case  DEFORMATION_STANDART :  
	     {Cal_explicit_Almansi_tdt
	            (gradV_instantane,epsBB_tdt,d_epsBB,DepsBB,delta_epsBB_tdt,premier_calcul,ex);
	      break;
      }
	    case DEFORMATION_LOGARITHMIQUE:
	     {Cal_explicit_logarithmique_tdt
	            (gradV_instantane,epsBB_tdt,d_epsBB,DepsBB,delta_epsBB_tdt,premier_calcul,ex);
	      break;
      }
//		case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE :
//		 {Cal_explicit_def_cumule_tdt
//		        (gradV_instantane,epsBB_tdt,d_epsBB,DepsBB,delta_epsBB_tdt,premier_calcul,ex);
//		  break;
//		  }
		   default :
       cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation)
			         << " ) non traite !\n";
			    cout << "Deformation::Cal_explicit_tdt(... \n";
			    Sortie(1);
	  };
	 // sauvegarde des infos à 0 éventuellement et init par recopie des grandeurs sur t
  if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique);
  // sauvegarde des infos à t à chaque passage
  saveDefResul->MiseAJourGrandeurs_a_tdt(metrique,DepsBB);
    // --- on calcul la déformation cumulée
	 {TenseurBH * delta_epsBH = NevezTenseurBH(delta_epsBB_tdt.Dimension(), 0.);
	  *delta_epsBH = delta_epsBB_tdt * (*ex.gijHH_tdt);
	  double delta_eps_equi = sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. ));
	  def_equi(1) = def_equi_t(1) + delta_eps_equi;
	  def_equi(4) = delta_eps_equi;
	  delete delta_epsBH;
	 };

	 {TenseurBH * epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.);
	  *epsBH = epsBB_tdt * (*ex.gijHH_tdt);
	  def_equi(2) = sqrt(2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. ));
	  delete epsBH;
	  if (def_equi(2) > def_equi_t(3))
	     def_equi(3) = def_equi(2);
  };

	 // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici
  //	 const Met_abstraite::Expli_t_tdt& toto = * (new Met_abstraite::Expli_t_tdt()); return toto;
  return ex; 
};
   
// calcul et récupération de la dérivée de la vitesse de déformation virtuelle à tdt
// dans le cas d'une discrétisation classique simple, ce calcul est indépendant des coordonnées
// donc peut être effectué indépendament du reste, il dépend cependant du point d'intégration
// dans le cas de discrétisation complexe, il faut s'assurer que les autres grandeurs utiles de la métrique
// sont déjà calculé (cf. D2_gijBB_tdt() ) 
//   total = true : indique que le calcul est complet, à partir des données de base 
//                  c-a-d calcul de la variation de vecteur de base puis calcul de la variation seconde
//         = false: le calcul est simplifié, on considère que la variation des vecteurs de base vient
//                  juste d'être calculé, dans un calcul implicit, on ne calcul alors que la variation seconde
void Deformation::Cal_var_def_virtuelle(bool total,Tableau2 <TenseurBB *>& d2_epsBB_tdt)
    	{ const Tableau2 <TenseurBB * > & d2_gijBB_tdt 
    	     = metrique->CalVar2GijBBtdt(total, (*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg));
   	      int d2_epsBB_tdtTaille1 = d2_epsBB_tdt.Taille1();
          for (int i=1; i<= d2_epsBB_tdtTaille1; i++)
           for (int j=1; j<= i; j++)  // symétrie du  tableau et du tenseur
	            { *(d2_epsBB_tdt(i,j)) = 0.5 * (*((d2_gijBB_tdt)(i,j))) ;
	              *(d2_epsBB_tdt(j,i)) = *(d2_epsBB_tdt(i,j)) ; 
             };
    	};
    
  	  // cas implicite : tous les parametres sont de resultats	
//const Met_abstraite::Impli& Deformation::Cal_implicit( bool gradV_instantane
//           ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB_tdt
//           ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul)
const Met_abstraite::Impli& Deformation::Cal_implicit(const Tableau <double>& def_equi_t
           ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB_tdt
           ,Tableau <double>& def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul)
{ bool gradV_instantane = false; // ************ pour l'instant figé
  // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc
  // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt
  // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes
  // toutes les variables de passage a metrique apres l'appel
  // pointeront sur des variables  deja dimensionnees     
  // pour les Tableau <> il y a dim
//------debug
//premier_calcul=true; 
//---- fin debug	 
  const Met_abstraite::Impli& ex =metrique->Cal_implicit
               ( *tabnoeud,gradV_instantane,(*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg)
                 ,premier_calcul);
  // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange ..
	 switch (type_deformation)
	 {  case  DEFORMATION_STANDART :  
	       {Cal_implicit_Almansi
	            (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex);
	        break;
	       }
	    case DEFORMATION_LOGARITHMIQUE:
	       {Cal_implicit_Logarithmique
	            (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex);
	        break;
	       }
		   case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE :
		      {Cal_implicit_def_cumule
		        (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex);
		       break;
		      }
		   default :
			    cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation)
			         << " ) non traite !\n";
			    cout << "Deformation::Cal_implicit(... \n";
			    Sortie(1);
	 };
	 // sauvegarde des infos à 0 et à t
  // *** non car dans le cas d'un restart ce n'est pas vrai !!!! // éventuellement et init par recopie des grandeurs sur t
  if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique);
  // sauvegarde des infos à tdt à chaque passage
  saveDefResul->MiseAJourGrandeurs_a_tdt(metrique,DepsBB);
	 // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici
  //	 const Met_abstraite::Impli& toto = * (new Met_abstraite::Impli()); return toto; 

  // --- on calcul la déformation cumulée
	 {TenseurBH * delta_epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.);
	  *delta_epsBH = delta_epsBB * (*ex.gijHH_tdt);
	  double x_inter = (2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. ));
   if (x_inter < 0)
    {if (Dabs(x_inter) < ConstMath::trespetit)
       { //debug
         //cout << "\n **************** x_inter= "<<x_inter<<endl;
         //fin debug
         x_inter = 0.;
       }
     else
       { if (ParaGlob::NiveauImpression() > 0)
           cout << "\n erreur calcul def equi: delta_def_equi2 est negatif ("<<x_inter<<") la racine -> nan! "
                << " on met a 0, mais ce n'est pas normal !! ";
         if (ParaGlob::NiveauImpression() > 5)
           cout << "\n Deformation::Cal_implicit(.." << endl;
       };
    };
	  double delta_eps_equi = sqrt(x_inter);
	  def_equi(1) = def_equi_t(1) + delta_eps_equi;
	  def_equi(4) = delta_eps_equi;
	  delete delta_epsBH;
  };

	 {TenseurBH * epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.);
	  *epsBH = epsBB_tdt * (*ex.gijHH_tdt);
   
	  double y_inter = 2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. );
   if (y_inter < 0)
    {if (Dabs(y_inter) < ConstMath::trespetit)
       { //debug
         //cout << "\n **************** x_inter= "<<x_inter<<endl;
         //fin debug
         y_inter = 0.;
       }
     else
       { if (ParaGlob::NiveauImpression() > 0)
           cout << "\n erreur calcul def equi: sqr(def_dual_mises est negatif) ("<<y_inter<<") la racine -> nan! "
                << " on met a 0, mais ce n'est pas normal !! ";
         if (ParaGlob::NiveauImpression() > 5)
           cout << "\n Deformation::Cal_implicit(.." << endl;
       };
    };
	  def_equi(2) = sqrt(y_inter);
	  delete epsBH;
	  if (def_equi(2) > def_equi_t(3))
	     def_equi(3) = def_equi(2);
  };
	 
  return ex;
};
      
//  ------------------------ flambage linéaire ------------------------------
const Met_abstraite::flambe_lin& Deformation::Cal_flambe_lin
//         ( bool gradV_instantane,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB_tdt,Tableau2 <TenseurBB *>& d2_epsBB_tdt
//           ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul)
         ( const Tableau <double>& def_equi_t,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB_tdt
           ,Tableau <double>& def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul)
  { bool gradV_instantane = false; // ************ pour l'instant figé
  
    // --- le calcul est identique au cas implicite sauf que 
    //     l'on doit absolument calculer la dérivée seconde de la déformation

    // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc
    // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt
    // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes
    // toutes les variables de passage a metrique apres l'appel
    // pointeront sur des variables  deja dimensionnees     
    // pour les Tableau <> il y a dimensionnement auto a l'affectation
    const Met_abstraite::Impli& ex =metrique->Cal_implicit
               ( *tabnoeud,gradV_instantane,(*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg)
                 ,premier_calcul);
    // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange ..
	   switch (type_deformation)
	    { case  DEFORMATION_STANDART :  
	         {Cal_implicit_Almansi(gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex);
	          break;
	         }
       case DEFORMATION_LOGARITHMIQUE:
	         {Cal_implicit_Logarithmique(gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex);
	          break;
	         }
//		case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE :
//		 {Cal_implicit_def_cumule
//		        (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex);
//		  break;
//		  }
       default :
			        cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation)
			             << " ) non traite !\n";
			        cout << "Deformation::Cal_flambe_lin(... \n";
			        Sortie(1);
	    };

    // --- on calcul la déformation cumulée
	   {TenseurBH * delta_epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.);
	    *delta_epsBH = delta_epsBB * (*ex.gijHH_tdt);
	    double delta_eps_equi = sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. ));
	    def_equi(1) = def_equi_t(1) + delta_eps_equi;
	    def_equi(4) = delta_eps_equi;
	    delete delta_epsBH;
	   };

	   {TenseurBH * epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.);
	    *epsBH = epsBB_tdt * (*ex.gijHH_tdt);
	    def_equi(2) = sqrt(2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. ));
	    delete epsBH;
	    if (def_equi(2) > def_equi_t(3))
	        def_equi(3) = def_equi(2);
	   };
	 
	   // sauvegarde des infos à 0 éventuellement et init par recopie des grandeurs sur t
    if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique);
    // sauvegarde des infos à tdt à chaque passage
    saveDefResul->MiseAJourGrandeurs_a_tdt(metrique,DepsBB);
	   // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici
    //	 const Met_abstraite::flambe_lin& toto = * (new Met_abstraite::flambe_lin()); return toto;
    return (Met_abstraite::flambe_lin&) ex; 
  };
  
// ------------------------- cas de la dilatation thermique ------------------------
    // l'objectif est de calculer la déformation d'origine thermique et la déformation d'origine mécanique
    // temperature_tdt,temperature_t : températures, temperature_0: température initiale
    // atdt : booléen qui indique si les grandeurs à tdt sont disponible ou pas
    // avec_repercution_sur_def_meca: si oui on met à jour la déformation méca, sinon, on ne calcul que les def thermiques
void Deformation::DeformationThermoMecanique(const double& temperature_0,const ThermoDonnee& dTP
                                ,const TenseurBB & epsBB_totale,TenseurBB & epsBB_therm,const double& temperature_tdt,TenseurBB & epsBB_meca
                                ,const TenseurBB & delta_epsBB_totale,TenseurBB & delta_epsBB_therm,TenseurBB & delta_epsBB_meca
                                ,const double& temperature_t,TenseurBB & DepsBB_totale,TenseurBB & DepsBB_therm,TenseurBB & DepsBB_meca
                                ,const Met_abstraite::Impli* ex_impli
                                ,const Met_abstraite::Expli_t_tdt* ex_expli_tdt
                                ,const Met_abstraite::Umat_cont* ex_umat
                                ,bool atdt,bool avec_repercution_sur_def_meca)
 { // la dilatation est déterminée par l'élévation de température 
   double coef_dila_global = dTP.Dilatation() * (temperature_tdt-temperature_0);
   
   // éléments de métrique
   TenseurHH* gijHH;TenseurBB* gijBB;BaseB* giB; BaseH* giH_0;BaseH* giH;
   BaseB* giB_0;BaseB* giB_t;
   bool pas_de_metrique_dispo = false; // init

   if (ex_impli != NULL)
     {   gijHH = ex_impli->gijHH_tdt;gijBB = ex_impli->gijBB_tdt;
         giB = ex_impli->giB_tdt; giH_0 = ex_impli->giH_0;giH = ex_impli->giH_tdt;
         giB_t = ex_impli->giB_t; giB_0 = ex_impli->giB_0;
     }
   else if (ex_expli_tdt != NULL)
     {gijHH = ex_expli_tdt->gijHH_tdt;gijBB = ex_expli_tdt->gijBB_tdt;
      giB = ex_expli_tdt->giB_tdt; giH_0 = ex_expli_tdt->giH_0;giH = ex_expli_tdt->giH_tdt;
      giB_t = ex_expli_tdt->giB_t; giB_0 = ex_expli_tdt->giB_0;
     }
   else if (ex_umat != NULL)
     {gijHH = ex_umat->gijHH_t;gijBB = ex_umat->gijBB_t;
      giB = giB_t = ex_umat->giB_t; giH_0 = ex_umat->giH_0;giH = ex_umat->giH_t;
      giB_0 = ex_umat->giB_0;
     }
   else
    { pas_de_metrique_dispo = true;
    };

   // -- cas de la déformation
   epsBB_therm = coef_dila_global * (*gijBB);
   
   // -- cas de l'incrément de déformation
   if (atdt)
     { // cas d'un calcul avec les grandeurs à tdt disponibles
       double coef_dila_t_tdt = dTP.Dilatation() * (temperature_tdt-temperature_t);
       delta_epsBB_therm = coef_dila_t_tdt * (*gijBB) ;
     }
   else
     { // cas où les valeurs à tdt ne sont pas dispo, on considère un coef moyen sur toute la durée
       // et on considère que le delta = la valeur totale de la déformation
       // donc c'est le même calcul que pour la déformation totale
       delta_epsBB_therm = coef_dila_global * (*gijBB) ;
     };
   
   // -- cas de la vitesse de déformation
   // recup de l'incrément de temps
	  double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
   double unSurDeltat=0;    
	  if (Abs(deltat) >= ConstMath::trespetit)
     { unSurDeltat = 1./deltat;}
   else
       // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
     { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
       if (unSurDeltat < 0)
        { cout << "\n le pas de temps est négatif !! "; };
       unSurDeltat = ConstMath::tresgrand;
     };
   if (atdt)
     { // cas d'un calcul avec les grandeurs à tdt disponibles
       double coef_dila_t_tdt = dTP.Dilatation() * (temperature_tdt-temperature_t);
       DepsBB_therm = coef_dila_t_tdt * (*gijBB) * unSurDeltat;
     }
   else
     { // cas où les valeurs à tdt ne sont pas dispo, on considère un coef moyen sur toute la durée
       // recup de l'incrément du temps global
	      double ttemps=ParaGlob::Variables_de_temps().TempsCourant();
       double unSurttemps=0;    
	      if (Abs(ttemps) >= ConstMath::trespetit)
           {unSurttemps = 1./ttemps;}
       else
           // si l'incrément de temps est tres petit on remplace 1/ttemps par un nombre tres grand
           { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
            if (unSurttemps < 0)
             { cout << "\n le pas de temps est négatif !! "; };
            unSurttemps = ConstMath::tresgrand;
           };
       DepsBB_therm = coef_dila_global * (*gijBB) * unSurttemps;
     }; 	


//     switch (abs(epsBB_meca.Dimension()))
//      { case 1: epsBB_therm = coef_dila * IdBB1;
//        case 2: epsBB_therm = coef_dila * IdBB2;
//        case 3: epsBB_therm = coef_dila * IdBB3;
//       }
   if (avec_repercution_sur_def_meca)
    { epsBB_meca =  epsBB_totale - epsBB_therm; // pour la déformation
      delta_epsBB_meca =  delta_epsBB_totale - delta_epsBB_therm; // pour la déformation
      DepsBB_meca = DepsBB_totale - DepsBB_therm; // pour la vitesse de déformation
    };
    
   
//// -- debug
//if (!pas_de_metrique_dispo)
//   {cout << "\n debug Deformation::DeformationThermoMecanique( ";
//    cout << "\n coef_dila_global= " << coef_dila_global
//    << " delta_temp total= "<< (temperature_tdt-temperature_0)
//    << " increment temp= "<< (temperature_tdt-temperature_t);
//    // on sort les tenseurs en absolue
//    Tenseur3BB tiutiu;
//    epsBB_therm.BaseAbsolue(tiutiu,*giH);
//    cout << "\n epsBB_therm(1,1)=" << tiutiu(1,1);
//    epsBB_meca.BaseAbsolue(tiutiu,*giH);
//    cout << " epsBB_meca(1,1)=" << tiutiu(1,1);
//    delta_epsBB_therm.BaseAbsolue(tiutiu,*giH);
//    cout << " \n delta_epsBB_therm(1,1)= "<< tiutiu(1,1);
//    delta_epsBB_meca.BaseAbsolue(tiutiu,*giH);
//    cout << " delta_epsBB_meca(1,1)=" << tiutiu(1,1) << endl;
//   };
//// -- fin debug
  
 };	   
	   
// ========== remontee aux informations =========================
		
// cas sortie d'un calcul implicit
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoImp Deformation::RemontImp(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { Met_abstraite::InfoImp ex = metrique->Cal_InfoImp
        ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_tdt);
    BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin);
    return ex;      
   };

// cas sortie d'un calcul implicit
// sans le calcul des matrices de passage
const Met_abstraite::InfoImp Deformation::RemontImp()
  { Met_abstraite::InfoImp ex = metrique->Cal_InfoImp
        ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_tdt);
    return ex;
   };

// cas sortie d'un calcul explicit à t
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoExp_t Deformation::RemontExp_t(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { Met_abstraite::InfoExp_t ex = metrique->Cal_InfoExp_t
                 ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_t);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_t);
    BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin);
    return ex;      
  };
    
// cas sortie d'un calcul explicit à t
// sans le calcul des matrices de passage
const Met_abstraite::InfoExp_t Deformation::RemontExp_t()
  { Met_abstraite::InfoExp_t ex = metrique->Cal_InfoExp_t
                 ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_t);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_t);
    return ex;
  };

   // cas sortie d'un calcul explicit à tdt
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoExp_tdt Deformation::RemontExp_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { Met_abstraite::InfoExp_tdt ex = metrique->Cal_InfoExp_tdt
                 ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_tdt);
    BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin);
    return ex;      
  };

   // cas sortie d'un calcul explicit à tdt
   // sans le calcul des matrices de passage
const Met_abstraite::InfoExp_tdt Deformation::RemontExp_tdt()
  { Met_abstraite::InfoExp_tdt ex = metrique->Cal_InfoExp_tdt
                 ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_tdt);
    return ex;
  };

    // cas sortie d'un calcul à 0, t et tdt
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::Info0_t_tdt Deformation::Remont0_t_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt)
  { Met_abstraite::Info0_t_tdt ex = metrique->Cal_Info0_t_tdt
                 ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giBt = *(ex.giB_t);
    BaseB & giBtdt = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giHt = *(ex.giH_t);
    BaseH & giHtdt = *(ex.giH_tdt);
    BasePassage(absolue,giB0,giBt,giBtdt,giH0,giHt,giHtdt,Aa0,Aat,Aatdt);
    return ex;      
  };

    // cas sortie d'un calcul à 0, t et tdt
    // sans le calcul des matrices de passage
const Met_abstraite::Info0_t_tdt Deformation::Remont0_t_tdt()
  { Met_abstraite::Info0_t_tdt ex = metrique->Cal_Info0_t_tdt
                 ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud);
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giBt = *(ex.giB_t);
    BaseB & giBtdt = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giHt = *(ex.giH_t);
    BaseH & giHtdt = *(ex.giH_tdt);
    return ex;
  };

// cas sortie d'un calcul implicit
// mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes
// d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices
// Aa0 et Aafin
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoImp Deformation::RemontImpSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { Met_abstraite::InfoImp ex = metrique->Recup_InfoImp();
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_tdt);
    BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin);
    return ex;      
   }; 
   
// cas sortie d'un calcul explicit à t
// mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes
// d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices
// Aa0 et Aafin
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoExp_t Deformation::RemontExp_tSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { Met_abstraite::InfoExp_t ex = metrique->Recup_InfoExp_t();
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_t);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_t);
    BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin);
    return ex;      
  };
    
   // cas sortie d'un calcul explicit à tdt
// mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes
// d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices
// Aa0 et Aafin
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoExp_tdt Deformation::RemontExp_tdtSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { Met_abstraite::InfoExp_tdt ex = metrique->Recup_InfoExp_tdt();
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giB = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giH = *(ex.giH_tdt);
    BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin);
    return ex;      
  };

    // cas sortie d'un calcul à 0, t et tdt
// mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes
// d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices
// Aa0 et Aafin
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::Info0_t_tdt Deformation::Remont0_t_tdtSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt)
  { Met_abstraite::Info0_t_tdt ex = metrique->Recup_Info0_t_tdt();
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giBt = *(ex.giB_t);
    BaseB & giBtdt = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giHt = *(ex.giH_t);
    BaseH & giHtdt = *(ex.giH_tdt);
    BasePassage(absolue,giB0,giBt,giBtdt,giH0,giHt,giHtdt,Aa0,Aat,Aatdt);
    return ex;      
  };

    // cas sortie d'un calcul à 0, t et tdt avec tous les métriques associées
// mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes
// d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices
// Aa0 et Aafin
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::Info_et_metrique_0_t_tdt Deformation::Remont_et_metrique_0_t_tdtSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt)
  { Met_abstraite::Info_et_metrique_0_t_tdt ex = metrique->Recup_Info_et_metrique_0_t_tdt();
    // determination des matrices de transformation de base
    BaseB & giB0 = *(ex.giB_0);
    BaseB & giBt = *(ex.giB_t);
    BaseB & giBtdt = *(ex.giB_tdt);
    BaseH & giH0 = *(ex.giH_0);
    BaseH & giHt = *(ex.giH_t);
    BaseH & giHtdt = *(ex.giH_tdt);
    BasePassage(absolue,giB0,giBt,giBtdt,giH0,giHt,giHtdt,Aa0,Aat,Aatdt);
    return ex;
  };

// cas où l'on veut les matrices de passages à 0 et final
// voir Deformation.h pour plus d'info
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
// (voir Deformation.h pour un descriptif plus complet)
// si absolue = true: on fait un passage vers la base absolue
// si = false : on fait un passage vers une base ad hoc
void Deformation::BasePassage
        (bool absolue,const BaseB & giB0,const BaseB & giB,const BaseH & giH0,const BaseH & giH,
         Mat_pleine& Aa0,Mat_pleine& Aafin)
{ // determination des matrices de transformation de base
  int dim = giB0.NbVecteur();
 
  // dim_espace X nb_vecteur X taille_matrice

  // cas d'une sortie en globale
  // 1X1X1 ou 2X2X2 ou 3X3X3
  if ((dim == ParaGlob::Dimension()) && (Aa0.Nb_ligne() == dim))
   { // --- ici il n'y a pas a priori de repère ad hoc, donc le calcul ne dépend pas de "absolue"
   
     // petite vérif
     #ifdef MISE_AU_POINT
	     if  ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim)
           && (Aafin.Nb_ligne() != dim) && (Aafin.Nb_colonne() !=dim))
        { cout << "\nErreur1 : les matrices Aa0 et /ou Aafin ne sont pas correctement"
               << " dimensionnees  ! \n";
          cout << "\n Aa0= "; Aa0.Affiche();
          cout << "\n Aafin= "; Aafin.Affiche();
          cout << "void Deformation::BasePassage( \n";
          Sortie(1);
        };
     #endif
     for (int i=1;i<=dim;i++)
        for (int j=1;j<=dim;j++)
          {Aa0 (i,j) = giH0(i)(j);
           Aafin(i,j) =giH(i)(j);
          };
   }
  else if ((dim==2)&&(ParaGlob::Dimension()==3))
   // cela comprend les cas: 3X2X2 -> un repère local ad hoc en 2D
   //                        3X2X3 -> un repère local ad hoc en 3D
   // ====  cas d'élément de membrane en 3D ====    
	  {// 1) si absolue = false: l'objectif est de determiner un repere pertinant dans le cas de membrane .
    // choix : un repere qui appartiend a la facette, obtenu apres projection
    // du repere global
    //------ cas de la config initiale, on regarde si la projection de I1 n'est pas trop petite
    // def de la normale a la facette
    // 2) si absolue = true; on complète le repère des gi avec la normale et la matrice de passage
    // correspond au passage des gi complètés -> I_a
    
    Coordonnee N = (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer();
    Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1)
    double norve = ve.Norme();
    Tableau <Coordonnee> vi(2); // les vecteurs plans orthonormes de la facette
    if (!absolue)
     {Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1)
      double norve = ve.Norme();
      Tableau <Coordonnee> vi(2); // les vecteurs plans orthonormes de la facette
      if (norve >= 0.01)
       { vi(2) = ve.Normer();
         vi(1) = Util::ProdVec_coor(vi(2),N);
       }
      else
       { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N)
         vi(1) = ve.Normer();
         vi(2) = Util::ProdVec_coor(N,vi(1));
       };
      for (int al=1 ;al<=2;al++)
         {Aa0(1,al) = giH0.Coordo(1) * vi(al) ;
          Aa0(2,al) = giH0.Coordo(2) * vi(al) ;
         };
      // si on veut une matrice 3x3,  il faut complèter la matrice avec un troisième vecteur
      // comme les vi sont normaux à N, le troisième vecteur est le vecteur N
      // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis
      // du troisième vecteur qui n'est autre que N
      if (Aa0.Nb_ligne()==3)
         // ici on a Ip_3 == N et également g_3=g^3=N
          {for (int al=1 ;al<=2;al++)
             {Aa0(3,al) = N * vi(al) ;
              Aa0(al,3) = giH0.Coordo(al) * N ;
             };
           Aa0(3,3)= 1.; // == N . N
          };
     }
    else // cas on l'on veut le passage des gi et N vers I_a
     {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i
      for (int al=1 ;al < 4;al++)
         {Aa0(1,al) = giH0.Coordo(1)(al) ;
          Aa0(2,al) = giH0.Coordo(2)(al) ;
         };
      // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N
      Aa0.RemplaceLigneSpe(3,N.Vect());
     };
    

    //------ cas de la config finale,
    N = (Util::ProdVec_coorBN(giB(1),giB(2))).Normer();
    if (!absolue)
      {ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec(N,I1)
       norve = ve.Norme();
       Tableau <Coordonnee> Aa(2);
       if (norve >= ConstMath::petit)
        { Aa(2) = ve.Normer();
          Aa(1) = Util::ProdVec_coor(Aa(2),N);
        }
       else
        { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N)
          Aa(1) = ve.Normer();
          Aa(2) = Util::ProdVec_coor(N,Aa(1));
        };
     
       for (int be=1;be<=2;be++)
        { Aafin(1,be) = giH.Coordo(1) * Aa(be);
          Aafin(2,be) = giH.Coordo(2) * Aa(be);
        };
       // si on veut une matrice 3x3,  il faut complèter la matrice avec un troisième vecteur
       // comme les vi sont normaux à N, le troisième vecteur est le vecteur N
       // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis
       // du troisième vecteur qui n'est autre que N
       if (Aafin.Nb_ligne()==3)
          // ici on a Ip_3 == N et également g_3=g^3=N
           {for (int al=1 ;al<=2;al++)
              {Aafin(3,al) = N * vi(al) ;
               Aafin(al,3) = giH.Coordo(al) * N ;
              };
            Aafin(3,3)= 1.; // == N . N
           };
      }
    else // cas on l'on veut le passage des gi et N vers I_a
     {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i
      for (int al=1 ;al < 4;al++)
         {Aafin(1,al) = giH.Coordo(1)(al) ;
          Aafin(2,al) = giH.Coordo(2)(al) ;
         };
      // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N
      Aafin.RemplaceLigneSpe(3,N.Vect());
     };
	  }
  else if (dim==1)
   // ====  cas des éléments 1D en espace 1D, 2D ou 3D ====
   { if (!absolue)
      {switch (ParaGlob::Dimension())
        { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début
           {cout << "\nErreur : bug!! on ne devrait pas passer ici \n";
            cout << "void Deformation::BasePassage( \n";
            Sortie(1);
            break;
           }
          case 3: // on est dans un espace 3D, ici on ne fait que le particulier à 3D et le reste est
           // fait dans le case 2: qui suit
           // 3X1X1 ou 3X1X2 ou 3X1X3, 2X1X1 , 2X1X2
           if (Aa0.Nb_ligne() == 3 )
             // 3X1X3
             { // tous les tenseurs vont utiliser que le premier vecteur, donc le troisième peut être quelconque
               // et l'expression de giH(3) n'existant pas on dit que par défaut (et par simplicité)
               // giH(3) = 1 * IP(3) d'où
               Aa0 (3,3) = Aafin(3,3) = 1.;
               // et on initialise les autres composantes au cas où
               Aa0 (1,3) = Aa0 (3,1) = Aafin(1,3) = Aafin(3,1) = 0.;
               Aa0 (2,3) = Aa0 (3,2) = Aafin(2,3) = Aafin(3,2) = 0.;
               // pas de break, on continue sur le 2D
             };
          case 2: // on est dans un espace 2D, 3X1X1 ou 3X1X2 ou 3X1X3
           { // le premier vecteur intéressant c'est le vecteur collinéaire avec gH(1), mais normé
             double norme0 = giH0(1).Norme();
             double norme = giH(1).Norme();
             Aa0 (1,1) = norme0;
             Aafin(1,1) = norme;
             // fin du cas 3X1X1 et 2X1X1
             if (Aa0.Nb_ligne() > 1)
               // 3X1X2 , 3X1X3 , 2X1X2
               // tous les tenseurs vont utiliser que le premier vecteur, donc le second peut être quelconque
               // et l'expression de giH(2) n'existant pas on dit que par défaut (et par simplicité)
               // giH(2) = 1 * IP(2) d'où
              {Aa0 (2,2) = Aafin(2,2) = 1.;
               // et on initialise les autres composantes au cas où
               Aa0 (1,2) = Aa0 (2,1) = Aafin(1,2) = Aafin(2,1) = 0.;
              };
             break;
           }
          default: cout << "\n erreur grossiere de dimension !! \n Deformation::BasePassage(.. ";
             Sortie(1);
        };
      }
     else // sinon on veut arriver en Ia
      { // On ne connait que le premier vecteur et normalement c'est seulement celui-là qui est
        // utilisé, par contre il faut complèter la matrice pour qu'elle ne soit pas singulière
        Aa0.Initialise(0.);Aafin.Initialise(0.);
        switch (ParaGlob::Dimension())
         { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début
            {cout << "\nErreur : bug!! on ne devrait pas passer ici \n";
             cout << "void Deformation::BasePassage( \n";
             Sortie(1);
             break;
            }
           case 3: // on est dans un espace 3D,
            {CoordonneeH V02(3); CoordonneeH V03(3);
             // on calcule deux vecteurs arbitraires normaux, avec un résultat orthonormé V2,V3
             // mais pas giH0(1) !
             MathUtil2::Def_vecteurs_plan(giH0(1),V02,V03);
             // idem pour le final
             CoordonneeH V2(3); CoordonneeH V3(3);
             MathUtil2::Def_vecteurs_plan(giH(1),V2,V3);
             int bornesup = ParaGlob::Dimension() +1;
             for (int al=1 ;al < bornesup;al++)
               {Aa0(1,al) = giH0.Coordo(1)(al) ;
                Aafin(1,al) = giH.Coordo(1)(al);
                Aa0(2,al) = V02(al) ;
                Aafin(2,al) = V2(al) ;
                Aa0(3,al) = V03(al) ;
                Aafin(3,al) = V3(al) ;
               };
             break;
            }
           case 2: // on est dans un espace 2D,
            {CoordonneeH V02(2);
             // on calcule le vecteur normal,
             // mais pas giH0(1) !
             MathUtil2::Def_vecteurs_plan(giH0(1),V02);
             // idem pour le final
             CoordonneeH V2(2);
             MathUtil2::Def_vecteurs_plan(giH(1),V2);
             int bornesup = ParaGlob::Dimension() +1;
             for (int al=1 ;al < bornesup;al++)
               {Aa0(1,al) = giH0.Coordo(1)(al) ;
                Aafin(1,al) = giH.Coordo(1)(al);
                Aa0(2,al) = V02(al) ;
                Aafin(2,al) = V2(al) ;
               };
             break;
            }
           default: cout << "\n erreur2 grossiere de dimension !! \n Deformation::BasePassage(.. ";
              Sortie(1);
         };
      };
   }
  else
   {// pour les autres cas on ramene la matrice identite
    #ifdef MISE_AU_POINT	 	 
	   if  ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) &&
	           (Aafin.Nb_ligne() != dim) && (Aafin.Nb_colonne() !=dim))
			   { cout << "\nErreur : les matrices Aa0 et /ou Aafin ne sont pas correctement"
			          << " dimensionnees  !\n";
			     cout << "void Deformation::BasePassage( \n";
			     Sortie(1);
			   };
    #endif
    for (int i=1;i<=dim;i++)
      { for (int j=1;j<=dim;j++)
         {Aa0 (i,j) = 0.;Aafin(i,j) = 0.;}
        Aa0 (i,i) = 1.; Aafin(i,i) = 1.;
      };
   };
  // retour
  return;
};
             
// cas où l'on veut les matrices de passages à 0 t et tdt
// voir Deformation.h pour plus d'info
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
// (voir Deformation.h pour un descriptif plus complet)
void Deformation::BasePassage(bool absolue,const BaseB & giB0,const  BaseB & giB_t,const  BaseB & giB_tdt
                              ,const  BaseH & giH0,const BaseH & giH_t,const BaseH & giH_tdt
                              ,Mat_pleine& Aa0,Mat_pleine& Aa_t,Mat_pleine& Aa_tdt)
 {  
    // determination des matrices de transformation de base
    int dim = giB0.NbVecteur();
  
    // dim_espace X nb_vecteur X taille_matrice

    // cas d'une sortie en globale
    // 1X1X1 ou 2X2X2 ou 3X3X3
    if ((dim == ParaGlob::Dimension()) && (Aa0.Nb_ligne() == dim))
     { // --- ici il n'y a pas a priori de repère ad hoc, donc le calcul ne dépend pas de "absolue"
   
       // petite vérif
       #ifdef MISE_AU_POINT
        if  ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim)
             && (Aa_t.Nb_ligne() != dim) && (Aa_t.Nb_colonne() !=dim)
             && (Aa_tdt.Nb_ligne() != dim) && (Aa_tdt.Nb_colonne() !=dim))
          { cout << "\nErreur1 : les matrices Aa0 et /ou Aa_t et / ou Aa_tdt ne sont pas correctement"
                 << " dimensionnees  ! \n";
            cout << "\n Aa0= "; Aa0.Affiche();
            cout << "\n Aa_t= "; Aa_t.Affiche();
            cout << "\n Aa_tdt= "; Aa_tdt.Affiche();
            cout << "void Deformation::BasePassage( \n";
            Sortie(1);
          };
       #endif
       for (int i=1;i<=dim;i++)
          for (int j=1;j<=dim;j++)
            {Aa0 (i,j) = giH0(i)(j);
             Aa_t(i,j) =giH_t(i)(j);
             Aa_tdt(i,j) =giH_tdt(i)(j);
            };
     }
    else if ((dim==2)&&(ParaGlob::Dimension()==3))
      // cela comprend les cas: 3X2X2 -> un repère local ad hoc en 2D
      //                        3X2X3 -> un repère local ad hoc en 3D
      // ====  cas d'élément de membrane en 3D ====
	    {// 1) si absolue = false: l'objectif est de determiner un repere pertinant dans le cas de membrane .
      // choix : un repere qui appartiend a la facette, obtenu apres projection
      // du repere global
      //------ cas de la config initiale, on regarde si la projection de I1 n'est pas trop petite
      // def de la normale a la facette
      // 2) si absolue = true; on complète le repère des gi avec la normale et la matrice de passage
      // correspond au passage des gi complètés -> I_a

      Coordonnee N = (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer();
      Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1), donc normal à N
      double norve = ve.Norme();
      Tableau <Coordonnee> vi(2); // les vecteurs plans orthonormes de la facette
      if (!absolue)
       {if (norve >= 0.01)
         { vi(2) = ve.Normer();
           vi(1) = Util::ProdVec_coor(vi(2),N);// donc normal à N
         }
        else
         { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N), donc normal à N
           vi(1) = ve.Normer();
           vi(2) = Util::ProdVec_coor(N,vi(1));// donc normal à N
         };
        // maintenant expression dans le repère local
        // Aa^i_{.a} = g^i . Ip_a avec les Ip_a == vi(a)
        for (int al=1 ;al<=2;al++)
         {Aa0(1,al) = giH0.Coordo(1) * vi(al) ;
          Aa0(2,al) = giH0.Coordo(2) * vi(al) ;
         };
        // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur
        // comme les vi sont normaux à N, le troisième vecteur est le vecteur N
        // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis
        // du troisième vecteur qui n'est autre que N
        if (Aa0.Nb_ligne()==3)
         // ici on a Ip_3 == N et également g_3=g^3=N
          {for (int al=1 ;al<=2;al++)
             {Aa0(3,al) = N * vi(al) ;
              Aa0(al,3) = giH0.Coordo(al) * N ;
             };
           Aa0(3,3)= 1.; // == N . N
          };
       }
      else // cas on l'on veut le passage des gi et N vers I_a
       {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i
        for (int al=1 ;al < 4;al++)
           {Aa0(1,al) = giH0.Coordo(1)(al) ;
            Aa0(2,al) = giH0.Coordo(2)(al) ;
           };
        // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N
        Aa0.RemplaceLigneSpe(3,N.Vect());
       };

      //------ cas de la config à t,
      N = (Util::ProdVec_coorBN(giB_t(1),giB_t(2))).Normer();
      Tableau <Coordonnee> Aa(2);
      if (!absolue)
      {ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec(N,I1)
       norve = ve.Norme();
       if (norve >= 0.01)
        { Aa(2) = ve.Normer();
          Aa(1) = Util::ProdVec_coor(Aa(2),N);
        }
       else
       { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N)
         Aa(1) = ve.Normer();
         Aa(2) = Util::ProdVec_coor(N,Aa(1));
       };
   
       for (int be=1;be<=2;be++)
       { Aa_t(1,be) = giH_t.Coordo(1) * Aa(be);
         Aa_t(2,be) = giH_t.Coordo(2) * Aa(be);
        };
       // si on veut une matrice 3x3,  il faut complèter la matrice avec un troisième vecteur
       // comme les vi sont normaux à N, le troisième vecteur est le vecteur N
       // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis
       // du troisième vecteur qui n'est autre que N
       if (Aa_t.Nb_ligne()==3)
        // ici on a Ip_3 == N et également g_3=g^3=N
         {for (int al=1 ;al<=2;al++)
            {Aa_t(3,al) = N * vi(al) ;
             Aa_t(al,3) = giH_t.Coordo(al) * N ;
            };
          Aa_t(3,3)= 1.; // == N . N
         };
       }
     else // cas on l'on veut le passage des gi et N vers I_a
      {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i
       for (int al=1 ;al < 4;al++)
          {Aa_t(1,al) = giH_t.Coordo(1)(al) ;
           Aa_t(2,al) = giH_t.Coordo(2)(al) ;
          };
       // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N
       Aa_t.RemplaceLigneSpe(3,N.Vect());
      };

//// ---- vérification que le déterminant n'est pas nul
//{double det = Aa_t(1,1) * Aa_t(2,2) - Aa_t(1,2) * Aa_t(2,1);
// if (Abs(det) < 0.00001)
//   cout << "\n erreur det0 null " << det << " dans Deformation::BasePassage(  ";
//};
//// ---- fin vérification        
      //------ cas de la config finale à tdt, 
      N = (Util::ProdVec_coorBN(giB_tdt(1),giB_tdt(2))).Normer();
      if (!absolue)
      {ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec(N,I1)
       norve = ve.Norme();
       if (norve >= 0.01)
        { Aa(2) = ve.Normer();
          Aa(1) = Util::ProdVec_coor(Aa(2),N);
        }
       else
       { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N)
         Aa(1) = ve.Normer();
         Aa(2) = Util::ProdVec_coor(N,Aa(1));
       };
   
       for (int be=1;be<=2;be++)
       { Aa_tdt(1,be) = giH_tdt.Coordo(1) * Aa(be);
         Aa_tdt(2,be) = giH_tdt.Coordo(2) * Aa(be);
        };
       // si on veut une matrice 3x3,  il faut complèter la matrice avec un troisième vecteur
       // comme les vi sont normaux à N, le troisième vecteur est le vecteur N
       // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis
       // du troisième vecteur qui n'est autre que N
       if (Aa_tdt.Nb_ligne()==3)
        // ici on a Ip_3 == N et également g_3=g^3=N
         {for (int al=1 ;al<=2;al++)
            {Aa_tdt(3,al) = N * vi(al) ;
             Aa_tdt(al,3) = giH_tdt.Coordo(al) * N ;
            };
          Aa_tdt(3,3)= 1.; // == N . N
         };
       }
     else // cas on l'on veut le passage des gi et N vers I_a
      {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i
       for (int al=1 ;al < 4;al++)
          {Aa_tdt(1,al) = giH_tdt.Coordo(1)(al) ;
           Aa_tdt(2,al) = giH_tdt.Coordo(2)(al) ;
          };
       // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N
       Aa_tdt.RemplaceLigneSpe(3,N.Vect());
      };

//// ---- vérification que le déterminant n'est pas nul
//{double det = Aa_tdt(1,1) * Aa_tdt(2,2) - Aa_tdt(1,2) * Aa_tdt(2,1);
// if (Abs(det) < 0.00001)
//   cout << "\n erreur det0 null " << det << " dans Deformation::BasePassage(  ";
//};
//// ---- fin vérification        
	    }
    else if (dim==1)
     // ====  cas des éléments 1D en espace 1D, 2D ou 3D ====
     { if (!absolue)
        {switch (ParaGlob::Dimension())
          { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début
             {cout << "\nErreur : bug!! on ne devrait pas passer ici \n";
              cout << "void Deformation::BasePassage( \n";
              Sortie(1);
              break;
             }
            case 3: // on est dans un espace 3D, ici on ne fait que le particulier à 3D et le reste est
             // fait dans le case 2: qui suit
             // 3X1X1 ou 3X1X2 ou 3X1X3, 2X1X1 , 2X1X2
             if (Aa0.Nb_ligne() == 3 )
               // 3X1X3
                { // tous les tenseurs vont utiliser que le premier vecteur, donc le troisième peut être quelconque
                  // et l'expression de giH(3) n'existant pas on dit que par défaut (et par simplicité)
                  // giH(3) = 1 * IP(3) d'où
                  Aa0 (3,3) = Aa_t(3,3)= Aa_tdt(3,3) = 1.;
                  // et on initialise les autres composantes au cas où
                  Aa0 (1,3) = Aa0 (3,1) = Aa_t(1,3) = Aa_t(3,1) = Aa_tdt(1,3) = Aa_tdt(3,1) = 0.;
                  Aa0 (2,3) = Aa0 (3,2) = Aa_t(2,3) = Aa_t(3,2) = Aa_tdt(2,3) = Aa_tdt(3,2) = 0.;
                  // pas de break, on continue sur le 2D
                }
            case 2: // on est dans un espace 2D, 3X1X1 ou 3X1X2 ou 3X1X3
             { // le premier vecteur intéressant c'est le vecteur collinéaire avec gH(1), mais normé
               double norme0 = giH0(1).Norme();
               double normet = giH_t(1).Norme();
               double normetdt = giH_tdt(1).Norme();
               Aa0 (1,1) = norme0;
               Aa_t(1,1) = normet;
               Aa_tdt(1,1) = normetdt;
               // fin du cas 3X1X1 et 2X1X1
               if (Aa0.Nb_ligne() > 1)
                 // 3X1X2 , 3X1X3 , 2X1X2
                 // tous les tenseurs vont utiliser que le premier vecteur, donc le second peut être quelconque
                 // et l'expression de giH(2) n'existant pas on dit que par défaut (et par simplicité)
                 // giH(2) = 1 * IP(2) d'où
                 {Aa0 (2,2) = Aa_t(2,2) = Aa_tdt(2,2)= 1.;
                  // et on initialise les autres composantes au cas où
                  Aa0 (1,2) = Aa0 (2,1) = Aa_t(1,2) = Aa_t(2,1)= Aa_tdt(1,2) = Aa_tdt(2,1) = 0.;
                 };
               break;
             }
            default: cout << "\n erreur grossiere de dimension !! \n Deformation::BasePassage(.. ";
               Sortie(1);
          };
        }
       else // sinon on veut arriver en Ia
        { // On ne connait que le premier vecteur et normalement c'est seulement celui-là qui est
          // utilisé, par contre il faut complèter la matrice pour qu'elle ne soit pas singulière
          Aa0.Initialise(0.);Aa_t.Initialise(0.);Aa_tdt.Initialise(0.);
          switch (ParaGlob::Dimension())
           { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début
              {cout << "\nErreur : bug!! on ne devrait pas passer ici \n";
               cout << "void Deformation::BasePassage( \n";
               Sortie(1);
               break;
              }
             case 3: // on est dans un espace 3D,
              {CoordonneeH V02(3); CoordonneeH V03(3);
               // on calcule deux vecteurs arbitraires normaux, avec un résultat orthonormé V2,V3
               // mais pas giH0(1) !
               MathUtil2::Def_vecteurs_plan(giH0(1),V02,V03);
               // idem pour t et tdt
               CoordonneeH V2_t(3); CoordonneeH V3_t(3);
               MathUtil2::Def_vecteurs_plan(giH_t(1),V2_t,V3_t);
               CoordonneeH V2_tdt(3); CoordonneeH V3_tdt(3);
               MathUtil2::Def_vecteurs_plan(giH_tdt(1),V2_tdt,V3_tdt);
               int bornesup = ParaGlob::Dimension() +1;
               for (int al=1 ;al < bornesup;al++)
                 {Aa0(1,al) = giH0.Coordo(1)(al) ;
                  Aa_t(1,al) = giH_t.Coordo(1)(al) ;
                  Aa_tdt(1,al) = giH_tdt.Coordo(1)(al) ;
                  Aa0(2,al) = V02(al) ;
                  Aa_t(2,al) = V2_t(al) ;
                  Aa_tdt(2,al) = V2_tdt(al) ;
                  Aa0(3,al) = V03(al) ;
                  Aa_t(3,al) = V3_t(al) ;
                  Aa_tdt(3,al) = V3_tdt(al) ;
                 };
               break;
              }
             case 2: // on est dans un espace 2D,
              {CoordonneeH V02(2);
               // on calcule le vecteur normal,
               // mais pas giH0(1) !
               MathUtil2::Def_vecteurs_plan(giH0(1),V02);
               // idem pour t et tdt
               CoordonneeH V2_t(3);
               MathUtil2::Def_vecteurs_plan(giH_t(1),V2_t);
               CoordonneeH V2_tdt(3);
               MathUtil2::Def_vecteurs_plan(giH_tdt(1),V2_tdt);
               int bornesup = ParaGlob::Dimension() +1;
               for (int al=1 ;al < bornesup;al++)
                 {Aa0(1,al) = giH0.Coordo(1)(al) ;
                  Aa_t(1,al) = giH_t.Coordo(1)(al) ;
                  Aa_tdt(1,al) = giH_tdt.Coordo(1)(al) ;
                  Aa0(2,al) = V02(al) ;
                  Aa_t(2,al) = V2_t(al) ;
                  Aa_tdt(2,al) = V2_tdt(al) ;
                 };
               break;
              }
             default: cout << "\n erreur2 grossiere de dimension !! \n Deformation::BasePassage(.. ";
                Sortie(1);
           };
        };
     }
    else
     {// pour les autres cas on ramene la matrice identite
     #ifdef MISE_AU_POINT	 	 
	     if  ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) &&
	           (Aa_t.Nb_ligne() != dim) && (Aa_t.Nb_colonne() !=dim) &&
	           (Aa_tdt.Nb_ligne() != dim) && (Aa_tdt.Nb_colonne() !=dim))
			     { cout << "\nErreur : les matrices Aa0 et /ou Aa_t et /ou Aa_tdt ne sont pas correctement"
			            << " dimensionnees  !\n";
          cout << "void Deformation::RemontImp( \n";
			       Sortie(1);
			     };
     #endif
      for (int i=1;i<=dim;i++)
       { for (int j=1;j<=dim;j++)
           {Aa0 (i,j) = 0.;Aa_t(i,j) = 0.;Aa_tdt(i,j) = 0.;}
         Aa0 (i,i) = 1.; Aa_t(i,i) = 1.;Aa_tdt(i,i) = 1.;
       };
     };
  // retour
  return;
 };

// cas où l'on veut la matrice de passage à 0 uniquement
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
// tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer
// (voir Deformation.h pour un descriptif plus complet)
void Deformation::BasePassage(bool absolue,const BaseB & giB0,const  BaseH & giH0,Mat_pleine& Aa0)
 {
  // determination des matrices de transformation de base
  int dim = giB0.NbVecteur();
 
  // dim_espace X nb_vecteur X taille_matrice

  // cas d'une sortie en globale
  // 1X1X1 ou 2X2X2 ou 3X3X3
  if ((dim == ParaGlob::Dimension()) && (Aa0.Nb_ligne() == dim))
     { // petite vérif
       #ifdef MISE_AU_POINT
        if  ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim))
          { cout << "\nErreur1 : la matrice Aa0 n'est pas correctement"
                 << " dimensionnee  ! \n";
            cout << "\n Aa0= "; Aa0.Affiche();
            cout << "void Deformation::BasePassage( \n";
            Sortie(1);
          };
       #endif
       for (int i=1;i<=dim;i++)
          for (int j=1;j<=dim;j++)
            {Aa0 (i,j) = giH0(i)(j);
            };
     }
    else if ((dim==2)&&(ParaGlob::Dimension()==3))
   // cela comprend les cas: 3X2X2 -> un repère local ad hoc en 2D
   //                        3X2X3 -> un repère local ad hoc en 3D
      // ====  cas d'élément de membrane en 3D ====
     {// 1) si absolue = false: l'objectif est de determiner un repere pertinant dans le cas de membrane .
      // choix : un repere qui appartiend a la facette, obtenu apres projection
      // du repere global
      //------ cas de la config initiale, on regarde si la projection de I1 n'est pas trop petite
      // def de la normale a la facette
      // 2) si absolue = true; on complète le repère des gi avec la normale et la matrice de passage
      // correspond au passage des gi complètés -> I_a

      Coordonnee N ( (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer() );
      Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1), donc normal à N
      double norve = ve.Norme();
      Tableau <Coordonnee> vi(2); // les vecteurs plans orthonormes de la facette
      if (!absolue)
       {if (norve >= 0.01)
         { vi(2) = ve.Normer();
           vi(1) = Util::ProdVec_coor(vi(2),N);// donc normal à N
         }
        else
         { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N), donc normal à N
           vi(1) = ve.Normer();
           vi(2) = Util::ProdVec_coor(N,vi(1));// donc normal à N
         };
        // maintenant expression dans le repère local
        for (int al=1 ;al<=2;al++)
         {Aa0(1,al) = giH0.Coordo(1) * vi(al) ;
          Aa0(2,al) = giH0.Coordo(2) * vi(al) ;
         };
        // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur
        // comme les vi sont normaux à N, le troisième vecteur est le vecteur N
        // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis
        // du troisième vecteur qui n'est autre que N
        if (Aa0.Nb_ligne()==3)
         // ici on a Ip_3 == N et également g_3=g^3=N
          {for (int al=1 ;al<=2;al++)
             {Aa0(3,al) = N * vi(al) ;
              Aa0(al,3) = giH0.Coordo(al) * N ;
             };
           Aa0(3,3)= 1.; // == N . N
          };
       }
      else // cas on l'on veut le passage des gi et N vers I_a
       {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i
        for (int al=1 ;al < 4;al++)
           {Aa0(1,al) = giH0.Coordo(1)(al) ;
            Aa0(2,al) = giH0.Coordo(2)(al) ;
           };
        // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N
        Aa0.RemplaceLigneSpe(3,N.Vect());
       };

//// ---- vérification que le déterminant n'est pas nul
//{double det = Aa0(1,1) * Aa0(2,2) - Aa0(1,2) * Aa0(2,1);
// if (Abs(det) < 0.00001)
//   cout << "\n erreur det0 null " << det << " dans Deformation::BasePassage(  ";
//};
//// ---- fin vérification

     }
    else if (dim==1)
     // ====  cas des éléments 1D en espace 1D, 2D ou 3D ====
     { if (!absolue)
        {switch (ParaGlob::Dimension())
          { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début
             {cout << "\nErreur : bug!! on ne devrait pas passer ici \n";
              cout << "void Deformation::BasePassage( \n";
              Sortie(1);
              break;
             }
            case 3: // on est dans un espace 3D, ici on ne fait que le particulier à 3D et le reste est
             // fait dans le case 2: qui suit
             // 3X1X1 ou 3X1X2 ou 3X1X3, 2X1X1 , 2X1X2
             if (Aa0.Nb_ligne() == 3 )
               // 3X1X3
                { // tous les tenseurs vont utiliser que le premier vecteur, donc le troisième peut être quelconque
                  // et l'expression de giH(3) n'existant pas on dit que par défaut (et par simplicité)
                  // giH(3) = 1 * IP(3) d'où
                  Aa0 (3,3)  = 1.;
                  // et on initialise les autres composantes au cas où
                  Aa0 (1,3) = Aa0 (3,1)  = 0.;
                  Aa0 (2,3) = Aa0 (3,2)  = 0.;
                  // pas de break, on continue sur le 2D
                }
            case 2: // on est dans un espace 2D, 3X1X1 ou 3X1X2 ou 3X1X3
             { // le premier vecteur intéressant c'est le vecteur collinéaire avec gH(1), mais normé
               double norme0 = giH0(1).Norme();
               Aa0 (1,1) = norme0;
               // fin du cas 3X1X1 et 2X1X1
               if (Aa0.Nb_ligne() > 1)
                 // 3X1X2 , 3X1X3 , 2X1X2
                 // tous les tenseurs vont utiliser que le premier vecteur, donc le second peut être quelconque
                 // et l'expression de giH(2) n'existant pas on dit que par défaut (et par simplicité)
                 // giH(2) = 1 * IP(2) d'où
                 {Aa0 (2,2) = 1.;
                  // et on initialise les autres composantes au cas où
                  Aa0 (1,2) = Aa0 (2,1)  = 0.;
                 };
               break;
             }
            default: cout << "\n erreur grossiere de dimension !! \n Deformation::BasePassage(.. ";
               Sortie(1);
          };
      }
     else // sinon on veut arriver en Ia
      { // On ne connait que le premier vecteur et normalement c'est seulement celui-là qui est
        // utilisé, par contre il faut complèter la matrice pour qu'elle ne soit pas singulière
        Aa0.Initialise(0.);
        switch (ParaGlob::Dimension())
         { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début
            {cout << "\nErreur : bug!! on ne devrait pas passer ici \n";
             cout << "void Deformation::BasePassage( \n";
             Sortie(1);
             break;
            }
           case 3: // on est dans un espace 3D,
            {CoordonneeH V02(3); CoordonneeH V03(3);
             // on calcule deux vecteurs arbitraires normaux, avec un résultat orthonormé V2,V3
             // mais pas giH0(1) !
             MathUtil2::Def_vecteurs_plan(giH0(1),V02,V03);
             int bornesup = ParaGlob::Dimension() +1;
             for (int al=1 ;al < bornesup;al++)
               {Aa0(1,al) = giH0.Coordo(1)(al) ;
                Aa0(2,al) = V02(al) ;
                Aa0(3,al) = V03(al) ;
               };
             break;
            }
           case 2: // on est dans un espace 2D,
            {CoordonneeH V02(2);
             // on calcule le vecteur normal,
             // mais pas giH0(1) !
             MathUtil2::Def_vecteurs_plan(giH0(1),V02);
             int bornesup = ParaGlob::Dimension() +1;
             for (int al=1 ;al < bornesup;al++)
               {Aa0(1,al) = giH0.Coordo(1)(al) ;
                Aa0(2,al) = V02(al) ;
               };
             break;
            }
           default: cout << "\n erreur2 grossiere de dimension !! \n Deformation::BasePassage(.. ";
              Sortie(1);
         };
        int bornesup = ParaGlob::Dimension() +1;
        for (int al=1 ;al < bornesup;al++)
         {Aa0(1,al) = giH0.Coordo(1)(al) ;
          if (al!=1)
           {Aa0 (al,al)  = 1.;};
         };
      };
     }
    else
     {// pour les autres cas on ramene la matrice identite
     #ifdef MISE_AU_POINT
      if  ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) )
        { cout << "\nErreur : la matrices Aa0 n'est pas correctement"
               << " dimensionnee  !\n";
          cout << "void Deformation::RemontImp( \n";
          Sortie(1);
        };
     #endif
      for (int i=1;i<=dim;i++)
       { for (int j=1;j<=dim;j++)
           {Aa0 (i,j) = 0.;}
         Aa0 (i,i) = 1.;
       };
     };
  // retour
  return;
 };

    // on suppose que gijHH et gijBB ont déjà été calculé et sont donc transmis
    // on suppose que gijHH et gijBB ont déjà été calculé à t=0, et à temps
void  Deformation::Cal_deformation (Enum_dure temps, TenseurBB & epsBB)
{ // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange ..
	 switch (type_deformation)
	 { case  DEFORMATION_STANDART :  
	     {return Cal_Almansi_auTemps(temps,epsBB);
	      break;
      }
    case DEFORMATION_LOGARITHMIQUE:
	     {return Cal_logarithmique_auTemps(temps,epsBB);
	      break;
	      }
		  case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE :
		    {return Cal_def_cumule_auTemps(temps,epsBB);
		     break;
		    }
		  default :
			  cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation)
			       << " ) non traite !\n";
			  cout << "Deformation::Cal_deformation (... \n";
			  Sortie(1);
  };
};
  
    // calcul de la deformation au temps donné  dans le cas d'une déformation d'Almansi
    // on suppose que les métriques en HH ou BB sont définis à 0 et au temps
void Deformation::Cal_def_cumule_auTemps (Enum_dure , TenseurBB & )
  {  cout << "\n methode pas encore implante (dommage!) "
          << "\n Deformation::Cal_def_cumule_auTemps (..";
     Sortie(1);
  };
  
// gestion du parcours de tous les points d'integration
void Deformation::PremierPtInteg()
 { sauve_numInteg = numInteg; numInteg = 1; };
bool Deformation::DernierPtInteg()
 { sauve_numInteg = numInteg; // sauvegarde
   if (numInteg <= tabPhi->Taille())
       return true;
     else
       return false;  
 };
void Deformation::NevezPtInteg()
   { sauve_numInteg = numInteg; // sauvegarde
     numInteg++;
   };
   
// méthode pour revenir au pti précédant
void Deformation::Retour_pti_precedant()
  {numInteg=sauve_numInteg;};

//==================================== méthodes protégées ===============================
  
  
     
// calcul implicite dans le cas d'une déformation tensorielle cumulée
const Met_abstraite::Impli& Deformation::Cal_implicit_def_cumule (bool 
           ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB_tdt
           ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul
           ,const Met_abstraite::Impli& ex)
  { 
     // dans le cas où ce n'est pas le premier calcul on récupère les datas qui ne sont pas recalculée
     if (!premier_calcul)
      { Deformation::Stmet& a_0 = saveDefResul->meti_00;  // pour simplifier
        Deformation::Stmet& a_t = saveDefResul->meti_t;  // pour simplifier     
        metrique->Recup_grandeur_0_t(*a_0.giB_,*a_0.giH_,*a_t.giB_,*a_t.giH_
                                     ,*a_0.gijBB_,*a_0.gijHH_,*a_t.gijBB_,*a_t.gijHH_
                                     ,*a_t.gradVmoyBB_,*a_t.jacobien_,*a_0.jacobien_);
      };
     // 1- calcul de la base duale et de la métrique à t=0, utiliser en 3-
     // non déjà fait dans le calcul actuel de la métrique
//     const Met_abstraite::gijHH_0_et_giH_0& ex1 = metrique->Cal_gijHH_0_et_giH_0_apres_im_expli();         
     // 2- calcul de l'opérateur gradient F(a,b)=d Xc^a/d X0^b, stockage sous forme d'un spseudo-tenseur
     //   alors que c'est un bi-tenseur !! permet ainsi une manipulation aisée
     int dim = ParaGlob::Dimension();
     TenseurHB * ftHB = NevezTenseurHB(dim);
     for (int i=1;i<=dim;i++)
       { TenseurHB * interHB = Produit_tensorielHB((*ex.giH_0)(i),(*ex.giB_tdt)(i));
         *ftHB += *interHB; delete interHB;
       };
     // 3- calcul du gradient de vitesse
     //    plusieurs possibilités, 
     //    1) . soit on calcul le gradient à partir du champ de vitesse au temps finale
     //    2) . soit on calcul le gradient à partir d'une hypothèse de vitesse contante sur le pas de temps
     //       avec la vitesse = delta X / delta t, le gradient étant déterminé à t+ (deltat/2) 
     //    3) . soit on calcul le gradient à partir d'une hypothèse de vitesse moyenne au temps t+ (deltat/2)
     //       c-a-d en utilisant la vitesse moyenne entre t et t+dt, ceci dans le cas de l'utilisation 
     //       directe des ddl vitesse  
    
/*     switch (type_gradient_vitesse) // traitement en fonction du cas
	  { case GRADVITESSE_V_TDT : // le gradient est déterminé à partir de ddl de vitesse à t+dt
           #ifdef MISE_AU_POINT
            // on vérifie que le gradient a été calculé dans l'appel de la métrique
            if (pas_de_gradV)	 	 
		  	  { cout << "\nErreur : le gradient de vitesse n'a pas ete calcule dans la metrique"
			         << " ce qui est contraire au type de calcul de gradient demande";			       
			    cout << "\n Deformation::Cal_implicit_def_cumule(... \n";
			    Sortie(1);
			  };
           #endif
	       // donc ici le gradient est dans (*ex.gradVBB_tdt)
	       break;
		case GRADVITESSE_VCONST : // calcul en considérant V constant =delta X/delta t 
		                          // dans la config à t+(delta t)/2
		   
//		   // 2) calcul du gradient à partir du champ de vitesse au temps final 
//		   if (!pas_de_gradV)
//		     {// cas où le gradient a été calculé
//	          DepsBB = 0.5 * ((*ex.gradVBB_tdt) + ex.gradVBB_tdt->Transpose());}
//		   else
//		     {
//		      }   
		   break;
		case GRADVITESSE_VT_VTDT : //calcul à partir des ddl de vitesse : moyenne de t et t+dt, 
		                           //dans la config à t+(delta t)/2 
		   break;
	   };*/

     
		  	
/*     // epsBB_tdt et delta_epsBB est dimensionne auparavant             
     epsBB_tdt = 0.5 * (*(ex.gijBB_tdt) - *(ex.gijBB_0));
     delta_epsBB = 0.5 * (*(ex.gijBB_tdt) - *(ex.gijBB_t));
     if (pas_de_gradV)
      { // on choisit une vitesse de déformation pour l'instant identique à deltaeps/t
	    const VariablesTemps& vartemps = ParaGlob::Variables_de_temps();
	    // dans le cas où l'incrément de temps est nul on garde la vitesse actuelle
	    double deltat=vartemps.IncreTempsCourant();
	    if (deltat >= ConstMath::trespetit)
	         DepsBB = delta_epsBB/deltat;
	   } 
	 else // cas où le gradient a été calculé
	   DepsBB = 0.5 * ((*ex.gradVBB_tdt) + ex.gradVBB_tdt->Transpose());
	 // variation de la déformation / au ddl  
     int d_epsBB_tdtTaille = d_epsBB_tdt.Taille();		      
     for (int i=1; i<= d_epsBB_tdtTaille; i++)
         *(d_epsBB_tdt(i)) = 0.5 * (*((*(ex.d_gijBB_tdt))(i)));
     // calcul éventuelle de la dérivée seconde de la déformation
     if (pa.Var_D())    
	  {// recup des variations secondes de la déformation
	   int d2_epsBB_tdtTaille1 = d2_epsBB_tdt.Taille1();
       for (int i=1; i<= d2_epsBB_tdtTaille1; i++)
        for (int j=1; j<= i; j++)  // symétrie du  tableau et du tenseur
	      { *(d2_epsBB_tdt(i,j)) = 0.5 * (*((*(ex.d2_gijBB_tdt))(i,j))) ;
	        *(d2_epsBB_tdt(j,i)) = *(d2_epsBB_tdt(i,j)) ; 
	       }
	   }    */
     // vérification éventuelle
 //    VerifCal_implicit( ex);
     // suppression des tenseurs de travail
     delete ftHB;
     // retour
     return ex;
  };
    
// calcul d'une vitesse de rotation cohérente avec un référentiel objectif particulier
void Deformation::Cal_vite_rota_objectif(EnumTypeViteRotat type_rotation,bool variation
        ,const TenseurBB&  gradVBB,const Tableau <TenseurBB * >& d_gradVBB
        ,const TenseurBH& gij_HH_0,const TenseurBB& gij_BB,Tableau <TenseurBB *> & d_gijBB
        ,const TenseurHH& gij_HH,Tableau <TenseurHH *> & d_gijHH
        ,const TenseurBB& D_BB, Tableau <TenseurBB *> & d_D_BB
        ,TenseurBB& OmegaBB,Tableau <TenseurBB* > & d_OmegaBB)
 { // on calcul le pseudo vecteur W représentant le tenseur anti-symétrique: rotation du gradient de vitesse
//   TenseurBB W_BB = 0.5 * (gradVBB - gradVBB.Transpose());
   int dima=Abs(gradVBB.Dimension());
/*   CoordonneeB W_B(dima);
   switch (dima) { case 3: W_B(1) = W_BB(3,2);W_B(2) = W_BB(1,3);W_B(3) = W_BB(2,1);break;
                   case 2: W_B(1) = W_BB(1,2);W_B(2) = 0.;break; // en attente
                   case 1: W_B(1) = 0.;break;}; // en attente*/
   int dimddl=d_gradVBB.Taille(); // dimension pour les variations
   switch (type_rotation)
    { case R_CORROTATIONNEL:
        OmegaBB =0.5 * (gradVBB - gradVBB.Transpose());
        // dans le cas où l'on veut également des variations 
        if (variation)
         { for (int i=1;i<=dimddl;i++) (*(d_OmegaBB(i))) = 0.5*( (*(d_gradVBB(i))) - (d_gradVBB(i))->Transpose()); }
        break;
      case R_REF_ROT_PROPRE: case R_ROT_LOGARITHMIQUE:
       // calcul des projections propres
       switch (dima)
        { case 3:
		         {// simplification et transformation en tenseur de dim 3 (optimisation des calculs)
            const Tenseur3HH & gijHH_0 = (const Tenseur3HH &) gij_HH_0;
            const Tenseur3BB & gijBB = (const Tenseur3BB &) gij_BB;
            const Tenseur3HH & gijHH = (const Tenseur3HH &) gij_HH;
            // def des grandeurs de travail
            DimensionementVarLog(dima,variation,dimddl);                  
            // def du tenseur B_BH (cauchy_green gauche)
            (*B_BH_tr) = gijBB * gijHH_0; Tenseur3BH&  B_BH= *((Tenseur3BH*) B_BH_tr);
            // calcul des valeurs propres et projection propres du tenseur B_BH 
            Tableau <Tenseur3BH * >& d_B_BH=*((Tableau <Tenseur3BH * >*) d_B_BH_tr);
            if (variation) // dans le cas de variation, calcul des variation de B_BH
               { for (int ic=1;ic<=dimddl;ic++) {(*(*d_B_BH_tr)(ic))= (*(d_gijBB(ic))) * gijHH_0;};};
            // def des grandeurs de travail
            Tableau <Tenseur3BH* >& Palpha_BH=*((Tableau <Tenseur3BH* >*) Palpha_BH_tr); // les projections propres
            Tableau <Tableau <Tenseur3BH* > >& d_Palpha_BH
                       =*((Tableau <Tableau <Tenseur3BH* > >*) d_Palpha_BH_tr); // variation des projections propres
            // appel de la méthode calculant les grandeurs de travail
            int cas_ki; // indique le cas des valeurs propres traitées (cf TenseurBH)
            Val_et_projection_prop_tenseur(*B_BH_tr,*d_B_BH_tr,ki,*Palpha_BH_tr,variation,*d_ki,*d_Palpha_BH_tr,cas_ki);
            // -- calcul de la rotation
            // calcul de la vitesse de rotation en mixte
            Tenseur3BH D_BH(D_BB * gijHH);
            // tout d'abord: calcul de tenseurs intermédiaires
            Tableau <Tenseur3BH> P_i_D_BH(3); Tableau <Tenseur3BH> D_P_i_BH(3);
            P_i_D_BH(1)=((*Palpha_BH(1)) * D_BH); Tenseur3BH P_1_D_P_2_BH(P_i_D_BH(1) * (*Palpha_BH(2)));
            P_i_D_BH(2)=((*Palpha_BH(2)) * D_BH); Tenseur3BH P_2_D_P_1_BH(P_i_D_BH(2) * (*Palpha_BH(1)));
            D_P_i_BH(1)=(D_BH * (*Palpha_BH(1))); Tenseur3BH P_1_D_P_3_BH(P_i_D_BH(1) * (*Palpha_BH(3)));
            P_i_D_BH(3)=((*Palpha_BH(3)) * D_BH); Tenseur3BH P_3_D_P_1_BH(P_i_D_BH(3) * (*Palpha_BH(1)));
            D_P_i_BH(2)=(D_BH * (*Palpha_BH(2))); Tenseur3BH P_2_D_P_3_BH(P_i_D_BH(2) * (*Palpha_BH(3)));
            D_P_i_BH(3)=(D_BH * (*Palpha_BH(3))); Tenseur3BH P_3_D_P_2_BH(P_i_D_BH(3) * (*Palpha_BH(2)));
                                                         
            double F_rot_1sur2= F_pour_rotat_objectif(type_rotation,ki(1)/ki(2));                                             
            double F_rot_1sur3= F_pour_rotat_objectif(type_rotation,ki(1)/ki(3));                                             
            double F_rot_2sur1= F_pour_rotat_objectif(type_rotation,ki(2)/ki(1));                                             
            double F_rot_3sur1= F_pour_rotat_objectif(type_rotation,ki(3)/ki(1));                                             
            double F_rot_2sur3= F_pour_rotat_objectif(type_rotation,ki(2)/ki(3));                                             
            double F_rot_3sur2= F_pour_rotat_objectif(type_rotation,ki(3)/ki(2));                                             
             
            OmegaBB =0.5 * (gradVBB - gradVBB.Transpose());
            Tenseur3BH sup_OmegaBH (  F_rot_1sur2 * P_1_D_P_2_BH   +   F_rot_2sur1 * P_2_D_P_1_BH
                                    + F_rot_1sur3 * P_1_D_P_3_BH   +   F_rot_3sur1 * P_3_D_P_1_BH
                                    + F_rot_2sur3 * P_2_D_P_3_BH   +   F_rot_3sur2 * P_3_D_P_2_BH );
            OmegaBB +=  sup_OmegaBH* gijBB ;
            
            // calcul éventuel des variations
            if (variation)
             { // mise sous forme indicée suivant l'ordre  1->12  2->21  3->13  4->31  5->23  6->32  à partir de 6 nombres
               Tableau <Tenseur3BH*> P_i_D_j_BH(6);
               P_i_D_j_BH(1)=&P_1_D_P_2_BH; P_i_D_j_BH(2)=&P_2_D_P_1_BH; P_i_D_j_BH(3)=&P_1_D_P_3_BH;
               P_i_D_j_BH(4)=&P_3_D_P_1_BH; P_i_D_j_BH(5)=&P_2_D_P_3_BH; P_i_D_j_BH(6)=&P_3_D_P_2_BH;
               Tableau <double *> F_rot_isurj(6);
               F_rot_isurj(1)=&F_rot_1sur2; F_rot_isurj(2)=&F_rot_2sur1; F_rot_isurj(3)=&F_rot_1sur3;
               F_rot_isurj(4)=&F_rot_3sur1; F_rot_isurj(5)=&F_rot_2sur3; F_rot_isurj(6)=&F_rot_3sur2;
               // boucle sur les ddl
              for (int ici=1;ici<=dimddl;ici++)
                { const Tenseur3BB & dgijBB = *((Tenseur3BB*)(d_gijBB(ici))) ; // pour simplifier l'ecriture
                  const Tenseur3HH & dgijHH = *((Tenseur3HH*)(d_gijHH(ici))) ; // pour simplifier l'ecriture
                  const Tenseur3BB & dD_BB = *((Tenseur3BB*)(d_D_BB(ici))) ; // pour simplifier l'ecriture

                  // variation du tenseur vitesse de déformation en mixte
                  Tenseur3BH dD_BH(dD_BB * gijHH + D_BB * dgijHH);
                  // variation du tenseur de rotation
                  Tenseur3BB & dOmegaBB = *((Tenseur3BB* )  (d_OmegaBB(ici)));  // pour simplifier l'ecriture
                  dOmegaBB = 0.5*( (*(d_gradVBB(ici))) - (d_gradVBB(ici))->Transpose());
                  for (int m=1;m<=6;m++)
                   { int i1=ccdex.iii(m); int i2=ccdex.jjj(m);
                     dOmegaBB += (( Fprime_pour_rotat_objectif(type_rotation,ki(i1)/ki(i2)) 
                               / (ki(i2)*ki(i2)) * (ki(i2) * ((*d_ki)(ici))(i1) - ki(i1) * ((*d_ki)(ici))(i2)) )  * (* P_i_D_j_BH(m))
                        +  (*F_rot_isurj(m)) * (  (*d_Palpha_BH(ici)(i2)) * D_P_i_BH(i2)  + (*Palpha_BH(i1)) * dD_BH * (*Palpha_BH(i2)) 
                                          + P_i_D_BH(i1) * (*d_Palpha_BH(ici)(i2)) )) * gijBB
                        +  sup_OmegaBH * dgijBB; 
                   };
                };
             }; // -- fin du grand "if variation "
            // effacement des tenseurs de travail
            for (int it=1;it<=dima;it++) delete Palpha_BH(it);
            if (variation)  for (int ic=1;ic<=dimddl;ic++) for (int it=1;it<=dima;it++)
                             delete d_Palpha_BH(ic)(it);
            break;
			        }
          default:  
            cout << "\n dimension (premier) non encore pris en compte: " << dima
                 << "\n Deformation::Cal_vite_rota_objectif(...";
            Sortie(1);
        }
      break;
       default:
        cout << "\n type de rotation non encore pris en compte"
             << "\n  Deformation::Cal_vite_rota_objectif(...";
        Sortie(1);
    };
   // liberation des tenseurs intermediaires
   LibereTenseur();   
 };
  
    // fonction f et f' utilisé dans la méthode  Cal_vite_rota_objectif:
double  Deformation::F_pour_rotat_objectif(EnumTypeViteRotat type_rotation,const double& x)           
  {switch (type_rotation)
    { case R_CORROTATIONNEL: return 0.; break;
      case R_REF_ROT_PROPRE: return (1.-sqrt(x))/(1.+sqrt(x)); break;
      case R_ROT_LOGARITHMIQUE: return (1.+x)/(1.-x) + 2./log(x); break;
      default:
        cout << "\n type de rotation non encore pris en compte: " << Nom_TypeViteRotat(type_rotation)
             << "\n Deformation::F_pour_rotat_objectif(...";
        Sortie(1);
      }           
    return 0.; // pour éviter le warning du retour             
   };           
double  Deformation::Fprime_pour_rotat_objectif(EnumTypeViteRotat type_rotation,const double& x)           
  {switch (type_rotation)
    { case R_CORROTATIONNEL: return 0.; break;
      case R_REF_ROT_PROPRE: return 1./(2.*x+sqrt(x)*(x+1.)); break;
      case R_ROT_LOGARITHMIQUE: 
        {double logx = log(x); double log2_x=logx*logx; 
         return 2.*(x*log2_x-x*x+2.*x-1.)/((x*x*x-2.*x*x+x)*log2_x); break;}
      default:
        cout << "\n type de rotation non encore pris en compte: " << Nom_TypeViteRotat(type_rotation)
             << "\n Deformation::Fprime_pour_rotat_objectif(...";
        Sortie(1);
      }
    return 0.; // pour éviter le warning du retour             
   };           
   
// -----------------   méthodes de vérifications------- ----
    
void Deformation::VerifCal_implicit(bool gradV_instantane,const Met_abstraite::Impli & ex,TenseurBB& )
 { // l'idée est de faire une vérification des dérivées à l'aide d'une méthode de différence finie
   int dim = ParaGlob::Dimension();
   // dans le cas du premier passage on indique qu'il y a vérification
   if (indic_VerifCal_implicit == 0)
     { cout << "\n ****vérification du calcul de la déformation et des éléments de la métrique associé****";
       cout << "\n Deformation::VerifCal_implicit \n";
      } 
   indic_VerifCal_implicit++;
  
   // on cré une seconde métrique pour éviter de détruire la métrique originale
   Met_abstraite metrique_bis(*metrique);
   // ici on considère que l'on a même nombre de ddl par noeud = dim
   // on va modifier chaque ddl de chaque noeud systématiquement
   int nbnoeud = tabnoeud->Taille();
   // le deltat pour les différences finis
   double delta = ConstMath::unpeupetit;
   double mini_val = ConstMath::pasmalpetit;
   int numddl = 1; // le compteur de ddl
   bool erreur = false; // indicateur d'erreur
   bool premier_calcul=true;
   for (int inoeud=1;inoeud<=nbnoeud;inoeud++)
    {// on récupère les coordonnées du noeud
     Coordonnee coordtdt = (*tabnoeud)(inoeud)->Coord2();
     for (int ix= 1;ix<=dim;ix++,numddl++)
     { Coordonnee X(dim); X(ix) += delta;
       (*tabnoeud)(inoeud)->Ajout_coord2(X);
       // appel de la métrique
       Met_abstraite::Expli_t_tdt  ex_n =metrique_bis.Cal_explicit_tdt
               (*tabnoeud,premier_calcul,(*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg),gradV_instantane);
       premier_calcul=false;               
               
       // calcul des dérivées numériques et  vérification
       for (int j=1;j<=dim;j++)
        { // variation des vecteurs giB_tdt
          CoordonneeB dgiB = ((*ex_n.giB_tdt)(j) -(*ex.giB_tdt)(j))/delta;
          for (int i=1;i<=dim;i++)
             if (diffpourcent(dgiB(i),(*ex.d_giB_tdt)(numddl)(j)(i),MaX(Dabs(dgiB(i)),Dabs((*ex.d_giB_tdt)(numddl)(j)(i))),0.05))
               {if (MiN(Dabs(dgiB(i)),Dabs((*ex.d_giB_tdt)(numddl)(j)(i))) <= mini_val)
                   {if ( MaX(Dabs(dgiB(i)),Dabs((*ex.d_giB_tdt)(numddl)(j)(i))) > 50.*delta) erreur = true;}
                else erreur = true;
               };
          // variation des vecteurs giH_tdt
          CoordonneeH dgiH = ((*ex_n.giH_tdt)(j) - (*ex.giH_tdt)(j))/delta;
          for (int i=1;i<=dim;i++)
             if (diffpourcent(dgiH(i),(*ex.d_giH_tdt)(numddl)(j)(i),MaX(Dabs(dgiH(i)),Dabs((*ex.d_giH_tdt)(numddl)(j)(i))),0.05))
               {if (MiN(Dabs(dgiH(i)),Dabs((*ex.d_giH_tdt)(numddl)(j)(i))) <= mini_val)
                   {if ( MaX(Dabs(dgiH(i)),Dabs((*ex.d_giH_tdt)(numddl)(j)(i))) > 50.*delta) erreur = true;}
                else erreur = true;
               };
         }       
       // variation du tenseur gijBB_tdt
       TenseurBB * gijBB = NevezTenseurBB(*ex_n.gijBB_tdt);
       *gijBB = (*ex_n.gijBB_tdt - *ex.gijBB_tdt) / delta;
       for (int i1=1;i1<=dim;i1++)
           for (int j1=1;j1<=dim;j1++)
             if (diffpourcent((*gijBB)(i1,j1),(*(*ex. d_gijBB_tdt)(numddl))(i1,j1),
                MaX(Dabs((*gijBB)(i1,j1)),Dabs((*(*ex. d_gijBB_tdt)(numddl))(i1,j1))),0.05))
                {if (MiN(Dabs((*gijBB)(i1,j1)),Dabs((*(*ex. d_gijBB_tdt)(numddl))(i1,j1))) <= mini_val)
                   {if( MaX(Dabs((*gijBB)(i1,j1)),Dabs((*(*ex. d_gijBB_tdt)(numddl))(i1,j1))) > 50.*delta) erreur = true;}
                 else erreur = true;
                };
       // variation du tenseur gijHH_tdt        
       TenseurHH * gijHH = NevezTenseurHH(*ex_n.gijHH_tdt);
       *gijHH = (*ex_n.gijHH_tdt - *ex.gijHH_tdt) / delta;
       for (int i1=1;i1<=dim;i1++)
           for (int j1=1;j1<=dim;j1++)
             if (diffpourcent((*gijHH)(i1,j1),(*(*ex. d_gijHH_tdt)(numddl))(i1,j1),
                MaX(Dabs((*gijHH)(i1,j1)),Dabs((*(*ex. d_gijHH_tdt)(numddl))(i1,j1))),0.05))
               {if (MiN(Dabs((*gijHH)(i1,j1)),Dabs((*(*ex. d_gijHH_tdt)(numddl))(i1,j1))) <= mini_val)
                   {if( MaX(Dabs((*gijHH)(i1,j1)),Dabs((*(*ex. d_gijHH_tdt)(numddl))(i1,j1))) > 50.*delta) erreur = true;}
                else erreur = true;
               };
       // variation du jacobien 
       double djaco = ((*ex_n.jacobien_tdt) - (*ex.jacobien_tdt))/delta;
       if (diffpourcent(djaco,(*ex.d_jacobien_tdt)(numddl),MaX(Dabs(djaco),Dabs((*ex.d_jacobien_tdt)(numddl))),0.05))
            if (MiN(Dabs(djaco),Dabs((*ex.d_jacobien_tdt)(numddl))) <= mini_val)
              {if( MaX(Dabs(djaco),Dabs((*ex.d_jacobien_tdt)(numddl))) > 50.*delta) erreur = true;
                else erreur = true;
               };
       // effacement des tenseurs intermédiaires
       delete gijBB; delete  gijHH;        
       // maintenant on remet les coordonnées du noeud à l'état initial         
       (*tabnoeud)(inoeud)->Change_coord2(coordtdt);        
      } // fin de boucle sur la dimension de coordonnée
    }  // fin de boucle sur les noeuds
  // message d'erreur si besoin
  if (erreur)
     { cout << "\n erreur dans le calcul analytique des dérivees de la metrique";
       cout << "\n Deformation::VerifCal_implicit(.."
            << " , numero d'increment = " << indic_VerifCal_implicit;
       Sortie(1);
      } 
 };
 

 
            
