// FICHIER : Hysteresis1D.cc
// CLASSE : Hysteresis1D


// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.


//#include "Debug.h"

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

#include "Hysteresis1D.h"

#include "Enum_TypeQuelconque.h"
#include "TypeQuelconqueParticulier.h"

// ========== fonctions pour la classe de sauvegarde des résultats =========

// constructeur par défaut
Hysteresis1D::SaveResulHysteresis1D::SaveResulHysteresis1D() :
	          sigma_barre_BH_t(),sigma_barre_BH_tdt(),sigma_barre_BH_R()
	          ,fonction_aide_t(0.),fonction_aide_tdt(0.),wprime_t(1.),wprime_tdt(1.)
	          ,modif(0),sigma_barre_BH_R_t_a_tdt(),nb_coincidence(0)
	          ,ip2(),indic_coin(),fct_aide_t_a_tdt(),fct_aide()
           ,indicateurs_resolution(),indicateurs_resolution_t()
{// la première valeur de la fonction d'aide est l'infini
 fct_aide.push_front(ConstMath::tresgrand);sigma_barre_BH_R.push_front(Tenseur1BH());
};
// constructeur de copie	           
Hysteresis1D::SaveResulHysteresis1D::SaveResulHysteresis1D(const SaveResulHysteresis1D& sav):
	          sigma_barre_BH_t(sav.sigma_barre_BH_t),sigma_barre_BH_tdt(sav.sigma_barre_BH_tdt)
	          ,sigma_barre_BH_R(sav.sigma_barre_BH_R)
	          ,fonction_aide_t(sav.fonction_aide_t),fonction_aide_tdt(sav.fonction_aide_tdt)
	          ,wprime_t(sav.wprime_t),wprime_tdt(sav.wprime_tdt)
	          ,modif(sav.modif),sigma_barre_BH_R_t_a_tdt(sav.sigma_barre_BH_R_t_a_tdt)
	          ,nb_coincidence(sav.nb_coincidence),fct_aide_t_a_tdt(sav.fct_aide_t_a_tdt)
	          ,ip2(),indic_coin(sav.indic_coin),fct_aide(sav.fct_aide)
           ,indicateurs_resolution(sav.indicateurs_resolution),indicateurs_resolution_t(sav.indicateurs_resolution_t)
 { if (fct_aide.size() >= 2) // pointage de ip2
     {ip2= fct_aide.end(); ip2--;ip2--; };
   }; 
  
// affectation
Loi_comp_abstraite::SaveResul & Hysteresis1D::SaveResulHysteresis1D::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { Hysteresis1D::SaveResulHysteresis1D& sav = *((Hysteresis1D::SaveResulHysteresis1D*) &a);
    // recopie de toutes les grandeurs
	   sigma_barre_BH_t = sav.sigma_barre_BH_t;
	   sigma_barre_BH_tdt = sav.sigma_barre_BH_tdt;
	   fonction_aide_t = sav.fonction_aide_t;
	   fonction_aide_tdt = sav.fonction_aide_tdt;
    fct_aide = sav.fct_aide;
	   wprime_t = sav.wprime_t;
    wprime_tdt = sav.wprime_tdt;
    if (fct_aide.size() >= 2) // pointage de ip2
       {ip2= fct_aide.end(); ip2--;ip2--; };
	   modif = sav.modif;
	   sigma_barre_BH_R_t_a_tdt = sav.sigma_barre_BH_R_t_a_tdt;
	   nb_coincidence = sav.nb_coincidence;
	   fct_aide_t_a_tdt = sav.fct_aide_t_a_tdt;
	   indic_coin = sav.indic_coin;
	   sigma_barre_BH_R = sav.sigma_barre_BH_R;
    indicateurs_resolution = sav.indicateurs_resolution;
    indicateurs_resolution_t = sav.indicateurs_resolution_t;
    return *this;
  };

//------- lecture écriture dans base info -------
   // cas donne le niveau de la récupération
   // = 1 : on récupère tout
   // = 2 : on récupère uniquement les données variables (supposées comme telles)
void Hysteresis1D::SaveResulHysteresis1D::Lecture_base_info (ifstream& ent,const int )
  { // ici toutes les données sont toujours a priori variables
    string toto; 
    ent >> toto >> sigma_barre_BH_t  ;sigma_barre_BH_tdt = sigma_barre_BH_t;
    ent >> toto >>  fonction_aide_t; fonction_aide_tdt=fonction_aide_t;
    ent >> toto >>  wprime_t; wprime_tdt=wprime_t;
    ent >> toto; // ----  lecture fonction d'aide 
    #ifdef MISE_AU_POINT
      if (toto != "list_fct_aide")
         { cout << "\n erreur dans la lecture de la  list_io fonction d'aide, on ne trouve pas le mot cle: debut_List_IO= "
                << "\n  Hysteresis1D::SaveResulHysteresis1D::Lecture_base_info (... ";
           Sortie(1);     
          }       
    #endif
    int taille;ent >> toto >> taille; // lecture de la taille
    double un_elem;
    // on vide la liste actuelle
    fct_aide.clear();
    for (int i=1;i<=taille;i++) // puis on lit
      { ent >> un_elem; // lecture
        fct_aide.push_back(un_elem); // enregistrement
       }       
    if (fct_aide.size() >= 2) // pointage de ip2
         {ip2= fct_aide.end(); ip2--;ip2--; }
     ent >> toto; // ----  lecture des points d'inversion 
    #ifdef MISE_AU_POINT
      if (toto != "list_pt_inver")
         { cout << "\n erreur dans la lecture de la list_io: ref contrainte, on ne trouve pas le mot cle: debut_List_IO= "
                << "\n  Hysteresis1D::SaveResulHysteresis1D::Lecture_base_info (... ";
           Sortie(1);     
          }       
    #endif
    ent >> toto >> taille; // lecture de la taille
    Tenseur1BH elem;
    // on vide la liste actuelle
    sigma_barre_BH_R.clear();
    for (int j=1;j<=taille;j++) // puis on lit 
      { ent >> elem; // lecture
        sigma_barre_BH_R.push_back(elem); // enregistrement
       }
    //re-initialisation des variables de travail
    Init_debut_calcul();
   };
   
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables 
//(supposées comme telles)
void Hysteresis1D::SaveResulHysteresis1D::Ecriture_base_info(ofstream& sort,const int )
  { // ici toutes les données sont toujours a priori variables
    sort << "  sigma_barre_BH_t " << sigma_barre_BH_t;
    sort << "  fct_aide_t " << fonction_aide_t; 
    sort << "  wprime_t " << wprime_t;
    // les listes: fonction d'aide et point d'inversion
    sort << "  list_fct_aide " << "taille= " << fct_aide.size() << " ";
    List_io <double>::const_iterator iter_courant,iter_fin = fct_aide.end();
    for (iter_courant=fct_aide.begin();iter_courant!=iter_fin;iter_courant++)
     { sort  << setprecision(ParaGlob::NbdigdoCA()) << (*iter_courant) ; sort << " "; }     
    sort << "  list_pt_inver " << "taille= " << sigma_barre_BH_R.size() << " ";
    List_io <Tenseur1BH>::const_iterator jter_courant,jter_fin = sigma_barre_BH_R.end();
    for (jter_courant=sigma_barre_BH_R.begin();jter_courant!=jter_fin;jter_courant++)
     { sort  << setprecision(ParaGlob::NbdigdoCA()) << (*jter_courant) ; sort << " "; }
   }; 
	        
// mise à jour des informations transitoires 
void Hysteresis1D::SaveResulHysteresis1D::TdtversT() 
   { // partie générale
     sigma_barre_BH_t = sigma_barre_BH_tdt;fonction_aide_t=fonction_aide_tdt;
	    wprime_t = wprime_tdt;
     // partie spécifique
     switch (modif)
      { case 0: // rien ne change sur le pas en terme de coincidence et d'inversion 
         { break;
          }
        case 1: // cas où l'on a une ou plusieurs coincidences 
         { // a chaque coincidence il faut supprimer 2 pt de ref, sauf si l'on revient
           // sur la courbe de première charge, et que l'on a fait une symétrie trac -> comp par exemple
           // dans ce cas on ne supprime qu'un point: en clair il faut toujours qu'il reste un point
           List_io <Tenseur1BH>::iterator itens;List_io <double>::iterator ifct;
           for (int i=1;i<=nb_coincidence;i++)
             { itens = sigma_barre_BH_R.begin();
               if (itens != sigma_barre_BH_R.end()) sigma_barre_BH_R.erase(itens);
               ifct = fct_aide.begin();
               if (ifct != fct_aide.end()) fct_aide.erase(ifct);
               // on dépile que si c'est une coincidence secondaire ou, dans le cas d'une coincidence avec 
               // la première charge, on dépile que si il reste 2 pt d'inversion (cas tout traction ou
               // tout compression
               if ((wprime_tdt != 1.) || 
                    ((wprime_tdt == 1.)&&(sigma_barre_BH_R.size()!=1)))
                 {itens = sigma_barre_BH_R.begin();
                  if (itens != sigma_barre_BH_R.end()) sigma_barre_BH_R.erase(itens);
                  ifct = fct_aide.begin();
                  if (ifct != fct_aide.end()) fct_aide.erase(ifct);
                 };
             };
          break;
          }
        case 2: // cas où l'on a une ou plusieurs inversions 
         { int nb_ref = fct_aide.size(); // récup du nombre de pt de ref actuel
           bool init_ip2 = false; if (nb_ref == 1) init_ip2=true; // pour gérer ip2
           int nb_ref_new = fct_aide_t_a_tdt.size(); // récup du nombre de nouveau pt 
           // on ajoute les différents points d'inversions
           List_io <Tenseur1BH>::iterator iitens = sigma_barre_BH_R_t_a_tdt.begin();
           List_io <double>::iterator iifct = fct_aide_t_a_tdt.begin();
           for (int ii=1;ii<=nb_ref_new;ii++,iitens++,iifct++)
            { sigma_barre_BH_R.push_front(*iitens);
	          
// -----  débug (a virer ) ------ 
//     // on vérifie que le niveau de la fonction d'aide est acceptable
//        if (*iifct > *fct_aide.begin())
//           {cout << "\n erreur 3 " << endl;Sortie(1);}
// ----- fin débug  (a virer ) ------ 
	          
	            fct_aide.push_front(*iifct);
	            if (init_ip2) // uniquement pour mémoriser le W_a de la première charge
              { // cas où l'on doit initialiser ip2 (car ici le nombre de pt = 2)
                ip2 = fct_aide.begin(); init_ip2 = false; 
              };
	           };
          break;
          }
        case 3: // cas où l'on a une ou plusieurs coincidence(s) et inversion (s)
         { // on itère sur indic_coin pour savoir si l'ordre des inversions et coincidence
           List_io <bool>::iterator iindic,iindic_fin = indic_coin.end();
	       // on ajoute les différents points d'inversions
	       List_io <Tenseur1BH>::iterator iitens = sigma_barre_BH_R_t_a_tdt.begin();
	       List_io <double>::iterator iifct = fct_aide_t_a_tdt.begin();
	       // a chaque coincidence il faut supprimer 2 pt de ref
	       List_io <Tenseur1BH>::iterator itens;List_io <double>::iterator ifct;
           for (iindic= indic_coin.begin();iindic != iindic_fin;iindic++)
            { if (*iindic )
               // cas d'une coincidence
	            {itens = sigma_barre_BH_R.begin();
              if (itens != sigma_barre_BH_R.end()) sigma_barre_BH_R.erase(itens);
	             ifct = fct_aide.begin();
              if (ifct != fct_aide.end()) fct_aide.erase(ifct);
	             // on dépile que si c'est une coincidence secondaire ou, dans le cas d'une coincidence avec 
	             // la première charge, on dépile que si il reste 2 pt d'inversion (cas tout traction ou
	             // tout compression
	             if ((wprime_tdt != 1.) || 
	                ((wprime_tdt == 1.)&&(sigma_barre_BH_R.size()!=1)))
	               {itens = sigma_barre_BH_R.begin();
                 if (itens != sigma_barre_BH_R.end()) sigma_barre_BH_R.erase(itens);
	                ifct = fct_aide.begin();
                 if (ifct != fct_aide.end()) fct_aide.erase(ifct);
	                }
	             }
               else
                {// cas d'une inversion
	             sigma_barre_BH_R.push_front(*iitens);
	             
// -----  débug (a virer ) ------ 
//     // on vérifie que le niveau de la fonction d'aide est acceptable
//        if (*iifct > *fct_aide.begin())
//           {cout << "\n erreur 4 " << endl;Sortie(1);}
// ----- fin débug  (a virer ) ------ 

	             fct_aide.push_front(*iifct);
	             iitens++;iifct++; // incrémentation pour la fois suivante  	            
	             }                
               }
           // mise à jour d'ip2
           if ( fct_aide_t_a_tdt.size() > 1)
            { ip2 = fct_aide.end(); ip2--;ip2--;}   
           break;
          }         
        default:
         cout << "\n erreur dans la mise a jour des informations transitoire: modif= " << modif
              << "\n Hysteresis1D::SaveResulHysteresis1D::TversTdt() ";
         Sortie(1);
        }       
     // on met à jour éventuellement les indicateurs de résolution
     if (indicateurs_resolution.Taille())
      { indicateurs_resolution_t = indicateurs_resolution;
        // on met les indicateurs à 0
        indicateurs_resolution.Change_taille(5,0.);
      };
     //re-initialisation des variables de travail
     Init_debut_calcul();
    };

void Hysteresis1D::SaveResulHysteresis1D::TversTdt() 
   { // partie générale
     sigma_barre_BH_tdt = sigma_barre_BH_t;fonction_aide_tdt=fonction_aide_t;
	    wprime_tdt=wprime_t;
     //re-initialisation des variables de travail
     Init_debut_calcul();
	};
			  
// affichage à l'écran des infos
void Hysteresis1D::SaveResulHysteresis1D::Affiche() const 
{ cout << "\n SaveResulHysteresis1D: " ; 
  cout << "\n sigma_barre_BH_t= " << sigma_barre_BH_t << " sigma_barre_BH_tdt= " << sigma_barre_BH_tdt
       << " fonction_aide_t= " << fonction_aide_t << " fonction_aide_tdt= " << fonction_aide_tdt
		     << " wprime_t= " << wprime_t << " wprime_tdt= " << wprime_tdt ;
  cout << "\n list sigma_barre_BH_R_t_a_tdt: " << sigma_barre_BH_R_t_a_tdt;
  cout << "\n nb_coincidence= " << nb_coincidence;		 
  cout << "\n list fct_aide_t_a_tdt: " << fct_aide_t_a_tdt;		 
  cout << "\n list indic_coin: " << indic_coin;		 
  cout << "\n list sigma_barre_BH_R: " << sigma_barre_BH_R;		 
  cout << "\n list fct_aide: " << fct_aide << " ";		 
};

//changement de base de toutes les grandeurs internes tensorielles stockées
// beta(i,j) represente les coordonnees de la nouvelle base naturelle gpB dans l'ancienne gB
// gpB(i) = beta(i,j) * gB(j), i indice de ligne, j indice de colonne
// gpH(i) = gamma(i,j) * gH(j)
void Hysteresis1D::SaveResulHysteresis1D::ChBase_des_grandeurs(const Mat_pleine& beta,const Mat_pleine& gamma)
{ // on ne s'intéresse qu'aux grandeurs tensorielles
  sigma_barre_BH_t.ChBase(beta,gamma);
  sigma_barre_BH_tdt.ChBase(beta,gamma);
  // encapsulage pour utiliser deux fois les mêmes itérators
  { List_io <Tenseur1BH>::iterator lit(sigma_barre_BH_R_t_a_tdt.begin()),
                                   lend(sigma_barre_BH_R_t_a_tdt.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit).ChBase(beta,gamma);
  };
  { List_io <Tenseur1BH>::iterator lit(sigma_barre_BH_R.begin()),
                                   lend(sigma_barre_BH_R.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit).ChBase(beta,gamma);
  };
};

// initialise les informations de travail concernant le pas de temps en cours 
void Hysteresis1D::SaveResulHysteresis1D::Init_debut_calcul()
   { //initialisation des variables de travail
     modif = 0; nb_coincidence=0;
     indic_coin.clear();
	    sigma_barre_BH_R_t_a_tdt.clear();
	    fct_aide_t_a_tdt.clear();
	  };

// ========== fin des fonctions pour la classe de sauvegarde des résultats =========

Hysteresis1D::Hysteresis1D ()  : // Constructeur par defaut
   Loi_comp_abstraite(HYSTERESIS_1D,CAT_MECANIQUE,1),xnp(ConstMath::tresgrand)
   ,xmu(ConstMath::tresgrand),Qzero(ConstMath::tresgrand)
   ,xnp_temperature(NULL),Qzero_temperature(NULL),xmu_temperature(NULL)
   ,tolerance_residu(1.e-3),tolerance_residu_rel(1.e-5),nb_boucle_maxi(100),nb_sous_increment(4)
   ,maxi_delta_var_sig_sur_iter_pour_Newton(-1)
   ,tolerance_coincidence()
   ,sigma_t_barre_tdt(),sigma_i_barre_BH(),sigma_barre_BH_R()
   ,delta_sigma_barre_BH_Rat(),delta_sigma_barre_BH_Ratdt()
   ,delta_sigma_barre_tdt_BH(),residuBH(),delta_barre_epsBH(),delta_barre_alpha_epsBH(),wprime()
   ,residu(1),derResidu(1,1),alg_zero(),alg_edp()
   ,rdelta_sigma_barre_BH_Ratdt(),rdelta_sigma_barre_tdt_BH()
   ,cas_kutta(5),erreurAbsolue(1.e-3),erreurRelative(1.e-5)
   ,sig_point(1),sigma_pointBH(),sigma_tauBH(),sigma_tau(1),delta_sigma_barre_R_a_tauBH()
   ,type_resolution_equa_constitutive(1),nbMaxiAppel(120)
   ,betaphideltasigHB(),deuxmudeltaepsHB(),nb_maxInvCoinSurUnPas(4)
  // ---- affichage
   ,sortie_post(0)
    {// initialisation des paramètres de la résolution de newton
     alg_zero.Modif_prec_res_abs(tolerance_residu);
     alg_zero.Modif_prec_res_rel(tolerance_residu_rel);
     alg_zero.Modif_iter_max(nb_boucle_maxi);
     alg_zero.Modif_nbMaxiIncre(nb_sous_increment);
     tolerance_coincidence = tolerance_residu; 
     // idem avec kutta
     alg_edp.Modif_nbMaxiAppel(nbMaxiAppel);    
    };
	
// Constructeur de copie
Hysteresis1D::Hysteresis1D (const Hysteresis1D& loi) :
   Loi_comp_abstraite(loi),xnp(loi.xnp),xmu(loi.xmu),Qzero(loi.Qzero)
   ,xnp_temperature(loi.xnp_temperature),Qzero_temperature(loi.xnp_temperature)
   ,xmu_temperature(loi.xnp_temperature)
   ,tolerance_residu(loi.tolerance_residu),tolerance_residu_rel(loi.tolerance_residu_rel)
   ,nb_boucle_maxi(loi.nb_boucle_maxi)
   ,nb_sous_increment(loi.nb_sous_increment)
   ,maxi_delta_var_sig_sur_iter_pour_Newton(loi.maxi_delta_var_sig_sur_iter_pour_Newton)
   ,tolerance_coincidence(loi.tolerance_coincidence)
   ,sigma_t_barre_tdt(loi.sigma_t_barre_tdt),sigma_i_barre_BH(loi.sigma_i_barre_BH)
   ,sigma_barre_BH_R(loi.sigma_barre_BH_R)   
   ,delta_sigma_barre_BH_Rat(loi.delta_sigma_barre_BH_Rat)
   ,delta_sigma_barre_BH_Ratdt(loi.delta_sigma_barre_BH_Ratdt)   
   ,delta_sigma_barre_tdt_BH(loi.delta_sigma_barre_tdt_BH)
   ,residuBH(loi.residuBH),delta_barre_epsBH(loi.delta_barre_epsBH)
   ,delta_barre_alpha_epsBH(loi.delta_barre_alpha_epsBH),wprime(loi.wprime)
   ,residu(1),derResidu(1,1),alg_zero(),alg_edp()
   ,rdelta_sigma_barre_BH_Ratdt(),rdelta_sigma_barre_tdt_BH()
   ,cas_kutta(loi.cas_kutta),erreurAbsolue(loi.erreurAbsolue),erreurRelative(loi.erreurRelative)
   ,sig_point(1),sigma_pointBH(),sigma_tauBH(),sigma_tau(1),delta_sigma_barre_R_a_tauBH()
   ,type_resolution_equa_constitutive(loi.type_resolution_equa_constitutive)
   ,nbMaxiAppel(loi.nbMaxiAppel),betaphideltasigHB(),deuxmudeltaepsHB()
   ,nb_maxInvCoinSurUnPas(loi.nb_maxInvCoinSurUnPas)
  // ---- affichage
   ,sortie_post(loi.sortie_post)
    {// initialisation des paramètres de la résolution de newton
     alg_zero.Modif_prec_res_abs(tolerance_residu);
     alg_zero.Modif_prec_res_rel(tolerance_residu_rel);
     alg_zero.Modif_iter_max(nb_boucle_maxi);
     alg_zero.Modif_nbMaxiIncre(nb_sous_increment);
     // idem avec kutta
     alg_edp.Modif_nbMaxiAppel(nbMaxiAppel);    
	 // pour les pointeurs de courbes, on regarde s'il s'agit d'une courbe locale ou d'une courbe globale
     if (xnp_temperature != NULL)
	     if (xnp_temperature->NomCourbe() == "_") 
	        xnp_temperature = Courbe1D::New_Courbe1D(*(loi.xnp_temperature));
	    if (Qzero_temperature != NULL)
         if (Qzero_temperature->NomCourbe() == "_") 
             Qzero_temperature = Courbe1D::New_Courbe1D(*(loi.Qzero_temperature));;
     if (xmu_temperature != NULL)
         if (xmu_temperature->NomCourbe() == "_") 
            xmu_temperature = Courbe1D::New_Courbe1D(*(loi.xmu_temperature));;
    };

Hysteresis1D::~Hysteresis1D ()
// Destructeur 
{ if (xnp_temperature != NULL)
      if (xnp_temperature->NomCourbe() == "_") delete xnp_temperature;
  if (Qzero_temperature != NULL)
      if (Qzero_temperature->NomCourbe() == "_") delete Qzero_temperature;
  if (xmu_temperature != NULL)
      if (xmu_temperature->NomCourbe() == "_") delete xmu_temperature;
};

// Lecture des donnees de la classe sur fichier
 void Hysteresis1D::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                        ,LesFonctions_nD& lesFonctionsnD)
  { // ---- lecture du paramètre de prager
    string nom;
    *(entreePrinc->entree) >> nom;  
    if(nom != "np=")
         { cout << "\n erreur en lecture du parametre de prager "
                << " on attendait la chaine : np= ";
           cout << "\n Hysteresis1D::LectureDonneesParticulieres  "
                << "(UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);          
          };
    // on regarde si le paramètre de prager est thermo dépendant
    if(strstr(entreePrinc->tablcar,"np_thermo_dependant_")!=0)
     { thermo_dependant=true;
       *(entreePrinc->entree) >> nom;
       if (nom != "np_thermo_dependant_") 
         { cout << "\n erreur en lecture de la thermodependance de np, on aurait du lire le mot cle np_thermo_dependant_"
                << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
           entreePrinc->MessageBuffer("**erreur2 Hysteresis1D::LectureDonneesParticulieres (...**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
          }
       // lecture de la loi d'évolution du paramètre de prager en fonction de la température
       *(entreePrinc->entree) >>  nom;    
       // on regarde si la courbe existe, si oui on récupère la référence 
       if (lesCourbes1D.Existe(nom)) 
         { xnp_temperature = lesCourbes1D.Trouve(nom);
          }
       else
        { // sinon il faut la lire maintenant
          string non_courbe("_");   
          xnp_temperature = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
          // lecture de la courbe
          xnp_temperature->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
         } 
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      }
    else // sinon on lit directement le paramètre de prager
     {*(entreePrinc->entree) >> xnp;
      if (xnp <= 0) 
        {cout << "\n erreur en lecture du parametre de prager np= " << xnp
              << " il doit etre superieur a 0 ! ";
         cout << "\n Hysteresis1D::LectureDonneesParticulieres  "
              << "(UtilLecture * entreePrinc) " << endl ;
         throw (UtilLecture::ErrNouvelleDonnee(-1));
         Sortie(1);
        };
     };
    // ---- lecture de mu : coefficient de lame ----
    *(entreePrinc->entree) >> nom;           
    if(nom != "mu=")
         { cout << "\n erreur en lecture du coefficient mu de lame "
                << " on attendait la chaine : mu= ";
           cout << "\n Hysteresis1D::LectureDonneesParticulieres  "
                << "(UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);          
          };
    // on regarde si le coefficient de lame est thermo dépendant
    if(strstr(entreePrinc->tablcar,"mu_thermo_dependant_")!=0)
     { thermo_dependant=true;
       *(entreePrinc->entree) >> nom;
       if (nom != "mu_thermo_dependant_") 
         { cout << "\n erreur en lecture de la thermodependance de mu, on aurait du lire le mot cle mu_thermo_dependant_"
                << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
           entreePrinc->MessageBuffer("**erreur3 Hysteresis1D::LectureDonneesParticulieres (...**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
          }
       // lecture de la loi d'évolution du coefficient mu en fonction de la température
       *(entreePrinc->entree) >>  nom;    
       // on regarde si la courbe existe, si oui on récupère la référence 
       if (lesCourbes1D.Existe(nom)) 
         { xmu_temperature = lesCourbes1D.Trouve(nom);
          }
       else
        { // sinon il faut la lire maintenant
          string non_courbe("_");   
          xmu_temperature = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
          // lecture de la courbe
          xmu_temperature->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
         } 
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      }
    else // sinon on lit directement le paramètre mu
     {*(entreePrinc->entree) >> xmu;};
    
    // ---- lecture de la limite de plasticité infini -----
    *(entreePrinc->entree) >> nom;           
    if(nom != "Qzero=")
         { cout << "\n erreur en lecture du coefficient mu de lame "
                << " on attendait la chaine : Qzero= ";
           cout << "\n Hysteresis1D::LectureDonneesParticulieres  "
                << "(UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);          
          };

    // on regarde si Qzero est thermo dépendant
    if(strstr(entreePrinc->tablcar,"Qzero_thermo_dependant_")!=0)
     { thermo_dependant=true;
       *(entreePrinc->entree) >> nom;
       if (nom != "Qzero_thermo_dependant_") 
         { cout << "\n erreur en lecture de la thermodependance de Qzero, on aurait du lire le mot cle Qzero_thermo_dependant_"
                << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
           entreePrinc->MessageBuffer("**erreur4 Hysteresis3D::LectureDonneesParticulieres (...**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
          }
       // lecture de la loi d'évolution du coefficient Qzero en fonction de la température
       *(entreePrinc->entree) >>  nom;    
       // on regarde si la courbe existe, si oui on récupère la référence 
       if (lesCourbes1D.Existe(nom)) 
         { Qzero_temperature = lesCourbes1D.Trouve(nom);
          }
       else
        { // sinon il faut la lire maintenant
          string non_courbe("_");   
          Qzero_temperature = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
          // lecture de la courbe
          Qzero_temperature->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
         } 
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      }
    else // sinon on lit directement le paramètre Qzero
     {*(entreePrinc->entree) >> Qzero;};
    
//    // --- lecture éventuelle des paramètres de réglage ----
//    //     de l'algo de résolution de l'équation d'avancement temporel
//    if(strstr(entreePrinc->tablcar,"avec_parametres_de_reglage_")!=0)
//     { entreePrinc->NouvelleDonnee();
//       if(strstr(entreePrinc->tablcar,"type_de_resolution_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "type_de_resolution_")
//           { cout << "\n erreur en lecture du type de resolution, on attendait la chaine: type_de_resolution_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//            }
//           else
//            {*(entreePrinc->entree) >> type_resolution_equa_constitutive;
//            };
//        };

//       if(strstr(entreePrinc->tablcar,"nb_iteration_maxi_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "nb_iteration_maxi_")
//           { cout << "\n erreur en lecture du nombre d'iteration maxi, on attendait la chaine: nb_iteration_maxi_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//            }
//           else
//            {*(entreePrinc->entree) >> nb_boucle_maxi;
//             alg_zero.Modif_iter_max(nb_boucle_maxi);
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"nb_dichotomie_maxi_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "nb_dichotomie_maxi_")
//           { cout << "\n erreur en lecture du nombre de dichotomies maxi, on attendait la chaine: nb_dichotomie_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//            }
//           else
//            {*(entreePrinc->entree) >> nb_sous_increment;
//             alg_zero.Modif_nbMaxiIncre(nb_sous_increment);
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"tolerance_residu_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "tolerance_residu_")
//           { cout << "\n erreur en lecture de la tolerance absolue sur le residu, on attendait la chaine: tolerance_residu_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//           }
//          else
//            {*(entreePrinc->entree) >> tolerance_residu;
//             alg_zero.Modif_prec_res_abs(tolerance_residu);
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"tolerance_residu_rel_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "tolerance_residu_rel_")
//           { cout << "\n erreur en lecture de la tolerance relative sur le residu, on attendait la chaine:"
//                  << " tolerance_residu_rel_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//           }
//          else
//            {*(entreePrinc->entree) >> tolerance_residu_rel;
//             alg_zero.Modif_prec_res_rel(tolerance_residu_rel);
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"cas_kutta_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "cas_kutta_")
//           { cout << "\n erreur en lecture du cas de Runge Kutta, on attendait la chaine: cas_kutta_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//           }
//          else
//            {*(entreePrinc->entree) >> cas_kutta;
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"erreurAbsolue_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "erreurAbsolue_")
//           { cout << "\n erreur en lecture de l'erreur absolu pour  Runge Kutta, on attendait la chaine: erreurAbsolue_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//           }
//          else
//            {*(entreePrinc->entree) >> erreurAbsolue;
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"erreurRelative_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "erreurRelative_")
//           { cout << "\n erreur en lecture de l'erreur relative pour  Runge Kutta, on attendait la chaine: erreurRelative_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//           }
//          else
//            {*(entreePrinc->entree) >> erreurRelative;
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"nbMaxiAppel_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "nbMaxiAppel_")
//           { cout << "\n erreur en lecture du nombre maxi d'appel de la derivee pour  Runge Kutta, on attendait la chaine: nbMaxiAppel_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//           }
//          else
//            {*(entreePrinc->entree) >> nbMaxiAppel;
//             alg_edp.Modif_nbMaxiAppel(nbMaxiAppel);    
//            };
//        };
//      if(strstr(entreePrinc->tablcar,"tolerance_coincidence_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "tolerance_coincidence_")
//           { cout << "\n erreur en lecture de la tolerance sur les coincidences, on attendait la chaine: tolerance_coincidence_ "
//                  << " et on a lu : " << nom
//                  << "\n Hysteresis3D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//            }
//           else
//            {*(entreePrinc->entree) >> tolerance_coincidence;
//            };
//        };
      
//      if(strstr(entreePrinc->tablcar,"nb_maxInvCoinSurUnPas_")!=0)
//        {*(entreePrinc->entree) >> nom;  
//          if (nom != "nb_maxInvCoinSurUnPas_")
//           { cout << "\n erreur en lecture sur le nombre maxi d'inversion sur le pas, on attendait la chaine:"
//                  << "\n nb_maxInvCoinSurUnPas_  et on a lu : " << nom
//                  << "\n Hysteresis1D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//             throw (UtilLecture::ErrNouvelleDonnee(-1));
//             Sortie(1);          
//            }
//           else
//            {*(entreePrinc->entree) >> nb_maxInvCoinSurUnPas;
//            };
//        };
//     }; //-- fin de la lecture des paramètres de réglage


    // --- lecture éventuelle des paramètres de réglage ----
    //     de l'algo de résolution de l'équation d'avancement temporel
    if(strstr(entreePrinc->tablcar,"avec_parametres_de_reglage_")!=0)
     {type_resolution_equa_constitutive = 0; // valeur voulant dire qu'il n'y a pas eu de lecture
      entreePrinc->NouvelleDonnee(); // on se positionne sur un nouvel enreg
      // on lit tant que l'on ne rencontre pas la ligne contenant "fin_parametres_reglage_Hysteresis_"
      // ou un nouveau mot clé global auquel cas il y a pb !!
      MotCle motCle; // ref aux mots cle
      while (strstr(entreePrinc->tablcar,"fin_parametres_reglage_Hysteresis_")==0) 
       {
        // si on a  un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur
        if ( motCle.SimotCle(entreePrinc->tablcar))
         { cout << "\n erreur de lecture des parametre de reglage d'hysteresis: on n'a pas trouve le mot cle "
                << " fin_parametres_reglage_Hysteresis_ et par contre la ligne courante contient un mot cle global  ";
           entreePrinc->MessageBuffer("** erreur5 des parametres de reglage de la loi de comportement d'hyteresis**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
         };
         
        // lecture d'un mot clé
        *(entreePrinc->entree) >> nom;
        
        if ((entreePrinc->entree)->rdstate() == 0) 
          {} // lecture normale
        #ifdef ENLINUX 
        else  if ((entreePrinc->entree)->fail())
           // on a atteind la fin de la ligne et on appelle un nouvel enregistrement 
          {   entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
              *(entreePrinc->entree) >>nom;
           }
        #else
        else  if ((entreePrinc->entree)->eof())
          // la lecture est bonne mais on a atteind la fin de la ligne
          { if(nom != "fin_parametres_reglage_Hysteresis_")
              {entreePrinc->NouvelleDonnee(); *(entreePrinc->entree) >> nom;};
          } 
        #endif  
        else // cas d'une erreur de lecture
         { cout << "\n erreur de lecture inconnue  ";
           entreePrinc->MessageBuffer("** erreur5 des parametres de reglage de la loi de comportement d'hyteresis**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
         };
        
        // cas du type de résolution
        if(nom == "type_de_resolution_")
         {*(entreePrinc->entree) >> type_resolution_equa_constitutive;
          if ((type_resolution_equa_constitutive < 1) || (type_resolution_equa_constitutive> 6)) // 6 valeur exploratoire
            { cout << "\n erreur en lecture du type de resolution, on attendait un nombre compris entre 1 et 6 "
                   << " et on a lu : " << type_resolution_equa_constitutive << " ce cas n'est pas implante (cf. doc) "
                   << "\n Hysteresis3D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);          
            };
         }
        // nombre d'itération maxi
        else if (nom == "nb_iteration_maxi_")
         {*(entreePrinc->entree) >> nb_boucle_maxi;
          alg_zero.Modif_iter_max(nb_boucle_maxi);
         }
        // nombre de dichotomie maxi
        else if (nom == "nb_dichotomie_maxi_")
         {*(entreePrinc->entree) >> nb_sous_increment;
          alg_zero.Modif_nbMaxiIncre(nb_sous_increment);
         }
        // tolérance absolue sur le résidu
        else if (nom == "tolerance_residu_")
         {*(entreePrinc->entree) >> tolerance_residu;
          alg_zero.Modif_prec_res_abs(tolerance_residu);
         }
        // tolérance relative sur le résidu
        else if (nom == "tolerance_residu_rel_")
         {*(entreePrinc->entree) >> tolerance_residu_rel;
          alg_zero.Modif_prec_res_rel(tolerance_residu_rel);
         }
        // le maxi de variation que l'on tolère d'une itération à l'autre
        else if (nom == "maxi_delta_var_sig_sur_iter_pour_Newton_")
         { *(entreePrinc->entree) >> maxi_delta_var_sig_sur_iter_pour_Newton;
         }
        // type d'algo de kutta
        else if (nom == "cas_kutta_")
         {*(entreePrinc->entree) >> cas_kutta;
         }
        // l'erreur absolue
        else if (nom == "erreurAbsolue_")
         {*(entreePrinc->entree) >> erreurAbsolue;
         }
        // l'erreur relative
        else if (nom == "erreurRelative_")
         {*(entreePrinc->entree) >> erreurRelative;
         }
        // le nombre d'appel maxi de la fonction f
        else if (nom == "nbMaxiAppel_")
         {*(entreePrinc->entree) >> nbMaxiAppel;
          alg_edp.Modif_nbMaxiAppel(nbMaxiAppel);    
         }
        // tolérance sur la coïncidence
        else if (nom == "tolerance_coincidence_")
         {*(entreePrinc->entree) >> tolerance_coincidence;
         }
        // nombre maxi d'inversion sur le pas
        else if (nom == "nb_maxInvCoinSurUnPas_")
         {*(entreePrinc->entree) >> nb_maxInvCoinSurUnPas;
         }
        
        // forcer un affichage particulier pour les méthodes
        else if (nom == "permet_affichage_")
         {Lecture_permet_affichage(entreePrinc,lesFonctionsnD);
          alg_edp.Change_niveau_affichage(Permet_affichage());
         }
        // forcer un stockage des indicateurs de la résolution
        else if (nom == "sortie_post_")
         {*(entreePrinc->entree) >> sortie_post;
         }
        // sinon ce n'est pas un mot clé connu, on le signale
        else if(nom != "fin_parametres_reglage_Hysteresis_")
         { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu "
                << " on a lu : " << nom << endl;
           if (Permet_affichage() > 3)
                cout << "\n Hysteresis3D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);          
         }
        
       }; //-- fin du while
     }; //-- fin de la lecture des paramètres de réglage

    // le niveau d'affichage
    alg_zero.Modif_affichage(Permet_affichage());

    // appel au niveau de la classe mère
    Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire
                 (*entreePrinc,lesFonctionsnD);

   };
    
 // affichage de la loi
void Hysteresis1D::Affiche() const 
  { cout << " \n loi_de_comportement d'hysteresis1D " ;
    if ( xnp_temperature != NULL) { cout << " np thermo dependant " 
                                        << " courbe np=f(T): " << xnp_temperature->NomCourbe() <<" ";}
    else                       { cout << " np= " << xnp ;}; 
    if ( Qzero_temperature != NULL) { cout << " Qzero thermo dependant " 
                                        << " courbe np=f(T): " << Qzero_temperature->NomCourbe() <<" ";}
    else                       { cout << " Qzero= " << Qzero ;}; 
    if ( xmu_temperature != NULL) { cout << " xmu thermo dependant " 
                                        << " courbe xmu=f(T): " << xmu_temperature->NomCourbe() <<" ";}
    else                       { cout << " mu= " << xmu ;}; 
    if (type_resolution_equa_constitutive == 1)
    	{ cout << " \n type de resolution: linearisation, nbmax iteration= " << nb_boucle_maxi
    	       << " nbmax_dichotonmie= " << nb_sous_increment
            << " tolerance_residu_absolue= " << tolerance_residu
            << " tolerance_residu_relative= " << tolerance_residu_rel
            << " maxi_delta_var_sig_sur_iter_pour_Newton= " << maxi_delta_var_sig_sur_iter_pour_Newton;
    	}
    else 	
    	{ cout << " \n type de resolution: Runge_Kutta " << cas_kutta << " erreurAbsolue " << erreurAbsolue
    	       << " erreurRelative= " << erreurRelative ;
    	};
    cout << " tolerance_coincidence= " << tolerance_coincidence 
         << " nb_maxInvCoinSurUnPas= " << nb_maxInvCoinSurUnPas;
    // niveau d'affichage
    Affiche_niveau_affichage();
    cout << " sortie_post "<< sortie_post
         << " ";
    // appel de la classe mère
    Loi_comp_abstraite::Affiche_don_classe_abstraite();
  };
            
// affichage et definition interactive des commandes particulières à chaques lois
void Hysteresis1D::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
 {  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
	   cout << "\n definition standart (rep o) ou exemples exhaustifs (rep n'importe quoi) ? ";
	   string rep = "_";
    // procédure de lecture avec prise en charge d'un retour chariot
    rep = lect_return_defaut(true,"o");

    Qzero = 200.; xnp = 1.; xmu = 1000;  // init à des exemples de valeurs 
    sort << "\n#-------------------------------------------------------------------"
         << "\n# .......  loi_de_comportement d'hysteresis 1D ........            |"
         << "\n# para de prager(>=0)  :         mu         : limite de plasticite |"
         << "\n#-------------------------------------------------------------------"
         << "\n   np= " << setprecision(6) << xnp << "       mu= " << setprecision(6) << xmu 
         << "     Qzero= "<<  setprecision(6) << Qzero ;
    	 if ((rep != "o") && (rep != "O" ) && (rep != "0") )
      { sort << "\n#-----------------------------------"
         << "\n#  il est possible de definir des parametres thermo-dependants (1 ou 2 ou 3 parametres)"
         << "\n#  par exemple pour les trois parametres on ecrit: "
         << "\n#-----------------------------------"
         << "\n#  np= np_thermo_dependant_ courbe1 "
         << "\n#  mu= xmu_temperature_ courbe4 "
         << "\n#  Qzero= Qzero_temperature_ courbe3 "
         << "\n#-----------------------------------"
         << "\n#  noter qu'apres la definition de chaque courbe, on change de ligne, d'une maniere inverse "
         << "\n#  si la valeur du parametre est fixe, on poursuit sur la meme ligne. "
         << "\n#  par exemple supposons np fixe, mu et Qzero thermo-dependant, on ecrit: "
         << "\n#-----------------------------------"
         << "\n#  np= 2.   mu= xmu_temperature_ courbe4 "
         << "\n#  Qzero= Qzero_temperature_ courbe3 "
         << "\n#-----------------------------------"
         << "\n# il est egalement possible (mais pas obligatoire) de definir les parametres de reglage "
         << "\n# de la resolution. Dans ce cas, a la suite de la limite maxi de plasticite on indique "
         << "\n# le mot cle: avec_parametres_de_reglage_ "
         << "\n# ensuite sur la ligne qui suit on peut indiquer en respectant l'ordre d'apparition: "
         << "\n# le type de resolution: par linearisation(1) (valeur par defaut) ou integration directe via Runge_Kutta(2)"
         << "\n# le nombre d'iteration (pour (1)), le nombre de dichotomie(pour (1)), "
         << "\n# la tolerance abolue et relative sur le residu(pour (1))"
         << "\n# la norme maximale du delta sigma qui est permise a chaque iteration de Newton  "
         << "\n#   par defaut = -1 , si on veut une autre valeur: exe: "
         << "\n# maxi_delta_var_sig_sur_iter_pour_Newton_ 2 # donc 2 MPa a chaque iter           "
         << "\n#   si on donne une valeur negative (val par defaut), il n'y a pas de limite           "
         << "\n# "
         << "\n# le type de Runge_kutta (pour (2)): 3 pour une methode imbriquee 2-3, 4 pour 3-4, 5 pour 4-5, "
         << "\n# l'erreur absolue sur la contrainte finale(pour (2)), l'erreur relative sur la contrainte finale(pour (2)) "
         << "\n# le nombre maxi d'appel de la fonction derivee (sigma_point) (pour (2)) "
         << "\n# la tolerance sur la detection des coincidences,"
         << "\n# NB: tous les parametres n'ont pas a etre presents, il en faut seulement 1 au minimum "
         << "\n# \n Exemple de declaration pour une resolution de l'equation linearisee: "
         << "\n#-------------------------------------------------------------------------"
         << "\n# .......  loi_de_comportement d'hysteresis 1D ........                   |"
         << "\n# para de prager       :         mu         : limite maxi de plasticite   |"
         << "\n#-------------------------------------------------------------------------"
         << "\n#   np= " << setprecision(6) << xnp << "       mu= " << setprecision(6) << xmu 
         << "     Qzero= "<<  setprecision(6) << Qzero << "   avec_parametres_de_reglage_ "
         << " nb_iteration_maxi_  20  nb_dichotomie_maxi_  20  tolerance_residu_ 1.e-3 tolerance_residu_rel_ 1.e-5 "
         << "  tolerance_coincidence_  1.e-3   "
         << "\n# \n Exemple de declaration pour une resolution avec une methode de Runge_Kutta: "
         << "\n#-------------------------------------------------------------------------"
         << "\n# .......  loi_de_comportement d'hysteresis 1D ........                   |"
         << "\n# para de prager       :         mu         : limite maxi de plasticite   |"
         << "\n#-------------------------------------------------------------------------"
         << "\n#   np= " << setprecision(6) << xnp << "       mu= " << setprecision(6) << xmu 
         << "     Qzero= "<<  setprecision(6) << Qzero << "   avec_parametres_de_reglage_ "
         << " type_de_resolution_  2 " 
         << " cas_kutta_  5  erreurAbsolue_  1.e-3  erreurRelative_ 1.e-5  nbMaxiAppel_  100"
         << "  tolerance_coincidence_  1.e-3   nb_maxInvCoinSurUnPas_  20 "
         << "\n# -------------- affichage des erreurs et des warning ---------- "
         << "\n# - l'affichage normale est fonction du parametre global d'affichage gerer par le niveau d'affichage"
         << "\n# cependant pour des raisons par exemple de mise au point, il est possible de permettre l'affichage "
         << "\n# a un niveau particulier (mot cle : permet_affichage_ suivi d'un nombre entier) en plus de l'affichage normal. "
         << "\n# l'affichage s'effectuera donc en fonction de l'affichage normale et de l'affichage particulier."
         << "\n# Le fonctionnement de l'affichage particulier suit les mêmes règles que l'affichage globale"
         << "\n# soit permet_affichage_ est nulle (cas par defaut), dans ce cas l'affichage est fonction du niveau global"
         << "\n# soit permet_affichage_ vaut n par exemple, dans ce cas l'affichage est fonction uniquement de n "
         << "\n# "
         << "\n# ex: permet_affichage_ 5  "
         << "\n# --------------- acces aux indicateurs de la resolution par -------"
         << "\n#  A chaque resolution, il est possible de stocker les indicateurs: nombre d'iteration, d'increment "
         << "\n#   precision etc. les indicateurs sont renseignes en fonction du type de resolution "
         << "\n#  le mot cle est sortie_post_ , par defaut il vaut 0, dans ce cas aucun indicateur n'est stoke"
         << "\n#  s'il est different de 0, on peut acceder aux indicateurs en post-traitement"
         << "\n#  seules les indicateurs en cours sont disponibles, il n'y a pas de stockage sur plusieurs increment "
         << "\n# "
         << "\n# ex: sortie_post_ 1 "
         << "\n# "
         << "\n# ";
       };
    sort << endl;
    // appel de la classe mère
    Loi_comp_abstraite::Info_commande_don_LoisDeComp(entreePrinc);     
  };  		  	  

 // test si la loi est complete
int Hysteresis1D::TestComplet()
    { int ret = LoiAbstraiteGeneral::TestComplet();
      if ((xnp_temperature == NULL) && (xnp == ConstMath::tresgrand)) 
       { cout << " \n le parametre de prager n'est pas défini pour  la loi " << Nom_comp(id_comp)
              << '\n';
         ret = 0;
       }
      if ((xmu_temperature) && (xmu == ConstMath::tresgrand)) 
       { cout << " \n le parametre de lame mu n'est pas défini pour  la loi " << Nom_comp(id_comp)
              << '\n';
         ret = 0;
       }
      if ((Qzero_temperature) && (Qzero == ConstMath::tresgrand)) 
       { cout << " \n la limite de plasticite n'est pas défini pour  la loi " << Nom_comp(id_comp)
              << '\n';
         ret = 0;
       }
       return ret; 
    }; 
          
// calcul d'un module d'young équivalent à la loi, ceci pour un
// chargement nul
double Hysteresis1D::Module_young_equivalent(Enum_dure temps,const Deformation & ,SaveResul * )
  { // par défaut on prend un mu de 0.3 et on utilise l'équivalent d'une loi élastique
    // mu = G = E/(2(1+nu)) -> E=2.6 * mu
    if (xmu_temperature != NULL) xmu = xmu_temperature->Valeur(*temperature);
    return (2.6 * xmu);
    };
   
// récupération des grandeurs particulière (hors ddl )
// correspondant à liTQ
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Hysteresis1D::Grandeur_particuliere
              (bool ,List_io<TypeQuelconque>& liTQ,Loi_comp_abstraite::SaveResul * saveDon,list<int>& decal) const
{  // ici on est en 3D et les grandeurs sont par principe en absolue, donc la variable absolue ne sert pas
   // on passe en revue la liste
   List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
   list<int>::iterator idecal=decal.begin();
   for (itq=liTQ.begin();itq!=itqfin;itq++,idecal++)
     {TypeQuelconque& tipParticu = (*itq); // pour simplifier
      if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
       switch (tipParticu.EnuTypeQuelconque().EnumTQ())
       {  case NB_INVERSION:
           // a) ----- cas du nombre d'inversion actuelle
            { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
              Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
              tyTQ(1+(*idecal))=save_resul.sigma_barre_BH_R.size();
              (*idecal)++; break;
            }
          case SIGMA_REF:
           // c) ----- cas de la contrainte de référence actuelle
            { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
              Tab_Grandeur_TenseurBH& tyTQ= *((Tab_Grandeur_TenseurBH*) (*itq).Grandeur_pointee()); // pour simplifier
              if (save_resul.sigma_barre_BH_R.size() != 0)
               {tyTQ(1+(*idecal))= *(save_resul.sigma_barre_BH_R.begin());}
              else
               {tyTQ(1+(*idecal)).Inita(0.);};
              (*idecal)++; break;
            }
           // e) ----- Q_sigma actuel de R à T
          case Q_SIG_HYST_R_A_T:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             Tenseur3BH delta__sigma_barre_BH_Ratdt (save_resul.sigma_barre_BH_tdt); // a priori la ref = 0: cas du début
             if (save_resul.sigma_barre_BH_R.size() != 0) delta__sigma_barre_BH_Ratdt -= *(save_resul.sigma_barre_BH_R.begin());
                   tyTQ(1+(*idecal))=sqrt(delta__sigma_barre_BH_Ratdt.II());
             (*idecal)++; break;
           }
           // i) ----- Q_delta_sig  d'hystérésis
          case Q_DELTA_SIG_HYST:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             Tenseur3BH delta__sigma_barre_BH_tatdt(save_resul.sigma_barre_BH_tdt-save_resul.sigma_barre_BH_t);
             tyTQ(1+(*idecal)) =  sqrt(delta__sigma_barre_BH_tatdt.II());
             (*idecal)++; break;
           }
           //  ----- fonction d'aide
          case FCT_AIDE:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             tyTQ(1+(*idecal)) =  save_resul.fonction_aide_tdt;
             (*idecal)++; break;
           }
          case NB_INCRE_TOTAL_RESIDU:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if ((save_resul.indicateurs_resolution_t.Taille()))
                  tyTQ(1+(*idecal)) =  save_resul.indicateurs_resolution_t(1);
             else tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
          case NB_ITER_TOTAL_RESIDU:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if ((save_resul.indicateurs_resolution_t.Taille()))
                  tyTQ(1+(*idecal)) =  save_resul.indicateurs_resolution_t(2);
             else tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
          case NB_APPEL_FCT:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if ((save_resul.indicateurs_resolution_t.Taille()))
                  tyTQ(1+(*idecal)) =  save_resul.indicateurs_resolution_t(3);
             else tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
          case NB_STEP:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if ((save_resul.indicateurs_resolution_t.Taille()))
                  tyTQ(1+(*idecal)) =  save_resul.indicateurs_resolution_t(4);
             else tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
          case ERREUR_RK:
           { SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if ((save_resul.indicateurs_resolution_t.Taille()))
                  tyTQ(1+(*idecal)) =  save_resul.indicateurs_resolution_t(5);
             else tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
         
          default: ;// on ne fait rien
       };

	    };
};
   
// récupération et création de la liste de tous les grandeurs particulières
// ces grandeurs sont ajoutées à la liste passées en paramètres
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Hysteresis1D::ListeGrandeurs_particulieres(bool absolue,List_io<TypeQuelconque>& liTQ) const
 {// ici on est en 3D et les grandeurs sont par principe en absolue, donc la variable absolue ne sert pas 
  Tableau <double> tab_1(1);
  Tab_Grandeur_scalaire_double grand_courant(tab_1); 
  // def d'un type quelconque représentatif à chaque grandeur
  // a priori ces grandeurs sont défini aux points d'intégration identique à la contrainte par exemple
  // enu_ddl_type_pt est définit dans la loi Abtraite générale
  // on n'ajoute que si sortie_post est vraie, sinon aucune grandeur n'est sauvegardé, donc on ne peut
  // plus y accèder
  //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
  // a) $$$ cas du nombre d'inversion actuelle
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == NB_INVERSION)
      { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
        int taille = tyTQ.Taille()+1;
        tyTQ.Change_taille(taille); nexistePas = false;
      };
   if (nexistePas)
     {TypeQuelconque typQ1(NB_INVERSION,enu_ddl_type_pt,grand_courant);
        liTQ.push_back(typQ1);
     };
  };
  // c) $$$ cas de la contrainte de référence actuelle
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == SIGMA_REF)
      {Tab_Grandeur_TenseurBH& tyTQ= *((Tab_Grandeur_TenseurBH*) (*itq).Grandeur_pointee()); // pour simplifier
       int taille = tyTQ.Taille()+1;
       tyTQ.Change_taille(taille); nexistePas = false;
      };
   if (nexistePas)
     {TenseurBH* tens = NevezTenseurBH(3); // un tenseur typique
      Tab_Grandeur_TenseurBH sigrefBH(*tens,1); 
      // def d'un type quelconque représentatif 
      TypeQuelconque typQ(SIGMA_REF,SIG11,sigrefBH);
      liTQ.push_back(typQ);
      delete tens; // car on n'en a plus besoin
    };
  };
  // e) $$$ Q_sigma actuel de R à T
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == Q_SIG_HYST_R_A_T)
      {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
       int taille = tyTQ.Taille()+1;
       tyTQ.Change_taille(taille); nexistePas = false;
      };
   if (nexistePas)
     {TypeQuelconque typQ1(Q_SIG_HYST_R_A_T,SIG11,grand_courant);
        liTQ.push_back(typQ1);
     };
  };
  // i) ----- Q_delta_sig  d'hystérésis
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == Q_DELTA_SIG_HYST)
      {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
       int taille = tyTQ.Taille()+1;
       tyTQ.Change_taille(taille); nexistePas = false;
      };
   if (nexistePas)
     {TypeQuelconque typQ1(Q_DELTA_SIG_HYST,SIG11,grand_courant);
        liTQ.push_back(typQ1);
     };
  };
  //  ----- fonction d'aide
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == FCT_AIDE)
      {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
       int taille = tyTQ.Taille()+1;
       tyTQ.Change_taille(taille); nexistePas = false;
      };
   if (nexistePas)
     {TypeQuelconque typQ1(FCT_AIDE,SIG11,grand_courant);
        liTQ.push_back(typQ1);
     };
  };
  
  // ---- la suite dépend de l'indicateur : sortie_post
  if (sortie_post)
   { // j) ----- NB_INCRE_TOTAL_RESIDU
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == NB_INCRE_TOTAL_RESIDU)
        {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TypeQuelconque typQ1(NB_INCRE_TOTAL_RESIDU,SIG11,grand_courant);
          liTQ.push_back(typQ1);
       };
    };
    // k) ----- NB_ITER_TOTAL_RESIDU
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == NB_ITER_TOTAL_RESIDU)
        {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TypeQuelconque typQ1(NB_ITER_TOTAL_RESIDU,SIG11,grand_courant);
          liTQ.push_back(typQ1);
       };
    };
    // l) ----- NB_APPEL_FCT
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == NB_APPEL_FCT)
        {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TypeQuelconque typQ1(NB_APPEL_FCT,SIG11,grand_courant);
          liTQ.push_back(typQ1);
       };
    };
    // m) ----- NB_STEP
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == NB_STEP)
        {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TypeQuelconque typQ1(NB_STEP,SIG11,grand_courant);
          liTQ.push_back(typQ1);
       };
    };
    // n) ----- ERREUR_RK
    {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
     for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == ERREUR_RK)
        {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+1;
         tyTQ.Change_taille(taille); nexistePas = false;
        };
     if (nexistePas)
       {TypeQuelconque typQ1(ERREUR_RK,SIG11,grand_courant);
          liTQ.push_back(typQ1);
       };
    };
   }; // fin du cas ou sortie_post est actif, c-a-d que l'on veut des infos sur les indicateurs
   // de résolution

 };




 // ========== codage des METHODES VIRTUELLES  protegees:================
        // calcul des contraintes 
void Hysteresis1D::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() != 1)
	    { cout << "\nErreur : la dimension devrait etre 3 !\n";
		     cout << " Hysteresis1D::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 << " Hysteresis1D::Calcul_SigmaHH\n";
		     Sortie(1);
		   };
    #endif

    const Tenseur1BB & epsBB = *((Tenseur1BB*) &epsBB_); // passage en dim 1
    const Tenseur1BB & delta_epsBB = *((Tenseur1BB*) &delta_epsBB_); // passage en dim 1
    const Tenseur1HH & gijHH = *((Tenseur1HH*) &gijHH_); //   "      "  "  "
    const Tenseur1BB & gijBB = *((Tenseur1BB*) &gijBB_); //   "      "  "  "
    Tenseur1HH & sigHH = *((Tenseur1HH*) &sigHH_);  //   "      "  "  "
    Tenseur1HH & sigHH_i = *((Tenseur1HH*) &sigHH_t);  //   "      "  "  "
    SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveResul);
    // initialisation des variables de travail
    save_resul.Init_debut_calcul();
    // initialisation éventuelle des variables thermo-dépendantes
    Init_thermo_dependance();
        
    // === 1 == calcul de l'avancement temporel sur 1 pas,
    Avancement_temporel(delta_epsBB,gijHH,save_resul,sigHH);
    
    LibereTenseur();        
 };
        
        // calcul des contraintes a t+dt et de ses variations  
void Hysteresis1D::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() != 1)
	    { cout << "\nErreur : la dimension devrait etre 1 !\n";
		     cout << " Hysteresis1D::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 << " Hysteresis1D::Calcul_DsigmaHH_tdt\n";
		     Sortie(1);
		   };
    #endif    

    const Tenseur1BB & epsBB = *((Tenseur1BB*) &epsBB_tdt); // passage en dim 1
    const Tenseur1BB & delta_epsBB = *((Tenseur1BB*) &delta_epsBB_); // passage en dim 1
    const Tenseur1HH & gijHH = *((Tenseur1HH*) &gijHH_tdt); //   "      "  "  "
    const Tenseur1BB & gijBB = *((Tenseur1BB*) &gijBB_tdt); //   "      "  "  "
    Tenseur1HH & sigHH = *((Tenseur1HH*) &sigHH_tdt);  //   "      "  "  "
    Tenseur1HH & sigHH_i = *((Tenseur1HH*) &sigHH_t);  //   "      "  "  "
    SaveResulHysteresis1D & save_resul = *((SaveResulHysteresis1D*) saveResul);
    // initialisation des variables de travail
    save_resul.Init_debut_calcul();
    // initialisation éventuelle des variables thermo-dépendantes
    Init_thermo_dependance();
    
    // === 1 == calcul de l'avancement temporel sur 1 pas,
    Avancement_temporel(delta_epsBB,gijHH,save_resul,sigHH);
    
    //  ==== 2 ===  calcul de l'opérateur tangent =============
    TenseurQ1geneBHBH T_BHBH; Dsig_depsilon(T_BHBH);
    //  ==== 3 === calcul de la variation de contrainte / au ddl
    // nombre de ddl pour la variation du tenseur des contraintes
    int nbddl = d_gijBB_tdt.Taille();
    Tenseur1BH depsBH_dll;
    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 ()
           Tenseur1HH & dsigHH = *((Tenseur1HH*) (d_sigHH(i)));  // passage en dim 1
           const Tenseur1BB & d_gijBB =  *((Tenseur1BB*)(d_gijBB_tdt(i)));  // passage en dim 1
           const Tenseur1HH & dgijHH = *((Tenseur1HH*)(d_gijHH_tdt(i))) ; // pour simplifier l'ecriture
           const Tenseur1BB & depsBB = *((Tenseur1BB *) (d_epsBB(i))); //    "
           depsBH_dll = (depsBB * gijHH +   epsBB  * dgijHH );
           dsigHH =  gijHH * (T_BHBH && depsBH_dll) 
                    + dgijHH * sigma_t_barre_tdt ;
         };
     
    LibereTenseur();        
 };
	 
	   //----- lecture écriture de restart -----
	   // cas donne le niveau de la récupération
       // = 1 : on récupère tout
       // = 2 : on récupère uniquement les données variables (supposées comme telles)
void Hysteresis1D::Lecture_base_info_loi(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { string toto; 
    if (cas == 1)
     { bool test;string nom;
       // param_prager_(np)
       ent >> nom >> test;
       if (!test)
         { ent >> xnp;
           if (xnp_temperature != NULL) {if (xnp_temperature->NomCourbe() == "_")
              delete xnp_temperature; xnp_temperature = NULL;};
          }
        else
         { ent >> nom; xnp_temperature = lesCourbes1D.Lecture_pour_base_info(ent,cas,xnp_temperature); };
       // limite_plasticite_(Q0)
       ent >> nom >> test;
       if (!test)
         { ent >> Qzero;
           if (Qzero_temperature != NULL) {if (Qzero_temperature->NomCourbe() == "_")
              delete Qzero_temperature; Qzero_temperature = NULL;};
          }
        else
         { ent >> nom; Qzero_temperature = lesCourbes1D.Lecture_pour_base_info(ent,cas,Qzero_temperature); };
       // param_lame_(mu)
       ent >> nom >> test;
       if (!test)
         { ent >> xmu;
           if (xmu_temperature != NULL) {if (xmu_temperature->NomCourbe() == "_")
              delete xmu_temperature; xmu_temperature = NULL;};
          }
        else
         { ent >> nom; xmu_temperature = lesCourbes1D.Lecture_pour_base_info(ent,cas,xmu_temperature); };
       // les paramètres de réglage de l'algorithme
          ent >>  nom >> tolerance_residu >> nom >> tolerance_residu_rel
              >> nom >> nb_boucle_maxi >> nom >> maxi_delta_var_sig_sur_iter_pour_Newton
              >> nom >> tolerance_coincidence;
          ent >>  nom >> type_resolution_equa_constitutive
              >>  nom >>  cas_kutta >> nom >>  erreurAbsolue >> nom >>  erreurRelative;
          ent >>  nom >> nb_maxInvCoinSurUnPas;
          // le niveau d'affichage
          Lecture_permet_affichage(ent,cas,lesFonctionsnD);
          ent >>  nom >> sortie_post;
      }
    // appel de la classe mère
    Loi_comp_abstraite::Lecture_don_base_info(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD); 
   };
       // cas donne le niveau de sauvegarde
       // = 1 : on sauvegarde tout
       // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Hysteresis1D::Ecriture_base_info_loi(ofstream& sort,const int cas)
  { if (cas == 1) 
     { sort << "  HYSTERESIS_1D ";
       sort << "  param_prager_(np) "; 
       if (xnp_temperature == NULL)
        { sort << false << " " << xnp << " ";}
       else 
        { sort << true << " fonction_xnp_temperature ";
          LesCourbes1D::Ecriture_pour_base_info(sort,cas,xnp_temperature);
         };
       sort  << " limite_plasticite_(Q0) ";
       if (Qzero_temperature == NULL)
        { sort << false << " " << Qzero << " ";}
       else 
        { sort << true << " fonction_Qzero_temperature ";
          LesCourbes1D::Ecriture_pour_base_info(sort,cas,Qzero_temperature);
         };
       sort << " param_lame_(mu) ";
       if (xmu_temperature == NULL)
        { sort << false << " " << xmu << " ";}
       else 
        { sort << true << " fonction_xmu_temperature ";
          LesCourbes1D::Ecriture_pour_base_info(sort,cas,xmu_temperature);
         };
       sort << "\n tolerance_algo_newton_equadiff:_absolue= " << tolerance_residu
            << " relative= "<< tolerance_residu_rel
            << " nb_boucle_maxi " << nb_boucle_maxi
            << " maxi_delta_var_sig_sur_iter_pour_Newton " << maxi_delta_var_sig_sur_iter_pour_Newton
            << " tolerance_coincidence " << tolerance_coincidence;
       sort << "\n type_resolution_equa_constitutive " << type_resolution_equa_constitutive
            << " cas_kutta " << cas_kutta 
            << " erreurAbsolue " << erreurAbsolue << " erreurRelative " << erreurRelative << " ";                
       sort << " nb_maxInvCoinSurUnPas " << nb_maxInvCoinSurUnPas ;
       // niveau d'affichage
       Affiche_niveau_affichage(sort,cas);
       sort << " sortie_post " << sortie_post
            << " ";
      }
	// appel de la classe mère
    Loi_comp_abstraite::Ecriture_don_base_info(sort,cas);  
   }; 

