
// 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 "DeformationSfe1.h"
# include "Met_Sfe1.h"
#include "ConstMath.h"
#include "ParaGlob.h"
#include "Util.h"

// -------------------------- variables static -------------------

//int DeformationSfe1::numInteg_total = 0;
// indicateur utilisé par VerifCal_def et VerifCal_implicit  
int DeformationSfe1::indic_VerifCal_implicitSfe1 = 0;        

// ---------- constructeur----------------------------------------

DeformationSfe1::DeformationSfe1 ()   // constructeur ne devant pas etre utilise
   {
     #ifdef MISE_AU_POINT	 	 
		{ cout << "\nErreur : le constructeur par defaut ne doit pa etre utilise !\n";
			  cout << "DeformationSfe1::DeformationSfe1 () \n";
			  Sortie(1);
			};
     #endif
   };
// constructeur normal dans le cas d'un ou de plusieurs pt d'integration             	  
DeformationSfe1::DeformationSfe1 (Met_abstraite & a,Tableau<Noeud *>& tabnoeud    
           ,Tableau <Mat_pleine>  const & tDphS,Tableau <Vecteur>  const & tPhS 
           ,Tableau <Mat_pleine>  const & tDphH,Tableau <Vecteur>  const & tPhH
): 
   Deformation (a,tabnoeud,tDphS,tPhS )
   ,epais(NULL),tabTypeCL(NULL),vplan(NULL)
   ,numInteg_ep(0),numInteg_surf(0),sauve_numInteg_ep(0),sauve_numInteg_surf(0)
   {  tabDphiH = &(tDphH);
      tabPhiH = &(tPhH);
      // on regarde s'il s'agit de 2D ou 3D c-a-d s'il faut stocker une épaisseur ou non
      if (a.Nbvec_des_bases() == 2)
        epais = new Epai();
    };
   
// constructeur de copie
DeformationSfe1::DeformationSfe1 (const  DeformationSfe1& a) :
   Deformation(a) 
   ,epais(NULL)
   ,tabTypeCL(a.tabTypeCL),vplan(a.vplan)
   ,numInteg_ep(a.numInteg_ep),numInteg_surf(a.numInteg_surf)
   ,sauve_numInteg_ep(a.sauve_numInteg_ep),sauve_numInteg_surf(a.sauve_numInteg_surf)
   { tabDphiH = a.tabDphiH;
     tabPhiH = a.tabPhiH;
     // on regarde s'il s'agit de 2D ou 3D c-a-d s'il faut stocker une épaisseur ou non
     if (a.epais != NULL)
        epais = new Epai(*(a.epais));
    };
   
     
DeformationSfe1::~DeformationSfe1 () 
   { if (epais != NULL) delete epais;}; 
   


//  ============      METHODES PUBLIQUES :  ==================
// change le numero d'integration courant
void DeformationSfe1::ChangeNumInteg(int ni)
  { int nbptSur = tabPhi->Taille();
	   int nbptEpa = tabPhiH->Taille();
    sauve_numInteg_surf=numInteg_surf;
    sauve_numInteg_ep = numInteg_ep;
    sauve_numInteg = numInteg;
	   numInteg_surf = (ni-1) / nbptEpa +1; // division entière
	   numInteg_ep = ni - (numInteg_surf-1) * nbptEpa ;
    //	numInteg_total = ni;
  } ;
   
// change les numeros d'integration de surface et d'epaisseur courant    
void DeformationSfe1::ChangeNumIntegSfe1
            (int nisurf, int niepaiss)
      { sauve_numInteg_surf=numInteg_surf;
        sauve_numInteg_ep = numInteg_ep;
        sauve_numInteg = numInteg;
        numInteg_ep = niepaiss; numInteg = numInteg_surf = nisurf;
         // on fait les changements dus aux nouveaux pts integ
//         numInteg_total = (tabPhiH->Taille()) * (numInteg_surf-1) + numInteg_ep;
      } ;

// affichage des informations
void DeformationSfe1::Affiche() const
 { cout << "\n -- deformation SFE : --- "
        << "\n nb noeud concerne = "<< tabnoeud->Taille()
        << " numInteg_surf= "<< numInteg_surf
        << " numInteg_ep= "<< numInteg_ep;
   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;
 };


// calcul explicit:tous les parametres sont de resultats cas d'un calcul à t
const Met_abstraite::Expli&  DeformationSfe1::Cal_explicit_t
                       ( 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
 bool pas_de_gradV=false; // indique que l'on veut a priori le calcul du gradient de vitesse
 Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
 const Met_abstraite::Expli*  ex; // le retour
 // on effectue un calcul simplifié si ce n'est pas un premier calcul et si ce n'est pas le premier ptinteg
 if ((numInteg_ep == 1)||(premier_calcul)) // cas ou l'on doit calculer tous les elements de la facette
   ex = &(met_Sfe1->CalSfe1_explicit_t(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                   ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                   ,epais,*tabTypeCL,*vplan));
                          
 else // cas d'un calcul simplifie
   ex = &(met_Sfe1->CalSfe1_explicit_simple_t(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                   ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                   ,epais));
         
 // 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);
};

	// sauvegarde des infos à 0 éventuellement
//$$$$$$$$$$$$ en fait je crois bien que ça ne sert à rien de sauvegarder le saveDefResul du sfe,
// car le seul qui est utiliser dans Almansi par exemple, c'est le général, donc relatif aux gi (et non au ai), 
// celui qui est spécifique au cas SFE contient en plus les infos de la facette, mais qui ne servent pas donc
// alourdisses le stockage !!!!

  // --- 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);
  };


  if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique);
  return *ex;
};

// calcul explicit:tous les parametres sont de resultats cas d'un calcul à tdt
const Met_abstraite::Expli_t_tdt&  DeformationSfe1::Cal_explicit_tdt
                  ( 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
  Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
  const Met_abstraite::Expli_t_tdt* ex; // le retour
  // appel de la metrique
  // on effectue un calcul simplifié si ce n'est pas un premier calcul et si ce n'est pas le premier ptinteg
  if ((numInteg_ep == 1)||(premier_calcul)) // cas ou l'on doit calculer tous les elements de la facette
    ex = &(met_Sfe1->CalSfe1_explicit_tdt(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                     ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                    ,epais,*tabTypeCL,*vplan));
  else // cas d'un calcul simplifie
    ex = &(met_Sfe1->CalSfe1_explicit_simple_tdt(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                     ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                    ,epais));
          
  
    // 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
  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);
	  };

   return *ex;
};

  	  // cas implicite : tous les parametres sont de resultats	
const Met_abstraite::Impli& DeformationSfe1::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é
     // recup d'un pointeur sur la metrique sfe1
     Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
     const Met_abstraite::Impli* ex; // la sortie
     // 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
     // appel de la metrique
     // on effectue un calcul simplifié si ce n'est pas un premier calcul et si ce n'est pas le premier ptinteg
     if ((numInteg_ep == 1)||(premier_calcul)) // cas ou l'on doit calculer tous les elements de la facette
       // dans le cas du premier calcul il y a calcul des grandeurs à 0 et à t, pas dans les autres cas
       ex =&(met_Sfe1->CalSfe1_implicit ( *tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                       ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan)); 
     else // cas d'un calcul simplifie
       // dans ce cas ci, les infos relatives à la facette, à la courbure, sont issue du calcul du premier pt d'integ
       // il n'y a pas de sauvegarde particulière, simplement, on considère que les infos n'ont pas été écrasées entre temps
       ex =&(met_Sfe1->CalSfe1_implicit_simple ( *tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                       ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais)); 
		  	
     // 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);
      };
//............... debug vérification ...................
//    // vérification éventuelle
//    VerifCal_implicit(gradV_instantane, *ex);
//............... debug vérification ...................

     // --- 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: 
     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; 
     return *ex;
  };    
  
// ---------------- calcul des variables primaires autre que pour la mécanique -------- 
// ------------     donc pas de retour relatif aux déformations   
     // calcul explicit à t :tous les parametres sont de resultats
const Met_abstraite::Expli&  DeformationSfe1::Cal_explicit_t(bool premier_calcul)

  {  bool gradV_instantane = false; // ************ pour l'instant figé
     // appel de la metrique
     Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
     const Met_abstraite::Expli* ex; // le retour
     // appel de la metrique
     // on effectue un calcul simplifié si ce n'est pas un premier calcul et si ce n'est pas le premier ptinteg
     if ((numInteg_ep == 1)||(premier_calcul)) // cas ou l'on doit calculer tous les elements de la facette
       ex = &(met_Sfe1->CalSfe1_explicit_t(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                        ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan));
     else // cas d'un calcul simplifie
       ex = &(met_Sfe1->CalSfe1_explicit_simple_t(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                        ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais));
     return *ex;           
  };

     // calcul explicit à tdt :tous les parametres sont de resultats
const Met_abstraite::Expli_t_tdt&  DeformationSfe1::Cal_explicit_tdt(bool premier_calcul)

  {  bool gradV_instantane = false; // ************ pour l'instant figé
     // appel de la metrique
     Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
     const Met_abstraite::Expli_t_tdt* ex; // le retour
     // appel de la metrique
     // on effectue un calcul simplifié si ce n'est pas un premier calcul et si ce n'est pas le premier ptinteg
     if ((numInteg_ep == 1)||(premier_calcul)) // cas ou l'on doit calculer tous les elements de la facette
       ex = &(met_Sfe1->CalSfe1_explicit_tdt(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                        ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan));
     else // cas d'un calcul simplifie
       ex = &(met_Sfe1->CalSfe1_explicit_simple_tdt(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                        ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais));
     return *ex;           
  };

  	  // cas implicite : tous les parametres sont de resultats	
const Met_abstraite::Impli& DeformationSfe1::Cal_implicit(bool premier_calcul)
  {  bool gradV_instantane = false; // ************ pour l'instant figé
     // recup d'un pointeur sur la metrique sfe1
     Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
     const Met_abstraite::Impli* ex; // la sortie
     // 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
     // appel de la metrique
     // on effectue un calcul simplifié si ce n'est pas un premier calcul et si ce n'est pas le premier ptinteg
     if ((numInteg_ep == 1)||(premier_calcul)) // cas ou l'on doit calculer tous les elements de la facette
       ex = &(met_Sfe1->CalSfe1_implicit (*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                        ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan)); 
     else // cas d'un calcul simplifie
       ex = &(met_Sfe1->CalSfe1_implicit_simple (*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                        ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais)); 
     return *ex;
  };    
// ========== remontee aux informations =========================
		
// cas sortie d'un calcul implicit
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * I^a
// tout ce passe comme si I^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoImp DeformationSfe1::RemontImp(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::InfoImp ex = met_Sfe1->CalSfe1_InfoImp( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                           ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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 calcul de matrices de passage
const Met_abstraite::InfoImp DeformationSfe1::RemontImp()
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::InfoImp ex = met_Sfe1->CalSfe1_InfoImp( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                           ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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} * I^a
// tout ce passe comme si I^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoExp_t DeformationSfe1::RemontExp_t(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::InfoExp_t ex = met_Sfe1->CalSfe1_InfoExp_t( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                                ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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 calcul de matrice de passage
const Met_abstraite::InfoExp_t DeformationSfe1::RemontExp_t()
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::InfoExp_t ex = met_Sfe1->CalSfe1_InfoExp_t( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                                ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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} * I^a
// tout ce passe comme si I^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::InfoExp_tdt DeformationSfe1::RemontExp_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin)
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::InfoExp_tdt ex = met_Sfe1->CalSfe1_InfoExp_tdt( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                              ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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 calcul de matrice de passage
const Met_abstraite::InfoExp_tdt DeformationSfe1::RemontExp_tdt()
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::InfoExp_tdt ex = met_Sfe1->CalSfe1_InfoExp_tdt( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                              ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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} * I^a
// tout ce passe comme si I^a est la nouvelle base vers laquelle on veut évoluer
const Met_abstraite::Info0_t_tdt DeformationSfe1::Remont0_t_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt)
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::Info0_t_tdt ex = met_Sfe1->CalSfe1_Info0_t_tdt( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                              ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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 calcul de matrice de passage
const Met_abstraite::Info0_t_tdt DeformationSfe1::Remont0_t_tdt()
  { // recup d'un pointeur sur la metrique sfe1
    Met_Sfe1* met_Sfe1 = (Met_Sfe1*) metrique;
    Met_abstraite::Info0_t_tdt ex = met_Sfe1->CalSfe1_Info0_t_tdt( *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud
                              ,(*tabPhi)(numInteg_surf),(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
    // 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;
  };

// gestion du parcours de tous les points d'integration
void DeformationSfe1::PremierPtInteg()
   { sauve_numInteg_surf=numInteg_surf;
     sauve_numInteg_ep = numInteg_ep;
     sauve_numInteg = numInteg;
     numInteg = 1 ; numInteg_ep = 1; numInteg_surf = 1;
   };
bool DeformationSfe1::DernierPtInteg()
   { sauve_numInteg_surf=numInteg_surf;
     sauve_numInteg_ep = numInteg_ep;
     sauve_numInteg = numInteg;
     // on ne contrôle que le numéro de surface vue le fonctionnement de NevezPtInteg
     if (numInteg_surf <= (tabPhi->Taille()) )
       return true;
     else
       return false;  
   };
void DeformationSfe1::NevezPtInteg()
   { sauve_numInteg_surf=numInteg_surf;
     sauve_numInteg_ep = numInteg_ep;
     sauve_numInteg = numInteg;
     // les pt varient d'abord en épaisseurs pour ensuite en surface, ce qui permet d'optimiser
     // le calcul de la courbure qui n'est fait que pour le premier pt d'épaisseur
     if (numInteg_ep < Nb_pt_int_epai())
       numInteg_ep++;
     else
      { numInteg_surf++;numInteg++;
        numInteg_ep = 1;
       }   
   };
      
 // méthode pour revenir au pti précédant
void DeformationSfe1::Retour_pti_precedant()
  {numInteg=sauve_numInteg;
   numInteg_surf = sauve_numInteg_surf;
   numInteg_ep = sauve_numInteg_ep;
  };

// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * I^a
// tout ce passe comme si I^a est la nouvelle base vers laquelle on veut évoluer
// si absolue = true: on fait un passage vers la base absolue
// si = false : on fait un passage vers une base ad hoc
void DeformationSfe1::BasePassage
        (bool absolue,const BaseB & giB0,const BaseB & giB,const BaseH & giH0,const BaseH & giH,
         Mat_pleine& Aa0,Mat_pleine& Aafin)
 {  
// *********$ sans doute à faire évoluer : (16 sept 2019) vers les cas généraux de Deformation
// car 1) c'est compliquer, et 2) je pense qu'il y a des cas qui manquent ici et donc que cela
// va -> des erreurs en sortie
// **** donc à voir si pb à venir


    // determination des matrices de transformation de base
    // l'objectif est de determiner un repere pertinant 
    // 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
    Coordonnee N = (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer();
    Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1)
    double norve = ve.Norme();
	   int tail_Aa0 = Aa0.Nb_ligne(); // pour tenir compte d'une dim = 2 ou 3
    Tableau <Coordonnee> vi(tail_Aa0); // 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));
      };
	   if (tail_Aa0 == 3)
	   vi(3) = N;

    if(giH0.NbVecteur()==tail_Aa0)
	    {for (int al=1 ;al<=tail_Aa0;al++)
	     for (int bl = 1;bl<=tail_Aa0;bl++)
       Aa0(bl,al) = giH0.Coordo(bl) * vi(al) ;
	    }
	   else // sinon cela signifie que le nombre est < donc à 3, car on traîte de repère pour facette
	    {for (int al=1 ;al<=tail_Aa0;al++)
	      {for (int bl = 1;bl<=2;bl++)
         Aa0(bl,al) = giH0.Coordo(bl) * vi(al) ;
		      Aa0(3,al) = N * vi(al) ; // on considère que le 3ième vecteur c'est la normale
       };
     };
 

//    for (int al=1 ;al<=2;al++)
//      {Aa0(1,al) = giH0.Coordo(1) * vi(al) ;
//       Aa0(2,al) = giH0.Coordo(2) * vi(al) ;
//       } 
// ---- 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 DeformationSfe1::BasePassage(  ";
//};
// ---- fin vérification        

    //------ cas de la config finale, 
    N = (Util::ProdVec_coorBN(giB(1),giB(2))).Normer();
    ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec(N,I1)
    norve = ve.Norme();
	   int tail_Aa = Aafin.Nb_ligne(); // pour tenir compte d'une dim = 2 ou 3
    Tableau <Coordonnee> Aa(tail_Aa);
    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));
     };
	   if (tail_Aa == 3)
	     Aa(3) = N;

	   if(giH.NbVecteur()==tail_Aa)
     {for (int be=1 ;be<=tail_Aa;be++)
       for (int bl = 1;bl<=tail_Aa;bl++)
          Aafin(bl,be) = giH.Coordo(bl) * Aa(be) ;
     }
	   else // sinon cela signifie que le nombre est < donc à 3, car on traîte de repère pour facette
     {for (int be=1 ;be<=tail_Aa;be++)
       {for (int bl = 1;bl<=2;bl++)
         Aafin(bl,be) = giH.Coordo(bl) * Aa(be) ;
        Aafin(3,be) = N * Aa(be) ; // on considère que le 3ième vecteur c'est la normale
       };
	    };

//    for (int be=1;be<=2;be++)
//      { Aafin(1,be) = giH.Coordo(1) * Aa(be);
//        Aafin(2,be) = giH.Coordo(2) * Aa(be);
//       };
// ---- vérification que le déterminant n'est pas nul
//{double det = Aafin(1,1) * Aafin(2,2) - Aafin(1,2) * Aafin(2,1);
// if (Abs(det) < 0.00001)
//   cout << "\n erreur det null " << det << " dans DeformationSfe1::BasePassage(  ";
//};
// ---- fin vérification        
    return;      
 };
             
// cas où l'on veut les matrices de passages à 0 t et tdt       
// Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * I^a
// tout ce passe comme si I^a est la nouvelle base vers laquelle on veut évoluer
void DeformationSfe1::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)
 {
// *********$ sans doute à faire évoluer : (16 sept 2019) vers les cas généraux de Deformation
// car 1) c'est compliquer, et 2) je pense qu'il y a des cas qui manquent ici et donc que cela
// va -> des erreurs en sortie
// **** donc à voir si pb à venir

    // determination des matrices de transformation de base
    // l'objectif est de determiner un repere pertinant 
    // 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
    Coordonnee N = (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer();
    Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1)
    double norve = ve.Norme();
	   int tail_Aa0 = Aa0.Nb_ligne(); // pour tenir compte d'une dim = 2 ou 3
    Tableau <Coordonnee> vi(tail_Aa0); // les vecteurs plans orthonormes de la facette
    if (norve >= ConstMath::petit)
     { 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));
     };
	   if (tail_Aa0 == 3)
	    vi(3) = N;

    if(giH0.NbVecteur()==tail_Aa0)
	    {for (int al=1 ;al<=tail_Aa0;al++)
	      for (int bl = 1;bl<=tail_Aa0;bl++)
        Aa0(bl,al) = giH0.Coordo(bl) * vi(al) ;
	    }
	   else // sinon cela signifie que le nombre est < donc à 3, car on traîte de repère pour facette
     {for (int al=1 ;al<=tail_Aa0;al++)
       {for (int bl = 1;bl<=2;bl++)
          Aa0(bl,al) = giH0.Coordo(bl) * vi(al) ;
        Aa0(3,al) = N * vi(al) ; // on considère que le 3ième vecteur c'est la normale
       };
	    };
		   
//    for (int al=1 ;al<=2;al++)
//      {Aa0(1,al) = giH0.Coordo(1) * vi(al) ;
//       Aa0(2,al) = giH0.Coordo(2) * vi(al) ;
//       }
    //------ cas de la config à t , 
    N = (Util::ProdVec_coorBN(giB_t(1),giB_t(2))).Normer();
    ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec_coor(N,I1)
    norve = ve.Norme();
	   int tail_jtB = Aa_t.Nb_ligne(); // pour tenir compte d'une dim = 2 ou 3
    Tableau <Coordonnee> jtB(tail_jtB);
    if (norve >= ConstMath::petit)
     { jtB(2) = ve.Normer();
       jtB(1) = Util::ProdVec_coor(jtB(2),N);
     }
    else
     { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec_coor(I2,N)
       jtB(1) = ve.Normer();
       jtB(2) = Util::ProdVec_coor(N,jtB(1));
     };
	   if (tail_jtB == 3)
	   jtB(3) = N;

	   if(giH_t.NbVecteur()==tail_jtB)
     {for (int be=1 ;be<=tail_jtB;be++)
       for (int bl = 1;bl<=tail_jtB;bl++)
          Aa_t(bl,be) = giH_t.Coordo(bl) * jtB(be) ;
     }
    else // sinon cela signifie que le nombre est < donc à 3, car on traîte de repère pour facette
     {for (int be=1 ;be<=tail_jtB;be++)
       {for (int bl = 1;bl<=2;bl++)
          Aa_t(bl,be) = giH_t.Coordo(bl) * jtB(be) ;
        Aa_t(3,be) = N * jtB(be) ; // on considère que le 3ième vecteur c'est la normale
       };
	    };

//    for (int be=1;be<=2;be++)
//      { Aa_t(1,be) = giH_t.Coordo(1) * jtB(be);
//        Aa_t(2,be) = giH_t.Coordo(2) * jtB(be);
//       } 
    //------ cas de la config tdt, 
    N = (Util::ProdVec_coorBN(giB_tdt(1),giB_tdt(2))).Normer();
    ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec_coor(N,I1)
    norve = ve.Norme();
	   int tail_jtdtB = Aa_tdt.Nb_ligne(); // pour tenir compte d'une dim = 2 ou 3
    Tableau <Coordonnee> jtdtB(tail_jtdtB);
    if (norve >= ConstMath::petit)
     { jtdtB(2) = ve.Normer();
       jtdtB(1) = Util::ProdVec_coor(jtdtB(2),N);
     }
    else
     { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec_coor(I2,N)
       jtdtB(1) = ve.Normer();
       jtdtB(2) = Util::ProdVec_coor(N,jtdtB(1));
     };
	   if (tail_jtdtB == 3)
	    jtdtB(3) = N;

	   if(giH_tdt.NbVecteur()==tail_jtdtB)
     {for (int be=1 ;be<=tail_jtdtB;be++)
       for (int bl = 1;bl<=tail_jtdtB;bl++)
          Aa_tdt(bl,be) = giH_tdt.Coordo(bl) * jtdtB(be) ;
     }
    else // sinon cela signifie que le nombre est < donc à 3, car on traîte de repère pour facette
     {for (int be=1 ;be<=tail_jtdtB;be++)
       {for (int bl = 1;bl<=2;bl++)
          Aa_tdt(bl,be) = giH_tdt.Coordo(bl) * jtdtB(be) ;
        Aa_tdt(3,be) = N * jtdtB(be) ; // on considère que le 3ième vecteur c'est la normale
       };
	    };

//    for (int be=1;be<=2;be++)
//      { Aa_tdt(1,be) = giH_tdt.Coordo(1) * jtdtB(be);
//        Aa_tdt(2,be) = giH_tdt.Coordo(2) * jtdtB(be);
//       } 
    return;      
 };
  
    // ------------------------ METHODES PROTEGEES : -------------------------------

// -----------------   méthodes de vérifications------- ----
    
void DeformationSfe1::VerifCal_def(bool gradV_instantane,const Met_abstraite::Impli & ,TenseurBB& epsBB_tdt
                                  ,Tableau <TenseurBB *> & d_epsBB_tdt)
 { // 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_implicitSfe1 == 0)
     { cout << "\n ****vérification du calcul de la déformation et des éléments de la métrique associé****";
       cout << "\n DeformationSfe1::VerifCal_def(... \n";
      } 
   indic_VerifCal_implicitSfe1++;
  
   // on cré une seconde métrique pour éviter de détruire la métrique originale
   Met_Sfe1 metrique_bis(*((Met_Sfe1*)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 metrique
       const Met_abstraite::Expli_t_tdt& ex_n = 
          metrique_bis.Cal_explicit_tdt(*tabnoeud,premier_calcul,(*tabDphi)(numInteg),
                                         nbNoeud,(*tabPhi)(numInteg),gradV_instantane);
     TenseurBB * epsBB_tdt_n = NevezTenseurBB(epsBB_tdt);
     //  calcul de la base duale et de la métrique à t=0
     const Met_abstraite::gijHH_0_et_giH_0& ex1_n = metrique_bis.Cal_gijHH_0_et_giH_0_apres_im_expli();         
     bool variation = false; // pour la variation de B et Palpha_BH
     Tableau <TenseurBB *>  d_epsBB_tdt_n(d_epsBB_tdt);
     for (int i=1;i<= d_epsBB_tdt_n.Taille();i++) d_epsBB_tdt_n(i)=NevezTenseurBB(*d_epsBB_tdt(1));
     // appel pour le calcul de la déformation logarithmique et de sa variation
//     Cal_Logarithmique (*ex_n.gijBB_0,*ex1_n.gijHH_0,d_epsBB_tdt_n,*ex_n.gijBB_tdt,*ex_n.gijHH_tdt,*epsBB_tdt_n
//                        ,*ex_n.d_gijBB_tdt,variation);
     // 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 epsBB_tdt
       TenseurBB * ddepsBB = NevezTenseurBB(epsBB_tdt);
       *ddepsBB = (*epsBB_tdt_n - epsBB_tdt) / delta; // la dérivée numérique
       for (int i1=1;i1<=dim;i1++)
           for (int j1=1;j1<=dim;j1++)
             if (diffpourcent((*ddepsBB)(i1,j1),(*(d_epsBB_tdt(numddl)))(i1,j1),
               MaX(Dabs((*ddepsBB)(i1,j1)),Dabs((*(d_epsBB_tdt(numddl)))(i1,j1))),0.05))
               {if (MiN(Dabs((*ddepsBB)(i1,j1)),Dabs((*(d_epsBB_tdt(numddl)))(i1,j1))) <= mini_val)
                   {if( MaX(Dabs((*ddepsBB)(i1,j1)),Dabs((*(d_epsBB_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 DeformationSfe1::VerifCal_def(.."
            << " , numero d'increment = " << indic_VerifCal_implicitSfe1;
       Sortie(1);
      } 
 };
 
void DeformationSfe1::VerifCal_implicit(bool gradV_instantane,const Met_abstraite::Impli & ex)
 { // 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_implicitSfe1 == 0)
     { cout << "\n ****verification du calcul de la deformation et des elements de la metrique associe****";
       cout << "\n DeformationSfe1::VerifCal_implicit \n";
      } 
   indic_VerifCal_implicitSfe1++;
  
   // on cré une seconde métrique pour éviter de détruire la métrique originale
   Met_Sfe1 metrique_bis(*((Met_Sfe1*)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
   int nberr = 10;
   Tableau<int>  erreur(nberr);
   double diff_admi = 0.1;
   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
       const Met_abstraite::Expli_t_tdt&  ex_n = metrique_bis.CalSfe1_explicit_tdt
               (*tabnoeud,gradV_instantane,(*tabDphi)(numInteg_surf),nbNoeud
                        ,(*tabPhi)(numInteg_surf),premier_calcul,(*tabDphiH)(numInteg_ep),(*tabPhiH)(numInteg_ep)
                       ,epais,*tabTypeCL,*vplan);
       premier_calcul=false;               
               
       // calcul des dérivées numériques et  vérification
       int nb_vecteur = 2;
       for (int j=1;j<=nb_vecteur;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))),diff_admi))
               {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(1) += 1;}
                else 
                	{erreur(2) += 1;
                     cout << "\ndgiB("<<i<<")="<<dgiB(i)<<",(*ex.d_giB_tdt)("<<numddl<<")("<<j<<")("<<i<<")="<< (*ex.d_giB_tdt)(numddl)(j)(i);
                	}
               };
          // 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))),diff_admi))
               {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(3) += 1;}
                else erreur(4) += 1;
               };
        };
       // 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<=nb_vecteur;i1++)
           for (int j1=1;j1<=nb_vecteur;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))),diff_admi))
               {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(5) += 1;}
                else erreur(6) += 1;
               };
       // 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<=nb_vecteur;i1++)
           for (int j1=1;j1<=nb_vecteur;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))),diff_admi))
               {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(7) += 1;}
                else erreur(8) += 1;
               };
       // 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))),diff_admi))
           {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(9) += 1; //(*ex.d_jacobien_tdt)(numddl) = djaco; // pour voir l'implication d'une bonne dérivée de jacobien
                     }
              }
            else erreur(10) += 1;
           };
       // 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
  bool une_erreur=false;
  for (int l=1;l<=nberr;l++) if (erreur(l) != 0) une_erreur=true;
  if (une_erreur)
     { cout << "\n erreur dans le calcul analytique des derivees de la metrique";
       cout << "\n DeformationSfe1::VerifCal_implicit(.."
            << " , numero d'increment = " << indic_VerifCal_implicitSfe1 << " erreur = " << erreur << endl;
//       Sortie(1);
      } 
 };
 
