

// 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 "Hyper3D.h"
#include "ComLoi_comp_abstraite.h"

# include <iostream>
using namespace std;  //introduces namespace std
#include <math.h>
#include <stdlib.h>
#include "Sortie.h"


//================== initialisation des variables static ======================
// indicateur utilisé par Verif_Potentiel_et_var
int Hyper3D::indic_Verif_Potentiel_et_var = 0;                            
double Hyper3D::limite_inf_Qeps = sqrt(2)*6.e-5 ; //001; 
double Hyper3D::limite_inf_bIIb = 36.e-10; // limite en dessous de laquelles on fait une ope spécial
                       

// ---------- classe Hyper3D ---------

Hyper3D::Hyper3D ()  : // Constructeur par defaut
 HyperD(RIEN_COMP,RIEN_CATEGORIE_LOI_COMP,3,false)
    {};
// Constructeur utile si l'identificateur du nom de la loi
// de comportement et le paramètre phase sont connus
Hyper3D::Hyper3D (Enum_comp id_compor,Enum_categorie_loi_comp categorie_comp,bool avec_ph) :
	 HyperD(id_compor,categorie_comp,3,avec_ph)
	  {} ;
// Constructeur utile si l'identificateur du nom de la loi
// de comportement et le paramètre phase sont connus			
Hyper3D::Hyper3D (char* nom,Enum_categorie_loi_comp categorie_comp,bool avec_ph) :
 HyperD(nom,categorie_comp,3,avec_ph)
	  {} ;
// Constructeur de copie
Hyper3D::Hyper3D (const Hyper3D& loi) :
  HyperD (loi)

	{};



// ===========  METHODES Protégées dérivant de virtuelles : ==============

 // Calcul des invariants, de epsBH, 
  // retour de IdGBH qui pointe sur le bon tenseur
//++ TensBH * Invariants (TenseurBB&  epsBB_t,TenseurBB& gijBB_t,
TenseurBH * Hyper3D::Invariants (const TenseurBB&  epsBB_t,const TenseurBB& ,
           const TenseurHH & gijHH_t,const double& jacobien_0,const double& jacobien_t,
//++           Invariant & invariant,TensBH & epsBH);
           Invariant & inv,TenseurBH & epsBH_t)
  {
    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_t); // passage en dim 3
    Tenseur3BH & epsBH = *((Tenseur3BH*) &epsBH_t); // passage en dim 3
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_t); // passage en dim 3

    epsBH = epsBB * gijHH;  // deformation en mixte
    inv.Ieps = epsBH.Trace(); // trace de la déformation
    Tenseur3BH  eps_barreBH = epsBH - (inv.Ieps/3.) * IdBH3;
    inv.V = (jacobien_t/jacobien_0);
    // dans le cas de la prise en compte de la dilatation il faut changer V
    if (dilatation)
     // on considère que la variation de volume thermique = la trace du tenseur de def thermique
     {double var_vol_thermique = (gijHH * (*epsBB_therm)).Trace();
      inv.V -= var_vol_thermique;
     };
    double inv_V = inv.V; // init pour être éventuellement modifié
    // s'il n'y a pas de régularisation : fact_regularisation = 0.
    if (Dabs(inv_V) < Dabs(fact_regularisation))
       inv_V += fact_regularisation;
    inv.bIIb = eps_barreBH.II() / 2.; // second invariant
//  la première méthode de calcul est la méthode traditionnelle, mais elle nécessite beaucoup
//  plus de calcul que la seconde (qui donne le même résultat à 10^{-18} près environ
//  une fois que V est calculé    
//    inv.bIIIb = eps_barreBH.III() / 3.; // troisième invariant 
    inv.bIIIb =  -0.125/(inv_V * inv_V ) +0.125  - 0.25*inv.Ieps
                 + 1./6. * inv.Ieps * inv.Ieps - inv.Ieps*inv.Ieps*inv.Ieps/27.
                 - 0.5*inv.bIIb  +1./3. * inv.bIIb  * inv.Ieps;    // troisième invariant 
//    if (avec_regularisation)
//     {// inv.V += fact_regularisation;
//       inv.bIIb += fact_regularisation;
//       inv.bIIIb += fact_regularisation;
//     };
    return & IdBH3;
   };
   
   
// calcul des invariants et de leurs variations, de epsBH,
 // et de sa variation, puis  retour de IdGBH qui pointe sur le bon tenseur 
//++ TensBH *  Invariants_et_var (TenseurBB&  epsBB_tdt,
TenseurBH *  Hyper3D::Invariants_et_var (const TenseurBB&  epsBB_tdt,
           const TenseurBB& ,const Tableau <TenseurBB *>& d_gijBB_tdt,
           const TenseurHH & gijHH_tdt,const Tableau <TenseurHH *>& d_gijHH_tdt,
           const double& jacobien_0,const double& jacobien_tdt,const Vecteur& d_jacobien_tdt,
           InvariantVarDdl& inv,
//++           TensBH & epsBH_tdt,Tableau<TensBH> & depsBH_tdt); 
           TenseurBH & epsBH_tdt,Tableau<TenseurBH*> & depsBH_tdt) 
  {
    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
    Tenseur3BH & epsBH = *((Tenseur3BH*) &epsBH_tdt); // passage en dim 3
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_tdt); // passage en dim 3

    epsBH = epsBB * gijHH;  // deformation en mixte
    inv.Ieps = epsBH.Trace(); // trace de la déformation
    Tenseur3BH  eps_barreBH = epsBH - (inv.Ieps/3.) * IdBH3;
    inv.V = (jacobien_tdt/jacobien_0);
    // dans le cas de la prise en compte de la dilatation il faut changer V
    if (dilatation)
     // on considère que la variation de volume thermique = la trace du tenseur de def thermique
     {double var_vol_thermique = (gijHH_tdt * (*epsBB_therm)).Trace();
      inv.V -= var_vol_thermique;
     };
    double inv_V = inv.V; // init pour être éventuellement modifié
    // s'il n'y a pas de régularisation : fact_regularisation = 0.
    if (Dabs(inv_V) < Dabs(fact_regularisation))
       inv_V += fact_regularisation;

    inv.bIIb = eps_barreBH.II() / 2.; // second invariant

//  la première méthode de calcul est la méthode traditionnelle, mais elle nécessite beaucoup
//  plus de calcul que la seconde (qui donne le même résultat à 10^{-18} près environ
//  une fois que V est calculé    
//    inv.bIIIb = eps_barreBH.III() / 3.; // troisième invariant
//    cout << "\n inv.bIIIb= "<< inv.bIIIb;
    inv.bIIIb =  -0.125/(inv_V * inv_V ) +0.125  - 0.25*inv.Ieps
                 + 1./6. * inv.Ieps * inv.Ieps - inv.Ieps*inv.Ieps*inv.Ieps/27.
                 - 0.5*inv.bIIb  +1./3. * inv.bIIb  * inv.Ieps;    // troisième invariant 
//    cout << "  ,   "<< inv.bIIIb << " debug Hyper3D::Invariants_et_var " << endl;
//    if (avec_regularisation)
//     { //inv.V += fact_regularisation;
//       inv.bIIb += fact_regularisation;
//       inv.bIIIb += fact_regularisation;
//     };
   
// --- debug
///   pour info la bonne expression de bIIIb est donnée par tutu !!
// mais le résultat est identique (au erreur de calcul près) avec titi (c'est d'après la formule de denis
// thèse chapitre, II.2.3, formule 2.19
// et idem avec toto1 , en fait il n'y a que toto2 qui est complètement faux 
//
//   double toto2 = inv.bIIIb - (-1./(8.*inv.V * inv.V ) +1./8. - 0.25*inv.Ieps
//                               + 1./3. * inv.Ieps * inv.Ieps - inv.Ieps*inv.Ieps*inv.Ieps*11/54.
//                               -0.5*inv.bIIb  + inv.bIIb  * inv.Ieps);
//                               
//   double je = 1.-2./3.* inv.Ieps;
//   double je3=je*je*je;
//   double titi = 1./(inv.V*inv.V) - (je3 - 4.*inv.bIIb*je-8.*inv.bIIIb); 
//   double tutu = 1./(8.*inv.V*inv.V) - 1./8.+1./4.*inv.Ieps-1./6.*inv.Ieps*inv.Ieps
//                                    +1./27.*inv.Ieps*inv.Ieps*inv.Ieps 
//                                    + 0.5*inv.bIIb*1.-1./3.*inv.bIIb* inv.Ieps+inv.bIIIb;                        
//   double toto1 = inv.bIIIb -( -1./(8.*inv.V * inv.V ) +1./8. - 0.25*inv.Ieps
//                               + 1./6. * inv.Ieps * inv.Ieps - inv.Ieps*inv.Ieps*inv.Ieps/27.
//                               - 0.5*inv.bIIb  +1./3. * inv.bIIb  * inv.Ieps);
//
//   if ((Abs(toto1)>ConstMath::petit) || (Abs(toto2)>ConstMath::petit)|| (Abs(titi)>ConstMath::petit)) 
//      cout << "\n ** toto1= " << toto1 << " toto2= " << toto2 << " titi= " << titi<< " tutu= " << tutu;
//
//// -- fin debug   
//   

    // cas le la variation 
    int nbddl = d_gijBB_tdt.Taille();
    Tenseur3BH  deps_barreBH; // grandeurs intermédiaires
    for (int i = 1; i<= nbddl; i++)
    {const Tenseur3HH & dgijHH = *((Tenseur3HH*)(d_gijHH_tdt(i))) ;  // pour simplifier l'ecriture
     const Tenseur3BB & dgijBB = *((Tenseur3BB*)(d_gijBB_tdt(i)));  // passage en dim 3
     Tenseur3BH & depsBH = *((Tenseur3BH*)(depsBH_tdt(i)));  // passage en dim 3
     depsBH = 0.5 * dgijBB * gijHH_tdt + epsBB * dgijHH;
     double dIeps = (depsBH).Trace();inv.dIeps(i) = dIeps;
     deps_barreBH = depsBH - (dIeps/3.) * IdBH3; // en mixte les coordonnées de IdBH3 sont fixes
     double dbIIb = inv.dbIIb(i) = deps_barreBH && eps_barreBH;
     double dV = inv.dV(i) = (d_jacobien_tdt(i)/jacobien_0) ; 
     
//   Pour minimiser le temps de calcul on calcul la dérivée à l'aide de la formule scalaire 
//     inv.dbIIIb(i) = (deps_barreBH * eps_barreBH) && eps_barreBH;
//  -- formule scalaire de base 
//     inv.bIIIb =  -0.125/(inv.V * inv.V ) +0.125  - 0.25*inv.Ieps
//                 + 1./6. * inv.Ieps * inv.Ieps - inv.Ieps*inv.Ieps*inv.Ieps/27.
//                 - 0.5*inv.bIIb  +1./3. * inv.bIIb  * inv.Ieps;    // troisième invariant 
//     d'où la variation
     inv.dbIIIb(i) =  0.25*dV/(inv_V * inv_V * inv_V)   - 0.25*dIeps
                     + 1./3. * dIeps * inv.Ieps - dIeps*inv.Ieps*inv.Ieps/9.
                     - 0.5*dbIIb  +1./3. * ( dbIIb  * inv.Ieps + inv.bIIb  * dIeps ) ;    // troisième invariant 

    };

// --- debug
//  affichage des invariants pour comparer
//   cout << "\n Hyper3D::Invariants_et_var ( V:" << inv.V <<" Ieps:" << inv.Ieps 
//	     << " bIIb:" << inv.bIIb << " bIIIb:" << inv.bIIIb 
//		  << "\n dV:" << inv.dV <<"\n dIeps:" << inv.dIeps 
//	     << "\n dbIIb:" << inv.dbIIb << "\n dbIIIb:" << inv.dbIIIb
//		  << endl;
//
//// -- fin debug   
       
    return & IdBH3;
   };
   
 // calcul des invariants  et de leurs variations par rapport aux déformations
 // et de sa variation, puis  retour de IdGBH qui pointe sur le bon tenseur 
TenseurBH *  Hyper3D::Invariants_et_varEps (const TenseurBB&  epsBB_tdt,
           const TenseurBB& ,const TenseurHH & gijHH_tdt,
           const double& jacobien_0,const double& jacobien_tdt,
           InvariantVarEps& inv,TenseurBH & epsBH_tdt) 
  {
    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
    Tenseur3BH & epsBH = *((Tenseur3BH*) &epsBH_tdt); // passage en dim 3
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_tdt); // passage en dim 3

    epsBH = epsBB * gijHH;  // deformation en mixte
    inv.Ieps = epsBH.Trace(); // trace de la déformation
    Tenseur3BH  eps_barreBH = epsBH - (inv.Ieps/3.) * IdBH3;
    inv.V = (jacobien_tdt/jacobien_0);
    // dans le cas de la prise en compte de la dilatation il faut changer V
    if (dilatation)
     // on considère que la variation de volume thermique = la trace du tenseur de def thermique
     {double var_vol_thermique = (gijHH * (*epsBB_therm)).Trace();
      inv.V -= var_vol_thermique;
     };
    double inv_V = inv.V; // init pour être éventuellement modifié
    // s'il n'y a pas de régularisation : fact_regularisation = 0.
    if (Dabs(inv_V) < Dabs(fact_regularisation))
       inv_V += fact_regularisation;

    inv.bIIb = eps_barreBH.II() / 2.; // second invariant

//  la première méthode de calcul est la méthode traditionnelle, mais elle nécessite beaucoup
//  plus de calcul que la seconde (qui donne le même résultat à 10^{-18} près environ
//  une fois que V est calculé    
    inv.bIIIb = eps_barreBH.III() / 3.; // troisième invariant
// cout << "\n inv.bIIIb= "<< inv.bIIIb;
    inv.bIIIb =  -0.125/(inv_V * inv_V ) +0.125  - 0.25*inv.Ieps
                 + 1./6. * inv.Ieps * inv.Ieps - inv.Ieps*inv.Ieps*inv.Ieps/27.
                 - 0.5*inv.bIIb  +1./3. * inv.bIIb  * inv.Ieps;    // troisième invariant 
// cout << "  ,   "<< inv.bIIIb << " debug Hyper3D::Invariants_et_varEps " << endl;
//    if (avec_regularisation)
//     { //inv.V += fact_regularisation;
//       inv.bIIb += fact_regularisation;
//       inv.bIIIb += fact_regularisation;
//     };
    // cas le la variation
    Tenseur3HH epsHH = gijHH_tdt * epsBH;
    inv.dIeps_deps_HH = gijHH_tdt - 2. * epsHH;
    // on a : bIIb = bII - 1/6 Ieps^2 ; et dbII = epsHH - 2. * epsHH * epsBH
    Tenseur3HH d_bII_HH =  epsHH - 2. * epsHH * epsBH ;
    inv.dbIIb_deps_HH = d_bII_HH - (inv.Ieps/3.) * inv.dbIIb_deps_HH;
    // on a = bIIIb = bIII - 2/3 (I * bII - I^3/9) : thèse denis, page II.2.1
    Tenseur3HH d_bIII = epsHH * epsBH - 2. * epsHH * epsBH * epsBH;
    inv.dbIIIb_deps_HH = d_bIII + ((inv.Ieps * inv.Ieps / 3.)- (2.*inv.bIIb/3.) ) // mise en facteur du coeff 
                                                 * inv.dIeps_deps_HH            // scalaire
                                          - (2.*inv.Ieps/3.) * inv.dbIIb_deps_HH;
    // formule identique au cas de Mooney Rivlin , voir document de synthèse sur les lois hyper-élastiques chap 9                                      
    inv.dV_deps_HH = inv.V * gijHH_tdt;
    // on libère les tenseurs 
    LibereTenseur();LibereTenseurQ();
    return & IdBH3;
   };
             
    // calcul du potentiel et de ses dérivées non compris la phase
Hyper3D::PotenSansPhaseSansVar Hyper3D::Potentiel(const Invariant & inv,const double& jacobien0)
  { // en fait il s'agit du transfert du calcul du potentiel de la forme grenobloise à la forme standard
    // mais ce transfert n'est possible que si bIIb est non nulle, dans le cas contraire on utilise `
    // directement une technique de différence finie pour obtenir une dérivée numérique
    // def du retour
    PotenSansPhaseSansVar potret;
    // récup du conteneur spécifique du point, pour sauvegarde éventuelle
    SaveResulHyperD & save_resulHyperD = *((SaveResulHyperD*) saveResul);
//    if (Dabs(inv.bIIb) > ConstMath::unpeupetit) 
    if ((Dabs(inv.bIIb) > limite_inf_bIIb)||(avec_regularisation))
      { // calcul du nouvel  invariant sous la nouvelle forme
        InvariantQeps inv_spes = InvariantSpecifSansPhase(inv);
        // calcul du potentiel sous la forme polaire
        PoGrenobleSansPhaseSansVar pot = PoGrenoble(inv_spes,inv);
        // calcul de potret
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V *  pot.EV  + pot.E);
        potret.EbIIb = jacobien0 * inv.V * pot.EQ * inv_spes.dQepsdbIIb;
        // stockage éventuel des invariants et du potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv.V;
           save_resulHyperD.invP->Qeps= inv_spes.Qeps;
           save_resulHyperD.invP->cos3phi= 0.;
           save_resulHyperD.invP->potentiel= pot.E;
         };
       }
    else
      // cas d'un calcul par différence finie
      { // calcul des invariants sous la nouvelle forme
        double Qeps = Invariant0Qeps(inv);
        // calcul du potentiel sous la forme polaire au point actuel
        // ainsi que la variation suivant V, la phase ne peut pas être prise en compte
        // car Qeps est nulle
        PoGrenoble_V pot = PoGrenoble_et_V(Qeps,inv);
        // calcul du potentiel pour une petite variation suivant bIIb
        Invariant inv_n = inv; inv_n.bIIb += limite_inf_bIIb;
        double Qeps_n = Invariant0Qeps(inv_n);
        // stockage éventuel des invariants et potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv_n.V;
           save_resulHyperD.invP->Qeps= Qeps_n;
           save_resulHyperD.invP->cos3phi= 0.;
           save_resulHyperD.invP->potentiel= pot.E;
         };
        double E_n = PoGrenoble(Qeps_n,inv_n);
        // calcul de potret
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V * pot.EV  + pot.E);
        potret.EbIIb = jacobien0 * inv.V * (pot.E - E_n)/limite_inf_bIIb;
       }
    return potret;             
   }; 

    // calcul du potentiel et de ses dérivées avec la phase
Hyper3D::PotenAvecPhaseSansVar Hyper3D::PotentielPhase(const Invariant& inv,const double& jacobien0)
  { // en fait il s'agit du transfert du calcul du potentiel de la forme grenobloise à la forme standard
    // mais ce transfert n'est possible que si bIIb est non nulle, dans le cas contraire on utilise `
    // directement une technique de différence finie pour obtenir une dérivée numérique
        // def du retour
    PotenAvecPhaseSansVar potret;
    // récup du conteneur spécifique du point, pour sauvegarde éventuelle
    SaveResulHyperD & save_resulHyperD = *((SaveResulHyperD*) saveResul);
    if ((Dabs(inv.bIIb) > limite_inf_bIIb)||(avec_regularisation))
      { // calcul des invariants sous la nouvelle forme
        InvariantQepsCosphi inv_spes = InvariantSpecif(inv);
        // calcul du potentiel sous la forme polaire
        PoGrenobleAvecPhaseSansVar pot = PoGrenoblePhase(inv_spes,inv);
        // stockage éventuel des invariants et potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv.V;
           save_resulHyperD.invP->Qeps= inv_spes.Qeps;
           save_resulHyperD.invP->cos3phi= inv_spes.cos3phi;
           save_resulHyperD.invP->potentiel= pot.E;
         };
        // calcul de potret
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V * ( pot.EV + pot.Ecos3phi * inv_spes.dcos3phidV) + pot.E);
        potret.EIeps = jacobien0 * inv.V * (pot.Ecos3phi * inv_spes.dcos3phidIeps);
        potret.EbIIb = jacobien0 * inv.V * (pot.EQ * inv_spes.dQepsdbIIb 
                       + pot.Ecos3phi * inv_spes.dcos3phidbIIb);
       }
    else
      // cas d'un calcul par différence finie, on considère que toute les dérivées suivant la phase
      // sont nulles dans ce cas
      { // calcul des invariants sous la nouvelle forme
        double Qeps = Invariant0Qeps(inv);
        // calcul du potentiel sous la forme polaire au point actuel
        // ainsi que la variation suivant V
        PoGrenoble_V pot = PoGrenoble_et_V(Qeps,inv);
        // calcul du potentiel pour une petite variation suivant bIIb
        Invariant inv_n = inv; inv_n.bIIb += limite_inf_bIIb;
        Invariant0QepsCosphi inv_spes_n = Invariant0Specif(inv_n);
        double E_n = PoGrenoble(inv_spes_n,inv_n);
        // stockage éventuel des invariants et du potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv.V;
           save_resulHyperD.invP->Qeps= inv_spes_n.Qeps;
           save_resulHyperD.invP->cos3phi= inv_spes_n.cos3phi;
           save_resulHyperD.invP->potentiel= pot.E;
         };
        // calcul de potret
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V * pot.EV  + pot.E);
        potret.EIeps = 0.;
        potret.EbIIb = jacobien0 * inv.V * (pot.E - E_n)/limite_inf_bIIb;
       }
                  
    return potret;             
   }; 
    // calcul  du potentiel sans phase et dérivées avec  ses variations par rapport aux invariants
Hyper3D::PotenSansPhaseAvecVar Hyper3D::Potentiel_et_var(const Invariant& inv,const double& jacobien0 )
  { // en fait il s'agit du transfert du calcul du potentiel de la forme grenobloise à la forme standard
    // mais ce transfert n'est possible que si bIIb est non nulle, dans le cas contraire on utilise `
    // directement une technique de différence finie pour obtenir une dérivée numérique
    // def du retour
    PotenSansPhaseAvecVar potret;
    // récup du conteneur spécifique du point, pour sauvegarde éventuelle
    SaveResulHyperD & save_resulHyperD = *((SaveResulHyperD*) saveResul);
    if ((Dabs(inv.bIIb) > ConstMath::petit)||(avec_regularisation))
      { // calcul des invariants sous la nouvelle forme
        Invariant2Qeps inv_spes = Invariant2SpecifSansPhase(inv);
        // calcul du potentiel sous la forme polaire
        PoGrenobleSansPhaseAvecVar pot = PoGrenoble_et_var(inv_spes,inv);
//debug
//cout << "\n debug: Hyper3D::"
//     << " E="<<pot.E << "  pot.EV=" << pot.EV << " pot.EVV="<<pot.EVV<<endl;
//if (pot.E < 0)
//   cout << "\n pb ";
//fin debug
        // calcul de potret
        //dérivées premières
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V *  pot.EV  + pot.E);
        potret.EbIIb = jacobien0 * inv.V * pot.EQ * inv_spes.dQepsdbIIb; 
        // dérivées secondes
        potret.EVV = jacobien0 * (2. * pot.EV + inv.V * pot.EVV );
        potret.EbIIb2 = jacobien0 * inv.V * ( pot.EQQ * inv_spes.dQepsdbIIb * inv_spes.dQepsdbIIb 
                        + pot.EQ * inv_spes.dQepsdbIIb2 ); 
        potret.EbIIbV = jacobien0 * ((pot.EQ + inv.V * pot.EQV) * inv_spes.dQepsdbIIb);
        // stockage éventuel des invariants et du potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv.V;
           save_resulHyperD.invP->Qeps= inv_spes.Qeps;
           save_resulHyperD.invP->cos3phi= 0.;
           save_resulHyperD.invP->potentiel= pot.E;
         };
        // appel d'une vérification éventuelle
//+++verif***        Verif_Potentiel_et_var(inv,jacobien0,potret);
       }
    else
      // cas d'un calcul par différence finie, on considère que toute les dérivées suivant la phase
      // sont nulles dans ce cas
      { // calcul des invariants sous la nouvelle forme
        Invariant inv_n0(inv.Ieps,inv.V,inv.bIIb,inv.bIIIb);
        double Qeps = Invariant0Qeps(inv_n0);
        // calcul du potentiel sous la forme polaire au point actuel
        // ainsi que la variation première et seconde suivant V
        PoGrenoble_VV pot = PoGrenoble_et_VV(Qeps,inv_n0);
        // calcul du potentiel pour une petite variation suivant bIIb
        Invariant inv_n = inv_n0;
        inv_n.bIIb += limite_inf_bIIb;
        double Qeps_n = Invariant0Qeps(inv_n);
        // stockage éventuel des invariants et du potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv.V;
           save_resulHyperD.invP->Qeps= Qeps_n;
           save_resulHyperD.invP->cos3phi= 0.;
           save_resulHyperD.invP->potentiel= pot.E;
         };
        PoGrenoble_V pot_V = PoGrenoble_et_V(Qeps_n,inv_n);
        // et pour la dérivée seconde de nouveau une petite variation
        inv_n.bIIb += limite_inf_bIIb;
        Qeps_n = Invariant0Qeps(inv_n);
        double E_n = PoGrenoble(Qeps_n,inv_n);
        // calcul de potret
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V * pot.EV  + pot.E);
        {double inter = (pot_V.E - pot.E);
         // on est obligé de faire ainsi car sinon on a des erreurs d'arrondi
         if (inter < ConstMath::trespetit)
            { potret.EbIIb = 0.; }
         else
            {potret.EbIIb = jacobien0 * inv.V * inter/limite_inf_bIIb;};
        };
//        potret.EbIIb = jacobien0 * inv.V * (pot_V.E - pot.E)/limite_inf_bIIb;
        // dérivées secondes
        potret.EVV = jacobien0 * (2. * pot.EV + inv.V * pot.EVV );
        {double inter = ((E_n + pot.E) - 2.*pot_V.E );
         // on est obligé de faire ainsi car sinon on a des erreurs d'arrondi
         if (inter < ConstMath::trespetit)
            { potret.EbIIb2 = 0.; }
         else
            {potret.EbIIb2 = jacobien0 * inv.V * inter
                         /(limite_inf_bIIb * limite_inf_bIIb);};
 //cout << "\n debug ((E_n + pot.E) - 2.*pot_V.E )= " << ((E_n + pot.E) - 2.*pot_V.E ) << endl;
        {double inter = (pot_V.EV - pot.EV);
         // on est obligé de faire ainsi car sinon on a des erreurs d'arrondi
         if (inter < ConstMath::trespetit)
            { potret.EbIIbV = potret.EbIIb / inv.V; }
         else
            {potret.EbIIbV = potret.EbIIb / inv.V
                          + jacobien0 * inv.V * inter / limite_inf_bIIb;};
        };
//         potret.EbIIbV =  potret.EbIIb / inv.V
//                          + jacobien0 * inv.V * (pot_V.EV - pot.EV) / limite_inf_bIIb;
        };
        // appel d'une vérification éventuelle
//+++verif***        Verif_Potentiel_et_var(inv,jacobien0,potret);
       }
    // retour                                 
    return potret;             
   }; 
    // calcul  du potentiel avec phase et dérivées avec  ses variations par rapport aux invariants
Hyper3D::PotenAvecPhaseAvecVar Hyper3D::PotentielPhase_et_var(const Invariant& inv,const double& jacobien0)
  { // en fait il s'agit du transfert du calcul du potentiel de la forme grenobloise à la forme standard
    // mais ce transfert n'est possible que si bIIb est non nulle, dans le cas contraire on utilise `
    // directement une technique de différence finie pour obtenir une dérivée numérique
    // def du retour
    PotenAvecPhaseAvecVar potret; // mise à 0 de tous les termes
    // récup du conteneur spécifique du point, pour sauvegarde éventuelle
    SaveResulHyperD & save_resulHyperD = *((SaveResulHyperD*) saveResul);
// cout << "\n " << potret.E; // pour avoir a cces en debug ??
    if ((Dabs(inv.bIIb) > limite_inf_bIIb)||avec_regularisation)
//    if (Dabs(inv.bIIb) > limite_inf_Qeps*limite_inf_Qeps) 
      { // calcul des invariants sous la nouvelle forme
        Invariant2QepsCosphi inv_spes = Invariant2Specif(inv);
        // calcul du potentiel sous la forme polaire
        PoGrenobleAvecPhaseAvecVar pot = PoGrenoblePhase_et_var(inv_spes,inv);
        // stockage éventuel des invariants et du potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv.V;
           save_resulHyperD.invP->Qeps= inv_spes.Qeps;
           save_resulHyperD.invP->cos3phi= inv_spes.cos3phi;
           save_resulHyperD.invP->potentiel= pot.E;
         };
//cout << "\n calcul normal";
//debug
//cout << "\n debug: Hyper3D::"
//     << " E="<<pot.E << "  pot.EV=" << pot.EV << " pot.EVV="<<pot.EVV<<endl;
//if (pot.E < 0)
//   cout << "\n pb ";
//fin debug
        // calcul de potret
        //dérivées premières
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V * ( pot.EV + pot.Ecos3phi * inv_spes.dcos3phidV) + pot.E);
        potret.EIeps = jacobien0 * inv.V * (pot.Ecos3phi * inv_spes.dcos3phidIeps);
        potret.EbIIb = jacobien0 * inv.V * (pot.EQ * inv_spes.dQepsdbIIb 
                      + pot.Ecos3phi * inv_spes.dcos3phidbIIb);
        // dérivées secondes
        double dcos3phidV_2 = inv_spes.dcos3phidV * inv_spes.dcos3phidV; // simplification
        double dcos3phidIeps_2 = inv_spes.dcos3phidIeps * inv_spes.dcos3phidIeps; //   "             
        double dcos3phidbIIb_2 = inv_spes.dcos3phidbIIb * inv_spes.dcos3phidbIIb; //   "             
        potret.EVV = jacobien0 * (2. * ( pot.Ecos3phi + inv.V * pot.EVcos3phi) * inv_spes.dcos3phidV
                     + 2. * pot.EV + inv.V * pot.EVV + inv.V * pot.Ecos3phi2 * dcos3phidV_2 
                     + inv.V * pot.Ecos3phi * inv_spes.dcos3phidV2);
        potret.EIeps2 = jacobien0 * inv.V * ( pot.Ecos3phi2 * dcos3phidIeps_2 + pot.Ecos3phi * inv_spes.dcos3phidIeps2);
        potret.EbIIb2 = jacobien0 * inv.V * ( pot.EQQ * inv_spes.dQepsdbIIb * inv_spes.dQepsdbIIb  
                        + 2. * pot.EQcos3phi * inv_spes.dQepsdbIIb * inv_spes.dcos3phidbIIb
                        + pot.Ecos3phi2 * dcos3phidbIIb_2
                        + pot.EQ * inv_spes.dQepsdbIIb2 +  pot.Ecos3phi * inv_spes.dcos3phidbIIb2); 
        potret.EIepsV = jacobien0 * (( pot.Ecos3phi + inv.V * pot.EVcos3phi) * inv_spes.dcos3phidIeps
                        + inv.V * pot.Ecos3phi2 * inv_spes.dcos3phidV * inv_spes.dcos3phidIeps);
        potret.EbIIbV = jacobien0 * ((pot.EQ + inv.V * pot.EQV) * inv_spes.dQepsdbIIb 
                        + (pot.Ecos3phi + inv.V * pot.EVcos3phi ) * inv_spes.dcos3phidbIIb
                        + inv.V * pot.EQcos3phi * inv_spes.dcos3phidV * inv_spes.dQepsdbIIb
                        + inv.V * pot.Ecos3phi2 * inv_spes.dcos3phidV * inv_spes.dcos3phidbIIb
                        + inv.V * pot.Ecos3phi * inv_spes.dcos3phidVdbIIb);
        potret.EbIIbIeps = jacobien0 * inv.V * ( pot.EQcos3phi * inv_spes.dcos3phidIeps * inv_spes.dQepsdbIIb
                        + pot.Ecos3phi2 * inv_spes.dcos3phidIeps * inv_spes.dcos3phidbIIb 
                        + pot.Ecos3phi * inv_spes.dcos3phidIepsdbIIb);

//   PotenAvecPhaseAvecVar toto = potret; // pour le debug
//   cout << "\n " <<  toto.E << " " << toto.EV; 
//  cout << "\n cas analytique ";
// --- pour le débug   
//   switch(fpclassify(toto.EV))
//    { case FP_NAN: case FP_INFINITE:
//        { // cas d'un nombre infini 
//          cout << "\n erreur valeur nan pour EV! ";
//          cout << " poret= " << potret.E; // pour que potret existe pour le débug
//        };
//        break;
//    };
    
// --- fin débug
        // appel d'une vérification éventuelle
//      Verif_Potentiel_et_var(inv,jacobien0,potret);
      }
      
// ---------------------------------------------------------------
// non, le calcul par différence finies vraiment ne marche pas !!! c'est la merde
// car le calcul normale est extrèmement sensible aux limites initiales limite_inf_Qeps et limite_inf_bIIb 
// la ça marche pour le cu mais peut-être pour un autre matériau ça ne marchera pas !!! 
// peut-être mettre en paramètre, mais c'est vraiment difficile à utiliser 
// bref à suivre ...
/*       
    else if (Dabs(inv.bIIb) > limite_inf_bIIb /10.)
      { // calcul des dérivées par différences finies
  cout << "\n cas difference fini avec phase ";
    
    Invariant inv_n0(inv.Ieps,inv.V,inv.bIIb,inv.bIIIb); // recopie des invariants sans les varddl 
    Invariant0QepsCosphi is_sp0 = Invariant0Specif(inv_n0);
    double E_n = PoGrenoble(is_sp0,inv_n0);  // la valeur du potentiel de référence
    // ici on est avec phase donc trois invariants indépendant V et Qeps et cos3phi,
    // pour calculer les variations on définit des points distants d'un incrément puis de deux incréments
    // pour les dérivées premières et secondes
    double delta = ConstMath::unpeupetit/100.;
    Invariant inv_et_dbIIb = inv_n0;inv_et_dbIIb.bIIb += delta;
    Invariant0QepsCosphi is_et_dbIIb = InvariantDe_V_bIIb_Ieps(inv_et_dbIIb);
    double E_et_dbIIb = PoGrenoble(is_et_dbIIb,inv_et_dbIIb);
    Invariant inv_et_dbIIb2 = inv_n0;inv_et_dbIIb2.bIIb += 2. * delta;
    Invariant0QepsCosphi is_et_dbIIb2 = InvariantDe_V_bIIb_Ieps(inv_et_dbIIb2);
    double E_et_dbIIb2 = PoGrenoble(is_et_dbIIb2,inv_et_dbIIb2);
    Invariant inv_et_dV = inv_n0;inv_et_dV.V += delta;
    Invariant0QepsCosphi is_et_dV = InvariantDe_V_bIIb_Ieps(inv_et_dV);
    double E_et_dV = PoGrenoble(is_et_dV,inv_et_dV);
    Invariant inv_et_dV2 = inv_n0;inv_et_dV2.V += 2. * delta;
    Invariant0QepsCosphi is_et_dV2 = InvariantDe_V_bIIb_Ieps(inv_et_dV2);
    double E_et_dV2 = PoGrenoble(is_et_dV2,inv_et_dV2);
    Invariant inv_et_dVdbIIb = inv_n0;
    inv_et_dVdbIIb.V += delta;
    inv_et_dVdbIIb.bIIb += delta;
    Invariant0QepsCosphi is_et_dVdbIIb = InvariantDe_V_bIIb_Ieps(inv_et_dVdbIIb);
    double E_et_dVdbIIb = PoGrenoble(is_et_dVdbIIb,inv_et_dVdbIIb);
    // cas avec Ieps
    
    Invariant inv_et_dIeps = inv_n0;inv_et_dIeps.Ieps += delta;
    Invariant0QepsCosphi is_et_dIeps = InvariantDe_V_bIIb_Ieps(inv_et_dIeps);
    double E_et_dIeps = PoGrenoble(is_et_dIeps,inv_et_dIeps);
    
    Invariant inv_et_dIeps2 = inv_n0;inv_et_dIeps2.Ieps += 2. * delta;
    Invariant0QepsCosphi is_et_dIeps2 = InvariantDe_V_bIIb_Ieps(inv_et_dIeps2);
    double E_et_dIeps2 = PoGrenoble(is_et_dIeps2,inv_et_dIeps2);
    
    Invariant inv_et_dIepsdbIIb = inv_n0;
    inv_et_dIepsdbIIb.Ieps += delta;
    inv_et_dIepsdbIIb.bIIb += delta;
    Invariant0QepsCosphi is_et_dIepsdbIIb = InvariantDe_V_bIIb_Ieps(inv_et_dIepsdbIIb);
    double E_et_dIepsdbIIb = PoGrenoble(is_et_dIepsdbIIb,inv_et_dIepsdbIIb);
    
    Invariant inv_et_dIepsdV = inv_n0;
    inv_et_dIepsdV.Ieps += delta;
    inv_et_dIepsdV.V += delta;
    Invariant0QepsCosphi is_et_dIepsdV = InvariantDe_V_bIIb_Ieps(inv_et_dIepsdV);
    double E_et_dIepsdV = PoGrenoble(is_et_dIepsdV,inv_et_dIepsdV);
    
    
    // calcul des dérivées premières
    potret.EV = jacobien0 *(E_et_dV * inv_et_dV.V - E_n * inv.V)/delta;
    potret.EbIIb = (jacobien0 * inv.V)*(E_et_dbIIb - E_n)/delta;
    potret.EIeps = (jacobien0 * inv.V)*(E_et_dIeps  - E_n )/delta;
    // calcul des dérivées secondes hors phases
    potret.EVV = jacobien0 *(E_et_dV2 * inv_et_dV2.V - 2.*E_et_dV * inv_et_dV.V + E_n * inv.V)
                   /(delta * delta);
    potret.EbIIb2 = (jacobien0 * inv.V)*(E_et_dbIIb2 - 2.*E_et_dbIIb + E_n) /(delta * delta);

    potret.EIeps2 = (jacobien0 * inv.V) *(E_et_dIeps2  - 2.*E_et_dIeps  + E_n )/(delta * delta);

    double E_V_a_dbIIb = jacobien0 * (E_et_dVdbIIb * inv_et_dVdbIIb.V - E_et_dbIIb * inv_et_dbIIb.V) /delta;
    potret.EbIIbV = ( E_V_a_dbIIb - potret.EV)/delta;
    
    double E_Ieps_a_dbIIb = (jacobien0 * inv.V) * (E_et_dIepsdbIIb  - E_et_dbIIb) /delta;
    potret.EbIIbIeps = ( E_Ieps_a_dbIIb - potret.EIeps)/delta;
    
    double E_Ieps_a_dV = jacobien0 * (E_et_dIepsdV * inv_et_dIepsdV.V - E_et_dV * inv.V) /delta;
    potret.EIepsV = ( E_Ieps_a_dV - potret.EIeps)/delta;
    
    		
    	}*/
/*    else if (Dabs(inv.bIIb) > ConstMath::petit)
      { // ici on calcul comme si on n'avait pas de phase
        // calcul des invariants sous la nouvelle forme
        Invariant2Qeps inv_spes = Invariant2SpecifSansPhase(inv);
        // calcul du potentiel sous la forme polaire
        PoGrenobleSansPhaseAvecVar pot = PoGrenoble_et_var(inv_spes,inv);
//  cout << "\n cas analytique sans phase ";
        // calcul de potret
        //dérivées premières
        potret.E = pot.E * inv.V * jacobien0;
        potret.EV = jacobien0 * (inv.V *  pot.EV  + pot.E);
        potret.EbIIb = jacobien0 * inv.V * pot.EQ * inv_spes.dQepsdbIIb; 
        // dérivées secondes
        potret.EVV = jacobien0 * (2. * pot.EV + inv.V * pot.EVV );
        potret.EbIIb2 = jacobien0 * inv.V * ( pot.EQQ * inv_spes.dQepsdbIIb * inv_spes.dQepsdbIIb 
                        + pot.EQ * inv_spes.dQepsdbIIb2 ); 
        potret.EbIIbV = jacobien0 * ((pot.EQ + inv.V * pot.EQV) * inv_spes.dQepsdbIIb);
        // appel d'une vérification éventuelle
//+++verif***        Verif_Potentiel_et_var(inv,jacobien0,potret);
       }*/
    else  // dernier cas avec un inv.bIIb vraiment petit
      // cas d'un calcul par différence finie, on considère que toute les dérivées suivant la phase
      // sont nulles dans ce cas, car de toutes manière on ne peut pas calculer la phase
      { // calcul des invariants sous la nouvelle forme
//  cout << "\n cas difference fini sans phase ";
        Invariant inv_n0(inv.Ieps,inv.V,inv.bIIb,inv.bIIIb);
        double Qeps = Invariant0Qeps(inv_n0);
        // calcul du potentiel sous la forme polaire au point actuel
        // ainsi que la variation première et seconde suivant V
        PoGrenoble_VV pot = PoGrenoble_et_VV(Qeps,inv_n0);
        // calcul du potentiel pour une petite variation suivant bIIb
        Invariant inv_n = inv_n0;
        double delta = limite_inf_bIIb; double unsurdelta = 1./delta;
        inv_n.bIIb += delta;
        Invariant0QepsCosphi inv_spes_n = Invariant0Specif(inv_n);
        // stockage éventuel des invariants et du potentiel
        if (sortie_post)
         { save_resulHyperD.invP->V= inv.V;
           save_resulHyperD.invP->Qeps= inv_spes_n.Qeps;
           save_resulHyperD.invP->cos3phi= inv_spes_n.cos3phi;
           save_resulHyperD.invP->potentiel= pot.E;
         };
        PoGrenoble_V pot_V = PoGrenoble_et_V(inv_spes_n,inv_n);
        // et pour la dérivée seconde de nouveau une petite variation
        inv_n.bIIb += delta;
        inv_spes_n = Invariant0Specif(inv_n);
        double E_n = PoGrenoble(inv_spes_n,inv_n);
        // calcul de potret
        potret.E = pot.E * inv.V * jacobien0;
        potret.Ks = pot.Ks;
        potret.EV = jacobien0 * (inv.V * pot.EV  + pot.E);
        potret.EbIIb = jacobien0 * inv.V * (pot.E - pot_V.E)*unsurdelta;
        // dérivées secondes
        potret.EVV = jacobien0 * (2. * pot.EV + inv.V * pot.EVV );
        potret.EbIIb2 = jacobien0 * inv.V * (E_n - 2.*pot_V.E + pot.E)
                        *unsurdelta*unsurdelta;
        potret.EbIIbV =  potret.EbIIb / inv.V 
                         + jacobien0 * inv.V * (pot_V.EV - pot.EV) *unsurdelta;
        // pour les dérivées selon l'angle tous les termes sont considéré nul
        potret.EIeps = 0.;
        potret.EIeps2 = 0.; potret.EIepsV = 0.; potret.EbIIbIeps = 0.;         
        // appel d'une vérification éventuelle
//        Verif_Potentiel_et_var(inv,jacobien0,potret);
      };
    // retour 
    
// --- debug --------
//cout << "\n E= " << potret.E << " EV= " << potret.EV << " EbIIb= " << potret.EbIIb << " EIeps= " << potret.EIeps
//     << "\n EVV= " << potret.EVV << " EbIIb2= " << potret.EbIIb2 << " EIeps2= " << potret.EIeps2
//     << "\n EbIIbIeps = " << potret.EbIIbIeps << " EIepsV= " << potret.EIepsV  << " EbIIbV= " << potret.EbIIbV << endl;

// ---- fin débug -------    
     
    return potret;             
   }; 
   
    // calcul de l'invariant Qeps seul valable même si Qeps est nul
double Hyper3D::Invariant0Qeps(const Invariant & inv)
 { // les nouveaux invariants
   double Qeps =  sqrt(2. * inv.bIIb);
//   if (avec_regularisation)
//    {Qeps += fact_regularisation;}
   return Qeps;
  };
  
    // calcul des invariants Qeps,cos3phi seuls
Hyper3D::Invariant0QepsCosphi Hyper3D::Invariant0Specif(const Invariant & inv)
 { Hyper3D::Invariant0QepsCosphi inv_ret; // def du retour
   // les nouveaux invariants
   inv_ret.Qeps = sqrt(2. * inv.bIIb);
   double inv_ret_Qeps = inv_ret.Qeps; // init pour être éventuellement modifié
     // ensuite avec la régularisation
   if (avec_regularisation)
    {inv_ret_Qeps += fact_regularisation;}
   double unsurQeps = 1./inv_ret_Qeps;  // pour simplifier
   // --- angle de phase
   double unsurQeps3 = unsurQeps * unsurQeps * unsurQeps;
   double troisracine6 = 3. * sqrt(6.);
   inv_ret.cos3phi = troisracine6 * inv.bIIIb * unsurQeps3;
   if (inv_ret.cos3phi > 1.) inv_ret.cos3phi=1.;
   if (inv_ret.cos3phi < -1.) inv_ret.cos3phi=-1.;
//debug
//cout << "\n inv_ret.cos3phi= "<<inv_ret.cos3phi << "Hyper3D::Invariant0Specif(" << endl;
//fin debug
   // retour
   return inv_ret;                     
  };

// calcul des invariants Qeps,cos3phi en fonction de V, bIIb Ieps
// on utilise pas l'invariant bIIIb, 
Hyper3D::Invariant0QepsCosphi Hyper3D::InvariantDe_V_bIIb_Ieps(const Invariant & inv)
 { Hyper3D::Invariant0QepsCosphi inv_ret; // def du retour
///******** en fait ça merdouille, le bIIIb calculé donne n'importe quoi quand c'est petit donc
/// a éviter !!! 
/// a défaut d'autre chose pour l'instant on utilise  Invariant0Specif
///
   // les nouveaux invariants
   inv_ret.Qeps = sqrt(2. * inv.bIIb); 
   double inv_ret_Qeps = inv_ret.Qeps; // init pour être éventuellement modifié
   double inv_V = inv.V; // init pour être éventuellement modifié
     // ensuite avec la régularisation
   if (avec_regularisation)
    {inv_ret_Qeps += fact_regularisation;
     inv_V += fact_regularisation;
    };
   double unsurQeps = 1./inv_ret_Qeps;  // pour simplifier
   // on recalcul bIIIb
   double bIIIb=-1./(8.*inv_V*inv_V) + 1./8.-1./4.*inv.Ieps+1./6.*inv.Ieps*inv.Ieps
                                    -1./27.*inv.Ieps*inv.Ieps*inv.Ieps 
                                    - 0.5*inv.bIIb+1./3.*inv.bIIb* inv.Ieps;   
   // --- angle de phase avec la valeur locale de bIIIb
   double unsurQeps3 = unsurQeps * unsurQeps * unsurQeps;
   double troisracine6 = 3. * sqrt(6.);
   inv_ret.cos3phi = troisracine6 * bIIIb * unsurQeps3;
   // on limite les valeurs au normal
   if (inv_ret.cos3phi > 1.) { inv_ret.cos3phi = 1.;}
   else if (inv_ret.cos3phi < -1.) { inv_ret.cos3phi = -1.;};
//debug
//cout << "\n inv_ret.cos3phi= "<<inv_ret.cos3phi << "Hyper3D::InvariantDe_V_bIIb_Ieps(" << endl;
//fin debug
   // retour
   return inv_ret;                     
  };
    

    // calcul de l'invariants Qeps ainsi que sa variation par rapport
    // à  bIIb (Qeps doit être non nul)
Hyper3D::InvariantQeps Hyper3D::InvariantSpecifSansPhase(const Invariant & inv)
 { Hyper3D::InvariantQeps inv_ret; // def du retour
   // tout d'abord le nouvel invariant
   inv_ret.Qeps = sqrt(2. * inv.bIIb); 
   // maintenant la variation
   if (avec_regularisation)
    {inv_ret.dQepsdbIIb = 1./(inv_ret.Qeps+fact_regularisation);}
   else
    {inv_ret.dQepsdbIIb = 1./inv_ret.Qeps;};
   // retour
   return inv_ret;                     
  };

    // calcul des invariants Qeps,cos3phi, ainsi que leur variation par rapport
    // aux trois invariants Ieps, V et bIIb
Hyper3D::InvariantQepsCosphi Hyper3D::InvariantSpecif(const Invariant & inv)
 { Hyper3D::InvariantQepsCosphi inv_ret; // def du retour
   // tout d'abord les nouveaux invariants
   inv_ret.Qeps = sqrt(2. * inv.bIIb); 
   double inv_V = inv.V; // init pour être éventuellement modifié
   double unsurQeps; // init = 1./inv_ret.Qeps;  // pour simplifier
   if (avec_regularisation)
        {unsurQeps = 1./(inv_ret.Qeps+fact_regularisation);
         inv_V += fact_regularisation;
        }
   else {unsurQeps = 1./inv_ret.Qeps;};
   // maintenant les variations / pour Qeps
   double untiers = 1./3.;
   inv_ret.dQepsdbIIb = unsurQeps;
   // --- angle de phase
   // dans le cas ou Qeps est trop petit on laisse les 0
   if ((inv_ret.Qeps >= limite_inf_Qeps)||(avec_regularisation))
    { double unsurQeps3 = unsurQeps * unsurQeps * unsurQeps;
      double unsurQeps5 = unsurQeps3 * unsurQeps * unsurQeps;
      double troisracine6 = 3. * sqrt(6.);
      double neufracine6 = 3. * troisracine6;
      inv_ret.cos3phi = troisracine6 * inv.bIIIb * unsurQeps3;
      if (inv_ret.cos3phi > 1.) inv_ret.cos3phi=1.;
      if (inv_ret.cos3phi < -1.) inv_ret.cos3phi=-1.;
      // puis les variations
      inv_ret.dcos3phidV = troisracine6 / 4. * unsurQeps3 /(inv_V * inv_V * inv_V);
      inv_ret.dcos3phidIeps = troisracine6  * unsurQeps3 * (-0.25 + inv.bIIb*untiers 
                              + inv.Ieps*untiers - inv.Ieps * inv.Ieps/9.);
      inv_ret.dcos3phidbIIb = - neufracine6  * unsurQeps5 * inv.bIIIb
                             + troisracine6  * unsurQeps3 * (inv.Ieps*untiers - 0.5); 
    };
//debug
//cout << "\n inv_ret.cos3phi= "<<inv_ret.cos3phi << "Hyper3D::InvariantSpecif(" << endl;
//fin debug
   // retour
   return inv_ret;                                       
  };

    // calcul de l'invariants Qeps ainsi que ses variations première et seconde
    // par rapport à bIIb (Qeps doit être non nul)
Hyper3D::Invariant2Qeps Hyper3D::Invariant2SpecifSansPhase(const Invariant & inv)
 { Hyper3D::Invariant2Qeps inv_ret; // def du retour
   // tout d'abord les nouveaux invariants
   inv_ret.Qeps = sqrt(2. * inv.bIIb); 
   double unsurQeps; // init = 1./inv_ret.Qeps;  // pour simplifier
   if (avec_regularisation)
        {unsurQeps = 1./(inv_ret.Qeps+fact_regularisation);}
   else {unsurQeps = 1./inv_ret.Qeps;};
//   double unsurQeps = 1./inv_ret.Qeps;  // pour simplifier
   // maintenant les variations
   inv_ret.dQepsdbIIb = unsurQeps;
   // et les variations secondes
   inv_ret.dQepsdbIIb2 = -1. * unsurQeps * unsurQeps * unsurQeps; 
   // retour
   return inv_ret;                     
  };


    // calcul des invariants Qeps,cos3phi, ainsi que leur variation première et seconde
    // par rapport aux trois invariants Ieps, V et bIIb
Hyper3D::Invariant2QepsCosphi Hyper3D::Invariant2Specif(const Invariant & inv)
 { Hyper3D::Invariant2QepsCosphi inv_ret; // def du retour
   // tout d'abord les nouveaux invariants
   inv_ret.Qeps = sqrt(2. * inv.bIIb); 
   double unsurQeps; // init = 1./inv_ret.Qeps;  // pour simplifier
   double inv_V = inv.V; // init pour être éventuellement modifié
   if (avec_regularisation)
        {unsurQeps = 1./(inv_ret.Qeps+fact_regularisation);
         inv_V += fact_regularisation;
        }
   else {unsurQeps = 1./inv_ret.Qeps;};
//   double unsurQeps = 1./inv_ret.Qeps;  // pour simplifier
   // et les variations / Qeps
   double untiers = 1./3.;
   inv_ret.dQepsdbIIb = unsurQeps;
   double unsurQeps3 = unsurQeps * unsurQeps * unsurQeps;
   inv_ret.dQepsdbIIb2 = -1. * unsurQeps3; 
   // --- angle de phase
   double unsurQeps5 = unsurQeps3 * unsurQeps * unsurQeps;
   double unsurQeps7 = unsurQeps5 * unsurQeps * unsurQeps;
   double racine6=sqrt(6.);
   double troisracine6 = 3. * racine6;
   double neufracine6 = 3. * troisracine6;
   inv_ret.cos3phi = troisracine6 * inv.bIIIb * unsurQeps3;
   if (inv_ret.cos3phi > 1.) inv_ret.cos3phi=1.;
   if (inv_ret.cos3phi < -1.) inv_ret.cos3phi=-1.;
  
   double unsurV3 = 1. / (inv_V * inv_V * inv_V);
   
   // maintenant les variations
   inv_ret.dcos3phidV = troisracine6 * unsurQeps3 * unsurV3 / 4. ;
   inv_ret.dcos3phidIeps = troisracine6  * unsurQeps3 * (-0.25 + inv.bIIb*untiers 
                           + inv.Ieps*untiers - inv.Ieps * inv.Ieps/9.);
   inv_ret.dcos3phidbIIb = - neufracine6  * unsurQeps5 * inv.bIIIb
                      + troisracine6  * unsurQeps3 * (inv.Ieps*untiers - 0.5);
   // les variations secondes
   inv_ret.dcos3phidV2 = - neufracine6 * unsurQeps3 * unsurV3 / (4. * inv_V);
   inv_ret.dcos3phidIeps2 = troisracine6 * unsurQeps3 * (1./3. - 2./9. * inv.Ieps);
   inv_ret.dcos3phidbIIb2 = 15. * troisracine6 * inv.bIIIb * unsurQeps7 
                           - 2.*neufracine6  * unsurQeps5 * (untiers * inv.Ieps - 0.5); 
   inv_ret.dcos3phidVdbIIb = - neufracine6 * unsurQeps5 * unsurV3 * 0.25;
   inv_ret.dcos3phidIepsdbIIb = racine6 * unsurQeps3  
                                - neufracine6 * unsurQeps5   
                            * (-0.25 + inv.bIIb*untiers + untiers * inv.Ieps 
                               - 1./9. * inv.Ieps * inv.Ieps );   
//debug
//cout << "\n inv_ret.cos3phi= "<<inv_ret.cos3phi << "Hyper3D::Invariant2Specif(" << endl;
//fin debug
   // retour
   return inv_ret;                     
  };

             
///=============== fonctions pour la vérification et la mise au point ===============
    
    // vérif des dérivées du potentiels par rapport aux invariants, ceci par différences finies
void Hyper3D::Verif_Potentiel_et_var(const InvariantVarDdl& inv,const double& jacobien0
                                     ,const PotenSansPhaseAvecVar& potret )
  { // dans le cas du premier passage on indique qu'il y a vérification
    if (indic_Verif_Potentiel_et_var == 0)
     { cout << "\n ****verification des derivees du potentiels par rapport aux invariants****";
       cout << "\n Hyper3D::Verif_Potentiel_et_var \n";
      } 
    indic_Verif_Potentiel_et_var++;
  
    // potret contiend le potentiel et ses variations première et seconde
    // on va calculer ces mêmes variations par différences finies et comparer les deux résultats
    // calcul des invariants sous la nouvelle forme
    
    double toto = potret.E; // pour que le débugger affiche potret
    
    Invariant inv_n0(inv.Ieps,inv.V,inv.bIIb,inv.bIIIb); // recopie des invariants sans les varddl 
    double Qeps = Invariant0Qeps(inv_n0);  
    double E_n = PoGrenoble(Qeps,inv_n0);  // la valeur du potentiel de référence
    // ici on est sans phase donc deux invariants indépendant V et Qeps,
    // pour calculer les variations on définit des points distants d'un incrément puis de deux incréments
    // pour les dérivées premières et secondes
    double delta = limite_inf_bIIb;
    double mini_val = ConstMath::pasmalpetit;
    Invariant inv_et_dbIIb = inv_n0;inv_et_dbIIb.bIIb += delta;
    double Qeps_et_dbIIb = Invariant0Qeps(inv_et_dbIIb);
    double E_et_dbIIb = PoGrenoble(Qeps_et_dbIIb,inv_et_dbIIb);
    Invariant inv_et_dbIIb2 = inv_n0;inv_et_dbIIb2.bIIb += 2. * delta;
    double Qeps_et_dbIIb2 = Invariant0Qeps(inv_et_dbIIb2);
    double E_et_dbIIb2 = PoGrenoble(Qeps_et_dbIIb2,inv_et_dbIIb2);
    Invariant inv_et_dV = inv_n0;inv_et_dV.V += delta;
    double Qeps_et_dV = Invariant0Qeps(inv_et_dV);
    double E_et_dV = PoGrenoble(Qeps_et_dV,inv_et_dV);
    Invariant inv_et_dV2 = inv_n0;inv_et_dV2.V += 2. * delta;
    double Qeps_et_dV2 = Invariant0Qeps(inv_et_dV2);
    double E_et_dV2 = PoGrenoble(Qeps_et_dV2,inv_et_dV2);
    Invariant inv_et_dVdbIIb = inv_n0;
    inv_et_dVdbIIb.V += delta;
    inv_et_dVdbIIb.bIIb += delta;
    double Qeps_et_dVdbIIb = Invariant0Qeps(inv_et_dVdbIIb);
    double E_et_dVdbIIb = PoGrenoble(Qeps_et_dVdbIIb,inv_et_dVdbIIb);
    // calcul des dérivées premières
    double E_V = jacobien0 *(E_et_dV * inv_et_dV.V - E_n * inv.V)/delta;
    double E_bIIb = (jacobien0 * inv.V)*(E_et_dbIIb - E_n)/delta;
    // calcul des dérivées secondes
    double E_V2 = jacobien0 *(E_et_dV2 * inv_et_dV2.V - 2.*E_et_dV * inv_et_dV.V + E_n * inv.V)
                   /(delta * delta);
    double E_bIIb2 = (jacobien0 * inv.V)*(E_et_dbIIb2 - 2.*E_et_dbIIb + E_n)
                     /(delta * delta);
    double E_V_a_dbIIb = jacobien0 * (E_et_dVdbIIb * inv_et_dVdbIIb.V - E_et_dbIIb * inv.V)
                         /delta;
    double E_VbIIb = ( E_V_a_dbIIb - E_V)/delta;
    // comparaison avec les valeurs de dérivées analytiques
    int erreur = 0;
    
    if (diffpourcent(potret.EV,E_V,E_V,0.05)) 
     { if (MiN(Dabs(potret.EV),Dabs(E_V)) <= mini_val)
         {if( MaX(Dabs(potret.EV),Dabs(E_V)) > 50.*delta)
           if (Dabs(potret.EV) == 0.)
           // on regarde si la dérivée numérique tend vers zéro lorque l'incrément tend vers 0
            { 
             Invariant inv_et_ddV = inv_n0;inv_et_ddV.V += delta/10.;
             double Qeps_et_ddV = Invariant0Qeps(inv_et_ddV);
             double E_et_ddV = PoGrenoble(Qeps_et_ddV,inv_et_ddV);
             double E_ddV = jacobien0 *(E_et_ddV * inv_et_ddV.V - E_n * inv.V)/(delta*10.);
             if (10.* Dabs(E_ddV) > Dabs(E_V)) erreur = 5;
             }
            else {erreur = 5;cout << " \n err5: potret.EV= " << potret.EV << " E_V= " << E_V;}
          else {erreur = 52;cout << " \n err52: potret.EV= " << potret.EV << " E_V= " << E_V;};
         } 
      else {erreur = 53;cout << " \n err53: potret.EV= " << potret.EV << " E_V= " << E_V;};
     };
      
// cout << " \n info: potret.EV= " << potret.EV << " E_V= " << E_V;      
      
      
    if (diffpourcent(potret.EbIIb,E_bIIb,E_bIIb,0.05)) 
     {if (MiN(Dabs(potret.EbIIb),Dabs(E_bIIb)) <= mini_val)
         {if( MaX(Dabs(potret.EbIIb),Dabs(E_bIIb)) > 50.*delta) 
         	{erreur = 1;cout << " \n err 1: potret.EbIIb= " << potret.EbIIb << " E_bIIb= " << E_bIIb;}
         }
      else {erreur = 11;cout << " \n err11: potret.EbIIbV= " << potret.EbIIbV << " E_VbIIb= " << E_VbIIb;};
     };
    if (diffpourcent(potret.EbIIb2,E_bIIb2,E_bIIb2,0.05)) 
     {if (MiN(Dabs(potret.EbIIb2),Dabs(E_bIIb2)) <= mini_val)
         {if( MaX(Dabs(potret.EbIIb2),Dabs(E_bIIb2)) > 50.*delta) 
         	{erreur = 2;cout << " \n err 2: potret.EbIIb2= " << potret.EbIIb2 << " E_bIIb2= " << E_bIIb2;}
         }
      else {erreur = 21;cout << " \n err21: potret.EbIIb2= " << potret.EbIIb2 << " E_bIIb2= " << E_bIIb2;};
     };
    if (diffpourcent(potret.EVV,E_V2,E_V2,0.05)) 
     {if (MiN(Dabs(potret.EVV),Dabs(E_V2)) <= mini_val)
         {if( MaX(Dabs(potret.EVV),Dabs(E_V2)) > 50.*delta) 
         	{erreur = 3;cout << " \n err 3: potret.EVV= " << potret.EVV << " E_V2= " << E_V2;}
         }
      else {erreur = 31;cout << " \n err31: potret.EVV= " << potret.EVV << " E_V2= " << E_V2;};
     };
   if (diffpourcent(potret.EbIIbV,E_VbIIb,E_VbIIb,0.05)) 
     {if (MiN(Dabs(potret.EbIIbV),Dabs(E_VbIIb)) <= mini_val)
         {if( MaX(Dabs(potret.EbIIbV),Dabs(E_VbIIb)) > 50.*delta) 
         	{erreur = 4;cout << " \n err 4: potret.EbIIbV= " << potret.EbIIbV << " E_VbIIb= " << E_VbIIb;}
         }
      else {erreur = 41;cout << " \n err41: potret.EbIIbV= " << potret.EbIIbV << " E_VbIIb= " << E_VbIIb;};
     };

//    if (erreur)
//     { cout << "\n erreur dans le calcul analytique des dérivées du potentiel";
//       cout << "\n Hyper3D::Verif_Potentiel_et_var, numéro d'appel = " 
//            << indic_Verif_Potentiel_et_var;
//       Sortie(1);
//      } 
 };

// vérif des dérivées du potentiels par rapport aux invariants, ceci par différences finies
// cas avec la phase
void Hyper3D::Verif_Potentiel_et_var(const InvariantVarDdl& inv,const double& jacobien0
                                 ,const PotenAvecPhaseAvecVar& potret )
  { // dans le cas du premier passage on indique qu'il y a vérification
    if (indic_Verif_Potentiel_et_var == 0)
     { cout << "\n ****verification des derivees du potentiels par rapport aux invariants****";
       cout << "\n Hyper3D::Verif_Potentiel_et_var \n";
      } 
    indic_Verif_Potentiel_et_var++;
  
    // potret contiend le potentiel et ses variations première et seconde
    // on va calculer ces mêmes variations par différences finies et comparer les deux résultats
    // calcul des invariants sous la nouvelle forme
    
    double toto = potret.E; // pour que le débugger affiche potret
    
    Invariant inv_n0(inv.Ieps,inv.V,inv.bIIb,inv.bIIIb); // recopie des invariants sans les varddl 
    Invariant0QepsCosphi is_sp0 = Invariant0Specif(inv_n0);
    double E_n = PoGrenoble(is_sp0,inv_n0);  // la valeur du potentiel de référence
    // ici on est avec phase donc trois invariants indépendant V et Qeps et cos3phi,
    // pour calculer les variations on définit des points distants d'un incrément puis de deux incréments
    // pour les dérivées premières et secondes
    double delta = limite_inf_bIIb;
    double mini_val = ConstMath::pasmalpetit;
    Invariant inv_et_dbIIb = inv_n0;inv_et_dbIIb.bIIb += delta;
    Invariant0QepsCosphi is_et_dbIIb = Invariant0Specif(inv_et_dbIIb);
    double E_et_dbIIb = PoGrenoble(is_et_dbIIb,inv_et_dbIIb);
    Invariant inv_et_dbIIb2 = inv_n0;inv_et_dbIIb2.bIIb += 2. * delta;
    Invariant0QepsCosphi is_et_dbIIb2 = Invariant0Specif(inv_et_dbIIb2);
    double E_et_dbIIb2 = PoGrenoble(is_et_dbIIb2,inv_et_dbIIb2);
    Invariant inv_et_dV = inv_n0;inv_et_dV.V += delta;
    Invariant0QepsCosphi is_et_dV = Invariant0Specif(inv_et_dV);
    double E_et_dV = PoGrenoble(is_et_dV,inv_et_dV);
    Invariant inv_et_dV2 = inv_n0;inv_et_dV2.V += 2. * delta;
    Invariant0QepsCosphi is_et_dV2 = Invariant0Specif(inv_et_dV2);
    double E_et_dV2 = PoGrenoble(is_et_dV2,inv_et_dV2);
    Invariant inv_et_dVdbIIb = inv_n0;
    inv_et_dVdbIIb.V += delta;
    inv_et_dVdbIIb.bIIb += delta;
    Invariant0QepsCosphi is_et_dVdbIIb = Invariant0Specif(inv_et_dVdbIIb);
    double E_et_dVdbIIb = PoGrenoble(is_et_dVdbIIb,inv_et_dVdbIIb);
    // cas avec Ieps
    
    Invariant inv_et_dIeps = inv_n0;inv_et_dIeps.Ieps += delta;
    Invariant0QepsCosphi is_et_dIeps = Invariant0Specif(inv_et_dIeps);
    double E_et_dIeps = PoGrenoble(is_et_dIeps,inv_et_dIeps);
    
    Invariant inv_et_dIeps2 = inv_n0;inv_et_dIeps2.Ieps += 2. * delta;
    Invariant0QepsCosphi is_et_dIeps2 = Invariant0Specif(inv_et_dIeps2);
    double E_et_dIeps2 = PoGrenoble(is_et_dIeps2,inv_et_dIeps2);
    
    Invariant inv_et_dIepsdbIIb = inv_n0;
    inv_et_dIepsdbIIb.Ieps += delta;
    inv_et_dIepsdbIIb.bIIb += delta;
    Invariant0QepsCosphi is_et_dIepsdbIIb = Invariant0Specif(inv_et_dIepsdbIIb);
    double E_et_dIepsdbIIb = PoGrenoble(is_et_dIepsdbIIb,inv_et_dIepsdbIIb);
    
    Invariant inv_et_dIepsdV = inv_n0;
    inv_et_dIepsdV.Ieps += delta;
    inv_et_dIepsdV.V += delta;
    Invariant0QepsCosphi is_et_dIepsdV = Invariant0Specif(inv_et_dIepsdV);
    double E_et_dIepsdV = PoGrenoble(is_et_dIepsdV,inv_et_dIepsdV);
    
    
    // calcul des dérivées premières

    // calcul des dérivées premières
    double E_V = jacobien0 *(E_et_dV * inv_et_dV.V - E_n * inv.V)/delta;
    double E_bIIb = (jacobien0 * inv.V)*(E_et_dbIIb - E_n)/delta;
    double E_Ieps = (jacobien0 * inv.V)*(E_et_dIeps  - E_n )/delta;
    // calcul des dérivées secondes hors phases
    double E_V2 = jacobien0 *(E_et_dV2 * inv_et_dV2.V - 2.*E_et_dV * inv_et_dV.V + E_n * inv.V)
                   /(delta * delta);
    double E_bIIb2 = (jacobien0 * inv.V)*(E_et_dbIIb2 - 2.*E_et_dbIIb + E_n) /(delta * delta);

    double E_Ieps2 = (jacobien0 * inv.V) *(E_et_dIeps2  - 2.*E_et_dIeps  + E_n )/(delta * delta);

    double E_V_a_dbIIb = jacobien0 * (E_et_dVdbIIb * inv_et_dVdbIIb.V - E_et_dbIIb * inv_et_dbIIb.V) /delta;
    double E_VbIIb = ( E_V_a_dbIIb - potret.EV)/delta;
    
    double E_Ieps_a_dbIIb = (jacobien0 * inv.V) * (E_et_dIepsdbIIb  - E_et_dbIIb) /delta;
    double E_bIIbIeps = ( E_Ieps_a_dbIIb - potret.EIeps)/delta;
    
    double E_Ieps_a_dV = jacobien0 * (E_et_dIepsdV * inv_et_dIepsdV.V - E_et_dV * inv.V) /delta;
    double E_IepsV = ( E_Ieps_a_dV - potret.EIeps)/delta;
    
    // comparaison avec les valeurs de dérivées analytiques
    int erreur = 0;
    
    if (diffpourcent(potret.EV,E_V,E_V,0.05)) 
     {if (MiN(Dabs(potret.EV),Dabs(E_V)) <= mini_val)
         {if( MaX(Dabs(potret.EV),Dabs(E_V)) > 50.*delta)
           if (Dabs(potret.EV) == 0.)
           // on regarde si la dérivée numérique tend vers zéro lorque l'incrément tend vers 0
            { 
             Invariant inv_et_ddV = inv_n0;inv_et_ddV.V += delta/10.;
             double Qeps_et_ddV = Invariant0Qeps(inv_et_ddV);
             double E_et_ddV = PoGrenoble(Qeps_et_ddV,inv_et_ddV);
             double E_ddV = jacobien0 *(E_et_ddV * inv_et_ddV.V - E_n * inv.V)/(delta*10.);
             if (10.* Dabs(E_ddV) > Dabs(E_V)) erreur = 5;
             }
            else {erreur = 5;cout << " \n err5: potret.EV= " << potret.EV << " E_V= " << E_V;}
          else {erreur = 52;cout << " \n err52: potret.EV= " << potret.EV << " E_V= " << E_V;};
         } 
      else 
       {erreur = 53;cout << " \n err53: potret.EV= " << potret.EV << " E_V= " << E_V;};
     };
    if (diffpourcent(potret.EbIIb,E_bIIb,E_bIIb,0.05))
     {if (MiN(Dabs(potret.EbIIb),Dabs(E_bIIb)) <= mini_val)
         {if( MaX(Dabs(potret.EbIIb),Dabs(E_bIIb)) > 50.*delta) 
         	{erreur = 1;cout << " \n err 1: potret.EbIIb= " << potret.EbIIb << " E_bIIb= " << E_bIIb;}
         }
      else {erreur = 11;cout << " \n err 11: potret.EbIIbV= " << potret.EbIIbV << " E_VbIIb= " << E_VbIIb;};
     };
    if (diffpourcent(potret.EbIIb2,E_bIIb2,E_bIIb2,0.05))
     {if (MiN(Dabs(potret.EbIIb2),Dabs(E_bIIb2)) <= mini_val)
         {if( MaX(Dabs(potret.EbIIb2),Dabs(E_bIIb2)) > 50.*delta) 
         	{erreur = 2;cout << " \n err 2: potret.EbIIb2= " << potret.EbIIb2 << " E_bIIb2= " << E_bIIb2;}
         }
      else {erreur = 21;cout << " \n err 21: potret.EbIIb2= " << potret.EbIIb2 << " E_bIIb2= " << E_bIIb2;};
     };
    if (diffpourcent(potret.EVV,E_V2,E_V2,0.05))
     {if (MiN(Dabs(potret.EVV),Dabs(E_V2)) <= mini_val)
         {if( MaX(Dabs(potret.EVV),Dabs(E_V2)) > 50.*delta) 
         	{erreur = 3;cout << " \n err 3: potret.EVV= " << potret.EVV << " E_V2= " << E_V2;}
         }
      else {erreur = 31;cout << " \n err 31: potret.EVV= " << potret.EVV << " E_V2= " << E_V2;};
     };
    if (diffpourcent(potret.EbIIbV,E_VbIIb,E_VbIIb,0.05))
     {if (MiN(Dabs(potret.EbIIbV),Dabs(E_VbIIb)) <= mini_val)
         {if( MaX(Dabs(potret.EbIIbV),Dabs(E_VbIIb)) > 50.*delta) 
         	{erreur = 4;cout << " \n err 4: potret.EbIIbV= " << potret.EbIIbV << " E_VbIIb= " << E_VbIIb;}
         }
      else {erreur = 41;cout << " \n err 41: potret.EbIIbV= " << potret.EbIIbV << " E_VbIIb= " << E_VbIIb;};
     };

    if (diffpourcent(potret.EIeps,E_Ieps,E_Ieps,0.05)) 
     {if (MiN(Dabs(potret.EIeps),Dabs(E_Ieps)) <= mini_val)
         {if( MaX(Dabs(potret.EIeps),Dabs(E_Ieps)) > 50.*delta) 
         	{erreur = 6;cout << " \n err 6: potret.EIeps= " << potret.EIeps << " E_Ieps= " << E_Ieps;}
         }
      else {erreur = 61;cout << " \n err 61: potret.EIeps= " << potret.EIeps << " E_Ieps= " << E_Ieps;};
     };

    if (diffpourcent(potret.EIeps2,E_Ieps2,E_Ieps2,0.05)) 
     {if (MiN(Dabs(potret.EIeps2),Dabs(E_Ieps2)) <= mini_val)
         {if( MaX(Dabs(potret.EIeps2),Dabs(E_Ieps2)) > 50.*delta) 
         	{erreur = 7;cout << " \n err 7: potret.EIeps2= " << potret.EIeps2 << " E_Ieps2= " << E_Ieps2;}
         }
      else {erreur = 71;cout << " \n err 71: potret.EIeps2= " << potret.EIeps2 << " E_Ieps2= " << E_Ieps2;};
     };
   
    if (diffpourcent(potret.EbIIbIeps,E_bIIbIeps,E_bIIbIeps,0.05)) 
     {if (MiN(Dabs(potret.EbIIbIeps),Dabs(E_bIIbIeps)) <= mini_val)
         {if( MaX(Dabs(potret.EbIIbIeps),Dabs(E_bIIbIeps)) > 50.*delta) 
         	{erreur = 8;cout << " \n err 8: potret.EbIIbIeps= " << potret.EbIIbIeps << " E_bIIbIeps= " << E_bIIbIeps;}
         }
      else {erreur = 81;cout << " \n err 81: potret.EbIIbIeps= " << potret.EbIIbIeps << " E_bIIbIeps= " << E_bIIbIeps;};
     };

    if (diffpourcent(potret.EIepsV,E_IepsV,E_IepsV,0.05)) 
     {if (MiN(Dabs(potret.EIepsV),Dabs(E_IepsV)) <= mini_val)
         {if( MaX(Dabs(potret.EIepsV),Dabs(E_IepsV)) > 50.*delta) 
         	{erreur = 9;cout << " \n err 9: potret.EIepsV= " << potret.EIepsV << " E_IepsV= " << E_IepsV;}
         }
      else {erreur = 91;cout << " \n err 91: potret.EIepsV= " << potret.EIepsV << " E_IepsV= " << E_IepsV;};
     };
/*    if (erreur)
     { cout << "\n erreur dans le calcul analytique des derivees du potentiel";
       cout << "\n Hyper3D::Verif_Potentiel_et_var, numero d'appel = " 
            << indic_Verif_Potentiel_et_var << " erreur = " << erreur << endl;
       Sortie(1);
      }*/ 
 };
