// FICHIER : Hyper_W_gene_3D.cc
// CLASSE : Hyper_W_gene_3D


// 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 "Hyper_W_gene_3D.h"

//#include "Debug.h"

# include <iostream>
using namespace std;  //introduces namespace std
#include <math.h>
#include <stdlib.h>
#include "Sortie.h"
#include "TypeConsTens.h"
#include "ParaGlob.h"
#include "Enum_TypeQuelconque.h"
#include "TypeQuelconqueParticulier.h"
#include "CharUtil.h"
  
// CONSTRUCTEURS :
// ---------- classe de stockage des grandeurs spécifiques pour la loi ---------

// constructeur par défaut
Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::SaveResulHyper_W_gene_3D() :
           invP(NULL),invP_t(NULL),map_type_quelconque()
           ,para_loi(NULL),para_loi_t(NULL)
{ // mise à jour de la liste des grandeurs quelconques internes
  Mise_a_jour_map_type_quelconque();
};
// avec_para : le nombre indique si on sauvegarde des paramètres matériaux qui varient
//             et également des invariants.
// si == 0 : pas de stockage (joue en fait le role de sortie_post)
Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::SaveResulHyper_W_gene_3D(int avec_para) :
   invP(NULL),invP_t(NULL)
   ,para_loi(NULL),para_loi_t(NULL)
   ,map_type_quelconque()
{ if (avec_para)
    {invP = new Invariantpost3D();
     invP_t = new Invariantpost3D();
    };
  if (avec_para)
    {para_loi = new Vecteur(avec_para,-ConstMath::trespetit);
     para_loi_t = new Vecteur(avec_para,-ConstMath::trespetit);
    };
  // mise à jour de la liste des grandeurs quelconques internes
  Mise_a_jour_map_type_quelconque();
};

// constructeur de copie	           
Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::SaveResulHyper_W_gene_3D(const SaveResulHyper_W_gene_3D& sav):
     invP(NULL),invP_t(NULL),para_loi(NULL),para_loi_t(NULL)
     ,map_type_quelconque(sav.map_type_quelconque)
 { if (sav.invP != NULL)
     {invP = new Invariantpost3D(*(sav.invP));
      invP_t = new Invariantpost3D(*(sav.invP_t));
     };
   if (sav.para_loi != NULL)
     {para_loi = new Vecteur(*sav.para_loi);
      para_loi_t = new Vecteur(*sav.para_loi_t);
     };
   // mise à jour de la liste des grandeurs quelconques internes
   Mise_a_jour_map_type_quelconque();

 };

//  destructeur
Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::~SaveResulHyper_W_gene_3D()
  { if (invP != NULL)
     { delete invP;
       delete invP_t;
     };
    if (para_loi != NULL) delete para_loi;
    if (para_loi_t != NULL) delete para_loi_t;
  };
  
// affectation
Loi_comp_abstraite::SaveResul & Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { Hyper_W_gene_3D::SaveResulHyper_W_gene_3D& sav = *((Hyper_W_gene_3D::SaveResulHyper_W_gene_3D*) &a);
    if (sav.invP != NULL)
     { if (invP == NULL)
         {invP = new Invariantpost3D(*(sav.invP));
          invP_t = new Invariantpost3D(*(sav.invP_t));
         }
       else
        { *invP = (*(sav.invP)); *invP_t = (*(sav.invP_t));
        };
     }
    else
     // sinon cela veut dire que invP et invP_t ne doivent pas être affecté
     { if (invP != NULL)
         {delete invP;invP=NULL;
          delete invP_t;invP_t=NULL;
         };
     };
    map_type_quelconque = sav.map_type_quelconque;
    if (sav.para_loi != NULL)
     {if (para_loi == NULL)
       {para_loi = new Vecteur(sav.para_loi->Taille(),-ConstMath::trespetit);
        para_loi_t = new Vecteur(sav.para_loi->Taille(),-ConstMath::trespetit);
       };
      *para_loi = *(sav.para_loi);
      *para_loi_t = *(sav.para_loi_t);
     };

    return *this;
  };

//------- lecture écriture dans base info -------
   // cas donne le niveau de la récupération
   // = 1 : on récupère tout
   // = 2 : on récupère uniquement les données variables (supposées comme telles)
void Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::Lecture_base_info (ifstream& ent,const int )
  { string toto; int presence=0;
    ent >> toto >> presence;
    #ifdef MISE_AU_POINT
      if (toto != "dat_sp_hyperelas:")
         { cout << "\n erreur dans la lecture des donnees specifiques hyperelastiques, on ne trouve pas le mot cle: dat_sp_hyperelas: "
                << "\n  Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::Lecture_base_info (... ";
           Sortie(1);
          }       
    #endif
    if (presence == 1)
     {if (invP == NULL)
        {invP = new Invariantpost3D();
         invP_t = new Invariantpost3D();
        };
      // lecture
      ent >> (*invP); (*invP_t)= (*invP); //toto >>  invP->V >> toto >>  invP->Qeps >> toto >>  invP->cos3phi;
     }
    else
     { if (invP != NULL)
         { delete invP;invP=NULL;
           delete invP_t;invP_t=NULL;
         };
     };
    // cas des paramètres de lois éventuelles
    ent >> toto;
    if (toto == "sans_para")
     {if (para_loi != NULL)
        {delete para_loi;para_loi=NULL;
         delete para_loi_t;para_loi_t=NULL;
        };
     }
    else if (toto == "avec_para_taille=")
     {int taille;
      ent >> taille;
      if (para_loi == NULL)
       {para_loi = new Vecteur(taille);
        para_loi_t = new Vecteur(taille);
       };
      ent >> *para_loi;
      *para_loi_t=*para_loi;
     };
    // mise à jour de la liste des grandeurs quelconques internes
    Mise_a_jour_map_type_quelconque();

   };
   
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables 
//(supposées comme telles)
void Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::Ecriture_base_info(ofstream& sort,const int )
  { sort << "\n dat_sp_hyperelas: ";
    if (invP != NULL)
      { sort << " 1 " << (*invP); }
    else { sort << " 0  ";};
    // cas des paramètres de lois éventuelles
    if (para_loi == NULL)
     {sort << " sans_para ";}
    else
     {sort << " avec_para_taille= "<<para_loi->Taille() << " ";
      sort << *para_loi;
     };

  };
 
      // mise à jour des informations transitoires
void Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::TdtversT()
   {if (invP != NULL)
      (*invP_t) = (*invP);
    if (para_loi != NULL)
      {*para_loi_t = *para_loi;};
    // mise à jour de la liste des grandeurs quelconques internes
    Mise_a_jour_map_type_quelconque();
   };
void Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::TversTdt()
   {if (invP != NULL)
      (*invP) = (*invP_t);
    if (para_loi != NULL)
      {*para_loi = *para_loi_t;};
    // mise à jour de la liste des grandeurs quelconques internes
    Mise_a_jour_map_type_quelconque();
   };


// affichage à l'écran des infos
void Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::Affiche() const
   { cout << "\n data specifiques hyperelastiques : " ;
     if (invP != NULL)
       { cout << (*invP); };
     if (para_loi == NULL)
      {cout << " sans_para ";}
     else
      {cout << " avec_para ";
       cout << *para_loi;
      };
   };


// mise à jour de la liste des grandeurs quelconques internes
void Hyper_W_gene_3D::SaveResulHyper_W_gene_3D::Mise_a_jour_map_type_quelconque()
  { // on parcours la map
    map <  EnumTypeQuelconque , TypeQuelconque, std::less < EnumTypeQuelconque> >::iterator
      il,ilfin=map_type_quelconque.end();
    for (il=map_type_quelconque.begin();il != ilfin;il++)
    
     { switch ((*il).first)
       {  case POTENTIEL:
           { Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*) (*il).second.Grandeur_pointee()); // pour simplifier
             (*tyTQ.ConteneurDouble()) = invP->potentiel;
             break;
           }
          // -----cas des paramètres de la loi
          case PARA_LOI_TYPE_MOONEY:
           { Grandeur_Vecteur& gr= *((Grandeur_Vecteur*) map_type_quelconque[PARA_LOI_TYPE_MOONEY].Grandeur_pointee()); // pour simplifier
            if (para_loi != NULL)
               {*(gr.ConteneurVecteur()) =  *(para_loi);}
            else {gr.ConteneurVecteur()->Zero();};
              break;
            }

          default:
            cout << "\n *** erreur on demande l'acces  a : "
                 << NomTypeQuelconque((*il).first)
                 << " or celui-ci n'est pas dispo pour la loi ";
            this->Affiche();
            cout << " revoir la mise en donnees ! " << endl;
            Sortie(1);
       };

     };

};

// ---------- classe Hyper_W_gene_3D ---------

		// Constructeur par defaut
Hyper_W_gene_3D::Hyper_W_gene_3D ():
     Loi_comp_abstraite()
     ,I_B(0.),I_BB(0.),II_B(0.),III_B(0.)
     ,sortie_post(0),nb_para_loi(0)
    // I_B(0.),I_BB(0.),I_BBB(0.),II_B(0.),III_B(0.)
     ,J_r(3)
     ,d_I_B_epsBB_HH(),d_II_B_epsBB_HH(),d_III_B_epsBB_HH()
     ,d_J_r_epsBB_HH(3)
    // ,d_I_B_eps2BB_HHHH(),d_II_B_eps2BB_HHHH(),d_III_B_eps2BB_HHHH()
     ,d_J_1_eps2BB_HHHH(),d_J_2_eps2BB_HHHH(),d_J_3_eps2BB_HHHH()
     ,V(0.),BB_HH(),BB_HB()
     ,IxI_HHHH(),IxbarreI_HHHH(),IxB_HHHH(),BxI_HHHH()
	{
		
	};
		
 
		// Constructeur utile si l'identificateur du nom de la loi
		// de comportement et la dimension sont connus
		// vit_def indique si oui ou non la loi utilise la vitesse de déformation
Hyper_W_gene_3D::Hyper_W_gene_3D (Enum_comp id_compor,Enum_categorie_loi_comp categorie_comp
		                    ,int dimension,bool vit_def):
     Loi_comp_abstraite(id_compor,categorie_comp,dimension,vit_def)
     ,I_B(0.),I_BB(0.),II_B(0.),III_B(0.)
     ,sortie_post(0),nb_para_loi(0)
    // I_B(0.),I_BB(0.),I_BBB(0.),II_B(0.),III_B(0.)
     ,J_r(3)
     ,d_I_B_epsBB_HH(),d_II_B_epsBB_HH(),d_III_B_epsBB_HH()
     ,d_J_r_epsBB_HH(3)
    // ,d_I_B_eps2BB_HHHH(),d_II_B_eps2BB_HHHH(),d_III_B_eps2BB_HHHH()
     ,d_J_1_eps2BB_HHHH(),d_J_2_eps2BB_HHHH(),d_J_3_eps2BB_HHHH()
     ,V(0.),BB_HH(),BB_HB()
     ,IxI_HHHH(),IxbarreI_HHHH(),IxB_HHHH(),BxI_HHHH()
	{
		
	};

		// Constructeur de copie
Hyper_W_gene_3D::Hyper_W_gene_3D (const Hyper_W_gene_3D& loi):
     Loi_comp_abstraite(loi)
     ,nb_para_loi(loi.nb_para_loi)
     ,I_B(loi.I_B),I_BB(loi.I_BB),II_B(II_B),III_B(III_B)
    // I_B(loi.I_B),I_BB(loi.I_BB),I_BBB(loi.I_BBB),II_B(II_B),III_B(III_B)
     ,J_r(loi.J_r)
     ,d_I_B_epsBB_HH(loi.d_I_B_epsBB_HH),d_II_B_epsBB_HH(loi.d_II_B_epsBB_HH)
    // ,d_III_B_epsBB_HH(loi.d_III_B_epsBB_HH)
     ,d_J_r_epsBB_HH(loi.d_J_r_epsBB_HH)
    // ,d_I_B_eps2BB_HHHH(loi.d_I_B_eps2BB_HHHH)
     ,d_J_1_eps2BB_HHHH(loi.d_J_1_eps2BB_HHHH)
     ,d_J_2_eps2BB_HHHH(loi.d_J_2_eps2BB_HHHH)
     ,d_J_3_eps2BB_HHHH(loi.d_J_3_eps2BB_HHHH)
    // ,d_II_B_eps2BB_HHHH(loi.d_II_B_eps2BB_HHHH)
    // ,d_III_B_eps2BB_HHHH(loi.d_III_B_eps2BB_HHHH)
     ,V(loi.V),BB_HH(loi.BB_HH),BB_HB(loi.BB_HB)
     ,IxI_HHHH(),IxbarreI_HHHH(),IxB_HHHH(),BxI_HHHH()
     ,sortie_post(loi.sortie_post)
	{
		
	};
		
		// DESTRUCTEUR :
		
Hyper_W_gene_3D::~Hyper_W_gene_3D ()
	{
		
	};

// récupération des grandeurs particulière (hors ddl )
// correspondant à liTQ
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Hyper_W_gene_3D::Grandeur_particuliere
              (bool ,List_io<TypeQuelconque>& liTQ,Loi_comp_abstraite::SaveResul * saveDon,list<int>& decal) const
{  // ici on est en 3D et les grandeurs sont par principe en absolue, donc la variable absolue ne sert pas
   // on passe en revue la liste
   List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
   list<int>::iterator idecal=decal.begin();
   for (itq=liTQ.begin();itq!=itqfin;itq++,idecal++)
     {TypeQuelconque& tipParticu = (*itq); // pour simplifier
      if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
       switch (tipParticu.EnuTypeQuelconque().EnumTQ())
       {  case POTENTIEL:
           { SaveResulHyper_W_gene_3D & save_resul = *((SaveResulHyper_W_gene_3D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if (sortie_post)
                   tyTQ(1+(*idecal)) = (save_resul.invP)->potentiel;
             else
                   tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
          case PARA_LOI_TYPE_MOONEY:
           //  ----- cas des coefficients de loi
            { SaveResulHyper_W_gene_3D & save_resul = *((SaveResulHyper_W_gene_3D*) saveDon);
              Tab_Grandeur_Vecteur& tyTQ= *((Tab_Grandeur_Vecteur*) (*itq).Grandeur_pointee()); // pour simplifier
              if (save_resul.para_loi != NULL) {tyTQ(1+(*idecal))=  *(save_resul.para_loi);}
              else {tyTQ(1+(*idecal)).Zero();};
              (*idecal)++; break;
            }

          default: ;// on ne fait rien
       };

	    };
};
   
// récupération et création de la liste de tous les grandeurs particulières
// ces grandeurs sont ajoutées à la liste passées en paramètres
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Hyper_W_gene_3D::ListeGrandeurs_particulieres(bool absolue,List_io<TypeQuelconque>& liTQ) const
 {// ici on est en 3D et les grandeurs sont par principe en absolue, donc la variable absolue ne sert pas 
  Tableau <double> tab_1(1);
  Tab_Grandeur_scalaire_double grand_courant(tab_1);
  // on ne propose des grandeurs que si elles ont été stockée
  // non car le choix est un choix global, par contre les valeurs ne seront différentes de 0 que si sortie_post
  // est activé !!
//  if (sortie_post)
   { // def d'un type quelconque représentatif à chaque grandeur
     // a priori ces grandeurs sont défini aux points d'intégration identique à la contrainte par exemple
     // enu_ddl_type_pt est définit dans la loi Abtraite générale
     // on n'ajoute que si sortie_post est vraie, sinon aucune grandeur n'est sauvegardé, donc on ne peut
     // plus y accèder
     //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
     // cas du potentiel
     {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
      for (itq=liTQ.begin();itq!=itqfin;itq++)
        if ((*itq).EnuTypeQuelconque() == POTENTIEL)
         { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
           int taille = tyTQ.Taille()+1;
           tyTQ.Change_taille(taille); nexistePas = false;
         };
      if (nexistePas)
        {TypeQuelconque typQ1(POTENTIEL,enu_ddl_type_pt,grand_courant);
         liTQ.push_back(typQ1);
        };
     };
   };
  // $$$ cas des paramètres de la loi de comportement
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == PARA_LOI_TYPE_MOONEY)
      {Tab_Grandeur_Vecteur& tyTQ= *((Tab_Grandeur_Vecteur*) (*itq).Grandeur_pointee()); // pour simplifier
       int taille = tyTQ.Taille()+1;
       tyTQ.Change_taille(taille); nexistePas = false;
       tyTQ(taille).Change_taille(nb_para_loi);
      };
   if (nexistePas)
     {Vecteur  tens(nb_para_loi); //
      Tab_Grandeur_Vecteur gr_vec_para(tens,1);
      // def d'un type quelconque représentatif
      TypeQuelconque typQ(PARA_LOI_TYPE_MOONEY,EPS11,gr_vec_para);
      liTQ.push_back(typQ);
    };
  };

 };
 
// activation du stockage de grandeurs quelconques qui pourront ensuite être récupéré
// via le conteneur SaveResul, si la grandeur n'existe pas ici, aucune action
void Hyper_W_gene_3D::Activation_stockage_grandeurs_quelconques(list <EnumTypeQuelconque >& listEnuQuelc)
 {  // récup de la liste de stockage
    list <EnumTypeQuelconque >& listlocale = ListQuelc_mis_en_acces_localement();
  
    // on parcours la liste des grandeurs à activer
    // et on remplit la liste locale
    list <EnumTypeQuelconque >::iterator il, ilfin = listEnuQuelc.end();
    for (il = listEnuQuelc.begin();il != ilfin; il++)
//    for (EnumTypeQuelconque enu : listEnuQuelc)
     // on ne remplit que s'il s'agit d'une grandeur qui peut-être accessible
     {switch (*il)
       {case POTENTIEL: case PARA_LOI_TYPE_MOONEY:
          listlocale.push_back(*(il));
          break;
        default: ;  // pour les autres cas on ne fait rien
       };
     };
  
    // on supprime les doublons localement
    listlocale.sort(); // on ordonne la liste
    listlocale.unique(); // suppression des doublons
  
 };
 
// insertion des conteneurs ad hoc concernant le stockage de grandeurs quelconques
// passée en paramètre, dans le save result: ces conteneurs doivent être valides
// c-a-d faire partie de listdeTouslesQuelc_dispo_localement
void Hyper_W_gene_3D::Insertion_conteneur_dans_save_result(SaveResul * a)
 {
    // -- autre stockage éventuel en fonction des grandeurs quelconques demandées par d'autres lois
    // on va regarder s'il faut activer ou non invP et invP_t, pour le cas
    // de la récupération de grandeur quelconque au moment de l'utilisation de la loi
    // récup de la liste de stockage
    list <EnumTypeQuelconque >& listlocale = ListQuelc_mis_en_acces_localement();
    // def
    Hyper_W_gene_3D::SaveResulHyper_W_gene_3D& sav = *((Hyper_W_gene_3D::SaveResulHyper_W_gene_3D*) a);
  
    List_io <EnumTypeQuelconque>::iterator jk,jkfin = listlocale.end();
    for (jk=listlocale.begin();jk != jkfin;jk++)
//    for (EnumTypeQuelconque enu : listQuelc_dispo_localement)
//     { switch (enu)
      {EnumTypeQuelconque enu = *jk;
       switch (enu)
        { case POTENTIEL: // cas on des grandeurs sont demandées
            { if (sav.invP == NULL) // def si ils n'existent pas
               {sav.invP = new Invariantpost3D();
                sav.invP_t = new Invariantpost3D();
                if ((Permet_affichage() > 0 ) && (sortie_post == 0))
                 {cout << "\n *** warning: on demande pour une loi hyper elastique, l'utilisation de la grandeur "
                       << NomTypeQuelconque(enu) << " or on n'a pas demande sortie_post_ different de 0 "
                       << " on met arbitrairement sortie_post_ = 1 ";
                 };
               if (sortie_post == 0)
                 sortie_post = 1;
               };
              // on crée le conteneur ad hoc pour le passage d'info
              // def d'un conteneur de grandeurs quelconques, initialisée à 0
              Grandeur_scalaire_double grand_courant(0.);
              TypeQuelconque typQ1(enu,EPS11,grand_courant);
              sav.map_type_quelconque[enu]=(typQ1);
              break;
            }
          case PARA_LOI_TYPE_MOONEY:  // cas on des grandeurs sont demandées
            { if (sav.para_loi == NULL) // def si ils n'existent pas
               {sav.para_loi = new Vecteur; // la dimension sera ensuite précisée
                sav.para_loi_t = new Vecteur; // dans la loi dérivée
               };
              // on crée le conteneur ad hoc pour le passage d'info
              // def d'un conteneur de grandeurs quelconques, initialisée à 0
              Grandeur_Vecteur grand_courant(3);grand_courant.ConteneurVecteur()->Zero();
              TypeQuelconque typQ1(enu,EPS11,grand_courant);
              sav.map_type_quelconque[enu]=(typQ1);
              break;
            }

          default:
            cout << "\n *** erreur on demande l'acces  a : "
                 << NomTypeQuelconque(enu)
                 << " or celui-ci n'est pas dispo pour la loi ";
            this->Affiche();
            cout << " revoir la mise en donnees ! " << endl;
            Sortie(1);
        };
     };
 
 };


// --------------- méthodes internes -------------
// affichage et definition interactive des commandes particulières à chaques lois
void Hyper_W_gene_3D::Info_commande_LoisDeComp_hyper3D(UtilLecture& entreePrinc)
 {  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
    sort << "\n# il est egalement possible de stocker et donc de recuperer en post-traitement, differentes grandeurs "
         << "\n#  specifiquement utilises : ici la valeur du potentiel ,"
         << "\n#  pour cela sur la derniere ligne des donnees de la loi il "
         << "\n#  faut la presence du mot cle: sortie_post_ suivi de 1, par defaut sa valeur est 0 "
         << "\n# ex: sortie_post_ 1 ";
 };


		// calcul des invariants et de leurs variations premières
void Hyper_W_gene_3D::InvariantsEtVar1(const TenseurBB & gijBB_0_,const TenseurHH & gijHH_0_
		                                ,const TenseurBB & gijBB_tdt_,const TenseurHH & gijHH_tdt_
		                                ,const double& jacobien_0,const double& jacobien)
	{ const Tenseur3BB & gijBB_0 = *((Tenseur3BB*) &gijBB_0_); // passage en dim 3 explicit
   const Tenseur3BB & gijBB_tdt = *((Tenseur3BB*) &gijBB_tdt_); //  "
   const Tenseur3HH & gijHH_0 = *((Tenseur3HH*) &gijHH_0_); //  "
   const Tenseur3HH & gijHH_tdt = *((Tenseur3HH*) &gijHH_tdt_); //  "
   // tout d'abord on définit deux tenseurs qui nous seront utiles par la suite
   const Tenseur3HH & B_HH = gijHH_0; // le tenseur B
   B_HB = B_HH * gijBB_tdt; // le tenseur B  en mixte
   BB_HB = B_HB * B_HB;
   BB_HH = BB_HB * gijHH_tdt; // le tenseur B . B en deux fois contra
// BB_HH = B_HB * B_HH ;
   // calcul des trois invariants traces primaires de B
   I_B= B_HB.Trace(); //gijBB_tdt && B_HH ; //gijHH_0;
   I_BB= BB_HB.Trace(); //gijBB_tdt && BB_HH; //((gijBB_tdt * gijHH_0) * gijBB_tdt) && gijHH_0;
//	 I_BBB= gijBB_tdt && ((BB_HH * gijBB_tdt) * B_HH); // ((((gijBB_tdt * gijHH_0) * gijBB_tdt) * gijHH_0) * gijBB_tdt) && gijHH_0;
   // calcul des trois invariants en I de B: I_B, II_B, III_B
   II_B=0.5*(I_B*I_B-I_BB);
   const double untiers=1./3.;
//	 III_B=untiers*I_BBB - 0.5*I_B*I_BB + I_B*I_B*I_B/6;
   V= jacobien/jacobien_0;  // variation relative de volume
   III_B=V*V;               // calcul plus rapide que le précédent
   // calcul des trois invariants en J
   if (III_B <= ConstMath::petit)
     { if (Permet_affichage() >= 1)
         cout << "\n **** erreur, le volume final sur volume initial est quasi-nulle ! III_B=" << (III_B)
              << " on limite (V**(2)) a : " << ConstMath::petit;
       if (Permet_affichage() >= 5)
         cout << "\n Hyper_W_gene_3D::Invariants_et_var1( ";
       III_B = ConstMath::petit;     
     };
   // variables intermédiaires 	
   J3_puiss_untiers=pow(III_B,untiers);
   unSurJ3_puissuntiers=1./J3_puiss_untiers;
   unSurJ3_puissuntiers2=unSurJ3_puissuntiers*unSurJ3_puissuntiers;
   unSurJ3_puissuntiers4=unSurJ3_puissuntiers2*unSurJ3_puissuntiers2;
   // les J
   J_r(1)= I_B*unSurJ3_puissuntiers;
   J_r(2)=II_B*unSurJ3_puissuntiers2;
   J_r(3)=III_B;
//	 V = sqrt(III_B); // autre calcul de la variation relative de volume
	 // calcul des variations premières des I_r par rapports aux composantes epsBB d'Almansi
// ( en fait on ne les calcul pas pour optimiser le temps)	 
//	 d_I_B_epsBB_HH=2.* B_HH ; //gijHH_0;
//	 d_II_B_epsBB_HH= 2.* (I_B * B_HH - BB_HH);      
//	                // - 2. * ((gijHH_0 * gijBB_tdt) * gijHH_0);
//	 d_III_B_epsBB_HH=(2.*III_B)*gijHH_tdt;
	 // calcul des variation premières des J_r par rapports aux composantes epsBB d'Almansi

   d_J_r_epsBB_HH(1)=(2.*unSurJ3_puissuntiers)*(B_HH - (untiers*I_B)*gijHH_tdt);
   d_J_r_epsBB_HH(2)=(2.*unSurJ3_puissuntiers2)*(I_B * B_HH - BB_HH - (2.*untiers*II_B)*gijHH_tdt);
   d_J_r_epsBB_HH(3)=(2.*III_B)*gijHH_tdt;
   #ifdef MISE_AU_POINT
   if  (Permet_affichage() > 4)
     { cout << "\nHyper_W_gene_3D::InvariantsEtVar1(..."
            << "\n I_B= " << I_B << ", II_B= "<< II_B <<", III_B= "<< III_B
            << "\n J_r(1)= " << J_r(1) <<", J_r(2)= " << J_r(2) << ", J_r(3)= " << J_r(3)
            << "\n d_J_r_epsBB_HH(1)= " << d_J_r_epsBB_HH(1)
            << ", d_J_r_epsBB_HH(2)= " << d_J_r_epsBB_HH(2)
            << ", d_J_r_epsBB_HH(3)= " << d_J_r_epsBB_HH(3);
     };
   #endif
	};

		// calcul des invariants et de leurs variations premières et secondes
void Hyper_W_gene_3D::InvariantsEtVar2(const TenseurBB & gijBB_0_,const TenseurHH & gijHH_0_
		                       ,const TenseurBB & gijBB_tdt_,const TenseurHH & gijHH_tdt_
		                       ,const  double& jacobien_0,const double& jacobien)
	{ // calcul des invariants et de leurs variations premières
	  Invariants_et_var1(gijBB_0_,gijHH_0_,gijBB_tdt_,gijHH_tdt_,jacobien_0,jacobien);

	  const double untiers=1./3.;
	  // calcul des variations secondes
	  const Tenseur3BB & gijBB_0 = *((Tenseur3BB*) &gijBB_0_); // passage en dim 3 explicit
   const Tenseur3BB & gijBB_tdt = *((Tenseur3BB*) &gijBB_tdt_); //  "
   const Tenseur3HH & gijHH_0 = *((Tenseur3HH*) &gijHH_0_); //  "
   const Tenseur3HH & gijHH_tdt = *((Tenseur3HH*) &gijHH_tdt_); //  "
   const Tenseur3HH & B_HH = gijHH_0; // récup du tenseur B
   // le tenseur BB est déjà calculé
   // calcul de variables intermédiaires
   IxI_HHHH=Tenseur3HHHH::Prod_tensoriel(gijHH_tdt,gijHH_tdt);
   IxbarreI_HHHH=Tenseur3HHHH::Prod_tensoriel_barre(gijHH_tdt,gijHH_tdt);
   IxB_HHHH=Tenseur3HHHH::Prod_tensoriel(gijHH_tdt,B_HH);
   BxI_HHHH=Tenseur3HHHH::Prod_tensoriel(B_HH,gijHH_tdt);
   
   // variations secondes des I_r 
   //(finalement on ne les calcule pas pour optimiser)
   ////  d_I_B_eps2BB_HHHH.Inita(0.);
   ////  d_II_B_eps2BB_HHHH = 4.*(Tenseur3HHHH::Prod_tensoriel(B_HH,B_HH)
   ////                        - Tenseur3HHHH::Prod_tensoriel_barre(B_HH,B_HH));
   ////  d_III_B_eps2BB_HHHH = (4. * III_B) * 
   ////           ( Tenseur3HHHH::Prod_tensoriel(gijHH_tdt,gijHH_tdt)
   ////            - Tenseur3HHHH::Prod_tensoriel_barre(gijHH_tdt,gijHH_tdt));

   // variations secondes des J_r
//       d_J_1_eps2BB_HHHH = (-2.*untiers*unSurJ3_puissuntiers4)*
//                         Tenseur3HHHH::Prod_tensoriel(d_I_B_epsBB_HH,d_III_B_epsBB_HH)
//                             - (untiers * I_B * unSurJ3_puissuntiers4) * d_III_B_eps2BB_HHHH;
                             
   d_J_1_eps2BB_HHHH = (-4.*untiers*unSurJ3_puissuntiers)*
                     ( BxI_HHHH + IxB_HHHH - I_B*(untiers*IxI_HHHH + IxbarreI_HHHH) );

   d_J_2_eps2BB_HHHH = (-8. * untiers * unSurJ3_puissuntiers2 )*
                          (I_B* BxI_HHHH
                           - Tenseur3HHHH::Prod_tensoriel(BB_HH,gijHH_tdt)
                           - (2.*untiers)*II_B * IxI_HHHH
                           )
                       +(4. * unSurJ3_puissuntiers2 )*    
                         (Tenseur3HHHH::Prod_tensoriel(B_HH,B_HH)
                           - Tenseur3HHHH::Prod_tensoriel_barre(B_HH,B_HH)
                         -(2.*untiers )*(I_B * IxB_HHHH
                           - Tenseur3HHHH::Prod_tensoriel(gijHH_tdt,BB_HH))
                         +(2.*untiers * II_B)*IxbarreI_HHHH
                         );
                           
   d_J_3_eps2BB_HHHH = (4. * III_B) *  ( IxI_HHHH - IxbarreI_HHHH);                   
		
	};

//-------------- vérification de la dérivée avec une dérivée numérique -------------


// calcul des dérivées numériques premières
void   Hyper_W_gene_3D::Calcul_derivee_numerique(const TenseurBB & gijBB_0_,const TenseurHH & gijHH_0_
		                       ,const TenseurBB & gijBB_tdt_,const TenseurHH & gijHH_tdt_
		                       ,const  double& jacobien_0,const double& jacobien) 
	{ const Tenseur3BB & gijBB_0 = *((Tenseur3BB*) &gijBB_0_); // passage en dim 3 explicit
   const Tenseur3BB & gijBB_tdt = *((Tenseur3BB*) &gijBB_tdt_); //  "
   const Tenseur3HH & gijHH_0 = *((Tenseur3HH*) &gijHH_0_); //  "
   const Tenseur3HH & gijHH_tdt = *((Tenseur3HH*) &gijHH_tdt_); //  "
	
   Tenseur3BB  gijBBtdt_N; // tenseur  modifié
   Tenseur3HH  gijHHtdt_N; // idem_0 
   const Tenseur3HH & B_HH = gijHH_0;	  
	  // on choisit un incrément
	  double delta = ConstMath::unpeupetit;///10.;
	  double unSurDelta = 1./delta;
	  // sauvegarde des invariants actuelles et de leur variations
	  Vecteur J_r_sauve(J_r) ; 
	  double I_B_sauve=I_B; double II_B_sauve=II_B; double III_B_sauve=III_B;
	  Tableau <Tenseur3HH> d_J_r_epsBB_HH_sauve(d_J_r_epsBB_HH);
	  Tenseur3HH d_I_B_epsBB_HH_sauve=d_I_B_epsBB_HH;
	  Tenseur3HH d_II_B_epsBB_HH_sauve = d_II_B_epsBB_HH;
	  Tenseur3HH d_III_B_epsBB_HH_sauve = d_III_B_epsBB_HH;
	  // dimensionnement
	  Tableau <Tenseur3HH> d_J_r_epsBB_HH_num(d_J_r_epsBB_HH);
	  // on va boucler sur les composantes de gijBB
	  for (int i=1;i<=3;i++) 
	    for (int j=1;j<=3;j++)
	     { gijBBtdt_N = gijBB_tdt;
	       gijBBtdt_N.Coor(i,j) += delta;
	       // en fait dans l'opération précédente on a modifier les termes (i,j) et (j,i)
	       // car le tenseur est symétrique
	       // on a donc en variation numérique la somme des deux dérivées
	       // on définit un coeff multiplicatif qui vaut 1 ou 0.5
	       double coef=1.; if (i != j) coef = 0.5;
	       gijHHtdt_N = gijBBtdt_N.Inverse();
	       double jacobien_N=sqrt(gijBBtdt_N.Det());
	       // calcul des invariants
	       InvariantsEtVar1(gijBB_0_,gijHH_0_,(const TenseurBB &)gijBBtdt_N,(const TenseurHH &)gijHHtdt_N
	                         ,jacobien_0,jacobien_N);
	       for (int r=1;r<=3;r++)
	         {double& der_num = d_J_r_epsBB_HH_num(r).Coor(i,j);
	          // comme on a la somme des dérivées (i,j) et (j,i) qui doivent être égale
	          // on divise par 2 lorsque i != j	          
	          der_num=coef*2.*(J_r(r)-J_r_sauve(r))*unSurDelta; // dérivée numérique
	          double& der = d_J_r_epsBB_HH(r).Coor(i,j); // dérivée analytique
           // comparaison avec les valeurs de dérivées analytiques
           bool erreur = false;
 //          if (r!=2)
           if (diffpourcent(der_num,der,MaX(Dabs(der_num),Dabs(der)),0.1))
            if (MaX(Dabs(der_num),Dabs(der)) > 1.e-5) //1000.*delta)
              {if (MiN(Dabs(der_num),Dabs(der)) == 0.)
                {if ( MaX(Dabs(der_num),Dabs(der)) > 5.e-6 ) erreur = true;} //50.*delta) erreur = true;}
               else erreur = true;
              };
           if (erreur)
             { 
               // calcul des dérivées des I pour voir
               double derI_B_num = coef * 2. * (I_B-I_B_sauve)*unSurDelta;
               double derII_B_num = coef * 2. * (II_B-II_B_sauve)*unSurDelta;
               double derIII_B_num = coef * 2. * (III_B-III_B_sauve)*unSurDelta;
               double& derI_B = d_I_B_epsBB_HH_sauve.Coor(i,j);
               double& derII_B = d_II_B_epsBB_HH_sauve.Coor(i,j);
               double& derIII_B = d_III_B_epsBB_HH_sauve.Coor(i,j);
             
               // calcul de dérivées partielles pour voir
//	           double dernumpartielle = pow(III_B,-1./3.)*2.*(I_B-I_B_sauve)*unSurDelta;
//	           double deranapartielle = 2.*J_r(3)*B_HH(i,j);
//	           double dernumpartielle = I_B * 2. *(pow(III_B,-1./3.)-pow(III_B_sauve,-1./3.))*unSurDelta;
//	           double deranapartielle = -2./3.*pow(III_B_sauve,-1./3.)*gijHH_tdt(i,j);
               double dernumpartielle = 2. *(III_B-III_B_sauve)*unSurDelta;
               double deranapartielle = 2.*III_B_sauve*gijHH_tdt(i,j);
               cout << "\n dernumpartielle= " << dernumpartielle << ", deranapartielle= " << deranapartielle; 
               //
               cout << "\n erreur dans le calcul analytique des derivees de l'invariants: " << r
                    << "\n der_num= " << der_num << " der= " << der <<" der_N=" << d_J_r_epsBB_HH(r)(i,j)
                    << " ietj= " << i << " " << j
                    << "\n derI_B_num= " << derI_B_num << " derI_B= " << derI_B 
                    << " derII_B_num= " << derII_B_num << " derII_B= " << derII_B 
                    << " derIII_B_num= " << derIII_B_num << " derIII_B= " << derIII_B ;
               cout << "\n Hyper_W_gene_3D::Calcul_derivee_numerique(..";
               cout << "\n un caractere ";
               string toto;
               toto=lect_chaine();
//       Sortie(1);
             };
	         };
	     };
	  // retour aux valeurs sauvegardées
	  J_r = J_r_sauve; 
	  I_B=I_B_sauve; II_B = II_B_sauve; III_B = III_B_sauve;
	  for (int e=1;e<=3;e++)
	    d_J_r_epsBB_HH(e)=d_J_r_epsBB_HH_sauve(e);	
	};

// calcul des dérivées numériques premières et seconde
void   Hyper_W_gene_3D::Calcul_derivee_numerique2(const TenseurBB & gijBB_0_,const TenseurHH & gijHH_0_
		                       ,const TenseurBB & gijBB_tdt_,const TenseurHH & gijHH_tdt_
		                       ,const  double& jacobien_0,const double& jacobien)
	{ const Tenseur3BB & gijBB_0 = *((Tenseur3BB*) &gijBB_0_); // passage en dim 3 explicit
   const Tenseur3BB & gijBB_tdt = *((Tenseur3BB*) &gijBB_tdt_); //  "
   const Tenseur3HH & gijHH_0 = *((Tenseur3HH*) &gijHH_0_); //  "
   const Tenseur3HH & gijHH_tdt = *((Tenseur3HH*) &gijHH_tdt_); //  "
	
   Tenseur3BB  gijBBtdt_N; // tenseur  modifié
   Tenseur3HH  gijHHtdt_N; // idem_0 
   const Tenseur3HH & B_HH = gijHH_0;	  
	  double delta = ConstMath::unpeupetit*10.;
	  double unSurDelta = 1./delta;
	  // sauvegarde des invariants actuelles et de leur variations
	  Vecteur J_r_sauve(J_r) ; 
	  double I_B_sauve=I_B; double II_B_sauve=II_B; double III_B_sauve=III_B;
	  Tableau <Tenseur3HH> d_J_r_epsBB_HH_sauve(d_J_r_epsBB_HH);
      // idem pour la partie variation seconde
	  Tenseur3HHHH d_J_1_eps2BB_HHHH_sauve = d_J_1_eps2BB_HHHH;
	  Tenseur3HHHH d_J_2_eps2BB_HHHH_sauve = d_J_2_eps2BB_HHHH; 
	  Tenseur3HHHH d_J_3_eps2BB_HHHH_sauve = d_J_3_eps2BB_HHHH;
      
	  // dimensionnement
	  Tableau <Tenseur3HH> d_J_r_epsBB_HH_num(d_J_r_epsBB_HH);
	  // on va boucler sur les composantes de gijBB
	  for (int i=1;i<=3;i++) 
	    for (int j=1;j<=3;j++)
	     { gijBBtdt_N = gijBB_tdt;
	       gijBBtdt_N.Coor(i,j) += delta;
	       // en fait dans l'opération précédente on a modifier les termes (i,j) et (j,i)
	       // car le tenseur est symétrique
	       // on a donc en variation numérique la somme des deux dérivées
	       // on définit un coeff multiplicatif qui vaut 1 ou 0.5
	       double coef=1.; if (i != j) coef = 0.5;
	       gijHHtdt_N = gijBBtdt_N.Inverse();
	       double jacobien_N=sqrt(gijBBtdt_N.Det());
	       // calcul des invariants
	       InvariantsEtVar1(gijBB_0_,gijHH_0_,(const TenseurBB &)gijBBtdt_N,(const TenseurHH &)gijHHtdt_N
	                         ,jacobien_0,jacobien_N);
	       for (int r=1;r<=3;r++)
	         {double& der_num = d_J_r_epsBB_HH_num(r).Coor(i,j);
	          der_num=coef*2.*(J_r(r)-J_r_sauve(r))*unSurDelta; // dérivée numérique
	          double& der = d_J_r_epsBB_HH(r).Coor(i,j); // dérivée analytique
           // comparaison avec les valeurs de dérivées analytiques
           bool erreur = false;
 //          if (r!=2)
           if (diffpourcent(der_num,der,MaX(Dabs(der_num),Dabs(der)),0.01))
            if (MaX(Dabs(der_num),Dabs(der)) > 1000.*delta)
             {if (MiN(Dabs(der_num),Dabs(der)) == 0.)
                {if ( MaX(Dabs(der_num),Dabs(der)) > 50.*delta) erreur = true;}
              else erreur = true;
             };
           if (erreur)
            { 
              // calcul des dérivées des I pour voir
              cout << "\n erreur dans le calcul analytique des derivees de l'invariants: " << r
                   << "\n der_num= " << der_num << " der= " << der << " ietj= " << i << " " << j
                   << " J_r= " << J_r(r);
              cout << "\n Hyper_W_gene_3D::Calcul_derivee_numerique(..";
              cout << "\n un caractere ";
              string toto;
              toto=lect_chaine();
            };
	         };
	       // cas des variations secondes
	         // calcul des dérivées secondes analytiques
	       InvariantsEtVar2(gijBB_0_,gijHH_0_,(const TenseurBB &)gijBBtdt_N,(const TenseurHH &)gijHHtdt_N
	                                ,jacobien_0,jacobien_N);
	       // calcul des dérivées numériques et comparaisons
	       for (int k=1;k<=3;k++)
	         for (int l=1;l<=3;l++)
	           { // cas de d_J_1_eps2BB_HHHH
	             double der2num = coef * 2.*(d_J_r_epsBB_HH(1)(k,l) - d_J_r_epsBB_HH_sauve(1)(k,l) )*unSurDelta;
	             double der2ana = 0.5*(d_J_1_eps2BB_HHHH(k,l,i,j) + d_J_1_eps2BB_HHHH(k,l,j,i));
              bool erreur = false;
              if ((Dabs(d_J_r_epsBB_HH(1)(k,l))> 0.8) && (Dabs(der2ana)<30))
                if (diffpourcent(der2num,der2ana,MaX(Dabs(der2num),Dabs(der2ana)),0.01))
                  if (MaX(Dabs(der2num),Dabs(der2ana)) > 1000.*delta) 
                    {if (MiN(Dabs(der2num),Dabs(der2ana)) == 0.)
                       {if ( MaX(Dabs(der2num),Dabs(der2ana)) > 50.*delta) erreur = true;}
                     else erreur = true;
                    };
              if (erreur)
                { 
                  // calcul des dérivées d'éléments intermédiaires pour voir
                  double der2anapartielle=-4./3.*pow(III_B,-1./3.)*(B_HH(k,l)-1./3.*I_B*gijHH_tdt(k,l))*gijHH_tdt(i,j)
                      +2.*pow(III_B,-1./3.)*(-2./3.*gijHH_tdt(k,l)*B_HH(i,j)+2./3.*I_B*gijHH_tdt(k,i)*gijHH_tdt(l,j));
                  double der2numpartielle=coef*2.*(2.*pow(III_B,-1./3.)*(B_HH(k,l)-1./3.*I_B*gijHHtdt_N(k,l))
                                       -(2.*pow(III_B_sauve,-1./3.)*(B_HH(k,l)-1./3.*I_B_sauve*gijHH_tdt(k,l)) ))*unSurDelta;
                  cout << "\n der2numpartielle= " << der2numpartielle << " der2anapartielle= " << der2anapartielle ;
                  
                  
                  
                  //
                  cout << "\n erreur dans le calcul analytique des derivees secondes de l'invariants: " << 1
                       << "\n der2num= " << der2num << " der2ana= " << der2ana 
                       << " klij= " << k << " " << l << " " << i << " " << j
                       << " d_J_r_epsBB_HH(1)(k,l)= " << d_J_r_epsBB_HH(1)(k,l);
                  cout << "\n Hyper_W_gene_3D::Calcul_derivee_numerique(..";
                  cout << "\n un caractere ";
                  string toto;
                  toto=lect_chaine();
                };
 //   d_J_1_eps2BB_HHHH.Change(k,l,i,j,der2num);     // a virer        
                 // cas de d_J_2_eps2BB_HHHH
	             der2num = coef * 2.*(d_J_r_epsBB_HH(2)(k,l) - d_J_r_epsBB_HH_sauve(2)(k,l) )*unSurDelta;
	             der2ana = 0.5*(d_J_2_eps2BB_HHHH(k,l,i,j) + d_J_2_eps2BB_HHHH(k,l,j,i));
              erreur = false;
              if (diffpourcent(der2num,der2ana,MaX(Dabs(der2num),Dabs(der2ana)),0.01))
                if (MaX(Dabs(der2num),Dabs(der2ana)) > 1000.*delta)
                  {if (MiN(Dabs(der2num),Dabs(der2ana)) == 0.)
                    {if ( MaX(Dabs(der2num),Dabs(der2ana)) > 50.*delta) erreur = true;}
                   else erreur = true;
                  };
              if (erreur)
                { 
                  // calcul des dérivées des I pour voir
                  cout << "\n erreur dans le calcul analytique des derivees  secondes de l'invariants: " << 2
                       << "\n der2num= " << der2num << " der2ana= " << der2ana 
                       << " klij= " << k << " " << l << " " << i << " " << j
                       << " d_J_r_epsBB_HH(2)(k,l)= " << d_J_r_epsBB_HH(2)(k,l);
                  cout << "\n Hyper_W_gene_3D::Calcul_derivee_numerique(..";
                  cout << "\n un caractere ";
                  string toto;
    //              cin >> toto;
                };
 //   d_J_2_eps2BB_HHHH.Change(k,l,i,j,der2num);     // a virer        
                 // cas de d_J_3_eps2BB_HHHH
	             der2num = coef * 2.*(d_J_r_epsBB_HH(3)(k,l) - d_J_r_epsBB_HH_sauve(3)(k,l) )*unSurDelta;
	             der2ana = 0.5*(d_J_3_eps2BB_HHHH(k,l,i,j) + d_J_3_eps2BB_HHHH(k,l,j,i));
              erreur = false;
              if (diffpourcent(der2num,der2ana,MaX(Dabs(der2num),Dabs(der2ana)),0.1))
                if (MaX(Dabs(der2num),Dabs(der2ana)) > 1000.*delta)
                  {if (MiN(Dabs(der2num),Dabs(der2ana)) == 0.)
                    {if ( MaX(Dabs(der2num),Dabs(der2ana)) > 50.*delta) erreur = true;}
                   else erreur = true;
                  };
              if (erreur)
                 { 
                   // calcul des dérivées des I pour voir
                   cout << "\n erreur dans le calcul analytique des derivees  secondes de l'invariants: " << 3
                        << "\n der2num= " << der2num << " der2ana= " << der2ana 
                        << " klij= " << k << " " << l << " " << i << " " << j
                        << " d_J_r_epsBB_HH(3)(k,l)= " << d_J_r_epsBB_HH(3)(k,l);
                   cout << "\n Hyper_W_gene_3D::Calcul_derivee_numerique(..";
                   cout << "\n un caractere ";
                   string toto;
       //            cin >> toto;
                 };
  //  d_J_3_eps2BB_HHHH.Change(k,l,i,j,der2num);     // a virer        
  
	           };
	     };
	  // retour aux valeurs sauvegardées
	  J_r = J_r_sauve;
	  I_B=I_B_sauve; II_B = II_B_sauve; III_B = III_B_sauve;
	  for (int e=1;e<=3;e++)
	    d_J_r_epsBB_HH(e)=d_J_r_epsBB_HH_sauve(e);
	  // pour les dérivées secondes  	
	  d_J_1_eps2BB_HHHH = d_J_1_eps2BB_HHHH_sauve;
	  d_J_2_eps2BB_HHHH = d_J_2_eps2BB_HHHH_sauve; 
	  d_J_3_eps2BB_HHHH = d_J_3_eps2BB_HHHH_sauve;
	};
