
// FICHIER : Hysteresis3D.cc
// CLASSE : Hysteresis3D


// 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-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.


//#include "Debug.h"

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

#include "Hysteresis3D.h"

 // ========== codage des METHODES VIRTUELLES  protegees:================
        // calcul des contraintes 
void Hysteresis3D::Calcul_SigmaHH (TenseurHH & sigHH_t,TenseurBB& ,DdlElement & tab_ddl,
             TenseurBB & ,TenseurHH & ,BaseB& ,BaseH& ,TenseurBB&  epsBB_,
             TenseurBB& delta_epsBB_,TenseurBB & gijBB_,
		  	 TenseurHH & gijHH_,Tableau <TenseurBB *>& d_gijBB_,double& ,double& ,
		  	  TenseurHH & sigHH_
		  	,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double&  module_cisaillement
		  	,const Met_abstraite::Expli_t_tdt& )
 {   
    #ifdef MISE_AU_POINT
    if (epsBB_.Dimension() != 3)
       { cout << "\nErreur : la dimension devrait etre 3 !\n";
         cout << " Hysteresis3D::Calcul_SigmaHH\n";
         Sortie(1);
       };
    if (tab_ddl.NbDdl() != d_gijBB_.Taille())
       { cout << "\nErreur : le nb de ddl est != de la taille de d_gijBB_  !\n";
         cout << " Hysteresis3D::Calcul_SigmaHH\n";
         Sortie(1);
       };
    #endif

    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_); // passage en dim 3
    const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_); // passage en dim 3
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_); //   "      "  "  "
    const Tenseur3BB & gijBB = *((Tenseur3BB*) &gijBB_); //   "      "  "  "
    Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_);  //   "      "  "  "
//    Tenseur3HH & sigHH_i = *((Tenseur3HH*) &sigHH_t);  //   "      "  "  "
    SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) saveResul);
    // initialisation des variables de travail
    save_resul.Init_debut_calcul();
    // initialisation éventuelle des variables thermo-dépendantes
    Init_thermo_dependance();
    
    // cas d'une dépendance à la phase de la déformation totale
    if (avec_phase_paradefEqui || avec_phaseEps)
      { xnp = xnp_lue; xmu = xmu_lue; Qzero = Qzero_lue;
	       ParaMateriauxAvecPhaseEpsilon(gijHH,epsBB,xnp,xmu,Qzero);
      };
    
    // === 1 == calcul de l'avancement temporel sur 1 pas,
    int cas = 1; // cas normal avec dérivée de Jauman
//   try { // débug
    Avancement_temporel(delta_epsBB,gijHH,gijBB,cas,save_resul,sigHH,energ_t,energ);
// débug---------
/*      }
    catch (ErrNonConvergence_loiDeComportement excep) 
       { // initialisation des variables de travail
         save_resul.Init_debut_calcul();
         // initialisation éventuelle des variables thermo-dépendantes
         Init_thermo_dependance();
         Avancement_temporel(delta_epsBB,gijHH,cas,save_resul,sigHH,energ_t,energ);
         }
    catch ( ... )  
       { // initialisation des variables de travail
         save_resul.Init_debut_calcul();
         // initialisation éventuelle des variables thermo-dépendantes
         Init_thermo_dependance();
         Avancement_temporel(delta_epsBB,gijHH,cas,save_resul,sigHH,energ_t,energ);
         }
*/			 
//    Verif_coincidence(delta_epsBB,gijHH,cas,save_resul,sigHH,energ_t,energ,true);
// fin débug -------------
    // on libère les tenseurs intermédiaires        
    LibereTenseur();LibereTenseurQ();        
 };
        
        // calcul des contraintes a t+dt et de ses variations  
void Hysteresis3D::Calcul_DsigmaHH_tdt (TenseurHH & sigHH_t,TenseurBB& ,DdlElement & tab_ddl
            ,BaseB& ,TenseurBB & ,TenseurHH &
            ,BaseB& ,Tableau <BaseB> & ,BaseH& ,Tableau <BaseH> &
            ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *>& d_epsBB,TenseurBB & delta_epsBB_
		          ,TenseurBB & gijBB_tdt ,TenseurHH & gijHH_tdt
		          ,Tableau <TenseurBB *>& d_gijBB_tdt
		  	       ,Tableau <TenseurHH *>& d_gijHH_tdt,double& ,double&
		  	       ,Vecteur& ,TenseurHH& sigHH_tdt,Tableau <TenseurHH *>& d_sigHH
		  	       ,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite
            ,double&  module_cisaillement,const Met_abstraite::Impli& )
 {
    #ifdef MISE_AU_POINT
     if (epsBB_tdt.Dimension() != 3)
        { cout << "\nErreur : la dimension devrait etre 3 !\n";
       cout << " Hysteresis3D::Calcul_DsigmaHH_tdt\n";
       Sortie(1);
     };
     if (tab_ddl.NbDdl() != d_gijBB_tdt.Taille())
        { cout << "\nErreur : le nb de ddl est != de la taille de d_gijBB_tdt  !\n";
       cout << " Hysteresis3D::Calcul_DsigmaHH_tdt\n";
       Sortie(1);
     };
    #endif

    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
    const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_); // passage en dim 3
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_tdt); //   "      "  "  "
    const Tenseur3BB & gijBB = *((Tenseur3BB*) &gijBB_tdt); //   "      "  "  "
    Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_tdt);  //   "      "  "  "
//    Tenseur3HH & sigHH_i = *((Tenseur3HH*) &sigHH_t);  //   "      "  "  "
    SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) saveResul);
    // initialisation des variables de travail
    save_resul.Init_debut_calcul(); 
    // initialisation éventuelle des variables thermo-dépendantes
    Init_thermo_dependance();
    
    // cas d'une dépendance à la phase de la déformation totale
    if (avec_phase_paradefEqui || avec_phaseEps)
      { xnp = xnp_lue; xmu = xmu_lue; Qzero = Qzero_lue;
	       ParaMateriauxAvecPhaseEpsilon(gijHH,epsBB,xnp,xmu,Qzero);
      };
    
    // === 1 == calcul de l'avancement temporel sur 1 pas,
    int cas = 1; // cas normal avec dérivée de Jauman
    Avancement_temporel(delta_epsBB,gijHH,gijBB,cas,save_resul,sigHH,energ_t,energ);
          
    //  ==== 2 ===  calcul de l'opérateur tangent =============
    Hysteresis3D::Dsig_d_ddl(d_sigHH,epsBB_tdt,gijHH_tdt,d_gijBB_tdt,d_gijHH_tdt,d_epsBB );
     
// débug---------
//    Verif_coincidence(delta_epsBB,gijHH,cas,save_resul,sigHH,energ_t,energ,true);
// fin débug -------------

    // on libère les tenseurs intermédiaires        
    LibereTenseur();LibereTenseurQ();        
 }; 
	 
		  	
// calcul des contraintes et ses variations  par rapport aux déformations a t+dt
// en_base_orthonormee:  le tenseur de contrainte en entrée est  en orthonormee
//                  le tenseur de déformation et son incrémentsont également en orthonormees
//                 si = false: les bases transmises sont utilisées
// ex: contient les éléments de métrique relativement au paramétrage matériel = X_(0)^a
void Hysteresis3D::Calcul_dsigma_deps (bool en_base_orthonormee, TenseurHH & sigHH_t,TenseurBB&
            ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB_,double& ,double& 
		  	      ,TenseurHH& sigHH_tdt,TenseurHHHH& d_sigma_deps
		  	,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double&  module_cisaillement
		  	,const Met_abstraite::Umat_cont& ex)

 {
   #ifdef MISE_AU_POINT	 	 
	  if (epsBB_tdt.Dimension() != 3)
	    { cout << "\nErreur : la dimension devrait etre 3 !\n";
       cout << " Hysteresis3D::Calcul_dsigma_deps\n";
		     Sortie(1);
     };
    #endif    

    const Tenseur3HH & gijHH = *((Tenseur3HH*) ex.gijHH_tdt); //   "      "  "  "
    const Tenseur3BB & gijBB = *((Tenseur3BB*) ex.gijBB_tdt); //   "      "  "  "
    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
    const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_); // passage en dim 3
    Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_tdt);  //   "      "  "  "
//    Tenseur3HH & sigHH_i = *((Tenseur3HH*) &sigHH_t);  //   "      "  "  "
    SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) saveResul);
    // initialisation des variables de travail
    save_resul.Init_debut_calcul(); 
    // initialisation éventuelle des variables thermo-dépendantes
    Init_thermo_dependance();
    
    // cas d'une dépendance à la phase de la déformation totale
    if (avec_phase_paradefEqui || avec_phaseEps)
      { xnp = xnp_lue; xmu = xmu_lue; Qzero = Qzero_lue;
        if (en_base_orthonormee)
	          ParaMateriauxAvecPhaseEpsilon(IdHH3,epsBB,xnp,xmu,Qzero);
        else
           ParaMateriauxAvecPhaseEpsilon(gijHH,epsBB,xnp,xmu,Qzero);
      };
    
    // === 1 == calcul de l'avancement temporel sur 1 pas,
    // ici il n'y a pas de différence entre orthonormeee ou pas au niveau du type de calcul
    int cas = 1; // donc cas avec dérivée de Jauman en mixte
    if (en_base_orthonormee)
       Avancement_temporel(delta_epsBB,IdHH3,IdBB3,cas,save_resul,sigHH,energ_t,energ);
    else
       Avancement_temporel(delta_epsBB,gijHH,gijBB,cas,save_resul,sigHH,energ_t,energ);
      
    //  ==== 2 ===  calcul de l'opérateur tangent =============
//    Hysteresis3D::Dsig_depsilon(en_base_orthonormee,gijHH,d_sigma_deps);

//    try { // débug
    Hysteresis3D::Dsig_depsilon(en_base_orthonormee,gijHH,d_sigma_deps,sigHH);
// débug---------
//      }
//    catch (ErrNonConvergence_loiDeComportement excep)
//       { // initialisation des variables de travail
//         save_resul.Init_debut_calcul();
//         // initialisation éventuelle des variables thermo-dépendantes
//         Init_thermo_dependance();
//         if (en_base_orthonormee)
//            Avancement_temporel(delta_epsBB,IdHH3,IdBB3,cas,save_resul,sigHH,energ_t,energ);
//         else
//            Avancement_temporel(delta_epsBB,gijHH,gijBB,cas,save_resul,sigHH,energ_t,energ);
//         Hysteresis3D::Dsig_depsilon(en_base_orthonormee,gijHH,d_sigma_deps);
//         }
//    catch ( ... )
//       { // initialisation des variables de travail
//         racine.Change_taille(9);
//         save_resul.Init_debut_calcul();
//         // initialisation éventuelle des variables thermo-dépendantes
//         Init_thermo_dependance();
//         if (en_base_orthonormee)
//            Avancement_temporel(delta_epsBB,IdHH3,IdBB3,cas,save_resul,sigHH,energ_t,energ);
//         else
//            Avancement_temporel(delta_epsBB,gijHH,gijBB,cas,save_resul,sigHH,energ_t,energ);
//         Hysteresis3D::Dsig_depsilon(en_base_orthonormee,gijHH,d_sigma_deps);
//       };

//    Verif_coincidence(delta_epsBB,gijHH,cas,save_resul,sigHH,energ_t,energ,true);
// fin débug -------------



    // on libère les tenseurs intermédiaires        
    LibereTenseur();LibereTenseurQ();        
 }; 
	 
		  	

// =============== fonction protegee ============

		  	
// calcul de la fonction résidu de la résolution de l'équation constitutive
// l'argument test ramène
//     . 1 si le calcul a été ok, -1 s'il y a eu un pb, mais on peut continuer, 0 s'il y a eu un pb
//       fatal, qui invalide le calcul du résidu
Vecteur& Hysteresis3D::Residu_constitutif (const double & alpha,const Vecteur & x, int& test)
  { // récupération du vecteur delta_sigma 
    for (int i=1;i<=9;i++) // accroissement de t à tdt
      rdelta_sigma_barre_tdt_BH.Coor(Tenseur3BH::idx_i(i),Tenseur3BH::idx_j(i)) = x(i);
    test = 1; // init par défaut
    // variation de sigma de R à tdt
    rdelta_sigma_barre_BH_Ratdt = sigma_i_barre_BH + rdelta_sigma_barre_tdt_BH - sigma_barre_BH_R;
    delta_barre_alpha_epsBH = alpha * delta_barre_epsBH; // limitation de la charge
    // -- calcul de QdeltaSigma
    QdeltaSigmaRatdt = sqrt(rdelta_sigma_barre_BH_Ratdt.II());
    // -- calculs relatifs aux angles de phases
    Cal_wprime(QdeltaSigmaRatdt,rdelta_sigma_barre_BH_Ratdt,Q_OiaR,delta_sigma_barre_BH_OiaR 
               ,wBase,rdelta_sigma_barre_tdt_BH,wprime,wprime_point,trajet_neutre);
    // --- si dépendance de la phase de sigma0i_tdt (et non delta sigma) mise à jour des para matériaux
    if (avec_phaseDeltaSig)
     {xnp = xnp_lue; xmu = xmu_lue; Qzero = Qzero_lue;
      ParaMateriauxAvecPhaseDeltaSig(xnp,delta_sigma_barre_BH_OiaR,rdelta_sigma_barre_BH_Ratdt,xmu,Qzero);
     };

	   // -- modif 	7 mai 2012 ---
	   // dans le cas où le phidt est négatif, l'équation constitutive n'est plus valide, dans ce cas on considère
	   // que phi est nulle, c-a-d que l'on évolue suivant un trajet neutre ce qui n'est sans doute pas l'idéal, mais permet d'éviter l'explosion
	       // -- calcul de phidt
	   double phidt = (rdelta_sigma_barre_BH_Ratdt && delta_barre_alpha_epsBH) ; // init partie radial   // -- modif 16 juin 2012 --
	   if (!trajet_neutre)																									   // -- modif 16 juin 2012 --
	     phidt -=  QdeltaSigmaRatdt * QdeltaSigmaRatdt * wprime_point / (2. * xmu * wprime);			// -- modif 16 juin 2012 --

// 	  if ((phidt < 0) && force_phi_zero_si_negatif)  // -- modif 16 juin 2012 --
 	  if (phidt < 0)                                      // -- modif 9 fev 2015 --
     {if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 8)) || (Permet_affichage() > 8) )
        cout << "\n  phidt= " << phidt << "\n Hysteresis3D::Residu_constitutif(..." << endl;
      if (  Dabs(phidt) < force_phi_zero_si_negatif)   // -- modif 9 fev 2015 --
       { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5) )
          {	cout << "\n attention on utilise une valeur de phi negative dans pour le calcul de l'equation constitutive "
                 << " phidt= " << phidt;
            if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
            cout  << "\n Hysteresis3D::Residu_constitutif(..." << endl;
          };
         phidt = 0.;trajet_neutre = true;
         test = -1; // c'est un pb mais pas fatal
       };
     };
	   // fin modif modif 	7 mai 2012 ---

    if (trajet_neutre)
     { // si c'est un trajet neutre, l'équation constitutive est beaucoup plus simple: sigma_point = 2 mu D_barre
       // -- calcul du résidu
       residuBH = rdelta_sigma_barre_tdt_BH - 2. * xmu * delta_barre_alpha_epsBH;
       // --- si dépendance à la déformation équivalente on calcul le xnp correspondant à un phi = 0
       if (avec_defEqui)
        { if (!avec_phaseDeltaSig && !avec_phaseEps) xnp = xnp_lue; // sinon ça déjà été fait
          double phitau = 0.;
		        if (Qzero_defEqui!=NULL) Qzero = Qzero_lue;
          ParaMateriauxAvecDefEqui(xnp,QdeltaSigmaRatdt,phitau,wprime,def_equi_R,trajet_neutre,def_i_equi,defEqui_maxi);
         };
     }
    else
     { // cas d'un trajet non neutre
		     // modif 	7 mai 2012 --- on ne recalcule plus le phi qui a été calculé plus haut pour savoir s'il était négatif
//       // -- calcul de phidt
//       double phidt = (rdelta_sigma_barre_BH_Ratdt && delta_barre_alpha_epsBH)
//                      - QdeltaSigmaRatdt * QdeltaSigmaRatdt * wprime_point / (2. * xmu * wprime);

       // --- si dépendance à la déformation équivalente 
       if (avec_defEqui)
        { if (!avec_phaseDeltaSig && !avec_phaseEps) xnp = xnp_lue; // sinon ça déjà été fait
		        if (Qzero_defEqui!=NULL) Qzero = Qzero_lue;
          ParaMateriauxAvecDefEqui(xnp,QdeltaSigmaRatdt,phidt,wprime,def_equi_R,trajet_neutre,def_i_equi,defEqui_maxi);
        };
       // -- calcul de Beta
       double unsurwprimeQ0_puiss_np = 1./pow(wprime*Qzero,xnp);
       double beta=0.; // init dans le cas où ne le calcul pas après
       if (QdeltaSigmaRatdt >= ConstMath::petit)
        // on ne calcul beta que si la norme de deltaSigmaRatdt est significative
        {if (xnp == 2.) { beta = - 2. * xmu *  unsurwprimeQ0_puiss_np;}
         else {beta = - 2. * xmu *  unsurwprimeQ0_puiss_np * pow(QdeltaSigmaRatdt,xnp-2.);};
        };
       // -- calcul du résidu
       residuBH = rdelta_sigma_barre_tdt_BH 
                 - 2. * xmu * delta_barre_alpha_epsBH - beta * phidt * rdelta_sigma_barre_BH_Ratdt;
     };
    // -- retour du résidu
    for (int i=1;i<=9;i++) 
       residu(i) = residuBH(Tenseur3BH::idx_i(i),Tenseur3BH::idx_j(i));
    return residu;
    };  	

// calcul de la matrice tangente de la résolution de l'équation constitutive
// l'argument test ramène
//     . 1 si le calcul a été ok, -1 s'il y a eu un pb, mais on peut continuer, 0 s'il y a eu un pb
//       fatal, qui invalide le calcul du résidu et de la dérivée
Mat_abstraite& Hysteresis3D::Mat_tangente_constitutif
                              (const double & alphap,const Vecteur & x, Vecteur& residu, int& test)
  { // récupération du vecteur delta_sigma
    for (int i=1;i<=9;i++) // accroissement de t à tdt
      rdelta_sigma_barre_tdt_BH.Coor(Tenseur3BH::idx_i(i),Tenseur3BH::idx_j(i)) = x(i);
    test = 1; // init par défaut
    rdelta_sigma_barre_BH_Ratdt = sigma_i_barre_BH + rdelta_sigma_barre_tdt_BH - sigma_barre_BH_R;
    delta_barre_alpha_epsBH = alphap * delta_barre_epsBH; // limitation de la charge
    // -- calcul de QdeltaSigmaRatdt
    QdeltaSigmaRatdt = sqrt(rdelta_sigma_barre_BH_Ratdt.II());
    // -- calculs relatifs aux angles de phases
    if (avecVarWprimeS)
     {Cal_wprime_et_der(QdeltaSigmaRatdt,rdelta_sigma_barre_BH_Ratdt,Q_OiaR,delta_sigma_barre_BH_OiaR
                      ,wBase,rdelta_sigma_barre_tdt_BH,wprime,d_wprime,wprime_point,d_wprime_point,trajet_neutre);
     }
    else 
     {Cal_wprime(QdeltaSigmaRatdt,rdelta_sigma_barre_BH_Ratdt,Q_OiaR,delta_sigma_barre_BH_OiaR 
               ,wBase,rdelta_sigma_barre_tdt_BH,wprime,wprime_point,trajet_neutre);
      d_wprime.Inita(0.); 
      d_wprime_point.Inita(0.);        
     };
    // --- si dépendance de la phase de sigma0i_tdt (et non delta sigma) mise à jour des para matériaux
    if (avec_phaseDeltaSig)
     {xnp = xnp_lue; xmu = xmu_lue; Qzero = Qzero_lue;
      ParaMateriauxAvecPhaseDeltaSig(xnp,delta_sigma_barre_BH_OiaR,rdelta_sigma_barre_BH_Ratdt,xmu,Qzero);
     };

//---- débug
//    wprime = 1.;wprime_point=0.;trajet_neutre = false;
// --- fin débug 

    // -- modif 	7 mai 2012 ---
    // dans le cas où le phidt est négatif, l'équation constitutive n'est plus valide, dans ce cas on considère
    // que phi est nulle, c-a-d que l'on évolue suivant un trajet neutre ce qui n'est sans doute pas l'idéal, mais permet d'éviter l'explosion
        // calcul de phidt
    double phidt = (rdelta_sigma_barre_BH_Ratdt && delta_barre_alpha_epsBH) ; // init partie radial   // -- modif 16 juin 2012 -- 
    if (!trajet_neutre)																									   // -- modif 16 juin 2012 --
	        phidt -=  QdeltaSigmaRatdt * QdeltaSigmaRatdt * wprime_point / (2. * xmu * wprime);			// -- modif 16 juin 2012 -- 

// 	  if ((phidt < 0) && force_phi_zero_si_negatif)  // -- modif 16 juin 2012 --
 	  if (phidt < 0)                                      // -- modif 9 fev 2015 --
     {if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 8)) || (Permet_affichage() > 8) )
        cout << "\n  phidt= " << phidt << "\n Hysteresis3D::Mat_tangente_constitutif(..." << endl;
      if (  Dabs(phidt) < force_phi_zero_si_negatif)   // -- modif 9 fev 2015 --
       { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
           {	cout << "\n attention on utilise une valeur de phi negative dans pour le calcul de l'equation constitutive "
                       << " phidt= " << phidt;
             if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
             cout << "\n Hysteresis3D::Mat_tangente_constitutif(..." << endl;
           };
         phidt = 0.;	trajet_neutre=true;
         test = -1; // c'est un pb mais pas fatal
       };
     };
    // fin modif modif 	7 mai 2012 ---

    if (trajet_neutre)
     { // si c'est un trajet neutre, l'équation constitutive est beaucoup plus simple: sigma_point = 2 mu D_barre
       // -- calcul du résidu
       residuBH = rdelta_sigma_barre_tdt_BH - 2. * xmu * delta_barre_alpha_epsBH;
       //  variation du résidu et retour du résidu
       for (int ig=1;ig<=9;ig++)
       {int i=Tenseur3BH::idx_i(ig); int j=Tenseur3BH::idx_j(ig);
        residu(ig) = residuBH(i,j);
        for (int jg=1;jg<=9;jg++)
         {int k=Tenseur3BH::idx_i(jg); int l=Tenseur3BH::idx_j(jg);
          derResidu(ig,jg) = IdBH3(i,k)*IdBH3(l,j);
         };
       };
       // --- si dépendance à la déformation équivalente on calcul le xnp correspondant à un phi = 0
       if (avec_defEqui)
        { if (!avec_phaseDeltaSig  && !avec_phaseEps) xnp = xnp_lue; // sinon ça déjà été fait
          double phitau = 0.;
		    if (Qzero_defEqui!=NULL) Qzero = Qzero_lue;
          ParaMateriauxAvecDefEqui(xnp,QdeltaSigmaRatdt,phitau,wprime,def_equi_R,trajet_neutre,def_i_equi,defEqui_maxi);
         };
     }
    else
     { // cas d'un trajet non neutre
		 // modif 	7 mai 2012 --- on ne recalcule plus le phi qui a été calculé plus haut pour savoir s'il était négatif
//       // calcul de phidt
//       double phidt = (rdelta_sigma_barre_BH_Ratdt && delta_barre_alpha_epsBH)
//                      - QdeltaSigmaRatdt * QdeltaSigmaRatdt * wprime_point / (2. * xmu * wprime);
							 
       // --- si dépendance à la déformation équivalente 
       if (avec_defEqui)
        { if (!avec_phaseDeltaSig && !avec_phaseEps) xnp = xnp_lue; // sinon ça déjà été fait
		        if (Qzero_defEqui!=NULL) Qzero = Qzero_lue;
          ParaMateriauxAvecDefEqui(xnp,QdeltaSigmaRatdt,phidt,wprime,def_equi_R,trajet_neutre,def_i_equi,defEqui_maxi);
         };
       // -- calcul de Beta
       double unsurwprimeQ0_puiss_np = 1./pow(wprime*Qzero,xnp);
       double beta=0.; // init dans le cas où ne le calcul pas après
       double unsurQdeltaSigma= ConstMath::grand; // on limite la valeur par exemple pour le démarrage
       double puiss = 1.; // variable intermédiaire qui resert par la suite
       if (QdeltaSigmaRatdt >= ConstMath::petit)
        // on ne calcul beta que si la norme de deltaSigmaRatdt est significative
        // idem pour unsurQdeltaSigma
        {unsurQdeltaSigma=1./QdeltaSigmaRatdt;
         if (xnp == 2.) { beta = - 2. * xmu *  unsurwprimeQ0_puiss_np;}
         else {puiss = pow(QdeltaSigmaRatdt,xnp-2.);
               beta = - 2. * xmu *  unsurwprimeQ0_puiss_np * pow(QdeltaSigmaRatdt,xnp-2.);
              };
        };
       // calcul du résidu
       residuBH = rdelta_sigma_barre_tdt_BH 
                 - 2. * xmu * delta_barre_alpha_epsBH - beta * phidt * rdelta_sigma_barre_BH_Ratdt;
       
       // -- calcul de la variation du résidu
       // 1 # variation de QdeltaSigmaRatdt ;
       // -- calcul de la variation de QdeltaSigmaRatdt par rapport à sigma_barre        
       Tenseur3BH d_QdeltaSigmaRatdt(unsurQdeltaSigma * rdelta_sigma_barre_BH_Ratdt);
       d_QdeltaSigmaRatdt.PermuteHautBas();
       // 2 # variation de beta
       Tenseur3BH d_beta; // initialisé par défaut à 0
       if (QdeltaSigmaRatdt >= ConstMath::petit)
        // dans le cas ou la norme de deltaSigmaRatdt n'est pas significative, beta est mis à zero
        // il en est de même pour le cas où xnp = 2, pour lequel beta est constant ainsi que sa variation. 
        //  A part ces deux cas  on peut calculer d_beta
        {if (xnp != 2.)
           {double a = 2. * xmu * unsurwprimeQ0_puiss_np * puiss;
            d_beta = (a * (2.-xnp) * unsurQdeltaSigma)  * d_QdeltaSigmaRatdt
                             + ( a *xnp / wprime) * d_wprime;
           }; // si xnp==2: cas où d_beta est nul, déjà fait dans l'initialisation de d_beta
        };
       // 3 # variation de phidt
       Tenseur3BH d_phidt(delta_barre_alpha_epsBH);
       d_phidt.PermuteHautBas();
       d_phidt -= (wprime_point*QdeltaSigmaRatdt/(xmu*wprime))*d_QdeltaSigmaRatdt;
       d_phidt -= (QdeltaSigmaRatdt*QdeltaSigmaRatdt/2. * xmu)*
                   (d_wprime_point/wprime - (wprime_point/(wprime*wprime))*d_wprime);
       // 4 # variation du résidu et retour du résidu
       for (int ig=1;ig<=9;ig++)
        {int i=Tenseur3BH::idx_i(ig); int j=Tenseur3BH::idx_j(ig);
         residu(ig) = residuBH(i,j);
         for (int jg=1;jg<=9;jg++)
           {int k=Tenseur3BH::idx_i(jg); int l=Tenseur3BH::idx_j(jg);
            derResidu(ig,jg) = (1.-beta * phidt)*IdBH3(i,k)*IdBH3(l,j)
                             - (d_beta(k,l) * phidt + beta * d_phidt(k,l))
                                *  rdelta_sigma_barre_BH_Ratdt(i,j);
           };
        };
     };// fin du cas non neutre
    calcul_dResi_dsig = true; // on indique que la matrice est calculée 
    return derResidu;
   };	

// calcul de l'opérateur tangent : dsigma/depsilon
TenseurHHHH& Hysteresis3D::Dsig_depsilon
      (bool en_base_orthonormee,const Tenseur3HH & gijHH_tdt, TenseurHHHH& dsig_deps_
       ,TenseurHH & sigHH)
 {  // -- calcul de la matrice MPC
    Dsig_d_(MPC);
    // -- calcul de dsigma / d_eps
    // comme le tenseur des contraintes est symétrique, idem pour le tenseur de déformation
    // on doit avoir un tenseur d'ordre 4 symétrique par rapport aux deux premiers indices
    // et symétrique par rapport aux deux derniers indices
    // donc modif à faire -> on devrait itérer de 1 à 6 et non de 1 à 9 <<<<< !!!!!
// ===> non ! car en fait il y a de la non symétrie qui traîne... voir modif plus bas
    Tenseur3HHHH & dsig_deps = *((Tenseur3HHHH*) &dsig_deps_);
//    TenseurQ3geneHHHH & dsig_deps = *((TenseurQ3geneHHHH*) &dsig_deps_);
// dans le cas d'une base orthonormeee, la position des indices importe peu, donc l'opérateur
    // déjà calculé est ok
    if (en_base_orthonormee)
     {for (int ig=1;ig<=9;ig++)
       {int i=Tenseur3BH::idx_i(ig); int j=Tenseur3BH::idx_j(ig);
        for (int jg=1;jg<=9;jg++)
          {int k=Tenseur3BH::idx_i(jg); int l=Tenseur3BH::idx_j(jg);
           dsig_deps.Change(i,j,k,l,-MPC(ig,jg));                       
          };
       };
     }
    else // dans le cas d'une base quelconque il faut intervenir sur le premier et dernier indice
     {
     
//     for (int i=1;i<4;i++)
//       for (int j=1;j<4;j++)
//        for (int k=1;k<4;k++)
//         for (int l=1;l<4;l++)
//          {double inter=0.;
//           for (int e=1;e<4;e++)
//             for (int f=1;f<4;f++)
//               {int ej = Tenseur3BH::OdVect(e,j);
//                int kf = Tenseur3HB::OdVect(k,f); // en fait idem mixte dans un sens ou l'autre
////                inter += gijHH_tdt(i,e) * MPC(ej,kf) * gijHH_tdt(f,l);
//// essai (a virer si pas concluant ) 1 oct 2020
//// a priori c'est concluant, cela fct nettement mieux, en particulier quand on l'utilise
//// en implicit : LoiAdditiveEnSigma::Calcul_DsigmaHH_via_eps_tdt
//// Je ne comprends pas pourquoi la matrice ne conduit pas à une symétrie, mais ...
//// forcé de constater qu'il faut intégrer tous les termes... et donc on force une symétrie !!
//                int je = Tenseur3BH::OdVect(j,e);
//                int fk = Tenseur3HB::OdVect(f,k); // en fait idem mixte dans un sens ou l'autre
//                inter += gijHH_tdt(i,e) *
//                          0.25* (MPC(ej,kf)+MPC(je,kf)+MPC(ej,fk)+MPC(je,fk))
//                          * gijHH_tdt(f,l);
////$$$$$ il manque les variation de gijHH_tdt par rapport à epsilon !!
//
//// fin essai: on garde car a priori concluant
//               }
//           dsig_deps.Change(i,j,k,l,-inter);
//          };
////$$$$ à voir la prise en compte de la partie der de Jauman
//// essai en suivant exactement la même procédure que dsigma/d_ddl


          // nouveau calcul car il manquait des termes
          for (int oj=1;oj<=9;oj++)
           {int o=Tenseur3BH::idx_i(oj); int j=Tenseur3BH::idx_j(oj);
            for (int ef=1;ef<=9;ef++)
             {int e=Tenseur3BH::idx_i(ef); int f=Tenseur3BH::idx_j(ef);
              double inter=0.;
              for (int i=1;i<4;i++)
               for (int k=1;k<4;k++)
                for (int l=1;l<4;l++)
                 { int ij = Tenseur3BH::OdVect(i,j);
                   int kl = Tenseur3BH::OdVect(k,l);
                   // ici un - car MPC(ij,kl) est = - d sig_i^j / d eps_k^l
                   inter -= gijHH_tdt(o,i) * MPC(ij,kl) * IdBH3(k,e) * gijHH_tdt(f,l);
                 };
              // ici - car c'est un - dans la formule
              inter -= 2.* gijHH_tdt(o,e) * sigHH(f,j);
              dsig_ojef_HHHH.Change(o,j,e,f,inter);
             };
           };
          // on symétrise
          dsig_deps.TransfertDunTenseurGeneral(dsig_ojef_HHHH.Symetrise1et2_3et4());
      };

    // retour
    return dsig_deps;
  };	
     
// calcul de l'opérateur tangent : dsigma/d_ddl
void Hysteresis3D::Dsig_d_ddl(Tableau <TenseurHH *>& d_sigHH,TenseurBB & epsBB_tdt
               ,TenseurHH & gijHH_tdt,Tableau <TenseurBB *>& d_gijBB_tdt
               ,Tableau <TenseurHH *>& d_gijHH_tdt,Tableau <TenseurBB *>& d_epsBB )
 {  // -- calcul de la matrice MPC
    Dsig_d_(MPC);
////----- debug
//cout << "\n debug Hysteresis3D::Dsig_d_ddl( ";
//MPC.Affiche();
//cout << endl;
////--- fin debug
    // -- calcul de dsigma / d_ddl
    // nombre de ddl pour la variation du tenseur des contraintes
    int nbddl = d_gijBB_tdt.Taille();
    Tenseur3BH depsBH_dll;Tenseur3BH dsig3BH; Tenseur_ns3HH dsig1_HH;
    const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_tdt); //   "      "  "  "
    const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
    for (int i = 1; i<= nbddl; i++)
      { // on fait  uniquement une égalité d'adresse de manière à ne pas utiliser
        // le constructeur d'ou la profusion d'* et de ()
        Tenseur3HH & dsigHH = *((Tenseur3HH*) (d_sigHH(i)));  // passage en dim 1
        const Tenseur3BB & d_gijBB =  *((Tenseur3BB*)(d_gijBB_tdt(i)));  // passage en dim 1
        const Tenseur3HH & dgijHH = *((Tenseur3HH*)(d_gijHH_tdt(i))) ; // pour simplifier l'ecriture
        const Tenseur3BB & depsBB = *((Tenseur3BB *) (d_epsBB(i))); //    "
        depsBH_dll = (depsBB * gijHH +   epsBB  * dgijHH );
        
        for (int ig=1;ig<=9;ig++)
         {int i=Tenseur3BH::idx_i(ig); int j=Tenseur3BH::idx_j(ig);
          dsig3BH.Coor(i,j) = 0.;
          for (int jg=1;jg<=9;jg++)
           {int k=Tenseur3BH::idx_i(jg); int l=Tenseur3BH::idx_j(jg);
//            dsig3BH(i,j) += -(dRdeps(ig,jg) * depsBH_dll(k,l)); 
            dsig3BH.Coor(i,j) += -(MPC(ig,jg) * depsBH_dll(k,l));
           };
         };
        // et en deux fois contra
        dsig1_HH = gijHH * dsig3BH + dgijHH * sigma_t_barre_tdt ;
        // et on symétrise
        dsigHH = 0.5*(dsig1_HH + dsig1_HH.Transpose());         
      }
 };	

// calcul de la première phase de l'opérateur tangent, est utilisé par Dsig_d_ddl et
// Dsig_depsilon
// calcul de la matrice MPC
void Hysteresis3D::Dsig_d_(MatLapack& MPC)
 {  // dans le cas où la résolution est faite avec du Runge on appelle une routine spécifique
    if (type_calcul_comportement_tangent==2)
      { Dsig_d_Runge(MPC);
    	   return;	
      };
    // ----  sinon il s'agit de l'algo avec linéarisation 
    double const untiers=1./3.;
    double beta=0.; // init dans le cas où ne le calcul pas après
    if (!trajet_neutre)
     { // si c'est un trajet non neutre, on utilise l'ensemble de la loi constitutive
       // -- calcul de Beta
       //     remarque: le xnp que l'on utilise ici est le dernier calculé dans l'algo
       //     d'avancement temporel (on ne le met pas à jour)
       double unsurwprimeQ0_puiss_np = 1./pow(wprime*Qzero,xnp);
       if (QdeltaSigmaRatdt >= ConstMath::petit)
        // on ne calcul beta que si la norme de deltaSigmaRatdt est significative
        {if (xnp == 2.)
           { beta = - 2. * xmu *  unsurwprimeQ0_puiss_np ;}
         else
          	{ beta = - 2. * xmu *  unsurwprimeQ0_puiss_np * pow(QdeltaSigmaRatdt,xnp-2.);}; 
        };
     }; // fin du calcul de beta pour le cas d'un trajet non neutre
    // normalement la matrice der_at_racine (qui vient d'être calculée
    // pour résoudre l'équation constitutive, contient  d_R_i^j / d_sigbarre_k^l)
// mais ce serait peut-être mieux de systématiquement la recalculer pour alpha = 1
// on aurait ainsi une matrice sécante ???    
    if (!calcul_dResi_dsig)
     {// cas où la matrice tangente n'a pas été calculée
     // calcul de la matrice tangente de la résolution de l'équation constitutive
// essai d'une nouvelle méthode

/* a prioiri ne fonctionne pas
     // on utilise une petite portion de tàtdt
     MatLapack der_at_racine_inter(9,9); 
     int nb_decoup = 10;
     double alphap = 1./nb_decoup; //00; // pour voir 1/100
     
     // sigma_i_barre_BH représente le point de ref sur la même courbe d'évolution 
     // delta_sigma_barre_tdt_BH représente le delta sigma depuis le point de ref
     Tenseur3BH sigma_courant_BH(sigma_i_barre_BH);
     Tenseur3BH sigma_i_barre_sauve_BH(sigma_i_barre_BH); // sauvegarde
     Tenseur3BH incr_sig_BH(delta_sigma_barre_tdt_BH);incr_sig_BH /= nb_decoup;
     for (int ig=1;ig<=9;ig++)
         racine(ig) = incr_sig_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
     for (int i=1;i<=nb_decoup;i++)
     	{ // on prend une nouvelle  référence ad Hoc
          sigma_i_barre_BH = sigma_courant_BH; 
          sigma_courant_BH += incr_sig_BH;
          // on calcul l'opérateur tangent pour le sigma_courant_BH
          der_at_racine_inter = Mat_tangente_constitutif(alphap,racine,residu);
          // on cumule l'opérateur tangent
     	  der_at_racine += der_at_racine_inter; 
     	};
     // calcul de l'opérateur tangent finale
     der_at_racine *= alphap; 
     
     */    
     
     
  // ici une solution qui fonctionne bien pour alpha = 10 !! incompréhensible !! 
/*     double alphap = 10;       
     // récup de la solution
     for (int ig=1;ig<=9;ig++)
//        racine(ig) = alphap * delta_sigma_barre_tdt_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
        racine(ig) =  delta_sigma_barre_tdt_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));

     // on prend une nouvelle  référence, proche de l'arrivée
//     sigma_i_barre_BH = sigma_t_barre_tdt-alphap * delta_sigma_barre_tdt_BH;  
     sigma_i_barre_BH = sigma_t_barre_tdt-delta_sigma_barre_tdt_BH;  
     der_at_racine = Mat_tangente_constitutif(alphap,racine,residu); */
     
// fin essai de la nouvelle méthode 
     // la méthode normale !    
     double alphap = 1.;
     // récup de la solution
     for (int ig=1;ig<=9;ig++)
        racine(ig) = delta_sigma_barre_tdt_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
     int test; // ne sert pas pour l'instant
     der_at_racine = Mat_tangente_constitutif(alphap,racine,residu,test);

// !!!!!!!! pour le débug     
//cout << " norme residu= " << residu.Max_val_abs()/delta_sigma_barre_tdt_BH.MaxiComposante() ;
//if (residu.Max_val_abs() <= ConstMath::petit)
//	   cout << " la norme est nulle !";
// !!!!!!!! pour le débug     

      };
    
    // 1-- on calcul son inverse
    der_at_racine.Inverse(dRdsigMoinsun);
    
// ------ pour le débug
//     MatLapack produit(9,9);
//     produit = dRdsigMoinsun * der_at_racine;
//     for (int i=1;i<=9;i++) 
//      { if (Dabs(produit(i,i)-1. ) > ConstMath::unpeupetit)
//          cout << "\n diag("<<i<<","<<i<<") n'est pas unitaire =" << produit(i,i);
//        for (int j=1;j<= 9; j++)
//       	{ if (i!=j)
//       	   if (Dabs(produit(i,j)) > ConstMath::unpeupetit)
//              cout << "\n  terme ("<<i<<","<<j<<") non nul =" << produit(i,j);
//       	  if ((produit(i,j) != produit(j,i)) && (Dabs(produit(i,j)) > ConstMath::unpeupetit))
//             cout << "\n  non symetrique ("<<i<<","<<j<<") =" << produit(i,j) << " et " << produit(j,i);
//      		
//       	}
//      }
//

//------ fin pour le débug    
    
    
    
    // 2-- maintenant il faut calculer la variation du résidu constitutif / aux déformations
    dRdeps.Initialise(0.);
    
//  ************ important ********************
    // en fait dans la suite on calcul - dSigma/ dEps et non + 
    // ensuite dans l'utilisation on met un moins (ce serait peut-être plus judicieux de mettre moins ici
    // et pas après !!!
    
    
    if (trajet_neutre)
     { // si c'est un trajet neutre, l'équation constitutive est beaucoup plus simple: sigma_point = 2 mu D_barre
       for (int ig=1;ig<=9;ig++)
        {int i=Tenseur3BH::idx_i(ig); int j=Tenseur3BH::idx_j(ig);
         for (int jg=1;jg<=9;jg++)
           {int k=Tenseur3BH::idx_i(jg); int l=Tenseur3BH::idx_j(jg);
            dRdeps(ig,jg) = -2. * xmu * (IdBH3(i,k)*IdBH3(l,j)-untiers*IdBH3(l,k)*IdBH3(i,j));
           };
        };
     }
    else
    { // cas non neutre 
       for (int ig=1;ig<=9;ig++)
        {int i=Tenseur3BH::idx_i(ig); int j=Tenseur3BH::idx_j(ig);
         for (int jg=1;jg<=9;jg++)
           {int k=Tenseur3BH::idx_i(jg); int l=Tenseur3BH::idx_j(jg);
             dRdeps(ig,jg) = -2. * xmu * (IdBH3(i,k)*IdBH3(l,j)-untiers*IdBH3(l,k)*IdBH3(i,j)) // originale
//            dRdeps(ig,jg) = 2. * xmu * (IdBH3(i,k)*IdBH3(l,j)-untiers*IdBH3(l,k)*IdBH3(i,j))    // essai
// //                         + beta * rdelta_sigma_barre_BH_Ratdt(i,j)
// //                                * rdelta_sigma_barre_BH_Ratdt(l,k);
//                            + beta * delta_sigma_barre_BH_Ratdt(i,j) // originale
                            // normalement suivant les formules, on devrait avoir un - ???? incompréhensible
                            // car avec un + ça marche mieux ??
                            - beta * delta_sigma_barre_BH_Ratdt(i,j)  // essai
                                   * delta_sigma_barre_BH_Ratdt(l,k);
           };
        };
    };
    // 3-- puis on calcul le produit des deux matrices 
    MPC =  dRdsigMoinsun * dRdeps;  // originale 
//    MPC =   -dRdeps * dRdsigMoinsun;   // essai
    
 };
 
// calcul de l'avancement temporel sur 1 pas,
// utilisé par les 3 programmes principaux: 
// Calcul_SigmaHH, Calcul_DsigmaHH_tdt, Calcul_dsigma_deps, 
void Hysteresis3D::Avancement_temporel(const Tenseur3BB & delta_epsBB,const Tenseur3HH & gijHH
                                 ,const Tenseur3BB & gijBB,int cas,SaveResulHysteresis3D & save_resul
                                 ,Tenseur3HH & sigHH,const EnergieMeca & energ_t,EnergieMeca & energ)
{   
    // . le tenseur des contraintes initiale en mixte, qui sera considéré comme la contrainte de début
    // de calcul, pour toute la suite, 
    // . s'il y a plusieurs passage dans la boucle while qui suit,  sigma_i_barre_BH variera, à chaque passage
    // . on utilise le sigmaBH sauvegardé plutôt que le sigmaHH ce qui signifie que l'on effectue un transport
    // en mixte plutôt qu'en 2 fois contravariants !!
 
    // mise en place d'un transport éventuelle sur toutes les grandeurs
    Transport_grandeur(gijBB,gijHH,save_resul);
 
 
    sigma_i_barre_BH = save_resul.sigma_barre_BH_t; // récup des info
    // même procédé pour la def équivalente de début de calcul, initié à t qui sert pour calculer la def équi de R à tdt
    def_i_equi = save_resul.def_equi_at;
    // init énergie
    energ = energ_t;
    double W_a = save_resul.fonction_aide_t; // valeur courante de la fonction d'aide
    double delta_W_a = 0.; // valeur courante du delta W
 
    
    // -- récup et initialisation des variables de travail
    // iatens_princ: pointeur sur la liste déjà enregistrée, iatens: pointeur courant
    List_io <Tenseur3BH>::iterator iatens_princ = save_resul.sigma_barre_BH_R.begin();
    List_io <Tenseur3BH>::iterator iatens = iatens_princ;
    // idem pour la fonction d'aide
    List_io <double>::iterator iafct_princ = save_resul.fct_aide.begin();
    List_io <double>::iterator iafct = iafct_princ;
    aucun_pt_inversion = true; // pour gérer le fait qu'au début il n'y a pas de pt d'inversion !
    if (iatens_princ != save_resul.sigma_barre_BH_R.end())
       aucun_pt_inversion = false; // cas où on a déjà des inversions enregistrées
    // idem pour les déformations équivalentes, fonctionnent avec l'indicateur "aucun_pt_inversion"
    List_io <double>::iterator iadef_equi_princ = save_resul.def_equi.begin();
    List_io <double>::iterator iadef_equi = iadef_equi_princ;
    // idem pour les centres de surfaces de coïncidence
    List_io <Tenseur3BH>::iterator iaOi_princ = save_resul.oc_BH_R.begin();
    List_io <Tenseur3BH>::iterator iaOi = iaOi_princ;
    // on récupère la def maxi de première charge, c'est celle qui correspond au premier point d'inversion
    // si on est sur la première charge on prend la dernière valeur enregistrée sinon on récupère
    // la valeur du premier point d'inversion
    if (aucun_pt_inversion) { defEqui_maxi = def_i_equi;}
    else { List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();
        		 iil++;defEqui_maxi = *iil; // la dernière valeur est nulle, c'est l'avant dernière qui est la bonne
         };
    centre_initial = true; // pour gérer le fait qu'au début le centre initial = tenseur nul
    if (iaOi_princ != save_resul.oc_BH_R.end())
       centre_initial = false; // cas où on a déjà de nouveaux centres enregistrés
    // un pointeur qui indique si les pointeurs courants sont sur les listes principales ou
    // sur les nouvelles listes
    bool pt_sur_principal = true; bool oi_sur_principal = true;

    wBase = save_resul.wBase_t; // initialisation du paramètre de masing
    double unSur_wBaseCarre= 1./(wBase*wBase);
    // -- la déformation
    delta_epsBH = delta_epsBB * gijHH; // incrément de def en mixte
    double trace = delta_epsBH.Trace();
    delta_barre_epsBH = delta_epsBH - (trace/3.)*IdBH3;
    //-- partie spécifique gestion via fct aide
    Tenseur3BH delta_epsBH_totale(delta_epsBH); // sauvegarde delta epsilon totale
	   Tenseur3BH delta_barre_epsBH_totale(delta_barre_epsBH);  // sauvegarde delta_barre epsilon totale
    // a priori, on fait un pas de calcul correspondant à la totalité de la déformation
    // sauf cas inversion ou coïncidence
    double ratio_deformation_en_cours = 0.; // utilisée pour l'instant uniquement avec l'algo fct aide
    double ratio_multiplicatif_coincidence = 1.; // ""
    int phase_coincidence = 0; // pour la gestion de la coincidence
    //-- fin partie spécifique gestion via fct aide
 
    // on définit un indicateur pour le type de gestion de la mémorisation discrète
    bool bascule_fct_aide=false; // init
    bool premier_passage = true; // init
    // indicateur pour gérer la fin du traitement
    bool fin_traitement= false; bool force_fin_traitement = false;
//--------débug- traçage
    #ifdef MISE_AU_POINT
    if (Permet_affichage() == -77)
	      { cout << "\n$$$ === Hysteresis3D::Avancement_temporel: debut de l'algo " << endl ;
       };
    #endif
//----- fin débug
    //  ==== 1 ===  calcul de la contrainte à tdt =============
    // faire tant que fin_traitement n'est pas bon
    int nb_coin_inver=0; // compteur pour éviter une boucle infinie
    while (!fin_traitement)
    {// initialisation des variables de travail qui peuvent varier à chaque passage du while
     // -- 1) sigma_barre_BH_R : initialisé sur la liste principal, mais ensuite peut évoluer sur liste secondaire
     if (aucun_pt_inversion) {sigma_barre_BH_R.Inita(0.);def_equi_R=0.;}
     else                    {sigma_barre_BH_R = *iatens; // la contrainte de référence
                              def_equi_R = *iadef_equi; }; // def équi au pt de référence
     delta_sigma_barre_BH_Rat = sigma_i_barre_BH - sigma_barre_BH_R;
     // -- 2) centre et rayon de la première surface de coïncidence
     if (centre_initial) {oc_BH_R.Inita(0.);}
     else                {oc_BH_R = *iaOi;};

     delta_sigma_barre_BH_OiaR = sigma_barre_BH_R-oc_BH_R; // le tenseur rayon
     // -- 3) calcul du rayon: la première fois le rayon est infini
     if (aucun_pt_inversion) {Q_OiaR = ConstMath::tresgrand;}
     else                    {Q_OiaR = sqrt(delta_sigma_barre_BH_OiaR.II());};
     
     // -- détermination du type de gestion de la mémorisation discrète au premier passage
     // restera constant pour tout le reste du traitement
     // le choix est donc fait par rapport aux valeurs de départ
     if (premier_passage)
      {Tenseur3BH delta_sigma_oi_a_t_BH = sigma_i_barre_BH - oc_BH_R; // OA_t
       double rayon_t = sqrt(delta_sigma_oi_a_t_BH.II());
       if (rayon_t > niveau_bascule_fct_aide * Qzero)
         bascule_fct_aide = true;
       premier_passage = false;
      };

     // le calcul de la contrainte s'effectue par la résolution de l'équation différentielle
     // du schéma constitutif en BH, et toutes les grandeurs sont relatives à BH
     // bien voir que que ce n'est qu'une partie de l'équation, et que pour l'intégration de 
     // la dérivée de Jauman, il faut aussi la partie HB qui est différente, mais on a une symétrie
     // formelle (cf théorie) 
     //  sigma_point = 2*mu*D_barre + beta*phi*(delta_barre de t à R de Sigma) 
	  
// ---7 mai 2012 ---	  
// point nouveau: cette équation n'est valide "que" si phi est positif !!	
// en effet, si phi est négatif, le sigma_point au lieu de saturé, a tendance a exploser (c'est normal car la tendance est inverse)  
   
     // méthode permettant le calcul de sigma à tdt par différente méthodes: linéarisation
     // ou kutta
     // en sortie calcul de : 
     //    sigma_t_barre_tdt, delta_sigma_barre_tdt_BH, delta_sigma_barre_BH_Ratdt
     //    également les grandeurs: QdeltaSigmaRatdt, et wprime,wprime_point, calculées à tdt
//--------débug- traçage
     #ifdef MISE_AU_POINT
     if (Permet_affichage() == -77)
	       { cout << " \nsigR_sur_principal= " << pt_sur_principal << ",      oi_sur_principal= " << oi_sur_principal
               << " save_resul.modif= " << save_resul.modif
               << " \n nb_Oi= "<<save_resul.oc_BH_R.size() << " nb_sigR= "<<save_resul.sigma_barre_BH_R.size()
               << " || nb_Oi_sec= " << save_resul.oc_BH_t_a_tdt.size()
               << " nb_sigR_sec= " << save_resul.sigma_barre_BH_R_t_a_tdt.size()
               << " || wBase= " << wBase;
        };
     #endif
//----- fin débug
     double phi_2_dt = 0.; // on initialise avec un trajet neutre par défaut
     CalculContrainte_tdt(phi_2_dt,save_resul.indicateurs_resolution);

//--------débug- traçage
     #ifdef MISE_AU_POINT
     if (Permet_affichage() == -77)
	       { cout << "\nCalculContrainte_tdt(phi_2_dt...";
          cout << " phi_2_dt = " << setprecision(ParaGlob::NbdigdoEC()) <<  phi_2_dt
               << " || wBase= " << wBase
          << endl ;
        };
     #endif
//----- fin débug
     
     // 2==== gestion de la mémoire discrète                        
     Tenseur3BH delta_sigma_oi_a_tdt_BH = sigma_t_barre_tdt - oc_BH_R; // OA
	    double rayon_tdt = sqrt(delta_sigma_oi_a_tdt_BH.II());
     double d_W_a_essai = 0.; // init
     if (wprime != 0.) // cas d'un trajet non neutre
       {d_W_a_essai = 2. * phi_2_dt / (wprime * wprime);};
//--------débug- traçage
     #ifdef MISE_AU_POINT
     if (Permet_affichage() == -77)
        { cout << "\n rayon_tdt = " << setprecision(ParaGlob::NbdigdoEC()) <<  rayon_tdt
               << " Q_OiaR= " << setprecision(ParaGlob::NbdigdoEC()) <<  Q_OiaR << endl ;
        };
     #endif
//----- fin débug

     if (!bascule_fct_aide) // cas d'une gestion à l'aide des rayons
      { if ((rayon_tdt < Q_OiaR)&&(!force_fin_traitement))
         // cas où le nouveau rayon est inférieur au rayon de référence (= infini si courbe de première charge)
         {int pb_calcul_centre_ok = 0; // init pour une gestion locale du cas où le calcul du centre cercle pose pb,
          
          if (phi_2_dt < 0) //===========================================================================
          // ce qui correspond également au cas d_W_a_essai < O
          // a priori on a détecté un point d'inversion
          // le calcul effectué n'est pas valide et on doit refaire une itération en initialisant les grandeurs ad hoc
          // ------------------ cas d'une inversion ----------
           {// -- on vérifie la cohérence de la valeur de la fonction d'aide (qui n'a rien à voir ici
            // et donc doit être inférieur au maxi)
            if (!aucun_pt_inversion) // si on a déjà des pt d'inversion, on vérifie les niveaux de la fonction d'aide
              if (W_a > *iafct)
                {if ( (ParaGlob::NiveauImpression() > 5) || (Permet_affichage() > 5))
                  {cout << "\n warning dans l'algorithme de gestion de la memoire discrete,  "
                      << " bien que l'on ait detecte un point d'inversion, il se trouve que la fonction d'aide "
                      << " est superieur au dernier maxi, ce qui signifie que le calcul de l'integrale de la puissance "
                      << " non reversible (phi(t)) n'a pas ete correcte (c'est une erreur cumulee), du sans doute a des pas de temps trop grand, "
                      << " le calcul aura peut-etre des pb si on gere avec la fct d'aide, essayer de le reprendre avec un pas de temps plus petit ! "
                      << " \n W_a= " << W_a  << " iafct= " << *iafct
                      << "\n Hysteresis3D::Avancement_temporel(...";
                   if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature(); cout << flush;
                  };
                };
       //--------débug- traçage
            #ifdef MISE_AU_POINT
            if (Permet_affichage() == -77)
               { cout << "\ninversion " << endl ;
               };
            #endif
       //----- fin débug
            // -- calcul des centre de cercle
            if (!aucun_pt_inversion) // s'il y a au moins déjà un point d'inversion valide on peut traiter
             {Tenseur3BH sig0i_BH;
              pb_calcul_centre_ok=CentreCercle(sig0i_BH,oc_BH_R,delta_sigma_barre_BH_OiaR
                          ,delta_sigma_barre_BH_Rat);
              if (!pb_calcul_centre_ok) // si le calcul a été ok
                {save_resul.oc_BH_t_a_tdt.push_front(sig0i_BH);
                 iaOi = save_resul.oc_BH_t_a_tdt.begin(); // init du centre courant pour la suite
                 oi_sur_principal = false;                // va être mis à jour au début de la prochaine boucle
                 centre_initial = false;                 // du while (!fin_traitement)
                };
             }
            else // si auparavant il n'y avait pas de pt d'inversion, maintenant il y en a un
             {aucun_pt_inversion = false;  // on le signal pour la suite
              // point d'inversion
              wBase = 2; unSur_wBaseCarre = 0.25; //=1./(wBase*wBase);
              defEqui_maxi = def_i_equi;
             };
            // -- s'il n'y a pas eu de pb de calcul de centre on met tout à jour ==> fonctionnement normal
            if (!pb_calcul_centre_ok)
              { // gestion du paramètre "modif" de saveresult
                bool inversion = true;
                Gestion_para_Saveresult_Modif(pt_sur_principal,save_resul,inversion);
           //--------débug- traçage
                #ifdef MISE_AU_POINT
                if (Permet_affichage() == -77)
                   { cout << "\npas de probleme de calcul de centre " ;
                   };
                #endif
           //----- fin débug
                // calcul du nouveau centre d'inversion et sauvegarde, sauf dans le cas du premier point
                // d'inversion, pour lequel le centre reste  encore le tenseur nul pour la suite
                
                // ajout de la contrainte de référence = sigma at
                save_resul.sigma_barre_BH_R_t_a_tdt.push_front(sigma_i_barre_BH);
                save_resul.fct_aide_t_a_tdt.push_front(W_a);
                iafct = save_resul.fct_aide_t_a_tdt.begin();
                W_a=0.; delta_W_a = 0.; // on ré-initialise pour les futures coincidences éventuelles
                iatens = save_resul.sigma_barre_BH_R_t_a_tdt.begin(); // pour l'init du début du while générale
                pt_sur_principal = false; // on indique que maintenant on pointe sur la nouvelle liste
                // on indique le point d'inversion pour les futurs traitements
                sigma_barre_BH_R =save_resul.sigma_barre_BH_R_t_a_tdt.front();
                // -- idem pour la déformation équivalente 
                save_resul.def_equi_t_a_tdt.push_front(def_i_equi);
                iadef_equi = save_resul.def_equi_t_a_tdt.begin(); // pour l'init du début du while générale
                 // on indique la déformation équivalente d'inversion pour les futurs traitements
                def_equi_R  = save_resul.def_equi_t_a_tdt.front();
                // on met à jour la def de début  de calcul (valant t au début, puis tau= pt d'inver ensuite ) pour def_equi_atdt
                def_i_equi =  def_equi_R;                    
                // le calcul d'énergie se fera ensuite dans le cas normale ou avec coïncidence
                // car la valeur actuelle de sigma est erroné, et phi est négatif

                fin_traitement = false; // -- il faut recalculer avec le nouveau point d'inversion
           //--------débug- traçage
                #ifdef MISE_AU_POINT
                if (Permet_affichage() == -77)
                   { cout << " fin_traitement = " << fin_traitement
                          << " save_resul.modif= " << save_resul.modif
                          << endl ;
                   };
                #endif
           //----- fin débug
              };
           // sinon on est dans le cas où il y a eu un pb dans le calcul du centre --> ce qui invalide le point d'inverion
           // on indique qu'il faut traiter la suite comme si il n'y avait pas de point d'inversion
           // ceci se fait au travers de l'indicateur: pb_calcul_centre_ok
            
           };//-- fin du cas de l'inversion
          
          // --- maintenant on traite le cas courant ou il n'y a pas de point d'inversion ---
          if ((phi_2_dt >= 0) || pb_calcul_centre_ok)
           //======================================================================================
           // c-a-d       si phi_2_dt = 0 : on se promène sur un cercle
           //             si phi_2_dt > 0 : progression normale
           //             si pb_calcul_centre_ok != 0 : on est dans un cas limite pour lequel il est préférable de ne pas
           //                                           introduire de point d'inversion
           { // --- cas d'une évolution normale sans inversion ni coincidence ---
             // mais cette évolution peut-être la fin après une coincidence par exemple, donc
             // on ne modifie pas save_resul.modif
             fin_traitement = true;
             // dans l'expression suivante, on utilise une intégration incrémentale ...
             // dans l'expression suivante, on utilise une intégration incrémentale ...
             // s'il y a eu un pb de calcul de centre, cela veut dire que phi_2_dt était légèrement
             // négatif à la prec près, il ne faut pas le compter
             if (pb_calcul_centre_ok) {delta_W_a = 0;}
             else if (wprime != 0.) // cas d'un trajet non neutre
               { delta_W_a =  2. * phi_2_dt / (wprime * wprime);}
             else {delta_W_a = 0.;};
            
             W_a += delta_W_a;
             save_resul.fonction_aide_tdt = W_a;
             // -- uptdate des énergies
             UpdateEnergieHyste(energ,sigma_i_barre_BH,sigma_t_barre_tdt,delta_sigma_barre_tdt_BH
                         ,delta_sigma_barre_BH_Ratdt,phi_2_dt,delta_barre_epsBH
                         ,QdeltaSigmaRatdt,wprime,wprime_point,trajet_neutre,def_equi_R,def_i_equi,def_equi_atdt);
             if (aucun_pt_inversion) { defEqui_maxi = def_equi_atdt;} // si sur la première charge on prend la valeur courante
             else  // on a des pt d'inversion, on prend le maxi des listes principales ou secondaires
             // non c'est pas bon
   /*				   defEqui_maxi = 0; // init
        // pour la liste principale, la dernière valeur est nulle, c'est l'avant dernière qui est la bonne
        if (save_resul.def_equi.size())
          { List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;};
                    // pour la liste secondaire c'est directement la dernière valeur
        if (save_resul.def_equi_t_a_tdt.size())
          { List_io <double>::reverse_iterator iil = save_resul.def_equi_t_a_tdt.rbegin();
            defEqui_maxi = MaX(*iil,defEqui_maxi);
         };*/
                 {   List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;};
       //--------débug- traçage
            #ifdef MISE_AU_POINT
            if (Permet_affichage() == -77)
               { cout << "\ncas courant sans point d'inversion " ;
                 cout << " fin_traitement = " << fin_traitement
                      << " save_resul.modif= " << save_resul.modif
                      << endl ;
               };
            #endif
       //----- fin débug
            
           };
         } // -- fin du cas où le nouveau rayon est inférieur au rayon de référence
        else if (!force_fin_traitement) // sinon cas d'une coincidence (rayon_tdt >= Q_OiaR )
         { // -- on calcul exactement le point de coïncidence
             // auparavant on sauvegarde le delta eps pour connaître la partie concernée pour le 
           Tenseur3BH delta_eps_sur_deltaTau_BH = delta_barre_epsBH;  // calcul d'énergie
           double def_equi_R_ancien= def_equi_R; // sauvegarde qui ne sert à rien, car Coincidence ne change pas 
           // directement def_equi_R, seulement le pointeur iadef_equi (qui lui ne pointe plus en sortie sur une valeur =  def_equi_R)
           // mais c'est pour bien marquer le fait que à la sortie de la coïncidence, le pointeur iadef_equi de def_equi à changé
           fin_traitement = Coincidence(bascule_fct_aide,unSur_wBaseCarre,gijHH,gijBB,save_resul
                                        ,W_a,iatens,iadef_equi
                                        ,iafct,pt_sur_principal,iaOi,oi_sur_principal,iatens_princ,iadef_equi_princ
                                        ,iaOi_princ,iafct_princ,rayon_tdt,false);
       //--------débug- traçage
           #ifdef MISE_AU_POINT
           if (Permet_affichage() == -77)
              { cout << "\ncas d'une coïncidence ";
                cout << " fin_traitement = " << fin_traitement
                     << " save_resul.modif= " << save_resul.modif
                     << " save_resul.nb_coincidence= " << save_resul.nb_coincidence
                     << endl ;
              };
           #endif
       //----- fin débug

           // dans le cas d'un trajet strictement radial, on a deux coïncidences à suivre
           // mais on laisse l'algorithme passer deux fois, car sinon il y a des pb dans le cas 
           // de grand incrément
          
           // -- uptdate des énergies
           // récup du delta eps concerné: delta_barre_epsBH est modifié dans Coïncidence, maintenant
           // il contient le reste de la déformation
           delta_eps_sur_deltaTau_BH -= delta_barre_epsBH; 
    
           // on recalcule la valeur de phi car ici on est après le calcul d'une coïncidence, la contrainte qu'il faut considérer est 
           // celle de la coïncidence, la deformation à considérer est delta_eps_sur_deltaTau_BH, il faut donc calculer le phi qui
           // correspond à ces deux grandeurs.
           delta_sigma_barre_BH_Ra_i = sigma_i_barre_BH - sigma_barre_BH_R;
           double QdeltaSigmaRai = sqrt(delta_sigma_barre_BH_Ra_i.II());
           phi_2_dt = (delta_sigma_barre_BH_Ra_i && delta_eps_sur_deltaTau_BH)
                          - QdeltaSigmaRai * QdeltaSigmaRai * wprime_point / (2.*xmu * wprime);
           // si le phi est négatif, on le met à 0 pour limiter les ennuis dans les calculs d'énergies (ici phi ne sert
           // ne sert que là par la suite), mais c'est quand même pas normal !! mais ça peut être due à une légère erreur
           // au niveau de la coïncidence 
           if (phi_2_dt < 0.) 
              phi_2_dt = 0.;              
                          
                          
           UpdateEnergieHyste(energ,sigma_i_barre_BH,sigma_t_barre_tdt,delta_sigma_barre_tdt_BH
                         ,delta_sigma_barre_BH_Ratdt,phi_2_dt,delta_eps_sur_deltaTau_BH
                         ,QdeltaSigmaRatdt,wprime,wprime_point,trajet_neutre,def_equi_R_ancien,def_i_equi,def_equi_atdt);
           if (aucun_pt_inversion) { defEqui_maxi = def_equi_atdt;} // si sur la première charge on prend la valeur courante
           else  // on a des pt d'inversion, on prend le maxi des listes principales ou secondaires
             // non c'est pas bon
                 { List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;};
           // on met à jour la def de début  de calcul (valant t au début )
           // il s'agit d'une grandeur scalaire (pas tensorielle) on peut donc reprendre la valeur qu'elle avait
           // au moment du précédent pt d'inversion, ce qui évitera de cumuler des erreurs d'intégration
           def_i_equi =  def_equi_R_ancien;  // def_equi_R n'a pas encore été modifié, il correspond à la précédente valeur d'inversion
           // NB: 1)on pourrait également prendre  def_equi_atdt, mais qui cumulle les erreurs d'integ entre les deux derniers pt d'integ
           // 2) c'est la même formule que dans le cas d'une inversion, mais cela ne donne pas du tout le même résultat
         }
        else // cas où on force la fin du traitement: force_fin_traitement = true
         { fin_traitement = true;
           // comme (rayon_tdt >= Q_OiaR ) on force la coincidence
           double def_equi_R_ancien= def_equi_R; // sauvegarde qui ne sert à rien, car Coincidence ne change pas 
           // directement def_equi_R, seulement le pointeur iadef_equi (qui lui ne pointe plus en sortie sur une valeur =  def_equi_R)
           // mais c'est pour bien marquer le fait que à la sortie de la coïncidence, le pointeur iadef_equi de def_equi à changé
           Coincidence(bascule_fct_aide,unSur_wBaseCarre,gijHH,gijBB,save_resul,W_a,iatens,iadef_equi
                       ,iafct,pt_sur_principal,iaOi,oi_sur_principal,iatens_princ,iadef_equi_princ
                       ,iaOi_princ,iafct_princ,rayon_tdt,true);
       //--------débug- traçage
           #ifdef MISE_AU_POINT
           if (Permet_affichage() == -77)
              { cout << "\non force la fin du traitement et la coincidence ";
                cout << " fin_traitement = " << fin_traitement
                     << " save_resul.modif= " << save_resul.modif
                     << endl ;
              };
           #endif
       //----- fin débug
          
           // si le phi est négatif, on le met à 0 pour limiter les ennuis dans les calculs d'énergies (ici phi ne sert
           // ne sert que là par la suite)
           if (phi_2_dt < 0.) 
              phi_2_dt = 0.;              
                          
           // -- uptdate des énergies
           UpdateEnergieHyste(energ,sigma_i_barre_BH,sigma_t_barre_tdt,delta_sigma_barre_tdt_BH
                         ,delta_sigma_barre_BH_Ratdt,phi_2_dt,delta_barre_epsBH
                         ,QdeltaSigmaRatdt,wprime,wprime_point,trajet_neutre,def_equi_R_ancien,def_i_equi,def_equi_atdt);
           if (aucun_pt_inversion) { defEqui_maxi = def_equi_atdt;} // si sur la première charge on prend la valeur courante
           else  // on a des pt d'inversion, on prend le maxi des listes principales ou secondaires
             // non c'est pas bon
   /*				   defEqui_maxi = 0; // init
        // pour la liste principale, la dernière valeur est nulle, c'est l'avant dernière qui est la bonne
        if (save_resul.def_equi.size())
          { List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;};
                    // pour la liste secondaire c'est directement la dernière valeur
        if (save_resul.def_equi_t_a_tdt.size())
          { List_io <double>::reverse_iterator iil = save_resul.def_equi_t_a_tdt.rbegin();
            defEqui_maxi = MaX(*iil,defEqui_maxi);
         };*/
                 {   List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;
                 };
           // on met à jour la def de début  de calcul (valant t au début )
           // il s'agit d'une grandeur scalaire (pas tensorielle) on peut donc reprendre la valeur qu'elle avait
           // au moment du précédent pt d'inversion, ce qui évitera de cumuler des erreurs d'intégration
           def_i_equi =  def_equi_R_ancien;  // def_equi_R n'a pas encore été modifié, il correspond à la précédente valeur d'inversion
           // NB: 1)on pourrait également prendre  def_equi_atdt, mais qui cumulle les erreurs d'integ entre les deux derniers pt d'integ
           // 2) c'est la même formule que dans le cas d'une inversion, mais cela ne donne pas du tout le même résultat
         };
      }
	// --- fin de la gestion par rapport au rayon
     else // sinon cas d'une gestion avec la fonction d'aide
      { int pb_calcul_centre_ok = 0; // init pour une gestion locale du cas où le calcul du centre cercle pose pb,
        if (((phase_coincidence==0) && (d_W_a_essai < 0.)) && (!force_fin_traitement))
          { // on a un point d'inversion
            // -- on vérifie la cohérence de la valeur de la fonction d'aide
            if (!aucun_pt_inversion) // si on a déjà des pt d'inversion, on vérifie les niveaux de la fonction d'aide
              if (W_a > *iafct)
                {cout << "\n erreur dans l'algorithme de gestion de la memoire discrete,  "
                      << " bien que l'on ait detecte un point d'inversion, il se trouve que la fonction d'aide "
                      << " est superieur au dernier maxi, ce qui signifie que le calcul de l'integrale de la puissance "
                      << " non reversible (phi(t)) n'a pas ete correcte (c'est une erreur cumulee), du sans doute a des pas de temps trop grand, "
                      << " il n'est pas possible de continuer le calcul, essayer de le reprendre avec un pas de temps plus petit ! "
                      << " \n W_a= " << W_a  << " iafct= " << *iafct
                      << "\n Hysteresis3D::Avancement_temporel(...";
                 if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature(); cout << flush;
                 Sortie(1);
                };
            // -- calcul des centre de cercle
            if (!aucun_pt_inversion) // s'il y a au moins déjà un point d'inversion valide on peut traiter
             {Tenseur3BH sig0i_BH;
              pb_calcul_centre_ok=CentreCercle(sig0i_BH,oc_BH_R,delta_sigma_barre_BH_OiaR
                          ,delta_sigma_barre_BH_Rat);
              if (!pb_calcul_centre_ok) // si le calcul a été ok
                {save_resul.oc_BH_t_a_tdt.push_front(sig0i_BH);
                 iaOi = save_resul.oc_BH_t_a_tdt.begin(); // init du centre courant pour la suite
                 oi_sur_principal = false;                // va être mis à jour au début de la prochaine boucle
                 centre_initial = false;                 // du while (!fin_traitement)
                };
             }
            else // si auparavant il n'y avait pas de pt d'inversion, maintenant il y en a un
             {aucun_pt_inversion = false;  // on le signal pour la suite
              // point d'inversion
              wBase = 2; unSur_wBaseCarre = 0.25; //=1./(wBase*wBase);
              defEqui_maxi = def_i_equi;
             };
            // -- s'il n'y a pas eu de pb de calcul de centre on met tout à jour ==> fonctionnement normal
            if (!pb_calcul_centre_ok)
              { // calcul du nouveau centre d'inversion et sauvegarde, sauf dans le cas du premier point
                // d'inversion, pour lequel le centre reste  encore le tenseur nul pour la suite

                // gestion du paramètre "modif" de saveresult
                bool inversion = true;
                Gestion_para_Saveresult_Modif(pt_sur_principal,save_resul,inversion);
               
                // ajout de la contrainte de référence = sigma at
                save_resul.sigma_barre_BH_R_t_a_tdt.push_front(sigma_i_barre_BH);
                // on ajoute le W_a et non le W_a_essai, car ce dernier n'est pas correcte
                // par contre le W_a est de dernier maxi correcte
                save_resul.fct_aide_t_a_tdt.push_front(W_a);
                W_a=0.; delta_W_a = 0.; // on ré-initialise pour les futures coincidences éventuelles
                iatens = save_resul.sigma_barre_BH_R_t_a_tdt.begin(); // pour l'init du début du while générale
                iafct = save_resul.fct_aide_t_a_tdt.begin();
                pt_sur_principal = false; // on indique que maintenant on pointe sur la nouvelle liste
                // on indique le point d'inversion pour les futurs traitements
                sigma_barre_BH_R =save_resul.sigma_barre_BH_R_t_a_tdt.front();
                // -- idem pour la déformation équivalente 
                save_resul.def_equi_t_a_tdt.push_front(def_i_equi);
                iadef_equi = save_resul.def_equi_t_a_tdt.begin(); // pour l'init du début du while générale
                 // on indique la déformation équivalente d'inversion pour les futurs traitements
                def_equi_R  = save_resul.def_equi_t_a_tdt.front();
                // on met à jour la def de début  de calcul (valant t au début, puis tau= pt d'inver ensuite ) pour def_equi_atdt
                def_i_equi =  def_equi_R;                    
                // le calcul d'énergie se fera ensuite dans le cas normale ou avec coïncidence
                // car la valeur actuelle de sigma est erroné, et phi est négatif

                fin_traitement = false; // -- il faut recalculer avec le nouveau point d'inversion
              };
           // sinon on est dans le cas où il y a eu un pb dans le calcul du centre --> ce qui invalide le point d'inverion
           // on indique qu'il faut traiter la suite comme si il n'y avait pas de point d'inversion
           // ceci se fait au travers de l'indicateur: pb_calcul_centre_ok
             
          };//-- fin du cas de l'inversion
        //-------------------------------------------------
        // arrivée ici on peu éventuellement calculer une valeur de la fonction d'aide correcte
        // dans l'expression suivante, on utilise une intégration incrémentale ...
        // s'il y a eu un pb de calcul de centre, cela veut dire que phi_2_dt était légèrement
        // négatif à la prec près, il ne faut pas le compter
        if (pb_calcul_centre_ok) {delta_W_a = 0;}
        else { delta_W_a =  d_W_a_essai;};
        if (phase_coincidence != 1)
           W_a += delta_W_a;
       
        if (((phase_coincidence==1) || (delta_W_a > 0.)) || force_fin_traitement)
          {if (W_a > *iafct) // on regarde si on est en coïncidence
              phase_coincidence=1;
          
           
           if (((phase_coincidence==0)&&(W_a <= *iafct)) && (!force_fin_traitement))// cas normal après plusieurs inversion
            //======================================================================================
            // c-a-d       si phi_2_dt = 0 : on se promène sur un cercle
            //             si phi_2_dt > 0 : progression normale
            //             si pb_calcul_centre_ok != 0 : on est dans un cas limite pour lequel il est préférable de ne pas
            //                                           introduire de point d'inversion
             { // --- cas d'une évolution normale sans inversion ni coincidence ---
                // mais cette évolution peut-être la fin après une coincidence par exemple, donc
                // on ne modifie pas save_resul.modif
                fin_traitement = true;
                save_resul.fonction_aide_tdt = W_a;
                // -- uptdate des énergies
                UpdateEnergieHyste(energ,sigma_i_barre_BH,sigma_t_barre_tdt,delta_sigma_barre_tdt_BH
                            ,delta_sigma_barre_BH_Ratdt,phi_2_dt,delta_barre_epsBH
                            ,QdeltaSigmaRatdt,wprime,wprime_point,trajet_neutre,def_equi_R,def_i_equi,def_equi_atdt);
                if (aucun_pt_inversion) { defEqui_maxi = def_equi_atdt;} // si sur la première charge on prend la valeur courante
                else  // on a des pt d'inversion, on prend le maxi des listes principales ou secondaires
                // non c'est pas bon
                    {   List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;};
              }
           else if ((phase_coincidence==1) && (!force_fin_traitement))
            //======================================================================================
            // cas où on est en coïncidence: on gère toutes les coïncidence en même temps c-a-d courbe secondaire
            // ou retour sur la courbe principale
            { // -- on calcul exactement le point de coïncidence
              // auparavant on sauvegarde le delta eps pour connaître la partie concernée pour le
              Tenseur3BH delta_eps_sur_deltaTau_BH = delta_barre_epsBH;  // calcul d'énergie
              double def_equi_R_ancien= def_equi_R; // sauvegarde qui ne sert à rien, car Coincidence ne change pas 
              // directement def_equi_R, seulement le pointeur iadef_equi (qui lui ne pointe plus en sortie
              // sur une valeur =  def_equi_R)
              // mais c'est pour bien marquer le fait que à la sortie de la coïncidence,
              // le pointeur iadef_equi de def_equi à changé
              double ratio_deformation_pour_coincidence=0;
              bool force_coincidence = false; // init par défaut
              if (phase_coincidence ==1)  // si on suit une phase de coincidence qui vient d'être repéré, à la boucle précédente
                force_coincidence = true; // on force au deuxième tour la coincidence
//--- debug


//-- fin debug
                          
              bool coincidence_exacte = Coincidence(bascule_fct_aide,unSur_wBaseCarre,gijHH,gijBB
                               ,save_resul,W_a
                               ,iatens,iadef_equi,iafct,pt_sur_principal,iaOi,oi_sur_principal,iatens_princ
                               ,iadef_equi_princ,ratio_deformation_pour_coincidence,iaOi_princ,iafct_princ,delta_W_a,force_coincidence);
             
              // si la coïncidence est parfaite, dans ce cas seulement elle a été validée dans l'algo  Coïncidence
              // et on peut updater les énergies, sinon on refait un passage avec une déformation diminuée pour
              // obtenir une coïncidence exacte
              if (coincidence_exacte)
               { // -- cas d'une coïncidence validée
                 // dans le cas d'un trajet strictement radial, on a deux coïncidences à suivre
                 // mais on laisse l'algorithme passer deux fois, car sinon il y a des pb dans le cas
                 // de grand incrément
                
                 // -- uptdate des énergies
                
                 UpdateEnergieHyste(energ,sigma_i_barre_BH,sigma_t_barre_tdt,delta_sigma_barre_tdt_BH
                               ,delta_sigma_barre_BH_Ratdt,phi_2_dt,delta_barre_epsBH
                               ,QdeltaSigmaRatdt,wprime,wprime_point,trajet_neutre,def_equi_R_ancien,def_i_equi,def_equi_atdt);
                 if (aucun_pt_inversion) { defEqui_maxi = def_equi_atdt;} // si sur la première charge on prend la valeur courante
                 else  // on a des pt d'inversion, on prend le maxi des listes principales ou secondaires
                   // non c'est pas bon
                       { List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;};
                 // on met à jour la def de début  de calcul (valant t au début )
                 // il s'agit d'une grandeur scalaire (pas tensorielle) on peut donc reprendre la valeur qu'elle avait
                 // au moment du précédent pt d'inversion, ce qui évitera de cumuler des erreurs d'intégration
                 def_i_equi =  def_equi_R_ancien;  // def_equi_R n'a pas encore été modifié, il correspond à la précédente valeur d'inversion
                 // NB: 1)on pourrait également prendre  def_equi_atdt, mais qui cumulle les erreurs d'integ entre les deux derniers pt d'integ
                 // 2) c'est la même formule que dans le cas d'une inversion, mais cela ne donne pas du tout le même résultat
                
                 // Mise en place de la déformation restante pour le calcul qui suit
                 delta_epsBH_totale -= delta_epsBH; delta_epsBH = delta_epsBH_totale;
                 delta_barre_epsBH_totale -= delta_barre_epsBH; delta_barre_epsBH = delta_barre_epsBH_totale;
                 // idem pour la contrainte de départ
                 sigma_i_barre_BH = sigma_t_barre_tdt;
//                 ratio_deformation_en_cours += ratio_multiplicatif_coincidence;
//                 ratio_multiplicatif_coincidence = 1.;
                 phase_coincidence = 0; // on réinitialise pour les autres passages
               }
              else
               { // -- cas non valide, on prépare pour une passe suivante
                 phase_coincidence = 1;
//                 ratio_multiplicatif_coincidence *= ratio_deformation_pour_coincidence;
//                 if (ratio_deformation_en_cours + ratio_multiplicatif_coincidence > 1.)
//                     // on ne peut pas dépasser la déformation imposée on limite donc
//                     ratio_multiplicatif_coincidence = 1.-ratio_deformation_en_cours;
                 delta_barre_epsBH *= ratio_deformation_pour_coincidence;
                 delta_epsBH *= ratio_deformation_pour_coincidence;
              }
            }
           else // cas où on force la fin du traitement: force_fin_traitement = true
            { // ici comme on force une coïncidence exacte, il n'y a pas de calcul de point intermédiaire
              // donc on reprend l'appel du cas des rayons, mais c'est équivalent à l'autre appel de Coincidence
              // avec la fonction d'aide
              fin_traitement = true;
              // comme (rayon_tdt >= Q_OiaR ) on force la coincidence
              double def_equi_R_ancien= def_equi_R; // sauvegarde qui ne sert à rien, car Coincidence ne change pas 
              // directement def_equi_R, seulement le pointeur iadef_equi (qui lui ne pointe plus en sortie sur une valeur =  def_equi_R)
              // mais c'est pour bien marquer le fait que à la sortie de la coïncidence, le pointeur iadef_equi de def_equi à changé
              Coincidence(bascule_fct_aide,unSur_wBaseCarre,gijHH,gijBB,save_resul,W_a,iatens,iadef_equi
                          ,iafct,pt_sur_principal,iaOi,oi_sur_principal,iatens_princ,iadef_equi_princ
                          ,iaOi_princ,iafct_princ,rayon_tdt,true);
             
              // si le phi est négatif, on le met à 0 pour limiter les ennuis dans les calculs d'énergies (ici phi ne sert
              // ne sert que là par la suite)
              if (phi_2_dt < 0.) 
                 phi_2_dt = 0.;              
                             
              // -- uptdate des énergies
              UpdateEnergieHyste(energ,sigma_i_barre_BH,sigma_t_barre_tdt,delta_sigma_barre_tdt_BH
                            ,delta_sigma_barre_BH_Ratdt,phi_2_dt,delta_barre_epsBH
                            ,QdeltaSigmaRatdt,wprime,wprime_point,trajet_neutre,def_equi_R_ancien,def_i_equi,def_equi_atdt);
              if (aucun_pt_inversion) { defEqui_maxi = def_equi_atdt;} // si sur la première charge on prend la valeur courante
              else  // on a des pt d'inversion, on prend le maxi des listes principales ou secondaires
                // non c'est pas bon
                    {   List_io <double>::reverse_iterator iil = save_resul.def_equi.rbegin();iil++;defEqui_maxi = *iil;
                    };
              // on met à jour la def de début  de calcul (valant t au début )
              // il s'agit d'une grandeur scalaire (pas tensorielle) on peut donc reprendre la valeur qu'elle avait
              // au moment du précédent pt d'inversion, ce qui évitera de cumuler des erreurs d'intégration
              def_i_equi =  def_equi_R_ancien;  // def_equi_R n'a pas encore été modifié, il correspond à la précédente valeur d'inversion
              // NB: 1)on pourrait également prendre  def_equi_atdt, mais qui cumulle les erreurs d'integ entre les deux derniers pt d'integ
              // 2) c'est la même formule que dans le cas d'une inversion, mais cela ne donne pas du tout le même résultat
            };
          };
      };
        
     // calcul de la contrainte de retour si le traitement est fini
     // et mise à jour a doc
     if (fin_traitement)
        {save_resul.sigma_barre_BH_tdt = sigma_t_barre_tdt;
         save_resul.wBase_tdt = wBase;
         save_resul.def_equi_atdt = def_equi_atdt;
         switch (cas)
          {case 1: 
            	{ // cas de la dérivée de jauman
                  Tenseur_ns3HH sig1HH(gijHH * sigma_t_barre_tdt);
                  sigHH = 0.5*(sig1HH+sig1HH.Transpose()); // jauman
            	  break;	
            	}
           case 2:
            	{ // pas de symétrisation du tenseur
                  sigHH = gijHH * sigma_t_barre_tdt; 
            	  break;	
            	}
           default:
             cout << "\n erreur: cas= " << cas << " non prevu pour le type de derivee de la contrainte ";
             if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
             cout << "\n Hysteresis3D::Avancement_temporel(...)" << endl;
             Sortie(1);      	
          };
       //--------débug- traçage
         #ifdef MISE_AU_POINT
         if (Permet_affichage() == -77)
            { cout << "\n$$$ === fin de l'algo d'avancement : calcul de la contrainte " << endl ;
            };
         #endif
       //----- fin débug
        };
     // on regarde si l'on n'a pas dépassé le nombre de boucle maxi permis: ce qui permet
     // d'éviter les boucles infinies
     nb_coin_inver++;
     if (nb_coin_inver > Abs(nb_maxInvCoinSurUnPas))
     	  { // dans ce cas cela signifie qu'il y a pb et on arrête en générant éventuellement
          // une interruption d'erreur de convergence dans une loi de comportement
          if (((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 3))
             {cout << "\n warning dans le calcul de la contrainte a t+dt, le nombre de coincidence et/ou"
                   << " d'inversion (" << nb_coin_inver << ") est superieur a la limite fixee: = " 
                   << nb_maxInvCoinSurUnPas ;
              if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature(); cout << flush;
             };
                   
// débug---------
//    Verif_coincidence(delta_epsBB,gijHH,cas,save_resul,sigHH,energ_t,energ,true);
//    Sortie(1);
// fin débug -------------
                   
          if (save_resul.nb_coincidence == 0) 
           { // on est dans un cas particulier où l'algo fait du sur-place: un coup il trouve une coïncidence
             // puis le coup après il trouve une inversion --> il revient au même endroit --> boucle infini
             // dans ce cas on décide de manière arbitraire a imposer la coïncidence ce qui garantie la cohérence de la
             // succession des rayons on contraire d'imposer l'inversion, qui conduira à un rayon incohérent (ce qui conduit
             // normalement tout de suite après à une coïncidence)
             force_fin_traitement = true;
             if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 3))
               cout << " on est dans le cas d'aller-retour identiques !! on impose la coincidence " << endl;
           }
          else // on regarde s'il faut imposer la valeur finale obtenue ou générer une erreur
           { if (nb_maxInvCoinSurUnPas > 0)
                { throw ErrNonConvergence_loiDeComportement();break;}  // envoie d'un signal a traiter en dehors
             else  
                { force_fin_traitement = true;
                  if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 3))
                    cout << " on impose la coincidence " << endl;
                }; // cas où on impose coûte que coûte (résultat pas sûr !!)
           };
     	  };
     
    };// -- fin du While (!fin_traitement)
		
};
 
// initialisation éventuelle des variables thermo-dépendantes
void Hysteresis3D::Init_thermo_dependance()
 { // cas d'une thermo dépendance, on calcul les grandeurs en fonction de la température
   if (xnp_temperature != NULL) xnp = xnp_lue = xnp_temperature->Valeur(*temperature);
   if (Qzero_temperature != NULL) Qzero = Qzero_lue = Qzero_temperature->Valeur(*temperature);
   if (xmu_temperature != NULL) xmu = xmu_lue = xmu_temperature->Valeur(*temperature);
//--- pour le debug
//cout << "\n np=" << xnp << " Q0=" << Qzero <<	" xmu=" << xmu  << " T=" << *temperature;
//--- fin debug
   		
 };		  	
 

// méthode permettant le calcul de sigma à tdt par différente méthodes: linéarisation
// ou kutta
// en sortie calcul de : 
//    sigma_t_barre_tdt, delta_sigma_barre_tdt_BH, delta_sigma_barre_BH_Ratdt
//    également les grandeurs: QdeltaSigmaRatdt, et wprime,wprime_point, calculées à tdt
// ramène en retour la valeur de phi_2_dt

void Hysteresis3D::CalculContrainte_tdt(double & phi_2_dt,Tableau<double>& indicateurs_resolution)
	{ // le calcul de la contrainte s'effectue par la résolution de l'équation différentielle
      // du schéma constitutif en BH, et toutes les grandeurs sont relatives à BH
      // bien voir que que ce n'est qu'une partie de l'équation, et que pour l'intégration de 
      // la dérivée de Jauman, il faut aussi la partie HB qui est différente, mais on a une symétrie
      // formelle (cf théorie) 
      //  sigma_point = 2*mu*D_barre + beta*phi*(delta_barre de t à R de Sigma)
  
      if ((sortie_post)&&(indicateurs_resolution.Taille()!= 5)) // dimensionnement éventuelle de la sortie d'indicateurs
        indicateurs_resolution.Change_taille(5); 
      
      calcul_dResi_dsig=false; // on indique que pour l'instant la matrice tangente n'est pas calculée
      // comme la matrice n'est pas forcément définie positive on utilise GAUSS avec MatLapack     
      der_at_racine.Change_Choix_resolution(GAUSS,RIEN_PRECONDITIONNEMENT); 
      bool passage_par_newton = false; // permettra de savoir si on est passé par du newton dans le cas d'un basculement de méthode
      //-- choix de la méthode 
      switch (type_resolution_equa_constitutive)
       {case 1: // cas de la linéarisation de l'équation
         {// ----- pour ce faire on appelle une methode de recherche de zero
          val_initiale.Zero(); // on démarre la recherche à la valeur à t 
          racine.Zero();            // init du résultat à 0.
          der_at_racine.Initialise(0.); // init de la matrice dérivée à 0.
          // on met à jour éventuellement le tableau d'indicateurs
          // 1== résolution de l'équation constitutive d'avancement discrétisée en euler implicite
          int nb_incr_total,nb_iter_total; // variables intermédiaires d'indicateurs
          bool conver = false; // init par défaut
          try // on met le bloc sous surveillance
           {
             conver=alg_zero.Newton_raphson
                   (*this,&Hysteresis3D::Residu_constitutif,&Hysteresis3D::Mat_tangente_constitutif
                    ,val_initiale,racine,der_at_racine,nb_incr_total,nb_iter_total
                    ,maxi_delta_var_sig_sur_iter_pour_Newton);
           }
          catch (ErrSortieFinale)
               // cas d'une direction voulue vers la sortie
               // on relance l'interuption pour le niveau supérieur
             { ErrSortieFinale toto;
               throw (toto);
             }
          catch ( ... ) //(ErrNonConvergence_Newton erreur)
           { double absracinemax=racine.Max_val_abs();
             if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 0))
                {cout << "\n non convergence 2 sur l'algo de la resolution du schema constitutif"
                      << " abs_racine_max " << absracinemax;
                 if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
                 cout << "\n Hysteresis3D::CalculContrainte_tdt(.." << endl;
                };
             LibereTenseur();
             LibereTenseurQ();
             // on génère une exception
             throw ErrNonConvergence_loiDeComportement();break;
           };
          
          if(sortie_post) // sauvegarde éventuelle des indicateurs
            {indicateurs_resolution(1)+=nb_incr_total;indicateurs_resolution(2)+=nb_iter_total;
////---- debug
//               cout << "\n Hysteresis3D::CalculContrainte_tdt: indicateurs_resolution(1)= "<< indicateurs_resolution(1)
//                    << "  indicateurs_resolution(2)=" << indicateurs_resolution(2)
//                    << " nb_incr_total "<< nb_incr_total << " nb_iter_total "<< nb_iter_total<< endl;
////---- fin debug
            };
//          if (!conver)
          double absracinemax=racine.Max_val_abs();
          if ((!conver) || (!isfinite(absracinemax)) || (isnan(absracinemax)) )
            { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 0))
                {cout << "\n non convergence sur l'algo de la resolution du schema constitutif"
                      << " abs_racine_max " << absracinemax;
                 if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
                 cout << "\n Hysteresis3D::CalculContrainte_tdt(.." << endl;
                };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
            }; 
          // récup de la solution
          for (int ig=1;ig<=9;ig++)
            delta_sigma_barre_tdt_BH.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=racine(ig);
           
          sigma_t_barre_tdt = sigma_i_barre_BH + delta_sigma_barre_tdt_BH;
//---- debug
          if ((ParaGlob::NiveauImpression() > 5)|| (Permet_affichage() > 5))
            // on vérifie que l'amplitude de la contrainte transmise, n'est pas supérieure à la saturation
            { double sigma_tau_II = sigma_tauBH.II();
              if ( sigma_tau_II > Qzero*Qzero)
                cout << "\n sigma_tau_II= "<< sigma_tau_II << "  Hysteresis3D::CalculContrainte_tdt" << endl;
            };
//---- fin debug

          // ici il n'est pas nécessaire de calculer QdeltaSigmaRatdt, et wprime,wprime_point
          // car ces grandeurs sont calculées à l'intérieur de la boucle de Newton, et 
          // pour t+dt donc pas de pb 
          delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;
          passage_par_newton = true; // c'est vrai compte tenu de la méthode
          
          //modif : 11 juin 2014
          // on vérifie que l'amplitude de la contrainte calculée
          {double QdeltaSigma = sqrt(delta_sigma_barre_R_a_tauBH.II());
           if ( QdeltaSigma > (Qzero*depassement_Q0*wBase))
             {if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
               {cout << "\n erreur10 fatale dans  l'algo de la resolution du schema constitutif"
                     << " concernant le niveau de saturation de la contrainte  "
                     << "\n QdeltaSigma =" << QdeltaSigma << " au lieu de "<< (Qzero*depassement_Q0*wBase);
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
                cout << "\n Hysteresis3D::CalculContrainte_tdt() (..." << endl;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
             };
          };
          break;
         }
        case 2: // cas d'une résolution par intégration explicite par du kutta
                // si cela ne converge pas on bascule sur de la linéarisation
         {//initialisation  des variables de calcul 
          for (int ig=1;ig<=9;ig++)
            sig_initiale(ig)=sigma_i_barre_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
          double tdeb=0.,tfi=1.;
          // calcul de la dérivée initiale
          int erreur=0; //init d'une erreur de calcul de Sigma_point
          Sigma_point(tdeb,sig_initiale,dersig_initiale,erreur);
//// --- debug ---
//cout << "\n Hysteresis3D::CalculContrainte_tdt avant kutta"
//     << "\n sig_initiale= ";sig_initiale.Affiche();
//cout << "\n dersig_initiale= "; dersig_initiale.Affiche();
//cout <<  endl;      double QdeltaSigma = sqrt(delta_sigma_barre_R_a_tauBH.II());

//// --- fin debug ---
          if (erreur) // cas où le calcul de la dérivée initiale n'est pas possible, on ne peut pas aller plus loin
            { if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
               {cout << "\n erreur0 fatale dans  l'algo de la resolution du schema constitutif"
                     << " au niveau du calcul de la derivee initiale "
                     << "\n QdeltaSigma =" << sqrt(delta_sigma_barre_R_a_tauBH.II())
                     << " au lieu de "<< (Qzero*depassement_Q0*wBase);
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
                cout << "\n Hysteresis3D::CalculContrainte_tdt() (..." << endl;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
            }; 
          double dernierTemps=0.,dernierdeltat=0.; // valeurs de retour
          int nombreAppelF=0,nb_step=0;            //  "          "
          double erreur_maxi_global=0.;            //   "
          
          // appel de la fonction kutta
          int conver=alg_edp.Pilotage_kutta
                      (cas_kutta,*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                       ,sig_initiale,dersig_initiale
                       ,tdeb,tfi,erreurAbsolue,erreurRelative
                       ,sig_finale,dersig_finale,dernierTemps,dernierdeltat
                       ,nombreAppelF,nb_step,erreur_maxi_global);
          if(sortie_post) // sauvegarde éventuelle des indicateurs
            {indicateurs_resolution(3)+=nombreAppelF;indicateurs_resolution(4)+=nb_step;
             indicateurs_resolution(5)+=erreur_maxi_global;
            };
           // gestion de l'erreur de retour
//           if ((conver != 2) || (sig_finale.Max_val_abs() > ConstMath::tresgrand))
// --- debug piloté ---
          if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
            cout << "\n Hysteresis3D::CalculContrainte_tdt "
                 << "nombreAppelF= " << nombreAppelF << " nb_step= " << nb_step << " erreur_maxi_global= "
                 << erreur_maxi_global << endl;
// --- fin debug piloté---

           double abssigmax=sig_finale.Max_val_abs();
           if ((conver != 2) || (!isfinite(abssigmax)) || (isnan(abssigmax)) )
           	{// dans le cas où le Runge ne marche pas on essaie avec la première méthode
             // linéarisation de l'équation
             // ----- pour ce faire on appelle une methode de recherche de zero             
             val_initiale.Zero(); // on démarre la recherche à la valeur à t 
             racine.Zero();            // init du résultat à 0.
             der_at_racine.Initialise(0.); // init de la matrice dérivée à 0.
             int nb_incr_total,nb_iter_total; // variables intermédiaires d'indicateurs
             // 1== résolution de l'équation constitutive d'avancement discrétisée en euler implicite
             bool converge=alg_zero.Newton_raphson
                   (*this,&Hysteresis3D::Residu_constitutif,&Hysteresis3D::Mat_tangente_constitutif
                    ,val_initiale,racine,der_at_racine,nb_incr_total,nb_iter_total
                    ,maxi_delta_var_sig_sur_iter_pour_Newton);
             if(sortie_post) // sauvegarde éventuelle des indicateurs
               {indicateurs_resolution(1)+=nb_incr_total;indicateurs_resolution(2)+=nb_iter_total;};
             double absracinemax=racine.Max_val_abs();
             if ((converge) && (isfinite(absracinemax)) && (!isnan(absracinemax)))
             	{ // on a convergé, donc on termine le calcul et on sort du switch
                  // récup de la solution
                  for (int ig=1;ig<=9;ig++)
                    delta_sigma_barre_tdt_BH.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=racine(ig);
           
                  sigma_t_barre_tdt = sigma_i_barre_BH + delta_sigma_barre_tdt_BH; 
                  // ici il n'est pas nécessaire de calculer QdeltaSigmaRatdt, et wprime,wprime_point
                  // car ces grandeurs sont calculées à l'intérieur de la boucle de Newton, et 
                  // pour t+dt donc pas de pb 
                  delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;
                  passage_par_newton = true; // on indique donc que l'on est passé par du newton
                  if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 3))
                  	 { cout << "\n probleme dans la resolution de l'equation constitutive avec Runge Kutta";
                      if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature(); cout << flush;
                      if (conver != 2)
                         alg_edp.Affiche_Explication_erreur_RG(conver);
                      if (!isfinite(abssigmax))
                         cout  << " abssigmax n'est pas fini = " << abssigmax ;
                      if (isnan(abssigmax))
                         cout  << " abssigmax = nan = " << abssigmax ;
                  	   if (Permet_affichage() > 2)
                       { cout << "\n  abs_racine_max " << absracinemax;}
                      if (Permet_affichage() > 4)
                       {cout <<  " (2) utilisation avec succes de la linearisation ";};
                      if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
                          cout << "\n Hysteresis3D::CalculContrainte_tdt (..."<<endl;
                    };
                  // puis on met conver à 2 pour signaler que pour la suite que ça a convergé
                  conver=2;        
                  break;
             	}
             else // sinon on n'a pas convergé également avec la linéarisation
              // on indique à toute fin utile que la première n'a pas convergé au cas ou cela n'aurait pas été noté
              { if (conver == 2)
                   conver = 0 ;
              };
           	};
           // arrivé ici cela signifie que: soit kutta a convergé -> conver=2, 
           // soit kutta n'a pas convergé et la méthode de linéarisation n'a pas également convergé -> conver != 2
           // --- si on n'a pas convergé:
           if (conver !=2) // cas d'une non convergence
            { // on appel du kutta adoc sans gestion d'erreur !!
              double deltat=tfi-tdeb;
              switch (cas_kutta)
              	{ case 3:
              	  	{ alg_edp.Runge_Kutta_step23(*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                                               ,sig_initiale,dersig_initiale,tdeb,deltat,sig_finale,estime_erreur);
                    break;                           
              	  	}
                 case 4:
              	  	{ alg_edp.Runge_Kutta_step34(*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                                               ,sig_initiale,dersig_initiale,tdeb,deltat,sig_finale,estime_erreur);
                    break;                           
              	  	}
                 case 5:
              	  	{ alg_edp.Runge_Kutta_step45(*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                                               ,sig_initiale,dersig_initiale,tdeb,deltat,sig_finale,estime_erreur);
                    break;                           
              	  	}
              	  default:
              	   cout << "\n erreur , cas Runge kutta non prevu ! "
              	        << "\n Hysteresis3D::CalculContrainte_tdt(..";
                  if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
              	   Sortie(1);
              	};
              if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 3))
              	{cout << "\n probleme dans la resolution de l'equation constitutive avec Runge Kutta";
                alg_edp.Affiche_Explication_erreur_RG(conver);
                cout <<  ", appel direct de kutta-> erreur estimee= " << estime_erreur(1)
                      << "\n Hysteresis3D::CalculContrainte_tdt (...";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               //  Sortie(1);
               // pour le debug
     //          if ((Dabs(estime_erreur(1)) > 10) || (Dabs(sig_finale(1)) > 10))
     //             alg_edp.Runge_Kutta_step45(*this,& Hysteresis3D::Sigma_point,sig_initiale,dersig_initiale
     //                    ,tdeb,deltat,sig_finale,estime_erreur);
                 
              	};
              double abssigmax=sig_finale.Max_val_abs();
              if ((!isfinite(abssigmax)) || (isnan(abssigmax)) )
               // dans le cas où la valeur de sig_finale est infinie, ce n'est pas la peine d'aller plus loin
               {
              	   cout << "\n erreur , l'appel directe de Kutta donne une valeur infinie de contrainte ! "
              	        << "\n Hysteresis3D::CalculContrainte_tdt(..";
                  if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                  // on génère une exception
                  throw ErrNonConvergence_loiDeComportement();
              	   Sortie(1);     	
               };
            }
          
           // -- arrivée ici, cela veut dire que: 1) soit le RG de départ a marché correctement,
           // 2) soit la linéarisation a marché correctement, 3) soit si les deux autres n'ont pas marché,
           // on a eu un appel directe à un Rg d'un ordre donné, avec un résultat non contrôlé
           else if (!passage_par_newton)// sinon cela veut dire que c'est le résultat avec Runge que l'on exploite
            {// récup des résultats
             for (int ig=1;ig<=9;ig++)
               sigma_t_barre_tdt.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=sig_finale(ig);
             delta_sigma_barre_tdt_BH =  sigma_t_barre_tdt - sigma_i_barre_BH;   
             // ici on doit calculer QdeltaSigmaRatdt, et wprime,wprime_point
             // car ces grandeurs ne sont pas calculées au temps final !! dans la méthode de Runge-Kutta
             // d'ailleurs elles ne sont même pas calculées en temps que grandeurs globales !!
             delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;          
             QdeltaSigmaRatdt = sqrt(delta_sigma_barre_BH_Ratdt.II());
            };
          // le dernier cas possible avec convergence est celui du passage par newton, et dans ce cas
          // la sauvegarde a déjà été faite
          
          //modif : 11 juin 2014
          // on vérifie que l'amplitude de la contrainte calculée
          {double QdeltaSigma = sqrt(delta_sigma_barre_R_a_tauBH.II());
           if ( QdeltaSigma > (Qzero*depassement_Q0*wBase))
             {if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
               {cout << "\n erreur11 fatale dans  l'algo de la resolution du schema constitutif"
                     << " concernant le niveau de saturation de la contrainte  "
                     << "\n QdeltaSigma =" << QdeltaSigma << " au lieu de "<< (Qzero*depassement_Q0*wBase)
                     << "\n Hysteresis3D::CalculContrainte_tdt() (...";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
             };
          };

          break;
         }
        case 3: // cas d'une résolution par intégration explicite par du kutta
                // mais ici si ça ne converge pas on génère une exception c'est tout , on ne cherche pas
                // a utiliser une autre méthode de secours
         {//initialisation  des variables de calcul 
          for (int ig=1;ig<=9;ig++)
            sig_initiale(ig)=sigma_i_barre_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
          double tdeb=0.,tfi=1.;
          int erreur=0; //init d'une erreur de calcul de Sigma_point
          // calcul de la dérivée initiale
          Sigma_point(tdeb,sig_initiale,dersig_initiale,erreur);
          if (erreur) // cas où le calcul de la dérivée initiale n'est pas possible, on ne peut pas aller plus loin
            { if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
               {cout << "\n erreur1 fatale dans  l'algo de la resolution du schema constitutif"
                     << " au niveau du calcul de la derivee initiale "
                     << "\n QdeltaSigma =" << sqrt(delta_sigma_barre_R_a_tauBH.II()) << " au lieu de "<< Qzero
                     << "\n Hysteresis3D::CalculContrainte_tdt() (...";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
            }; 
          
          double dernierTemps=0.,dernierdeltat=0.; // valeurs de retour
          int nombreAppelF=0,nb_step=0;            //  "          "
          double erreur_maxi_global=0.;            //   "
          
          // appel de la fonction kutta
          int conver=alg_edp.Pilotage_kutta
                      (cas_kutta,*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                       ,sig_initiale,dersig_initiale
                       ,tdeb,tfi,erreurAbsolue,erreurRelative
                       ,sig_finale,dersig_finale,dernierTemps,dernierdeltat
                       ,nombreAppelF,nb_step,erreur_maxi_global);
          if(sortie_post) // sauvegarde éventuelle des indicateurs
            {indicateurs_resolution(3)+=nombreAppelF;indicateurs_resolution(4)+=nb_step;
             indicateurs_resolution(5)+=erreur_maxi_global;
            };
// --- debug piloté ---
          if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
            cout << "\n Hysteresis3D::CalculContrainte_tdt "
                 << "nombreAppelF= " << nombreAppelF << " nb_step= " << nb_step << " erreur_maxi_global= "
                 << erreur_maxi_global << endl;
// --- fin debug piloté---
           // gestion de l'erreur de retour
//           if ((conver != 2) || (sig_finale.Max_val_abs() > ConstMath::tresgrand))
           double abssigmax=sig_finale.Max_val_abs();
           if ((conver != 2) || (!isfinite(abssigmax)) || (isnan(abssigmax)) )
             { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 0))
                 {cout << "\n non convergence sur l'algo de la resolution du schema constitutif"
                       << "\n Hysteresis3D::CalculContrainte_tdt(.." ;
                  if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                 };
                // on génère une exception
                throw ErrNonConvergence_loiDeComportement();break;
             }; 
          // récup des résultats
          for (int ig=1;ig<=9;ig++)
            sigma_t_barre_tdt.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=sig_finale(ig);
          delta_sigma_barre_tdt_BH =  sigma_t_barre_tdt - sigma_i_barre_BH;   
          // ici on doit calculer QdeltaSigmaRatdt, et wprime,wprime_point
          // car ces grandeurs ne sont pas calculées au temps final !! dans la méthode de Runge-Kutta
          // d'ailleurs elles ne sont même pas calculées en temps que grandeurs globales !!
          delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;          
          QdeltaSigmaRatdt = sqrt(delta_sigma_barre_BH_Ratdt.II());
          
          //modif : 11 juin 2014
          // on vérifie que l'amplitude de la contrainte calculée
          {if ( QdeltaSigmaRatdt > (Qzero*depassement_Q0*wBase))
             {if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 0))
               {cout << "\n erreur12 fatale dans  l'algo de la resolution du schema constitutif"
                     << " concernant le niveau de saturation de la contrainte  "
                     << "\n QdeltaSigma =" << QdeltaSigmaRatdt << " au lieu de "<< (Qzero*depassement_Q0*wBase)
                     << "\n Hysteresis3D::CalculContrainte_tdt() (...";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
             };
          };
          
          break;
         }
        case 4: // cas d'une résolution par intégration explicite par du kutta
         {//initialisation  des variables de calcul 
          for (int ig=1;ig<=9;ig++)
            sig_initiale(ig)=sigma_i_barre_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
          double tdeb=0.,tfi=1.;
          // calcul de la dérivée initiale
          int erreur=0; //init d'une erreur de calcul de Sigma_point
          Sigma_point(tdeb,sig_initiale,dersig_initiale,erreur);
          if (erreur) // cas où le calcul de la dérivée initiale n'est pas possible, on ne peut pas aller plus loin
            { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 0))
               {cout << "\n erreur2 fatale dans  l'algo de la resolution du schema constitutif"
                     << " au niveau du calcul de la derivee initiale "
                     << "\n QdeltaSigma =" << sqrt(delta_sigma_barre_R_a_tauBH.II()) << " au lieu de "<< (Qzero*depassement_Q0*wBase)
                     << "\n Hysteresis3D::CalculContrainte_tdt() (...";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
            }; 
          double dernierTemps=0.,dernierdeltat=0.; // valeurs de retour
          int nombreAppelF=0,nb_step=0;            //  "          "
          double erreur_maxi_global=0.;            //   "
          
          // appel de la fonction kutta
          int conver=alg_edp.Pilotage_kutta
                      (cas_kutta,*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                       ,sig_initiale,dersig_initiale
                       ,tdeb,tfi,erreurAbsolue,erreurRelative
                       ,sig_finale,dersig_finale,dernierTemps,dernierdeltat
                       ,nombreAppelF,nb_step,erreur_maxi_global);
          if(sortie_post) // sauvegarde éventuelle des indicateurs
            {indicateurs_resolution(3)+=nombreAppelF;indicateurs_resolution(4)+=nb_step;
             indicateurs_resolution(5)+=erreur_maxi_global;
            };
// --- debug piloté ---
          if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
           {cout << "\n Hysteresis3D::CalculContrainte_tdt "
                 << "nombreAppelF= " << nombreAppelF << " nb_step= " << nb_step << " erreur_maxi_global= "
                 << erreur_maxi_global;
            if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature(); cout << flush;
           };
// --- fin debug piloté---
           // gestion de l'erreur de retour
//           if ((conver != 2) || (sig_finale.Max_val_abs() > ConstMath::tresgrand))
           double abssigmax=sig_finale.Max_val_abs();
           if ((conver != 2) || (!isfinite(abssigmax)) || (isnan(abssigmax)) )
           	{// dans le cas où le Runge ne marche pas on essaie avec la première méthode
             // linéarisation de l'équation
             // ----- pour ce faire on appelle une methode de recherche de zero
             val_initiale.Zero(); // on démarre la recherche à la valeur à t 
             racine.Zero();            // init du résultat à 0.
             der_at_racine.Initialise(0.); // init de la matrice dérivée à 0.
             int nb_incr_total,nb_iter_total; // variables intermédiaires d'indicateurs
             // 1== résolution de l'équation constitutive d'avancement discrétisée en euler implicite
             bool converge=alg_zero.Newton_raphson
                   (*this,&Hysteresis3D::Residu_constitutif,&Hysteresis3D::Mat_tangente_constitutif
                    ,val_initiale,racine,der_at_racine,nb_incr_total,nb_iter_total
                    ,maxi_delta_var_sig_sur_iter_pour_Newton);
             if(sortie_post) // sauvegarde éventuelle des indicateurs
               {indicateurs_resolution(1)+=nb_incr_total;indicateurs_resolution(2)+=nb_iter_total;};
             double absracinemax=racine.Max_val_abs();
             if ((converge) && (isfinite(absracinemax)) && (!isnan(absracinemax)))
             	{ // on a convergé, donc on termine le calcul et on sort du switch
                  // récup de la solution
                  for (int ig=1;ig<=9;ig++)
                    delta_sigma_barre_tdt_BH.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=racine(ig);
                  sigma_t_barre_tdt = sigma_i_barre_BH + delta_sigma_barre_tdt_BH;
                  // ici il n'est pas nécessaire de calculer QdeltaSigmaRatdt, et wprime,wprime_point
                  // car ces grandeurs sont calculées à l'intérieur de la boucle de Newton, et 
                  // pour t+dt donc pas de pb 
                  delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;
                  passage_par_newton = true; // on indique donc que l'on est passé par du newton
                  if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 2)) || (Permet_affichage() > 2))
                  	 { if (Permet_affichage() > 4)
                       {cout << " -> probleme dans la resolution de l'equation constitutive avec Runge Kutta";
                        alg_edp.Affiche_Explication_erreur_RG(conver);
                        cout <<  ", (1) utilisation avec succes de la linearisation ";
                        cout << "\n  abs_racine_max " << absracinemax;
                        if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;                      
                       };
                      if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
                          cout << "\n Hysteresis3D::CalculContrainte_tdt (..."<<endl;
                    };
                  // puis on met conver à 2 pour signaler que pour la suite que ça a convergé
                  conver=2;        
                  break;
             	}
             else
           	  { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 2)) || (Permet_affichage() > 2))
                  {cout << "\n non convergence sur l'algo de la resolution du schema constitutif"
                       << " abs_racine_max " << absracinemax << " conver= " << conver << " abssigmax= " << abssigmax;
                   if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                  };
                
                if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 7)) || (Permet_affichage() > 7))
                  cout   << "\n Hysteresis3D::CalculContrainte_tdt(.." << endl;
                // on génère une exception
                throw ErrNonConvergence_loiDeComportement();break;
             }; 
           	}
           else // sinon cela veut dire que le calcul avec Runge est correcte on sauvegarde les résutats
            {// récup des résultats
             for (int ig=1;ig<=9;ig++)
               sigma_t_barre_tdt.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=sig_finale(ig);
             delta_sigma_barre_tdt_BH =  sigma_t_barre_tdt - sigma_i_barre_BH;   
             // ici on doit calculer QdeltaSigmaRatdt, et wprime,wprime_point
             // car ces grandeurs ne sont pas calculées au temps final !! dans la méthode de Runge-Kutta
             // d'ailleurs elles ne sont même pas calculées en temps que grandeurs globales !!
             delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;          
             QdeltaSigmaRatdt = sqrt(delta_sigma_barre_BH_Ratdt.II());
            };
          
          //modif : 11 juin 2014
          // on vérifie que l'amplitude de la contrainte calculée
          {double QdeltaSigma = sqrt(delta_sigma_barre_R_a_tauBH.II());
           if ( QdeltaSigma > (Qzero*depassement_Q0*wBase))
             {if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
               {cout << "\n erreur13 fatale dans  l'algo de la resolution du schema constitutif"
                     << " concernant le niveau de saturation de la contrainte  "
                     << "\n QdeltaSigma =" << QdeltaSigma << " au lieu de "<< (Qzero*depassement_Q0*wBase)
                     << "\n Hysteresis3D::CalculContrainte_tdt() (..." ;
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
             };
          };
          
          break;
         }
        case 5: case 6:// cas d'une résolution par intégration explicite par du kutta
         // l'idée est ici de diminuer la précision jusqu'à un résultat si on ne converge pas normalement
         {//initialisation  des variables de calcul 
          for (int ig=1;ig<=9;ig++)
            sig_initiale(ig)=sigma_i_barre_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
          double tdeb=0.,tfi=1.;
          // calcul de la dérivée initiale
          int erreur=0; //init d'une erreur de calcul de Sigma_point
          Sigma_point(tdeb,sig_initiale,dersig_initiale,erreur);
          if (erreur) // cas où le calcul de la dérivée initiale n'est pas possible, on ne peut pas aller plus loin
            { if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
               {cout << "\n erreur3 fatale dans  l'algo de la resolution du schema constitutif"
                     << " au niveau du calcul de la derivee initiale "
                     << "\n QdeltaSigma =" << sqrt(delta_sigma_barre_R_a_tauBH.II()) << " au lieu de "
                     << (Qzero*depassement_Q0*wBase)
                     << "\n Hysteresis3D::CalculContrainte_tdt() (...";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
            }; 
          double dernierTemps=0.,dernierdeltat=0.; // valeurs de retour
          int nombreAppelF=0,nb_step=0;            //  "          "
          double erreur_maxi_global=0.;            //   "
          
          // appel de la fonction kutta
          int conver=alg_edp.Pilotage_kutta
                      (cas_kutta,*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                       ,sig_initiale,dersig_initiale
                       ,tdeb,tfi,erreurAbsolue,erreurRelative
                       ,sig_finale,dersig_finale,dernierTemps,dernierdeltat
                       ,nombreAppelF,nb_step,erreur_maxi_global);
          if(sortie_post) // sauvegarde éventuelle des indicateurs
            {indicateurs_resolution(3)+=nombreAppelF;indicateurs_resolution(4)+=nb_step;
             indicateurs_resolution(5)+=erreur_maxi_global;
            };
// --- debug piloté ---
          if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
            cout << "\n Hysteresis3D::CalculContrainte_tdt "
                 << "nombreAppelF= " << nombreAppelF << " nb_step= " << nb_step << " erreur_maxi_global= "
                 << erreur_maxi_global << endl;
// --- fin debug piloté---
          // gestion de l'erreur de retour
//           if ((conver != 2) || (sig_finale.Max_val_abs() > ConstMath::tresgrand))
          double abssigmax=sig_finale.Max_val_abs();
          if ((conver != 2) || (!isfinite(abssigmax)) || (isnan(abssigmax)) )
           	{// dans le cas où le Runge ne marche pas on essaie avec la première méthode
             // linéarisation de l'équation
             // ----- pour ce faire on appelle une methode de recherche de zero
             val_initiale.Zero(); // on démarre la recherche à la valeur à t 
             racine.Zero();            // init du résultat à 0.
             der_at_racine.Initialise(0.); // init de la matrice dérivée à 0.
             int nb_incr_total,nb_iter_total; // variables intermédiaires d'indicateurs
             // 1== résolution de l'équation constitutive d'avancement discrétisée en euler implicite
             bool converge=alg_zero.Newton_raphson
                   (*this,&Hysteresis3D::Residu_constitutif,&Hysteresis3D::Mat_tangente_constitutif
                    ,val_initiale,racine,der_at_racine,nb_incr_total,nb_iter_total
                    ,maxi_delta_var_sig_sur_iter_pour_Newton);
             if(sortie_post) // sauvegarde éventuelle des indicateurs
               {indicateurs_resolution(1)+=nb_incr_total;indicateurs_resolution(2)+=nb_iter_total;};
//             if (converge)
             double absracinemax=racine.Max_val_abs();
             if ((converge) && (isfinite(absracinemax)) && (!isnan(absracinemax)))
             	{ // on a convergé, donc on termine le calcul et on sort du switch
                  // récup de la solution
                  for (int ig=1;ig<=9;ig++)
                    delta_sigma_barre_tdt_BH.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=racine(ig);
           
                  sigma_t_barre_tdt = sigma_i_barre_BH + delta_sigma_barre_tdt_BH; 
                  // ici il n'est pas nécessaire de calculer QdeltaSigmaRatdt, et wprime,wprime_point
                  // car ces grandeurs sont calculées à l'intérieur de la boucle de Newton, et 
                  // pour t+dt donc pas de pb 
                  delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;
                  passage_par_newton = true; // on indique donc que l'on est passé par du newton
                 if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 2)) || (Permet_affichage() > 2))
                  	 { cout << "\n  estime_erreur= " << estime_erreur(1);
                      if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                      if (Permet_affichage() > 4)
                       {cout << " -> probleme dans la resolution de l'equation constitutive avec Runge Kutta";
                        alg_edp.Affiche_Explication_erreur_RG(conver);
                        cout << ", (3) utilisation avec succes de la linearisation ";
                       };
                      if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
                          cout << "\n Hysteresis3D::CalculContrainte_tdt (..."<<endl;
                    };
                  // puis on met conver à 2 pour signaler que pour la suite que ça a convergé
                  conver=2;        
                  break;
             	}
             else // sinon on n'a pas convergé également avec la linéarisation
              // on indique à toute fin utile que la première n'a pas convergé au cas ou cela n'aurait pas été noté
              { if (conver == 2)
                   conver = 0 ;
              };
           	};
          // arrivé ici cela signifie que: soit kutta a convergé -> conver=2, 
          // soit kutta n'a pas convergé et la méthode de linéarisation n'a pas également convergé -> conver != 2
          if (conver !=2) // cas d'une non convergence
            { // l'idée est de diminuer la précision jusqu'à une solution
              int conver_interne = 0;
              double erreurAsolue_inter=erreurAbsolue;
              double erreurRelative_inter = erreurRelative;
              int nb_boucle=1;
              double abssigmax0; // init
              do
              	{  erreurAsolue_inter *=10;
              	   erreurRelative_inter *=10;
              	   nb_boucle ++;
                  for (int ig=1;ig<=9;ig++)
                     sig_initiale(ig)=sigma_i_barre_BH(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig));
                  double tdeb=0.,tfi=1.;
                  // calcul de la dérivée initiale
                  int erreur=0; //init d'une erreur de calcul de Sigma_point
                  Sigma_point(tdeb,sig_initiale,dersig_initiale,erreur);
                  if (erreur) // cas où le calcul de la dérivée initiale n'est pas possible, on ne peut pas aller plus loin
                   { if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
                      {cout << "\n erreur4 fatale dans  l'algo de la resolution du schema constitutif"
                            << " au niveau du calcul de la derivee initiale "
                            << "\n QdeltaSigma =" << sqrt(delta_sigma_barre_R_a_tauBH.II()) << " au lieu de "<< Qzero
                            << "\n Hysteresis3D::CalculContrainte_tdt() (...";
                       if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                      };
                     // on génère une exception
                     throw ErrNonConvergence_loiDeComportement();break;
                   }; 
                  double dernierTemps=0.,dernierdeltat=0.; // valeurs de retour
                  int nombreAppelF=0,nb_step=0;            //  "          "
                  erreur_maxi_global=0.;           
                  // appel de la fonction kutta
                  conver_interne=alg_edp.Pilotage_kutta
                      (cas_kutta,*this,& Hysteresis3D::Sigma_point,& Hysteresis3D::Verif_integrite_Sigma
                       ,sig_initiale,dersig_initiale
                       ,tdeb,tfi,erreurAsolue_inter,erreurRelative_inter
                       ,sig_finale,dersig_finale,dernierTemps,dernierdeltat
                       ,nombreAppelF,nb_step,erreur_maxi_global);
                  if(sortie_post) // sauvegarde éventuelle des indicateurs
                    {indicateurs_resolution(3)+=nombreAppelF;indicateurs_resolution(4)+=nb_step;
                     indicateurs_resolution(5)+=erreur_maxi_global;
                    };
// --- debug piloté ---
                  if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
                    cout << "\n Hysteresis3D::CalculContrainte_tdt "
                         << "nombreAppelF= " << nombreAppelF << " nb_step= " << nb_step << " erreur_maxi_global= "
                         << erreur_maxi_global << endl;
// --- fin debug piloté---
              	   if (nb_boucle > 10) // si en * par 10^10 on n'a pas réussi on arrête
              	    { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 0))
                       {cout << "\n non convergence extreme !! sur l'algo de la resolution du schema constitutif"
                             << "\n Hysteresis3D::CalculContrainte_tdt(.." ;
                        if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                       };
                      // on génère une exception
                      throw ErrNonConvergence_loiDeComportement();break;
                   }; 
                  abssigmax=sig_finale.Max_val_abs();
              	}
              while ((conver_interne != 2) || (!isfinite(abssigmax)) || (isnan(abssigmax)) );
             
             
              if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 3))
              	{cout << "\n probleme dans la resolution de l'equation constitutive avec Runge Kutta";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                alg_edp.Affiche_Explication_erreur_RG(conver);
                cout  << ", decroissance de la precision -> erreur estimee= "
                      << erreur_maxi_global << " nb cycle= " << nb_boucle
                      << "\n Hysteresis3D::CalculContrainte_tdt (..."<< endl;
              	};
             }
           else if (!passage_par_newton)// sinon cela veut dire que le calcul avec Runge est correcte on sauvegarde les résutats
            {// récup des résultats
             for (int ig=1;ig<=9;ig++)
               sigma_t_barre_tdt.Coor(Tenseur3BH::idx_i(ig),Tenseur3BH::idx_j(ig))=sig_finale(ig);
             delta_sigma_barre_tdt_BH =  sigma_t_barre_tdt - sigma_i_barre_BH;   
             // ici on doit calculer QdeltaSigmaRatdt, et wprime,wprime_point
             // car ces grandeurs ne sont pas calculées au temps final !! dans la méthode de Runge-Kutta
             // d'ailleurs elles ne sont même pas calculées en temps que grandeurs globales !!
             delta_sigma_barre_BH_Ratdt = sigma_t_barre_tdt - sigma_barre_BH_R;          
             QdeltaSigmaRatdt = sqrt(delta_sigma_barre_BH_Ratdt.II());
            };
          // le dernier cas possible avec convergence est celui du passage par newton, et dans ce cas
          // la sauvegarde a déjà été faite
                    //modif : 11 juin 2014
          // on vérifie que l'amplitude de la contrainte calculée
          {double QdeltaSigma = sqrt(delta_sigma_barre_R_a_tauBH.II());
           if ( QdeltaSigma > (Qzero*depassement_Q0*wBase))
             {if ((ParaGlob::NiveauImpression() > 3)|| (Permet_affichage() > 0))
               {cout << "\n erreur14 fatale dans  l'algo de la resolution du schema constitutif"
                     << " concernant le niveau de saturation de la contrainte  "
                     << "\n QdeltaSigma =" << QdeltaSigma << " au lieu de "<< (Qzero*depassement_Q0*wBase)
                     << "\n Hysteresis3D::CalculContrainte_tdt() (...";
                if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();break;
             };
          };

          break;
         }
       };
      //--- // fin du switch sur les différentes méthodes pour calculer la contraintes à tdt 
      // --- on calcul certaines grandeurs globales et locales
//------ debug------
//cout << "\n dd " << delta_sigma_barre_BH_Ratdt.MaxiComposante() << ", "
//     << " fini ? " << isfinite(delta_sigma_barre_BH_Ratdt.MaxiComposante())
//     << " isnan . " << isnan(delta_sigma_barre_BH_Ratdt.MaxiComposante());
//cout << "\n delta_sigma_barre_BH_Ratdt=== ";
//delta_sigma_barre_BH_Ratdt.Ecriture(cout);
//if  ((!isfinite(delta_sigma_barre_BH_Ratdt.MaxiComposante()))||(isnan(delta_sigma_barre_BH_Ratdt.MaxiComposante())))
// { cout << " delta_sigma_barre_BH_Ratdt= ";
//   delta_sigma_barre_BH_Ratdt.Ecriture(cout);
// };
//----- fin debug -----
      if ((type_resolution_equa_constitutive != 1)&& (!passage_par_newton))
      	{ // sauf le cas 1, tous les autres c'est des kutta  on doit calculer wprime,wprime_point
          // car ces grandeurs ne sont pas calculées au temps final !! dans la méthode de Runge-Kutta
          // d'ailleurs elles ne sont même pas calculées en temps que grandeurs globales !!
          Cal_wprime(QdeltaSigmaRatdt,delta_sigma_barre_BH_Ratdt,Q_OiaR,delta_sigma_barre_BH_OiaR 
                     ,wBase,delta_sigma_barre_tdt_BH,wprime,wprime_point,trajet_neutre);      
          // --- si dépendance de la phase de sigma0i_tdt (et non delta sigma) mise à jour des para matériaux
          if (avec_phaseDeltaSig)
             {xnp = xnp_lue; xmu = xmu_lue; Qzero = Qzero_lue;
              ParaMateriauxAvecPhaseDeltaSig(xnp,delta_sigma_barre_BH_OiaR,delta_sigma_barre_BH_Ratdt,xmu,Qzero);
             };
      		
      	};
      // --<< calcul de phi >>---	
      if (trajet_neutre) // cas où l'on n'a pas un trajet neutre
          { phi_2_dt = 0.;} // pas de variation sur un trajet neutre
      else 
          { phi_2_dt = (delta_sigma_barre_BH_Ratdt && delta_barre_epsBH)
                        - QdeltaSigmaRatdt * QdeltaSigmaRatdt * wprime_point / (2.*xmu * wprime);
//------ debug------
//if ((!isfinite(phi_2_dt))||(isnan(phi_2_dt)))
// { cout << "\n";
//   delta_sigma_barre_BH_Ratdt.Ecriture(cout);
//   delta_barre_epsBH.Ecriture(cout);
//   cout << " q= " << QdeltaSigmaRatdt;
////   Sortie(1);
// };
//// if (phi_2_dt < 0.) cout << "\n phi_2_dt = " << phi_2_dt;
// cout << " " << phi_2_dt;
//----- fin debug -----
           
           
          };
      // --- si dépendance à la déformation équivalente on calcul le xnp correspondant à un phi = 0
      if (avec_defEqui)
          { if (!avec_phaseDeltaSig && !avec_phaseEps) xnp = xnp_lue; // sinon ça déjà été fait
		          if (Qzero_defEqui!=NULL) Qzero = Qzero_lue;
            ParaMateriauxAvecDefEqui(xnp,QdeltaSigmaRatdt,phi_2_dt,wprime,def_equi_R,trajet_neutre,def_i_equi,defEqui_maxi);
          };
	};
 
// calcul de l'expression permettant d'obtenir la dérivée temporelle de la contrainte
// en fait il s'agit de l'équation constitutive
// utilisée dans la résolution explicite (runge par exemple) de l'équation constitutive
// erreur : indique si le calcul est valide =0 dans ce cas
//          sinon (diff de 0) indique que les valeurs calculées ne sont pas licite
//          =1:  la norme de sigma est supérieure à la valeur limite de saturation
Vecteur& Hysteresis3D::Sigma_point(const double & tau, const Vecteur & sigma_tau, Vecteur& sig_point,int& erreur)
  {
    double titi= tau; // sert à rien, c'est pour taire le compilo car tau ne sert pas directement
    // récup de la contrainte à tau
    for (int i=1;i<=9;i++)
      sigma_tauBH.Coor(Tenseur3BH::idx_i(i),Tenseur3BH::idx_j(i)) = sigma_tau(i);
    //modif : 1 juin 2014
// non on fait la vérif sur le delta cf. plus bas
//    // on vérifie que l'amplitude de la contrainte transmise, n'est pas supérieure à la saturation
//    double sigma_tau_II = sigma_tauBH.II();
//    if ( sigma_tau_II > Qzero*Qzero)
//     {erreur = 1;
//  //--- pour le debug
//      if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
//        cout << "\n sigma_tau_II =" << sigma_tau_II << " au lieu de "<< Qzero*Qzero
//             << " Hysteresis3D::Sigma_point " << endl ;
//  //--- fin debug
//     }
//    else // sinon on continue 
//     { erreur = 0;
   
  //--- pour le debug
  //cout << "\n tt np=" << xnp << " Q0=" << Qzero <<	" xmu=" << xmu  << " T=" << *temperature;
  //--- fin debug
      // variation de sigma de R à tau
      delta_sigma_barre_R_a_tauBH = sigma_tauBH - sigma_barre_BH_R; // ne sert que dans Sigma_point
      delta_sigma_barre_t_a_tauBH = sigma_tauBH - sigma_i_barre_BH; // ne sert que dans Sigma_point
      // calcul de QdeltaSigma: on prend la valeur absolue car dans les petits nombres on peut avoir des presques 0 !!
      // négatifs qui conduisent à une racine infinie !!
      double QdeltaSigma = sqrt(delta_sigma_barre_R_a_tauBH.II());
      
      //modif : 1 juin 2014
      // on vérifie que l'amplitude de la contrainte transmise, n'est pas supérieure à la saturation
      // on fait la vérification sur le delta, car si on est sur une branche non initiale, on peut très bien
      // dépasser le Qzero, localement, mais ce sera invalidé ensuite avec l'algo de coincidence
      if ( QdeltaSigma > (Qzero*depassement_Q0*wBase))
       {erreur = 1;
    //--- pour le debug
        if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
          cout << "\n QdeltaSigma =" << QdeltaSigma << " au lieu de "<< (Qzero*depassement_Q0*wBase)
               << " Hysteresis3D::Sigma_point " << endl ;
    //--- fin debug
       }
      else // sinon on continue 
       { erreur = 0;
      
      // -- calculs relatifs aux angles de phases : calcul de -> wprime,wprime_point,trajet_neutre
      Cal_wprime(QdeltaSigma,delta_sigma_barre_R_a_tauBH,Q_OiaR,delta_sigma_barre_BH_OiaR 
                 ,wBase,delta_sigma_barre_t_a_tauBH,wprime,wprime_point,trajet_neutre);
      // --- si dépendance de la phase de sigma0i_tdt (et non delta sigma) mise à jour des para matériaux
      if (avec_phaseDeltaSig)
       {xnp = xnp_lue; xmu = xmu_lue; Qzero = Qzero_lue;
        // calcul de xnp, xmu et Qzero
        ParaMateriauxAvecPhaseDeltaSig(xnp,delta_sigma_barre_BH_OiaR,delta_sigma_barre_R_a_tauBH,xmu,Qzero);
       };

      double phitau = (delta_sigma_barre_R_a_tauBH && delta_barre_epsBH) ; // init partie radial // -- modif 16 juin 2012 --
      if (!trajet_neutre)																							 // -- modif 16 juin 2012 --
        phitau -=  QdeltaSigma * QdeltaSigma * wprime_point / (2. * xmu * wprime);				// -- modif 16 juin 2012 -- 

      // -- modif 	7 mai 2012 ---
      // dans le cas où le phidt est négatif, l'équation constitutive n'est plus valide, dans ce cas on considère
      // que phi est nulle, c-a-d que l'on évolue suivant un trajet neutre ce qui n'est sans doute pas l'idéal, mais permet d'éviter l'explosion
          // -- calcul de phidt
//      if ((phitau < 0) && force_phi_zero_si_negatif)
      if (phitau < 0)                                      // -- modif 9 fev 2015 --
       {if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 8)) || (Permet_affichage() > 8) )
          cout << "\n  phidt= " << phitau << "\n Hysteresis3D::Sigma_point(..." << endl;
         if (  Dabs(phitau) < force_phi_zero_si_negatif)   // -- modif 9 fev 2015 --
           { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
      //        if (MaX(ParaGlob::NiveauImpression(),Permet_affichage()) >= 5)
               {	cout << "\n attention on utilise une valeur de phi negative dans pour le calcul de l'equation constitutive "
                      << " phitau= " << phitau
                      << "\n Hysteresis3D::Sigma_point(..." ;
                 if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
               };
             phitau = 0.;trajet_neutre = true;
           };
        };
      // fin modif modif 	7 mai 2012 ---


      if (trajet_neutre)						// -- modif 16 juin 2012 --
       { // si c'est un trajet neutre, l'équation constitutive est beaucoup plus simple: sigma_point = 2 mu D_barre
         // variables intermédiaires pour les tests
         betaphideltasigHB.Inita(0.);
         deuxmudeltaepsHB = (2. * xmu ) * delta_barre_epsBH;
         // formule pour un trajet neutre :   sigma_pointBH = 2. * xmu * delta_barre_epsBH ;
         sigma_pointBH = deuxmudeltaepsHB;
         // --- si dépendance à la déformation équivalente on calcul le xnp correspondant à un phi = 0
         if (avec_defEqui)
          { if (!avec_phaseDeltaSig  && !avec_phaseEps) xnp = xnp_lue; // sinon ça déjà été fait
            double phitau = 0.;
            if (Qzero_defEqui!=NULL) Qzero = Qzero_lue;
            ParaMateriauxAvecDefEqui(xnp,QdeltaSigma,phitau,wprime,def_equi_R,trajet_neutre,def_i_equi,defEqui_maxi);
          };
       }
      else
       { // cas d'un trajet non neutre
     // modif 	7 mai 2012 --- on ne recalcule plus le phi qui a été calculé plus haut pour savoir s'il était négatif
  //       // --- calcul de phi
  //       double phitau = (delta_sigma_barre_R_a_tauBH && delta_barre_epsBH)
  //                      - QdeltaSigma * QdeltaSigma * wprime_point / (2. * xmu * wprime);
         // --- si dépendance à la déformation équivalente 
         if (avec_defEqui)
          { if (!avec_phaseDeltaSig && !avec_phaseEps) xnp = xnp_lue; // sinon ça déjà été fait
            if (Qzero_defEqui!=NULL) Qzero = Qzero_lue;
              // calcul de xnp (qui est le seul paramètre de retour de la méthode)
              ParaMateriauxAvecDefEqui(xnp,QdeltaSigma,phitau,wprime,def_equi_R,trajet_neutre,def_i_equi,defEqui_maxi);
          };
         // --- calcul de Beta
         double unsurwprimeQ0_puiss_np = 1./pow(wprime*Qzero,xnp);
         double beta=0.; // init dans le cas où ne le calcul pas après
         if (QdeltaSigma >= ConstMath::petit)
          // on ne calcul beta que si la norme de QdeltaSigma est significative
          {if (xnp == 2.) { beta = - 2. * xmu *  unsurwprimeQ0_puiss_np;}
           else {beta = - 2. * xmu *  unsurwprimeQ0_puiss_np * pow(QdeltaSigma,xnp-2.);};
          };
         // -- calcul de la dérivée temporelle de la contrainte
         // on considère que D est constant = delta_barre_epsBH/deltat et comme deltat = 1 
         //  ==> = delta_barre_epsBH
         // variables intermédiaires pour les tests
         betaphideltasigHB = beta * phitau * delta_sigma_barre_R_a_tauBH;
         deuxmudeltaepsHB = (2. * xmu ) * delta_barre_epsBH;
         // formule normale :   sigma_pointBH = 2. * xmu * delta_barre_epsBH + beta * phitau * delta_sigma_barre_R_a_tauBH;
         sigma_pointBH = deuxmudeltaepsHB + betaphideltasigHB;
       }; // fin du test sur  trajet_neutre

      
  // si pb : a faire sur toutes les composantes: limitations des dérivées: spécifiques  à la loi d'évolution
      // on limite la variation de la dérivée de la contrainte 
  /*    for (int i=1;i<=3;i++) for (int j=1;j<=3;j++)
        if (deuxmudeltaepsHB(i,j) > 0.)
         {// cas d'une contrainte positive et normalement la dérivée doit évoluer entre 2mu et 0 (saturation)
          if (sigma_pointBH(i,j) < 0. ) sigma_pointBH(i,j) = 0.;
          if (sigma_pointBH(i,j) > deuxmudeltaepsHB(i,j)) sigma_pointBH(i,j) = deuxmudeltaepsHB(i,j);
         }
        else
         {// cas d'une contrainte négative et normalement la dérivée doit évoluer entre -2mu et 0 (saturation)
          if (sigma_pointBH(i,j) < deuxmudeltaepsHB(i,j) ) sigma_pointBH(i,j) = deuxmudeltaepsHB(i,j);
          if (sigma_pointBH(i,j) > 0.) sigma_pointBH(i,j) = 0.;
         }; */
       
  // si pb : a faire sur toutes les composantes: limitations des dérivées: spécifiques  à la loi d'évolution
      // on limite la variation de la dérivée de la contrainte au niveau de la dérivée à l'origine
  // en fait cela introduit une erreur systématique "dramatique !!" sur le résultat qui est alors erroné !!!
  // car il y a accumulation, et il n'y a pas de détection de cette erreur
  // donc au lieu de regarder si l'on est juste supérieur, on met une petite marge ???
  // non pas bon non plus, donc on supprime !!! à voir par la suite
  // sans doute que s'il y a une erreur il faut récupérer une exception à un autre endroit
      if (type_resolution_equa_constitutive==6)  // cas exploratoire
        { double marge = 100.;    
  ////    for (int i=1;i<=3;i++) for (int j=1;j<=3;j++)
  ////        if (Dabs(sigma_pointBH(i,j)) > marge*Dabs(deuxmudeltaepsHB(i,j))) sigma_pointBH(i,j) = deuxmudeltaepsHB(i,j);
  // on tente une autre stratégie: on regarde l'intensité et on limite, parcontre on garde la même direction que celle calculée
          // calcul de l'intensité de cisaillement de la vitesse de déformation
          double deuxmuQdeltaeps = sqrt(deuxmudeltaepsHB.II());
          // on n'intervient que si deuxmuQdeltaeps a une valeur non nulle
          if (deuxmuQdeltaeps > ConstMath::petit)
            if (QdeltaSigma > marge * deuxmuQdeltaeps) // normalement pb
              {sigma_pointBH *= marge*deuxmuQdeltaeps/QdeltaSigma;
               if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 3)) || (Permet_affichage() > 3))
                    {cout << "\n limitation de sigma_point ";
                     if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
                    };
              };
        };
          
      // retour de la dérivée temporelle de la contrainte
      for (int i=1;i<=9;i++) 
         sig_point(i) = sigma_pointBH(Tenseur3BH::idx_i(i),Tenseur3BH::idx_j(i));
     };
    // retour de la dérivée, qui n'a été calculée que si l'erreur = 0
	   return sig_point;
  };

// vérification de l'intégrité du sigma calculé
// erreur : =0: le calcul est licite, si diff de 0, indique qu'il y a eu une erreur
//          =1:  la norme de sigma est supérieure à la valeur limite de saturation
void Hysteresis3D::Verif_integrite_Sigma(const double & , const Vecteur & sigma_tau,int & erreur)
  { // récup de la contrainte à tau
    for (int i=1;i<=9;i++)
      sigma_tauBH.Coor(Tenseur3BH::idx_i(i),Tenseur3BH::idx_j(i)) = sigma_tau(i);
    //modif : 1 juin 2014
// non on fait la vérif sur le delta cf. plus bas
//    // on vérifie que l'amplitude de la contrainte transmise, n'est pas supérieure à la saturation
//    double sigma_tau_II = sigma_tauBH.II();
//    if ( sigma_tau_II > Qzero*Qzero)
//     {erreur = 1;
//  //--- pour le debug
//      if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
//        cout << "\n sigma_tau_II =" << sigma_tau_II << " au lieu de "<< Qzero*Qzero
//             << " Hysteresis3D::Sigma_point " << endl ;
//  //--- fin debug
//     }
//    else // sinon on continue 
//     { erreur = 0;
   
  //--- pour le debug
  //cout << "\n tt np=" << xnp << " Q0=" << Qzero <<	" xmu=" << xmu  << " T=" << *temperature;
  //--- fin debug
      // variation de sigma de R à tau
      delta_sigma_barre_R_a_tauBH = sigma_tauBH - sigma_barre_BH_R; // ne sert que dans Sigma_point
      delta_sigma_barre_t_a_tauBH = sigma_tauBH - sigma_i_barre_BH; // ne sert que dans Sigma_point
      // calcul de QdeltaSigma: on prend la valeur absolue car dans les petits nombres on peut avoir des presques 0 !!
      // négatifs qui conduisent à une racine infinie !!
      double QdeltaSigma = sqrt(delta_sigma_barre_R_a_tauBH.II());
      
      //modif : 1 juin 2014
      // on vérifie que l'amplitude de la contrainte transmise, n'est pas supérieure à la saturation
      // on fait la vérification sur le delta, car si on est sur une branche non initiale, on peut très bien
      // dépasser le Qzero, localement, mais ce sera invalidé ensuite avec l'algo de coincidence
      if ( QdeltaSigma > (Qzero*depassement_Q0*wBase))
       {erreur = 1;
    //--- pour le debug
        if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
          cout << "\n QdeltaSigma =" << QdeltaSigma << " au lieu de "<< (Qzero*depassement_Q0*wBase)
               << " Hysteresis3D::Sigma_point " << endl ;
    //--- fin debug
       }
      else // sinon on continue 
       { erreur = 0;
     };
  };



// update des différentes énergies sur le pas de temps ou la partie de pas de temps effectué
// et calcul de defEqui finalisée
void Hysteresis3D::UpdateEnergieHyste(EnergieMeca & energ
		                              ,const Tenseur3BH & sigma_deb_BH,const Tenseur3BH & sigma_fin_BH
		                              ,const Tenseur3BH & delta_sigma_sur_tau_BH
		                              ,const Tenseur3BH & delta_sigma_R_tau_BH
		                              ,const double& phi_2_dt
		                              ,const Tenseur3BH & delta_eps_sur_deltaTau_BH,double& QdeltaSigmaRatdt
		                              ,const double& wprime,const double& w_prime_point,const bool& trajet_neutre
		                              ,const double& def_equi_R,const double& def_i_equi, double& def_equi)
{ // delta tau = 1 ici, en fait c'est un paramètre formel
  // double delta_ener_interne = - 0.5*((sigma_deb_BH + sigma_fin_BH) && delta_eps_sur_deltaTau_BH);
  double delta_ener_interne = - (sigma_fin_BH && delta_eps_sur_deltaTau_BH);
  // -------- débug au cas où -----------
  //if (phi_2_dt < 0)
  //  cout << "\n attention, phi_2_dt = " << phi_2_dt << " est negatif ??, normalement, a l'issue d'une convergence"
  //       << " phi est positif ou nul , a regarder en debug "
  //       << "\n Hysteresis3D::UpdateEnergieHyste(.... ";
  // ------- fin débug --------       	

	
  if (trajet_neutre)
    {// -- calcul du delta énergie interne
     // a priori ici tout est élastique: phi = 0, tau_C=0, 
     // -- calcul du taux fondamental C (formule thèse Mayssa Chache p. 71: formule 2.51, avec les formules
     //     2.52, )
     // calcul de la déformation équivalente 
     def_equi = def_i_equi ;
     // -- delta énergies : on considère un tau C constant sur l'incrément de temps ainsi que phi
     double delta_energie_elastique = - delta_ener_interne ;
     double delta_energie_frotteurs = 0.;
     EnergieMeca delta_ener(delta_energie_elastique,delta_energie_frotteurs,0.);
     energ += delta_ener;
    }
  else
    {// -- calcul du delta énergie interne
     // -- calcul du taux fondamental C (formule thèse Mayssa Chache p. 71: formule 2.51, avec les formules
     //     2.52, )
     double unsurwprime = 1./wprime;
     // si QdeltaSigmaRatdt est très petit on considère qu'il n'y a qu'un calcul élastique, pas de dissipation
     // on plus simple on considère que la def équivalente ne bouge pas 
     if (QdeltaSigmaRatdt >= ConstMath::petit )
      { double unsurQdeltaSigma=1./QdeltaSigmaRatdt;
	 	     def_equi = def_i_equi + unsurwprime * phi_2_dt * unsurQdeltaSigma;
	 	     double def_equi_Ratdt = def_equi-def_equi_R;
        // calcul de QpointDeltaSigma
        double QpointDeltaSigma = unsurQdeltaSigma * (delta_sigma_R_tau_BH && delta_sigma_sur_tau_BH);
        // calcul du tau_C qui représente en fait : delta_R^tdt eps : sigma_point
        double tau_C = (wprime * QpointDeltaSigma - w_prime_point * QdeltaSigmaRatdt) * def_equi_Ratdt;
        // -- delta énergies : on considère un tau C constant sur l'incrément de temps ainsi que phi
        double delta_energie_elastique = - delta_ener_interne - unsurwprime * phi_2_dt + unsurwprime * tau_C;
        double delta_energie_frotteurs = unsurwprime * ( phi_2_dt - tau_C);
        // si l'énergie des frotteurs est négative, on considère que c'est due aux différentes imprécisions, 
        // comme je ne vois pas de solution, donc
        // on la met à 0, et on modifie le tau_C en conséquence, et donc
        // on recalcule l'énergie élastique en conséquence, ce qui conduit, tout calcul fait à un trajet 
        // purement élastique ( finalement idem que neutre ??)
        if (delta_energie_frotteurs < 0.)
         { delta_energie_frotteurs = 0.;
            delta_energie_elastique = - delta_ener_interne;
         }
//-----pour le debug
//   if (delta_energie_frotteurs < 0.)
//      cout << "\n (1) delta_energie_frotteurs= " << delta_energie_frotteurs << endl; 
// ----- fin débug

	       // si l'énergie frotteur est négative, on considère que c'est due à une erreur d'arrondie, on met 0 à la place
//	      if (delta_energie_frotteurs < 0.)
//	        delta_energie_frotteurs = 0.;
	       EnergieMeca delta_ener(delta_energie_elastique,delta_energie_frotteurs,0.);
	       energ += delta_ener;
	 	   }
	    else
	 	   { // cas où l'accroissement de sigma est trop faible donc considéré nul
        // on a sigma_point = delta_sigma/delta_t, avec ici delta_t=1 donc delta_sigma = 0 => sigma_point=0
        // comme en fait : tau_C= delta_R^(t+deltat) eps  : sigma_point, on a tau_C = 0 
        // on considère donc tau_C = 0
        double delta_energie_elastique = - delta_ener_interne - unsurwprime * phi_2_dt ;
        double delta_energie_frotteurs = unsurwprime * ( phi_2_dt );
//-----pour le debug
        if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 5)) || (Permet_affichage() > 5))
          if (delta_energie_frotteurs < 0)
            cout << "\n (2) delta_energie_frotteurs= " << delta_energie_frotteurs << endl; 
// ----- fin débug
        EnergieMeca delta_ener(delta_energie_elastique,delta_energie_frotteurs,0.);
        energ += delta_ener;
      }; 
//-------- ancien calcul en commentaire -------	 
//    double unsurQdeltaSigma= ConstMath::grand; // on limite la valeur par exemple pour le démarrage
//     if (QdeltaSigmaRatdt >= ConstMath::petit) unsurQdeltaSigma=1./QdeltaSigmaRatdt;
//	   // calcul de la déformation équivalente 
//	   def_equi = def_equi_R + unsurwprime * phi_2_dt * unsurQdeltaSigma;

//	 // calcul de QpointDeltaSigma
//	 double QpointDeltaSigma = unsurQdeltaSigma * (delta_sigma_R_tau_BH && delta_sigma_sur_tau_BH);
	 // calcul du tau_C qui représente en fait : delta_R^tdt eps : sigma_point
//	 double tau_C = (wprime * QpointDeltaSigma - w_prime_point * QdeltaSigmaRatdt) * def_equi;
	 // -- delta énergies : on considère un tau C constant sur l'incrément de temps ainsi que phi
//	 double delta_energie_elastique = - delta_ener_interne - unsurwprime * phi_2_dt + unsurwprime * tau_C;
//	 double delta_energie_frotteurs = unsurwprime * ( phi_2_dt - tau_C);
//	 EnergieMeca delta_ener(delta_energie_elastique,delta_energie_frotteurs,0.);
//	 energ += delta_ener;
//-------- fin ancien calcul en commentaire -------	 
    };
};

// vérif de la coïncidence: prog de mise au point
// premiere_fois: comme il y a une récursion, pour arrêter la boucle infinie        
void Hysteresis3D::Verif_coincidence(const Tenseur3BB & delta_epsBB,const Tenseur3HH & gijHH
                                 ,const Tenseur3BB & gijBB,int cas,SaveResulHysteresis3D & save_resul
                                 ,Tenseur3HH & sigHH,const EnergieMeca & energ_t,EnergieMeca & energ
                                 ,bool premiere_fois)
{   
    // l'objectif est ici de vérifier que l'on a bien la position de la nouvelle contrainte cohérente avec
    // le rayon de référence
    // --- 1ere étape, récupérer les infos de position de référence qui vont-être enregistrées
    Tenseur3BH sigBH_de_ref; Tenseur3BH centreBH_de_ref;  // init à 0 par défaut
    int aucun_pt_inv=false;
    switch (save_resul.modif)
      { case 0: // rien ne change sur le pas en terme de coincidence et d'inversion 
         { if(save_resul.sigma_barre_BH_R.begin() != save_resul.sigma_barre_BH_R.end())
              {sigBH_de_ref = *(save_resul.sigma_barre_BH_R.begin());}
           else aucun_pt_inv=true;   
           if(save_resul.oc_BH_R.begin() != save_resul.oc_BH_R.end())
              centreBH_de_ref = *(save_resul.oc_BH_R.begin());
           break;
          }
        case 1: // cas où l'on a une ou plusieurs coincidences 
         { // a chaque coincidence il faudra supprimer 1 pt de ref et un centre de cercle
           // sauf si l'on arrive au centre nul ou au point de référence null
	       List_io <Tenseur3BH>::iterator itens;List_io <Tenseur3BH>::iterator ioc_i;
	       itens = save_resul.sigma_barre_BH_R.begin(); ioc_i = save_resul.oc_BH_R.begin();
	       for (int i=1;i<=save_resul.nb_coincidence;i++)
	         { if (itens != save_resul.sigma_barre_BH_R.end()) // si itens == sigma_barre_BH_R.end(), cela signifie
	                itens++;  // que la référence est le tenseur nulle, on arrête de dépiler
	           if (ioc_i != save_resul.oc_BH_R.end())  // si ioc_i == oc_BH_R.end(), cela signifie que le centre de référence
	                ioc_i++;   // est le tenseur nulle 
	          };
	       if(itens != save_resul.sigma_barre_BH_R.end())   
              {sigBH_de_ref = *(itens);}
           else aucun_pt_inv=true;   
	       if (ioc_i != save_resul.oc_BH_R.end())
              centreBH_de_ref = *(ioc_i);
          break;
          }
        case 2: // cas où l'on a une ou plusieurs inversions 
         { // on traite les centres différement des points d'inversions
           // --- cas des centres ---
	       if (save_resul.oc_BH_t_a_tdt.size() != 0)
	          {centreBH_de_ref = *(save_resul.oc_BH_t_a_tdt.begin());} // on récupère le premier
	       else if (save_resul.oc_BH_R.size() != 0)   
	          {centreBH_de_ref = *(save_resul.oc_BH_R.begin());}; // on récupère le premier
	       // sinon tous les centres sont nuls on utilise le centre de départ initialisé à 0   
	       // --- cas des ref ---   
	       if (save_resul.sigma_barre_BH_R_t_a_tdt.size() != 0)
	          {sigBH_de_ref = *(save_resul.sigma_barre_BH_R_t_a_tdt.begin());}
	       else if (save_resul.sigma_barre_BH_R.size() != 0)
	          {sigBH_de_ref = *(save_resul.sigma_barre_BH_R.begin());}
	       else  aucun_pt_inv=true;   
	       
          break;
          }
        case 3: // cas où l'on a une ou plusieurs coincidence(s) et inversion (s)
         { // on traite les centres différement des points d'inversions
           // --- cas des centres ---
	       if (save_resul.oc_BH_t_a_tdt.size() != 0) // cas on ajoutera des inversions 
	          {centreBH_de_ref = *(save_resul.oc_BH_t_a_tdt.begin());} // on récupère le premier
	       else // cas où on a déjà une coincidence et pas d'inversion
	       	{ List_io <Tenseur3BH>::iterator ioc_i = save_resul.oc_BH_R.begin();
	          for (int i=1;i<=save_resul.nb_coincidence;i++)
	             if (ioc_i != save_resul.oc_BH_R.end())  // si ioc_i == oc_BH_R.end(), cela signifie que le centre de référence
	                  ioc_i++;   // est le tenseur nulle 
	          if (ioc_i != save_resul.oc_BH_R.end())
                  centreBH_de_ref = *(ioc_i);
	       	};
	       // --- cas des références ----
	       if (save_resul.sigma_barre_BH_R_t_a_tdt.size() != 0)
	          {sigBH_de_ref = *(save_resul.sigma_barre_BH_R_t_a_tdt.begin());}
	       else // cas où on a déjà une coincidence et pas d'inversion
	       	{ List_io <Tenseur3BH>::iterator itens = save_resul.sigma_barre_BH_R.begin();
	          for (int i=1;i<=save_resul.nb_coincidence;i++)
	            if (itens != save_resul.sigma_barre_BH_R.end()) // si itens == sigma_barre_BH_R.end(), cela signifie
	                itens++;  // que la référence est le tenseur nulle, on arrête de dépiler
	          if(itens != save_resul.sigma_barre_BH_R.end())   
                  {sigBH_de_ref = *(itens);}
              else aucun_pt_inv=true;   
	       	};
           break;
          }         
        default:
         cout << "\n erreur  modif= " << save_resul.modif
              << "\n Hysteresis3D::Verif_coincidence(... ";
         // on génère une exception
         throw ErrNonConvergence_loiDeComportement();
         Sortie(1);
        }       
      
      // --- calcul du rayon de Oi à R  sigBH_de_ref
      Tenseur3BH ddelta_sigma_barre_BH_OiaR = sigBH_de_ref - centreBH_de_ref; // le tenseur rayon
      // calcul du rayon: la première fois le rayon est infini
      double QQ_OiaR=0.;
      if (aucun_pt_inv) {QQ_OiaR = ConstMath::tresgrand;}
      else              {QQ_OiaR = sqrt(ddelta_sigma_barre_BH_OiaR.II());};  

      // --- calcul du nouveau rayon ----
      Tenseur3BH delta_sigma_oi_a_tdt_BH = save_resul.sigma_barre_BH_tdt - centreBH_de_ref; // OA
      double rayon_tdt = sqrt(delta_sigma_oi_a_tdt_BH.II());
      // ---- vérif ---
      if (rayon_tdt > QQ_OiaR) // cas d'un inchoérence
      	{ cout << "\n *********** inchoerence de coincidence ";
         if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();cout << flush;
         // re-appel de l'algo pour passer en débug dedans
         // initialisation des variables de travail
         save_resul.Init_debut_calcul();
         // initialisation éventuelle des variables thermo-dépendantes
         Init_thermo_dependance();
         // vérif de l'emboitement
         save_resul.Verif_centre_reference(Permet_affichage());
         // re-calcul pour vérif pas à pas
         Avancement_temporel(delta_epsBB,gijHH,gijBB,cas,save_resul,sigHH,energ_t,energ);
         if (premiere_fois)
          {premiere_fois = false;
           Verif_coincidence(delta_epsBB,gijHH,gijBB,cas,save_resul,sigHH,energ_t,energ,premiere_fois);
          };
         // on génère une exception
         throw ErrNonConvergence_loiDeComportement();
         Sortie(1);
      };
};

// vérif de la cohérence des centres et références: les rayons associés doivent être de taille
// décroissante
void Hysteresis3D::SaveResulHysteresis3D::Verif_centre_reference(const int &permet_affichage)
	{ // on va balayer les différents centres et points de références, pour construire les différents rayons
	  // qui devront être de tailles croissantes à partir du premier
	  double rayon_precedent = 0.; List_io <double> les_rayons;
	  List_io <Tenseur3BH>::iterator itens,itens_fin = sigma_barre_BH_R.end();
	  List_io <Tenseur3BH>::iterator ioc_i,ioc_i_fin = oc_BH_R.end();
	  for (itens=sigma_barre_BH_R.begin(), ioc_i = oc_BH_R.begin();
	       itens != itens_fin; itens++,ioc_i++)
	  	{double rayon = 0;
	  	 if (ioc_i != ioc_i_fin)
	  	 	{ Tenseur3BH dsigmaBH = *itens - *ioc_i;
	  	 	  rayon = sqrt(dsigmaBH.II());
	  	 	}
	  	 else 	
	  	 	{ Tenseur3BH dsigmaBH = *itens;
	  	 	  rayon = sqrt(dsigmaBH.II());
	  	 	}
	  	 les_rayons.push_front(rayon);	
	  	 if (rayon >= rayon_precedent)
	  	 	{ rayon_precedent = rayon;}
	  	 else
	  	 	{ cout << "\n ---- ******* attention la croissance des rayons n'est pas verifiee !! " ;
        if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 5)) || (permet_affichage > 5))
          {// les listes
           cout << "\n save_resul.sigma_barre_BH_R_t_a_tdt= " << sigma_barre_BH_R_t_a_tdt;
           cout << "\n save_resul.sigma_barre_BH_R= " << sigma_barre_BH_R;
           cout << "\n save_resul.oc_BH_t_a_tdt= " << oc_BH_t_a_tdt;
           cout << "\n save_resul.oc_BH_R= " << oc_BH_R;
           cout << "\n les rayons= " << les_rayons;
           // on vide le buffer
           cout << endl;
          };
       
//	  	      Sortie(1);
	  	 	}; 	
	  	};
	};
 
