// 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-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 "MatLapack.h"
#include "ExceptionsLoiComp.h"
#include "MotCle.h"
#include "CharUtil.h"

#include "Hysteresis3D.h"

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

// $$$$$$$$$$$$$$$$$$$$$ a faire $$$$$$$$$$$$$$$$$
// a priori la sauvegarde de w_base n'est pas nécessaire car c'est un résultat
// mais on ne sans sert pas comme test, et à l'aide des listes on peut savoir si l'on est sur
// une première charge ou non, ce qui donne la valeur de w_base

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

// constructeur par défaut
Hysteresis3D::SaveResulHysteresis3D::SaveResulHysteresis3D() :
	          sigma_barre_BH_t(),sigma_barre_BH_tdt(),sigma_barre_BH_R()
	          ,oc_BH_R(),oc_BH_t(),oc_BH_tdt(),fonction_aide_t(0.),fonction_aide_tdt(0.)
           ,wBase_t(1),wBase_tdt(1)
	          ,def_equi_at(0.),def_equi_atdt(0.)
           ,ip2(),fct_aide_t_a_tdt(),fct_aide()
	          ,modif(0),sigma_barre_BH_R_t_a_tdt(),nb_coincidence(0)
	          ,oc_BH_t_a_tdt(),def_equi_t_a_tdt(),def_equi()
           ,sigma_barre_BH_R_atrans(),oc_BH_R_atrans()
           ,indicateurs_resolution(),indicateurs_resolution_t()

//           ,modif_sauve(0),sigma_barre_BH_R_sauve(),nb_ref_new_sauve(0)
//           ,nb_coincidence_sauve(0),oc_BH_R_sauve(),nb_centre_new_sauve(0)
//           ,def_equi_sauve()
{ // la première valeur de la déformation équivalente est 0
 def_equi.push_front(0.);
 // la première valeur de la fonction d'aide est l'infini
 fct_aide.push_front(ConstMath::tresgrand); 
 }; 
// constructeur de copie	           
Hysteresis3D::SaveResulHysteresis3D::SaveResulHysteresis3D(const SaveResulHysteresis3D& 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)
	          ,oc_BH_R(sav.oc_BH_R),oc_BH_t(sav.oc_BH_t),oc_BH_tdt(sav.oc_BH_tdt)
	          ,fonction_aide_t(sav.fonction_aide_t),fonction_aide_tdt(sav.fonction_aide_tdt)
	          ,wBase_t(sav.wBase_t),wBase_tdt(sav.wBase_tdt)
	          ,def_equi_at(sav.def_equi_at),def_equi_atdt(sav.def_equi_atdt)
	          ,modif(sav.modif),sigma_barre_BH_R_t_a_tdt(sav.sigma_barre_BH_R_t_a_tdt)
	          ,nb_coincidence(sav.nb_coincidence),oc_BH_t_a_tdt(sav.oc_BH_t_a_tdt)
	          ,def_equi_t_a_tdt(sav.def_equi_t_a_tdt),def_equi(sav.def_equi)
           ,ip2(),fct_aide_t_a_tdt(sav.fct_aide_t_a_tdt),fct_aide(sav.fct_aide)
           ,sigma_barre_BH_R_atrans(sav.sigma_barre_BH_R_atrans),oc_BH_R_atrans(sav.oc_BH_R_atrans)
           ,indicateurs_resolution(sav.indicateurs_resolution),indicateurs_resolution_t(sav.indicateurs_resolution_t)

//           ,modif_sauve(sav.modif_sauve),sigma_barre_BH_R_sauve(sav.sigma_barre_BH_R_sauve)
//           ,nb_ref_new_sauve(sav.nb_ref_new_sauve),nb_coincidence_sauve(sav.nb_coincidence_sauve)
//           ,oc_BH_R_sauve(sav.oc_BH_R_sauve),nb_centre_new_sauve(sav.nb_centre_new_sauve)
//           ,def_equi_sauve(sav.def_equi_sauve)


 { if (fct_aide.size() >= 2) // pointage de ip2
     {ip2= fct_aide.end(); ip2--;ip2--; }
   }; 
  
// affectation
Loi_comp_abstraite::SaveResul & Hysteresis3D::SaveResulHysteresis3D::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { Hysteresis3D::SaveResulHysteresis3D& sav = *((Hysteresis3D::SaveResulHysteresis3D*) &a);
    // recopie de toutes les grandeurs
	   oc_BH_t = sav.oc_BH_t;
	   oc_BH_tdt = sav.oc_BH_tdt;
	   def_equi_at = sav.def_equi_at;
	   def_equi_atdt = sav.def_equi_atdt;
	   oc_BH_t_a_tdt = sav.oc_BH_t_a_tdt;
	   def_equi_t_a_tdt = sav.def_equi_t_a_tdt;
	   oc_BH_R = sav.oc_BH_R;
	   def_equi = sav.def_equi;
	   sigma_barre_BH_R_atrans = sav.sigma_barre_BH_R_atrans;
	   oc_BH_R_atrans = sav.oc_BH_R_atrans;
	   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;
	   wBase_t = sav.wBase_t;
    wBase_tdt = sav.wBase_tdt;
    fct_aide = sav.fct_aide;
    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;
	   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 Hysteresis3D::SaveResulHysteresis3D::Lecture_base_info (istream& 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 >>  oc_BH_t; oc_BH_tdt=oc_BH_t;
    ent >> toto >>  wBase_t; wBase_tdt=wBase_t;
    ent >> toto >> def_equi_at >> def_equi_atdt;
    ent >> toto >>  fonction_aide_t; fonction_aide_tdt=fonction_aide_t;
    // ----  lecture liste fonction d'aide
    ent >> toto;
    #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: list_fct_aide "
                << " on a lu "<< toto
                << " avec auparavent: "
                << "\n fonction_aide_t= "<< fonction_aide_t
                << "\n def_equi_at= "<< def_equi_at
                << "\n def_equi_atdt= "<< def_equi_atdt
                << "\n wBase_t= "<< wBase_t
                << "\n  Hysteresis3D::SaveResulHysteresis3D::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--; }
    // ----  lecture des centre de cercle
    ent >> toto;
    #ifdef MISE_AU_POINT
      if (toto != "list_oc_BH_R")
         { cout << "\n erreur dans la lecture de la  list_io de centre, on ne trouve pas le mot cle: list_oc_BH_R "
                << "\n  Hysteresis3D::SaveResulHysteresis3D::Lecture_base_info (... ";
           Sortie(1);     
          }       
    #endif
    ent >> toto >> taille; // lecture de la taille de la liste
    Tenseur3BH elem;
    // on vide la liste actuelle
    oc_BH_R.clear();
    for (int i=1;i<=taille;i++) // puis on lit
      { ent >> elem; // lecture
        oc_BH_R.push_back(elem); // enregistrement
       }       
    // initialisation pour le transport éventuel
    oc_BH_R_atrans= oc_BH_R;
   
    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: list_pt_inver "
                << "\n  Hysteresis3D::SaveResulHysteresis3D::Lecture_base_info (... ";
           Sortie(1);     
          }       
    #endif
    // on vide la listes actuelle et on lit
    sigma_barre_BH_R.clear();
    ent >> toto >> taille; // lecture de la taille du nombre de point d'inversion
    for (int j=1;j<=taille;j++) // puis on lit 
      { ent >> elem; // lecture
        sigma_barre_BH_R.push_back(elem); // enregistrement
      };
    // initialisation pour le transport éventuel
    sigma_barre_BH_R_atrans = sigma_barre_BH_R;
    ent >> toto; // ----  lecture def équivalente
    #ifdef MISE_AU_POINT
      if (toto != "list_def_equi")
         { cout << "\n erreur dans la lecture de la  list_io def equivalente, on ne trouve pas le mot cle: list_def_equi "
                << "\n  Hysteresis3D::SaveResulHysteresis3D::Lecture_base_info (... ";
           Sortie(1);     
          }       
    #endif
    int taille_C;ent >> toto >> taille_C; // lecture de la taille
    double un_elem_eps;
    // on vide la liste actuelle
    def_equi.clear();
    for (int i=1;i<=taille_C;i++) // puis on lit
      { ent >> un_elem_eps; // lecture
        def_equi.push_back(un_elem_eps); // enregistrement
       }       
    //re-initialisation des variables de travail
    TversTdt();
//    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 Hysteresis3D::SaveResulHysteresis3D::Ecriture_base_info(ostream& sort,const int )
  { // ici toutes les données sont toujours a priori variables
    sort << "  sigma_barre_BH_t " << sigma_barre_BH_t;
    sort << "\n     oc_BH_t " << oc_BH_t; 
    sort << "\n     wBase_t " << wBase_t;
    sort << "\n def_equi_at_et_tdt " << def_equi_at << " " << def_equi_atdt;
    sort << "  fct_aide_t " << fonction_aide_t; 
    // liste des fonctions d'aide
    {sort << "\n  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 << " "; }
    }
    // listes: centre de cercle  et point d'inversion
    sort << "\n     list_oc_BH_R " << "taille= " << oc_BH_R.size() << " ";
    List_io <Tenseur3BH>::const_iterator iter_courant,iter_fin = oc_BH_R.end();
    for (iter_courant=oc_BH_R.begin();iter_courant!=iter_fin;iter_courant++)
     { sort  << setprecision(ParaGlob::NbdigdoCA()) << (*iter_courant) ; sort << " "; 
      };
    int taille_sigma_barre_BH_R= sigma_barre_BH_R.size(); 
    sort << "\n     list_pt_inver " << "taille= " << taille_sigma_barre_BH_R << " ";
    List_io <Tenseur3BH>::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 << " "; 
     };
    // les listes: def équivalente
    sort << "  list_def_equi " << "taille= " << def_equi.size() << " ";
    List_io <double>::const_iterator kter_courant,kter_fin = def_equi.end();
    for (kter_courant=def_equi.begin();kter_courant!=kter_fin;kter_courant++)
     { sort  << setprecision(ParaGlob::NbdigdoCA()) << (*kter_courant) ; sort << " "; };     
     
   }; 
	        
// mise à jour des informations transitoires 
void Hysteresis3D::SaveResulHysteresis3D::TdtversT() 
   { // partie générale
     sigma_barre_BH_t = sigma_barre_BH_tdt;oc_BH_t=oc_BH_tdt;
     wBase_t = wBase_tdt;
     def_equi_at = def_equi_atdt;  // def équivalente
     fonction_aide_t=fonction_aide_tdt;
     // partie spécifique
     
// en fait ici on pourrait simplifier car le cas 3 est toujours valide -> supprime l'utilité
// du paramètre modif !!     
     
//     int maxi_ref_en_plus = 0; // indique le maximum de ref que l'on a mis en plus dans la liste

//------- débug ---------
     // vérif de la cohérence des centres et références: les rayons associés doivent être de tailles
     // décroissantes
//     Verif_centre_reference();
//-------- fin débug -----------


     // ------- mise en place des modifs ----------
//     modif_sauve = modif ; // pour le retour t -> tdt éventuel
//     nb_coincidence_sauve = nb_coincidence; // idem
    
     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 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;
           for (int i=1;i<=nb_coincidence;i++)
             { itens = sigma_barre_BH_R.begin(); 
               if (itens != sigma_barre_BH_R.end()) // si itens == sigma_barre_BH_R.end(), cela signifie
                   {//sigma_barre_BH_R_sauve.push_back(*itens); // on sauve avant de détruire
                    sigma_barre_BH_R.erase(itens);  // que la référence est le tenseur nulle, on arrête de dépiler
                   };
               ioc_i = oc_BH_R.begin(); 
               if (ioc_i != oc_BH_R.end())  // si ioc_i == oc_BH_R.end(), cela signifie que le centre de référence
                   {//oc_BH_R_sauve.push_back(*ioc_i);  // on sauve avant de détruire
                    oc_BH_R.erase(ioc_i);   // est le tenseur nulle
                   };
               // idem pour les def équivalentes
               List_io <double>::iterator idouble;     
               idouble = def_equi.begin();
               if (idouble != def_equi.end())  // si idouble == def_equi.end(), cela signifie que l'on est arrivé
                  { //def_equi_sauve.push_back(*idouble);  // on sauve avant de détruire
                    def_equi.erase(idouble);   // sur la branche fondamentale
                  };
               // idem pour la fonction d'aide
               List_io <double>::iterator ifct;
               ifct = fct_aide.begin();
               if (ifct != fct_aide.end())  // si ifct == fct_aide.end(), cela signifie que l'on est arrivé
                  { //fct_aide_sauve.push_back(*ifct);  // on sauve avant de détruire
                    fct_aide.erase(ifct);   // sur la branche fondamentale
                  };
             };
          break;
          }
        case 2: // cas où l'on a une ou plusieurs inversions 
         { // on traite les centres différement des points d'inversions
           int nb_centre_new  = oc_BH_t_a_tdt.size(); // récup du nombre de nouveaux centres
//           nb_centre_new_sauve = nb_centre_new; // on sauvegarde pour un retour t -> tdt éventuel
           // on ajoute les différents nouveaux centres, en tenant compte du fait que le premier rentrée est 
           // le dernier dans la liste, d'où l'utilisation de reverse_iterator
           List_io <Tenseur3BH>::reverse_iterator iifoi = oc_BH_t_a_tdt.rbegin();
           for (int ii=1;ii<=nb_centre_new;ii++,iifoi++)
               oc_BH_R.push_front(*iifoi);
           // maintenant on traites les points d'inversions    
           int nb_ref_new = sigma_barre_BH_R_t_a_tdt.size(); // récup du nombre de nouveaux pt
//           nb_ref_new_sauve = nb_ref_new; // on sauve pour le retour t -> tdt éventuel
           // on ajoute les différents points d'inversions
           List_io <Tenseur3BH>::reverse_iterator iitens = sigma_barre_BH_R_t_a_tdt.rbegin();
           for (int ii=1;ii<=nb_ref_new;ii++,iitens++)
              sigma_barre_BH_R.push_front(*iitens);
           // pour les def équivalentes
           List_io <double>::reverse_iterator iidouble = def_equi_t_a_tdt.rbegin();
           for (int ij=1;ij<=nb_ref_new;ij++,iidouble++)
              def_equi.push_front(*iidouble);
           // cas de la fonction d'aide
           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_fct_new = fct_aide_t_a_tdt.size(); // récup du nombre de nouveau pt
           // on ajoute les différentes valeurs
           List_io <double>::iterator iifct = fct_aide_t_a_tdt.begin();
           for (int ii=1;ii<=nb_ref_new;ii++,iitens++,iifct++)
            {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)
         { // les coïncidences   sont forcéments au début puis on a les inversions qui sont
           // au nombre d'éléments sur la liste secondaire
           //  a) on commence par traiter les coïncidences
           // a chaque coincidence il faut 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;
           for (int i=1;i<=nb_coincidence;i++)
             { itens = sigma_barre_BH_R.begin(); 
               if (itens != sigma_barre_BH_R.end()) // si itens == sigma_barre_BH_R.end(), cela signifie
                   {//sigma_barre_BH_R_sauve.push_back(*itens); // on sauve avant de détruire
                    sigma_barre_BH_R.erase(itens);  // que la référence est le tenseur nulle, on arrête de dépiler
                   };
               ioc_i = oc_BH_R.begin();
               if (ioc_i != oc_BH_R.end())  // si ioc_i == oc_BH_R.end(), cela signifie que le centre de référence
                   {//oc_BH_R_sauve.push_back(*ioc_i);  // on sauve avant de détruire
                    oc_BH_R.erase(ioc_i);   // est le tenseur nulle
                   };
              // idem pour les def équivalentes
               List_io <double>::iterator idouble;     
               idouble = def_equi.begin(); 
               if (idouble != def_equi.end())  // si idouble == def_equi.end(), cela signifie que l'on est arrivé
                  { //def_equi_sauve.push_back(*idouble);  // on sauve avant de détruire
                    def_equi.erase(idouble);   // sur la branche fondamentale
                  }
               // idem pour la fonction d'aide
               List_io <double>::iterator ifct;
               ifct = fct_aide.begin();
               if (ifct != fct_aide.end())  // si ifct == fct_aide.end(), cela signifie que l'on est arrivé
                  { //fct_aide_sauve.push_back(*ifct);  // on sauve avant de détruire
                    fct_aide.erase(ifct);   // sur la branche fondamentale
                  };
              };
           //   b) maintenant on s'occupe des inversions
           // on traite les centres différemment des points d'inversions
           int nb_centre_new = oc_BH_t_a_tdt.size(); // récup du nombre de nouveaux centres
//           nb_centre_new_sauve = nb_centre_new; // on sauvegarde pour un retour t -> tdt éventuel
           // on ajoute les différents nouveaux centres
           List_io <Tenseur3BH>::reverse_iterator iifoi = oc_BH_t_a_tdt.rbegin();
           for (int ii=1;ii<=nb_centre_new;ii++,iifoi++)
               oc_BH_R.push_front(*iifoi);
           // maintenant on traites les points d'inversions    
           int nb_ref_new = sigma_barre_BH_R_t_a_tdt.size(); // récup du nombre de nouveaux pt
//           nb_ref_new_sauve = nb_ref_new; // on sauve pour le retour t -> tdt éventuel
           // on ajoute les différents points d'inversions
           List_io <Tenseur3BH>::reverse_iterator iitens = sigma_barre_BH_R_t_a_tdt.rbegin();
           for (int ii=1;ii<=nb_ref_new;ii++,iitens++)
              sigma_barre_BH_R.push_front(*iitens);
           // pour les def équivalentes
           List_io <double>::reverse_iterator iidouble = def_equi_t_a_tdt.rbegin();
           for (int ij=1;ij<=nb_ref_new;ij++,iidouble++)
              def_equi.push_front(*iidouble);
           // cas de la fonction d'aide
           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_fct_new = fct_aide_t_a_tdt.size(); // récup du nombre de nouveau pt
           // on ajoute les différentes valeurs
           List_io <double>::iterator iifct = fct_aide_t_a_tdt.begin();
           for (int ii=1;ii<=nb_ref_new;ii++,iitens++,iifct++)
            {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;
          }         
        default:
         cout << "\n erreur dans la mise a jour des informations transitoire: modif= " << modif
              << "\n Hysteresis3D::SaveResulHysteresis3D::TversTdt() ";
         Sortie(1);
        }       
	 // --------------------- très important: traitement de finition --------------------------
	 // si les rayons résultants que l'on a ajoute sont à une distance inférieure à la précision de la coincidence
	 // on les collapses !!
// finalement on va traiter directement au niveau des coincidences pour l'instant !!	 
//	 if (maxi_ref_en_plus != 0)
//	  {
//	 	}

//------- débug ---------
     // vérif de la cohérence des centres et références: les rayons associés doivent être de tailles
     // décroissantes
//     Verif_centre_reference(6);
//-------- fin débug -----------

     // on sauve les grandeurs transportables
     sigma_barre_BH_R_atrans = sigma_barre_BH_R;
     oc_BH_R_atrans= oc_BH_R;
     // 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 Hysteresis3D::SaveResulHysteresis3D::TversTdt() 
   { // partie générale
     sigma_barre_BH_tdt = sigma_barre_BH_t;oc_BH_tdt=oc_BH_t;
	    wBase_tdt=wBase_t;
     def_equi_atdt = def_equi_at;   // def équivalente
     // on supprime le transport éventuel
     sigma_barre_BH_R = sigma_barre_BH_R_atrans;
     oc_BH_R = oc_BH_R_atrans;
     fonction_aide_tdt=fonction_aide_t;

// en fait le tant que le pas n'est pas validé, les différentes listes ne sont pas changées
// donc il n'y a pas à mettre en place une stratégie pour revenir en arrière
// une fois que le pas est validé, effectivement on ne peut pas revenir en arrière, mais
// c'est aussi vrai pour toutes les autres lois
// ceci étant la suite serait une solution pour revenir en arrière
    
    
//     // maintenant on essaie de remettre les choses d'aplomb
//     switch (modif_sauve)
//      { case 0: // rien n'a changé sur le pas en terme de coincidence et d'inversion
//         { break; // donc rien n'a faire !! ouf
//          }
//        case 1: // cas où l'on a eu une ou plusieurs coincidences
//         { // ici il suffit de rajouter tous les tenseurs qui ont été supprimés
//           List_io <Tenseur3BH>::iterator itens;List_io <Tenseur3BH>::iterator ioc_i;
//           {List_io <Tenseur3BH>::iterator itens_fin=sigma_barre_BH_R_sauve.end();
//            for (itens = sigma_barre_BH_R_sauve.begin(); itens != itens_fin;itens++)
//              sigma_barre_BH_R.push_front(*itens);
//           };
//           {List_io <Tenseur3BH>::iterator itens_fin=oc_BH_R_sauve.end();
//            for (itens = oc_BH_R_sauve.begin(); itens != itens_fin;itens++)
//              oc_BH_R.push_front(*itens);
//           };
//           {List_io <double>::iterator idouble,idouble_fin= def_equi_sauve.end();
//            for (idouble = def_equi_sauve.begin(); idouble != idouble_fin;idouble++)
//              def_equi.push_front(*idouble);
//           };
//           // puis on supprime les sauvegardes histoire de ne pas rajouter une nouvelle fois
//           sigma_barre_BH_R.clear();oc_BH_R_sauve.clear();def_equi_sauve.clear();
//          break;
//         }
//        case 2: // cas où l'on a eu une ou plusieurs inversions
//         { // pour les centres on en a rajouté nb_centre_new_sauve, on les supprimes
//           List_io <Tenseur3BH>::iterator ioc_i;
//           for (int i=1; i<= nb_centre_new_sauve;i++)
//             { ioc_i = oc_BH_R.begin();
//               oc_BH_R.erase(ioc_i);
//             };
//           // maintenant on traites les points d'inversions, même chose que les centres on supprime
//           List_io <Tenseur3BH>::iterator iitens;
//           for (int i=1; i<= nb_ref_new_sauve;i++)
//             { iitens = sigma_barre_BH_R.begin();
//               sigma_barre_BH_R.erase(iitens);
//             };
//           // pour les def équivalentes, même chose
//           List_io <double>::iterator iidouble;
//           for (int i=1; i<= nb_ref_new_sauve;i++)
//             { iidouble = def_equi.begin();
//               def_equi.erase(iidouble);
//             };
//           // on supprime les compteurs pour éviter une autre suppression future
//           nb_centre_new_sauve=0;nb_ref_new_sauve=0;
//          break;
//         }
//        case 3: // cas où l'on a eu une ou plusieurs coincidence(s) et inversion (s)
//         { // on traite dans l'ordre inverse du cas tdt -> t
//           // -- a) on s'occupe des inversions
//           // pour les centres on en a rajouté nb_centre_new_sauve, on les supprimes
//          {List_io <Tenseur3BH>::iterator ioc_i;
//           for (int i=1; i<= nb_centre_new_sauve;i++)
//             { ioc_i = oc_BH_R.begin();
//               oc_BH_R.erase(ioc_i);
//             };
//           // maintenant on traites les points d'inversions, même chose que les centres on supprime
//           List_io <Tenseur3BH>::iterator iitens;
//           for (int i=1; i<= nb_ref_new_sauve;i++)
//             { iitens = sigma_barre_BH_R.begin();
//               sigma_barre_BH_R.erase(iitens);
//             };
//           // pour les def équivalentes, même chose
//           List_io <double>::iterator iidouble;
//           for (int i=1; i<= nb_ref_new_sauve;i++)
//             { iidouble = def_equi.begin();
//               def_equi.erase(iidouble);
//             };
//           // on supprime les compteurs pour éviter une autre suppression future
//           nb_centre_new_sauve=0;nb_ref_new_sauve=0;
//          };
//           // -- b) on s'occupe des coincidences
//           // ici il suffit de rajouter tous les tenseurs qui ont été supprimés
//          {List_io <Tenseur3BH>::iterator itens;List_io <Tenseur3BH>::iterator ioc_i;
//           {List_io <Tenseur3BH>::iterator itens_fin=sigma_barre_BH_R_sauve.end();
//            for (itens = sigma_barre_BH_R_sauve.begin(); itens != itens_fin;itens++)
//              sigma_barre_BH_R.push_front(*itens);
//           };
//           {List_io <Tenseur3BH>::iterator itens_fin=oc_BH_R_sauve.end();
//            for (itens = oc_BH_R_sauve.begin(); itens != itens_fin;itens++)
//              oc_BH_R.push_front(*itens);
//           };
//           {List_io <double>::iterator idouble,idouble_fin= def_equi_sauve.end();
//            for (idouble = def_equi_sauve.begin(); idouble != idouble_fin;idouble++)
//              def_equi.push_front(*idouble);
//           };
//           // puis on supprime les sauvegardes histoire de ne pas rajouter une nouvelle fois
//           sigma_barre_BH_R.clear();oc_BH_R_sauve.clear();def_equi_sauve.clear();
//          };
//           break;
//          }         
//        default:
//         cout << "\n erreur dans la mise a jour des informations transitoire: modif= " << modif
//              << "\n Hysteresis3D::SaveResulHysteresis3D::TversTdt() ";
//         Sortie(1);
//      };
     //re-initialisation des variables de travail
     Init_debut_calcul();
	  };
			  
// affichage à l'écran des infos
void Hysteresis3D::SaveResulHysteresis3D::Affiche() const 
{ cout << "\n SaveResulHysteresis3D: " ; 
  cout << "\n sigma_barre_BH_t= " << sigma_barre_BH_t << " sigma_barre_BH_tdt= " << sigma_barre_BH_tdt
       << " oc_BH_t= " << oc_BH_t << " oc_BH_tdt= " << oc_BH_tdt
       << " wBase_t= " << wBase_t << " wBase_tdt= " << wBase_tdt
       << " def_equi_at= " << def_equi_at << " def_equi_atdt= " << def_equi_atdt
       << " fonction_aide_t= " << fonction_aide_t << " fonction_aide_tdt= " << fonction_aide_tdt;
  cout << "\n -- info de travail en cours: ";
  cout << " modif= " << modif << "\n list sigma_barre_BH_R_t_a_tdt: " << sigma_barre_BH_R_t_a_tdt
       << "\n nb_coincidence= " << nb_coincidence 
       << "\n list oc_BH_t_a_tdt: " << oc_BH_t_a_tdt
       << "\n list def_equi_t_a_tdt: " << def_equi_t_a_tdt;
  cout << "\n -- memorisation discrete de 0 a t: ";
  cout << "\n list sigma_barre_BH_R: " << sigma_barre_BH_R;
  cout << "\n list oc_BH_R: " << oc_BH_R;		 
  cout << "\n list def_equi: " << def_equi;		 
  cout << "\n list fct_aide: " << fct_aide << " ";		 
  cout  << "\n .. fin SaveResulHysteresis3D ... ";
};

//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 Hysteresis3D::SaveResulHysteresis3D::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);
  oc_BH_t.ChBase(beta,gamma);
  oc_BH_tdt.ChBase(beta,gamma);
  // encapsulage pour utiliser deux fois les mêmes itérators
  { List_io <Tenseur3BH>::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 <Tenseur3BH>::iterator lit(oc_BH_t_a_tdt.begin()),
                                   lend(oc_BH_t_a_tdt.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit).ChBase(beta,gamma);
  };
  { List_io <Tenseur3BH>::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);
  };
  { List_io <Tenseur3BH>::iterator lit(oc_BH_R.begin()),
                                   lend(oc_BH_R.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit).ChBase(beta,gamma);
  };
  { List_io <Tenseur3BH>::iterator lit(sigma_barre_BH_R_atrans.begin()),
                                   lend(sigma_barre_BH_R_atrans.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit).ChBase(beta,gamma);
  };
  { List_io <Tenseur3BH>::iterator lit(oc_BH_R_atrans.begin()),
                                   lend(oc_BH_R_atrans.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 Hysteresis3D::SaveResulHysteresis3D::Init_debut_calcul()
   { //initialisation des variables de travail
     modif = 0; nb_coincidence=0;
     sigma_barre_BH_R_t_a_tdt.clear();oc_BH_t_a_tdt.clear();def_equi_t_a_tdt.clear();
     fct_aide_t_a_tdt.clear();
//---- debug
//               cout << "\n Hysteresis3D::SaveResulHysteresis3D::Init_debut_calcul() "<<  endl;
//---- fin debug
	};
///----------***** fin de l'introduction de la fonction d'aide

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

Hysteresis3D::Hysteresis3D ()  : // Constructeur par defaut
  Loi_comp_abstraite(HYSTERESIS_3D,CAT_MECANIQUE,3)
  // ---- para matériau 
  ,xnp(ConstMath::tresgrand),xnp_temperature(NULL),xnp_lue(ConstMath::tresgrand)
  ,Qzero(ConstMath::tresgrand),Qzero_temperature(NULL),Qzero_lue(ConstMath::tresgrand)
  ,xmu(ConstMath::tresgrand),xmu_temperature(NULL),xmu_lue(ConstMath::tresgrand)
  // parmètres de phase éventuelles
  ,xnp_phase(NULL),Qzero_defEqui(NULL),xnp_defEqui(NULL),Qzero_phase(NULL),xmu_phase(NULL)
  ,avec_phaseDeltaSig(false),avec_phaseEps(NULL)
  ,avec_defEqui(false),avec_phase_paradefEqui(false),coef_paradefEqui(NULL)
  ,val_coef_paradefEqui(1.),mini_QepsilonBH(1.e-4)
  ,type_de_transport_memorisation(0)
  ,niveau_bascule_fct_aide(10.) //volontairement très grand => ne sert pas

  // --- réglage résolution de l'équation constitutive
   ,tolerance_coincidence(),mini_rayon(ConstMath::pasmalpetit)
   ,tolerance_centre(0.001)
   ,min_angle_trajet_neutre(0.008),possibilite_cosAlphaNegatif(true) // environ 90° - 0.5°
   ,mini_Qsig_pour_phase_sigma_Oi_tdt(1.5) // 1.5 MPa
   ,type_resolution_equa_constitutive(1)
   ,type_calcul_comportement_tangent(1),avecVarWprimeS(false)
   ,nb_maxInvCoinSurUnPas(4),force_phi_zero_si_negatif(0.)
   ,depassement_Q0(2.)
  // ---- réglage résolution avec linéarisation
   ,tolerance_residu(1.e-3),tolerance_residu_rel(1.e-5),nb_boucle_maxi(6),nb_dichotomie(4)
   ,maxi_delta_var_sig_sur_iter_pour_Newton(-1)
  // ---- réglage résolution avec Kutta
   ,cas_kutta(5),erreurAbsolue(1.e-3),erreurRelative(1.e-5),nbMaxiAppel(1000)
  // ---- affichage
   ,sortie_post(0)
  // ---- init variable de travail
   ,sigma_t_barre_tdt(),sigma_i_barre_BH(),sigma_barre_BH_R()
   ,def_equi_R(0.),def_i_equi(0.),def_equi_atdt(0.),defEqui_maxi(0.)
   ,delta_sigma_barre_BH_Rat(),delta_sigma_barre_BH_Ra_i(),delta_sigma_barre_BH_Ratdt()
   ,delta_sigma_barre_tdt_BH(),residuBH()
   ,delta_epsBH(),delta_barre_epsBH(),delta_barre_alpha_epsBH()
   ,wBase(1),wprime(1),wprime_point(0.),trajet_neutre(false),d_wprime(),d_wprime_point()
   ,residu(9),derResidu(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,derResidu_adefConstant(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,alg_zero(),alg_edp()
   ,rdelta_sigma_barre_BH_Ratdt(),rdelta_sigma_barre_tdt_BH()
   ,sig_point(9),sigma_pointBH(),sigma_tauBH(),sigma_tau(9)
   ,delta_sigma_barre_R_a_tauBH(),delta_sigma_barre_t_a_tauBH()
   ,betaphideltasigHB(),deuxmudeltaepsHB()
   ,sig_initiale(9),dersig_initiale(9),sig_finale(9),dersig_finale(9),estime_erreur(9)
   ,val_initiale(9),racine(9)
   ,der_at_racine(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,centre_initial(true),aucun_pt_inversion(true)
   ,dRdsigMoinsun(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,dRdeps(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,MPC(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,dsig_ojef_HHHH()
   ,matriceH(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,matriceM(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,matHmoinsun(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
   ,calcul_dResi_dsig(false)
    {// 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_dichotomie);
     tolerance_coincidence = tolerance_residu * 100;
     tolerance_centre = tolerance_coincidence;
     // idem avec kutta
     alg_edp.Modif_nbMaxiAppel(nbMaxiAppel);    
    };
	
// Constructeur de copie
Hysteresis3D::Hysteresis3D (const Hysteresis3D& loi) :
   Loi_comp_abstraite(loi)
  // ---- para matériau 
   ,xnp(loi.xnp),xmu(loi.xmu),Qzero(loi.Qzero)
   ,xnp_lue(loi.xnp_lue),xmu_lue(loi.xmu_lue),Qzero_lue(loi.Qzero_lue)
   ,xnp_temperature(loi.xnp_temperature),Qzero_temperature(loi.Qzero_temperature)
   ,xmu_temperature(loi.xmu_temperature)
   // paramètres de phase éventuelles
   ,xnp_phase(loi.xnp_phase),Qzero_defEqui(loi.Qzero_defEqui)
	  ,xnp_defEqui(loi.xnp_defEqui),Qzero_phase(loi.Qzero_phase),xmu_phase(loi.xmu_phase)
   ,avec_phaseDeltaSig(loi.avec_phaseDeltaSig),avec_phaseEps(loi.avec_phaseEps)
   ,avec_defEqui(loi.avec_defEqui)
   ,avec_phase_paradefEqui(loi.avec_phase_paradefEqui),coef_paradefEqui(loi.coef_paradefEqui)
   ,val_coef_paradefEqui(1.),mini_QepsilonBH(loi.mini_QepsilonBH)
   ,type_de_transport_memorisation(loi.type_de_transport_memorisation)
   ,niveau_bascule_fct_aide(loi.niveau_bascule_fct_aide)
 
  // --- réglage résolution de l'équation constitutive
   ,tolerance_coincidence(loi.tolerance_coincidence),mini_rayon(loi.mini_rayon)
   ,tolerance_centre(loi.tolerance_centre)
   ,min_angle_trajet_neutre(loi.min_angle_trajet_neutre) // environ 90° - 0.5°
   ,possibilite_cosAlphaNegatif(loi.possibilite_cosAlphaNegatif)
	  ,mini_Qsig_pour_phase_sigma_Oi_tdt(loi.mini_Qsig_pour_phase_sigma_Oi_tdt)
   ,type_resolution_equa_constitutive(loi.type_resolution_equa_constitutive)
   ,type_calcul_comportement_tangent(loi.type_calcul_comportement_tangent),avecVarWprimeS(loi.avecVarWprimeS)
   ,nb_maxInvCoinSurUnPas(loi.nb_maxInvCoinSurUnPas),force_phi_zero_si_negatif(loi.force_phi_zero_si_negatif)
   ,depassement_Q0(loi.depassement_Q0)

  // ---- réglage résolution avec linéarisation
   ,tolerance_residu(loi.tolerance_residu),tolerance_residu_rel(loi.tolerance_residu_rel)
   ,nb_boucle_maxi(loi.nb_boucle_maxi),nb_dichotomie(loi.nb_dichotomie)
   ,maxi_delta_var_sig_sur_iter_pour_Newton(loi.maxi_delta_var_sig_sur_iter_pour_Newton)
  // ---- réglage résolution avec Kutta
   ,cas_kutta(loi.cas_kutta),erreurAbsolue(loi.erreurAbsolue),erreurRelative(loi.erreurRelative)
   ,nbMaxiAppel(loi.nbMaxiAppel)
  // ---- affichage
   ,sortie_post(loi.sortie_post)
  // ---- intit variable de travail
   ,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)   
   ,def_equi_R(loi.def_equi_R),def_i_equi(loi.def_i_equi),def_equi_atdt(loi.def_equi_atdt)
	  ,defEqui_maxi(loi.defEqui_maxi)
   ,delta_sigma_barre_BH_Rat(loi.delta_sigma_barre_BH_Rat)
   ,delta_sigma_barre_BH_Ra_i(loi.delta_sigma_barre_BH_Ra_i)
   ,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_epsBH(loi.delta_epsBH)
   ,delta_barre_epsBH(loi.delta_barre_epsBH)
   ,delta_barre_alpha_epsBH(loi.delta_barre_alpha_epsBH)
   ,wBase(loi.wBase),wprime(loi.wprime),trajet_neutre(loi.trajet_neutre),wprime_point(loi.wprime_point)
   ,d_wprime(loi.d_wprime),d_wprime_point(loi.d_wprime_point)
   ,residu(9),derResidu(loi.derResidu),derResidu_adefConstant(loi.derResidu_adefConstant),alg_zero(),alg_edp()
   ,rdelta_sigma_barre_BH_Ratdt(),rdelta_sigma_barre_tdt_BH()
   ,centre_initial(true),aucun_pt_inversion(true)
   ,dRdsigMoinsun(loi.dRdsigMoinsun),dRdeps(loi.dRdeps),MPC(loi.MPC)
   ,dsig_ojef_HHHH()
   ,matriceH(loi.matriceH), matriceM(loi.matriceM),matHmoinsun(loi.matHmoinsun)
   ,calcul_dResi_dsig(false)
   ,sig_point(9),sigma_pointBH(),sigma_tauBH(),sigma_tau(9)
   ,delta_sigma_barre_R_a_tauBH(),delta_sigma_barre_t_a_tauBH()
   ,betaphideltasigHB(),deuxmudeltaepsHB()
   ,sig_initiale(9),dersig_initiale(9),sig_finale(9),dersig_finale(9),estime_erreur(9)
   ,val_initiale(9),racine(9)
   ,der_at_racine(9,9,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)

    {// 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_dichotomie);
     // 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));
      // pour la phase   
     if (xnp_phase != NULL)
	     if (xnp_phase->NomCourbe() == "_") 
	        xnp_phase = Courbe1D::New_Courbe1D(*(loi.xnp_phase));
	    if (Qzero_phase != NULL)    
         if (Qzero_phase->NomCourbe() == "_") 
             Qzero_phase = Courbe1D::New_Courbe1D(*(loi.Qzero_phase));
     if (xmu_phase != NULL)
         if (xmu_phase->NomCourbe() == "_") 
            xmu_phase = Courbe1D::New_Courbe1D(*(loi.xmu_phase));
      // pour la dépendance à la déformation équivalente
     if (xnp_defEqui != NULL)
      if (xnp_defEqui->NomCourbe() == "_")
	        xnp_defEqui = Courbe1D::New_Courbe1D(*(loi.xnp_defEqui));
      // pour la dépendance à la déformation équivalente
     if (Qzero_defEqui != NULL)
	     if (Qzero_defEqui->NomCourbe() == "_") 
	        Qzero_defEqui = Courbe1D::New_Courbe1D(*(loi.Qzero_defEqui));
      // pour la dépendance à la déformation totale
     if (coef_paradefEqui != NULL)
	     if (coef_paradefEqui->NomCourbe() == "_") 
	        coef_paradefEqui = Courbe1D::New_Courbe1D(*(loi.coef_paradefEqui));
    };

Hysteresis3D::~Hysteresis3D ()
// 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;
  if (xnp_phase != NULL)
      if (xnp_phase->NomCourbe() == "_") delete xnp_phase;
  if (xnp_defEqui != NULL)
      if (xnp_defEqui->NomCourbe() == "_") delete xnp_defEqui;
  if (Qzero_defEqui != NULL)
      if (Qzero_defEqui->NomCourbe() == "_") delete Qzero_defEqui;
  if (Qzero_phase != NULL)
      if (Qzero_phase->NomCourbe() == "_") delete Qzero_phase;
  if (xmu_phase != NULL)
      if (xmu_phase->NomCourbe() == "_") delete xmu_phase;  
  if (coef_paradefEqui != NULL)
      if (coef_paradefEqui->NomCourbe() == "_") delete coef_paradefEqui;
};

// Lecture des donnees de la classe sur fichier
 void Hysteresis3D::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                      ,LesFonctions_nD& lesFonctionsnD)
{   // ---- lecture  du paramètre de prager -----
    string nom;
    *(entreePrinc->entree) >> nom; // lecture d'un identificateur 
    if(nom != "np=")
         { cout << "\n erreur en lecture du parametre de prager "
                << " on attendait la chaine : np= et on a lue " << nom;
           cout << "\n Hysteresis3D::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 "<< endl;
           entreePrinc->MessageBuffer("**erreur2 Hysteresis3D::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 Hysteresis3D::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= et on a lue " << nom;
           cout << "\n Hysteresis3D::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 Hysteresis3D::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= et on a lue " << nom;
           cout << "\n Hysteresis3D::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;};
    // on garde en mémoire ce que l'on a lue
    xnp_lue=xnp; Qzero_lue=Qzero; xmu_lue=xmu;
    
    // --- lecture éventuelle d'une dépendance à la phase
    if ((strstr(entreePrinc->tablcar,"avec_phaseDeltaSig")!=NULL)
       || (strstr(entreePrinc->tablcar,"avec_phaseEps")!=NULL))
     { string nom1,nom2;
       int drapeau=0;  // une variable intermédiaire
       if (strstr(entreePrinc->tablcar,"avec_phaseDeltaSig")!=NULL) {drapeau=1;}
       else { drapeau=2; };  // on oriente le type de dépendance (contrainte ou def)
       // lecture des  paramètres de phase
       entreePrinc->NouvelleDonnee();  // passage d'une ligne
       // cas de np
       if (strstr(entreePrinc->tablcar,"xnp_phase=")!=NULL)
        {drapeau +=10; // petite ope pour valider que l'on a bien lue qqchose
         *(entreePrinc->entree) >> nom;
         if (nom != "xnp_phase=") 
           { cout << "\n erreur en lecture de la dependance a la phase de xnp, on aurait du lire"
                  << "  le mot cle xnp_phase="
                  << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
             entreePrinc->MessageBuffer("**erreur41 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            }
         // lecture de la loi d'évolution du coefficient xnp en fonction de la phase
         *(entreePrinc->entree) >>  nom;    
         // on regarde si la courbe existe, si oui on récupère la référence 
         if (lesCourbes1D.Existe(nom)) 
           { xnp_phase = lesCourbes1D.Trouve(nom);
            }
         else
          { // sinon il faut la lire maintenant
            string non_courbe("_");   
            xnp_phase = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
            // lecture de la courbe
            xnp_phase->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
           } 
         entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
        };
       // cas de xmu
       if (strstr(entreePrinc->tablcar,"xmu_phase=")!=NULL)
        {drapeau +=10; // petite ope pour valider que l'on a bien lue qqchose
         *(entreePrinc->entree) >> nom;
         if (nom != "xmu_phase=") 
           { cout << "\n erreur en lecture de la dependance a la phase de xmu, on aurait du lire"
                  << "  le mot cle xmu_phase="
                  << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
             entreePrinc->MessageBuffer("**erreur42 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            }
         // lecture de la loi d'évolution du coefficient xmu en fonction de la phase
         *(entreePrinc->entree) >>  nom;    
         // on regarde si la courbe existe, si oui on récupère la référence 
         if (lesCourbes1D.Existe(nom)) 
           { xmu_phase = lesCourbes1D.Trouve(nom);
            }
         else
          { // sinon il faut la lire maintenant
            string non_courbe("_");   
            xmu_phase = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
            // lecture de la courbe
            xmu_phase->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
           } 
         entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
        };
       // cas de Qzero
       if (strstr(entreePrinc->tablcar,"Qzero_phase=")!=NULL)
        {drapeau +=10; // petite ope pour valider que l'on a bien lue qqchose
         *(entreePrinc->entree) >> nom;
         if (nom != "Qzero_phase=") 
           { cout << "\n erreur en lecture de la dependance a la phase de Qzero, on aurait du lire"
                  << "  le mot cle Qzero_phase="
                  << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
             entreePrinc->MessageBuffer("**erreur43 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            }
         // lecture de la loi d'évolution du coefficient Qzero en fonction de la phase
         *(entreePrinc->entree) >>  nom;    
         // on regarde si la courbe existe, si oui on récupère la référence 
         if (lesCourbes1D.Existe(nom)) 
           { Qzero_phase = lesCourbes1D.Trouve(nom);
            }
         else
          { // sinon il faut la lire maintenant
            string non_courbe("_");   
            Qzero_phase = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
            // lecture de la courbe
            Qzero_phase->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
           } 
         entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
        };
       // fin de la manip avec le drapeau
       // si drapeau > 10 cela veut dire qu'il y a eu au moins une validation
       // le reste de la division euclidienne = la valeur initiale
       if ((drapeau % 10) == 1) {avec_phaseDeltaSig = true; avec_phaseEps = false; }
       else if ((drapeau % 10) == 2) {avec_phaseDeltaSig = false; avec_phaseEps = true; }
       else
         // sinon, malgré la dépendance à la phase il n'y a aucun paramètre lue
         // donc on désactive
         {avec_phaseDeltaSig = false; avec_phaseEps = false; };   
     };
     
    // --- lecture éventuelle d'une dépendance à la déformation équivalente
    if (strstr(entreePrinc->tablcar,"avec_defEquivalente")!=NULL)
     { string nom1,nom2;
       // lecture des  de dépendance
       entreePrinc->NouvelleDonnee();  // passage d'une ligne
       // cas de np
       if (strstr(entreePrinc->tablcar,"xnp_defEqui=")!=NULL)
        {avec_defEqui=true;
         *(entreePrinc->entree) >> nom;
         if (nom != "xnp_defEqui=") 
           { cout << "\n erreur en lecture de la dependance a la deformation equivalente de xnp, on aurait du lire"
                  << "  le mot cle xnp_defEqui="
                  << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
             entreePrinc->MessageBuffer("**erreur44 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            }
         // lecture de la loi d'évolution du coefficient xnp en fonction de def Equi
         *(entreePrinc->entree) >>  nom;    
         // on regarde si la courbe existe, si oui on récupère la référence 
         if (lesCourbes1D.Existe(nom)) 
           { xnp_defEqui = lesCourbes1D.Trouve(nom);
            }
         else
          { // sinon il faut la lire maintenant
            string non_courbe("_");   
            xnp_defEqui = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
            // lecture de la courbe
            xnp_defEqui->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
           } 
         entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
        }
		 else { xnp_defEqui=NULL;};
       // cas de Qzero
       if (strstr(entreePrinc->tablcar,"Qzero_defEqui=")!=NULL)
        {avec_defEqui=true;
         *(entreePrinc->entree) >> nom;
         if (nom != "Qzero_defEqui=") 
           { cout << "\n erreur en lecture de la dependance a la deformation equivalente de Qzero, on aurait du lire"
                  << "  le mot cle Qzero_defEqui="
                  << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
             entreePrinc->MessageBuffer("**erreur44 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            }
         // lecture de la loi d'évolution du coefficient Qzero en fonction de def Equi
         *(entreePrinc->entree) >>  nom;    
         // on regarde si la courbe existe, si oui on récupère la référence 
         if (lesCourbes1D.Existe(nom)) 
           { Qzero_defEqui = lesCourbes1D.Trouve(nom);
            }
         else
          { // sinon il faut la lire maintenant
            string non_courbe("_");   
            Qzero_defEqui = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
            // lecture de la courbe
            Qzero_defEqui->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
           } 
         entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
        }
		 else {Qzero_defEqui = NULL;} ;
     };
     
    // --- lecture éventuelle d'une dépendance à la phase de la déformation
    if (strstr(entreePrinc->tablcar,"avec_phase_paradefEqui")!=NULL)
     { string nom1,nom2;
       // pour l'instant ne fonctionne qu'avec la dépendance conjointe à la def équivalente
       if (!avec_defEqui)
           { cout << "\n erreur la dependance a la phase de la deformation n'est licite que "
                  << " conjointement avec la dependance  la deformation equivalente de xnp qui n'est pas ici"
                  << " activee on s'arrete donc !!  ";
             entreePrinc->MessageBuffer("**erreur444 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            };
       // lecture des  de dépendance
       entreePrinc->NouvelleDonnee();  // passage d'une ligne
       // lecture de la fonction
       if (strstr(entreePrinc->tablcar,"coef_paradefEqui=")!=NULL)
        {avec_phase_paradefEqui=true;
         *(entreePrinc->entree) >> nom;
         if (nom != "coef_paradefEqui=") 
           { cout << "\n erreur en lecture de la dependance a la phase de la deformation totale, "
                  << " on aurait du lire  le mot cle coef_paradefEqui="
                  << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
             entreePrinc->MessageBuffer("**erreur445 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            }
         // lecture de la loi d'évolution du paradefEqui en fonction de cos(3phi) de la déformation totale
         *(entreePrinc->entree) >>  nom;    
         // on regarde si la courbe existe, si oui on récupère la référence 
         if (lesCourbes1D.Existe(nom)) 
           { coef_paradefEqui = lesCourbes1D.Trouve(nom);
            }
         else
          { // sinon il faut la lire maintenant
            string non_courbe("_");   
            coef_paradefEqui = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
            // lecture de la courbe
            coef_paradefEqui->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
           } 
         entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
        }
       else
           { cout << "\n erreur en lecture de la dependance a la phase de la deformation totale, "
                  << " on devrait avoir sur la ligne courante le mot cle  coef_paradefEqui="
                  << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
             entreePrinc->MessageBuffer("**erreur446 Hysteresis3D::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
            };
     };

    // --- 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);          
            };
         }
        // type de calcul de la matrice tangente
        else if (nom == "type_calcul_comportement_tangent_")
         {*(entreePrinc->entree) >> type_calcul_comportement_tangent;
          if ((type_calcul_comportement_tangent < 1) || (type_calcul_comportement_tangent> 2))
           { cout << "\n erreur en lecture du type de calcul du comportement tangent,"
                  << " on attendait un nombre compris entre 1 et 2 "
                  << " et on a lu : " << type_calcul_comportement_tangent << " 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_dichotomie;
          alg_zero.Modif_nbMaxiIncre(nb_dichotomie);
         }
        // 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;
         }
        // tolérance sur le calcul de centre
        else if (nom == "tolerance_centre_")
         {*(entreePrinc->entree) >> tolerance_centre;
         }
        // minimun du rayon
        else if (nom == "mini_rayon_")
         {*(entreePrinc->entree) >> mini_rayon;
         }
        // nombre maxi d'inversion sur le pas
        else if (nom == "nb_maxInvCoinSurUnPas_")
         {*(entreePrinc->entree) >> nb_maxInvCoinSurUnPas;
         }
		      else if (nom == "force_phi_zero_si_negatif_")
         {*(entreePrinc->entree) >> force_phi_zero_si_negatif;
         }
		      else if (nom == "depassement_Q0_")
         {*(entreePrinc->entree) >> depassement_Q0;
         }
		      else if (nom == "type_de_transport_memorisation_")
         {*(entreePrinc->entree) >> type_de_transport_memorisation;
         }
        else if (nom == "niveau_bascule_fct_aide_")
         {*(entreePrinc->entree) >> niveau_bascule_fct_aide;
         }
        
        // l'angle mini pour les trajets neutre
        else if (nom == "min_angle_trajet_neutre_")
         {*(entreePrinc->entree) >> min_angle_trajet_neutre;
          if ((min_angle_trajet_neutre < 0.) || (min_angle_trajet_neutre > 1.))
            { cout << "\n erreur en lecture sur le l'angle mini pour les trajets neutre, "
                   << "\n il doit etre compris entre 0 et 1 on a lu : " << min_angle_trajet_neutre
                   << "\n Hysteresis3D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);          
            };
         }
        // possibilité ou non d'accepter transitoirement un cosAlpha négatif
        else if (nom == "possibilite_cosAlphaNegatif_")
         {*(entreePrinc->entree) >> possibilite_cosAlphaNegatif;
         }

        else if (nom == "mini_Qsig_pour_phase_sigma_Oi_tdt_")
         {*(entreePrinc->entree) >> mini_Qsig_pour_phase_sigma_Oi_tdt;
//          if (mini_Qsig_pour_phase_sigma_Oi_tdt < 0.) 
//            { cout << "\n erreur en lecture sur mini_Qsig_pour_phase_sigma_Oi_tdt, "
//                   << "\n il doit etre positif on a lu : " << mini_Qsig_pour_phase_sigma_Oi_tdt
//                   << "\n Hysteresis3D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//              throw (UtilLecture::ErrNouvelleDonnee(-1));
//              Sortie(1);          
//            };
         }
        else if (nom == "mini_QepsilonBH_")
         {*(entreePrinc->entree) >> mini_QepsilonBH;
//          if (mini_QepsilonBH < 0.) 
//            { cout << "\n erreur en lecture sur mini_QepsilonBH, "
//                   << "\n il doit etre positif on a lu : " << mini_QepsilonBH
//                   << "\n Hysteresis3D::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
//              throw (UtilLecture::ErrNouvelleDonnee(-1));
//              Sortie(1);          
//            };
         }
        // prise en compte des variations de w' et w'point dans le calcul de l'évolution tangente
        else if (nom == "avecVarWprimeS_")
         {*(entreePrinc->entree) >> avecVarWprimeS;
         }
        // 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 (ParaGlob::NiveauImpression()>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
     
     // traitement de certains paramètres non initialisés
     if (type_calcul_comportement_tangent == 0)
     	{ // == 0 signifie qu'il n'y a pas eu de lecture, on met donc les valeurs cohérentes par défaut
           if (type_resolution_equa_constitutive == 1) {type_calcul_comportement_tangent = 1;}
           else {type_calcul_comportement_tangent = 2;};
     	};
 
    // 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 Hysteresis3D::Affiche() const 
  { cout << " \n loi_de_comportement d'hysteresis3D " ;  
    if ( xnp_temperature != NULL) { cout << " np thermo dependant " 
                                        << " courbe np=f(T): " << xnp_temperature->NomCourbe() <<" ";}
    else                       { cout << " np= " << xnp_lue ;}; 
    if ( Qzero_temperature != NULL) { cout << " Qzero thermo dependant " 
                                        << " courbe np=f(T): " << Qzero_temperature->NomCourbe() <<" ";}
    else                       { cout << " Qzero= " << Qzero_lue ;}; 
    if ( xmu_temperature != NULL) { cout << " xmu thermo dependant " 
                                        << " courbe xmu=f(T): " << xmu_temperature->NomCourbe() <<" ";}
    else                       { cout << " mu= " << xmu_lue ;}; 
    // -- éventuellement dépendance à la phase
    if (avec_phaseDeltaSig || avec_phaseEps)
    	{if (avec_phaseDeltaSig ) { cout << " \n dependance a la phase de Delta_R^t_sigma ";}
    	 else { cout << " \n dependance a la phase de la deformation ";};
    	 if (xnp_phase != NULL) { cout << " np dependant de la phase " 
                                       << " courbe np=f(3cos(phi)): " << xnp_phase->NomCourbe() <<" ";};
    	 if (Qzero_phase != NULL) { cout << " Qzero dependant de la phase " 
                                       << " courbe Qzero=f(3cos(phi)): " << Qzero_phase->NomCourbe() <<" ";};
         if (xmu_phase != NULL) { cout << " xmu dependant de la phase " 
                                       << " courbe xmu=f(3cos(phi)): " << xmu_phase->NomCourbe() <<" ";};
    	};
    // -- éventuellement dépendance à la defEqui
    if (avec_defEqui)
    	{if (xnp_defEqui != NULL) { cout << " np dependant de la deformation equivalente " 
                                       << " courbe np=f(3cos(phi)): " << xnp_defEqui->NomCourbe() <<" ";};
    	 if (Qzero_defEqui != NULL) { cout << " Qzero dependant de la deformation equivalente " 
                                       << " courbe np=f(3cos(phi)): " << Qzero_defEqui->NomCourbe() <<" ";};
    	};
    // -- éventuellement dépendance à la phase de la déformation totale
    if (avec_phase_paradefEqui)
    	{if (coef_paradefEqui != NULL) { cout << " dependance a la phase de la deformation totale " 
                      << " courbe coef_paradefEqui=f(3cos(phi)): " << coef_paradefEqui->NomCourbe() <<" ";};
    	};
    // --- paramètre de réglage
    cout    << "\n type_resolution_equa_constitutive " << type_resolution_equa_constitutive
            << " type_calcul_comportement_tangent " << type_calcul_comportement_tangent;
    
    if (type_resolution_equa_constitutive == 1)
    	{ cout << " \n type de resolution: linearisation, nbmax iteration= " << nb_boucle_maxi
    	       << " nbmax_dichotonmie= " << nb_dichotomie
            << " 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 //if ((type_resolution_equa_constitutive == 2) || (type_resolution_equa_constitutive == 3))
    	{ cout << " \n type de resolution: Runge_Kutta " << cas_kutta << " erreurAbsolue " << erreurAbsolue
    	       << " erreurRelative= " << erreurRelative ;
    	};
    cout << " tolerance_coincidence= " << tolerance_coincidence << " mini_rayon " << mini_rayon
         << " tolerance_centre= " << tolerance_centre
         << " nb_maxInvCoinSurUnPas= " << nb_maxInvCoinSurUnPas 
         << " min_angle_trajet_neutre= " << min_angle_trajet_neutre 
         << " possibilite_cosAlphaNegatif= " << possibilite_cosAlphaNegatif
         << " mini_Qsig_pour_phase_sigma_Oi_tdt= " << mini_Qsig_pour_phase_sigma_Oi_tdt 
         << " mini_QepsilonBH= " << mini_QepsilonBH
         << " force_phi_zero_si_negatif= " << force_phi_zero_si_negatif << " "
         << " depassement_Q0= " << depassement_Q0
         << " type_de_transport_memorisation= "<< type_de_transport_memorisation
         << " niveau_bascule_fct_aide= "<< niveau_bascule_fct_aide;
    // 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 Hysteresis3D::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 
    if ((rep != "o") && (rep != "O" ) && (rep != "0") )
      { sort << "\n#-------------------------------------------------------------------------"
         << "\n# .......  loi_de_comportement d'hysteresis 3D ........                   |"
         << "\n# para de prager       :         mu         : limite maxi de plasticite   |"
         << "\n#-------------------------------------------------------------------------"
         << "\n   np= " << setprecision(6) << xnp << "       mu= " << setprecision(6) << xmu 
         << "     Qzero= "<<  setprecision(6) << Qzero
         << "\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= mu_thermo_dependant_ courbe4 "
         << "\n#  Qzero= Qzero_thermo_dependant_ 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= mu_thermo_dependant_ courbe4 "
         << "\n#  Qzero= Qzero_thermo_dependant_ courbe3 "
         << "\n#-----------------------------------"
         << "\n# il est egalement possible de definir une dependance a la phase des parametres "
         << "\n# deux possibilites: soit une dependance a la phase du delta deviateur de contrainte "
         << "\n#  entre le centre instantane et sa valeur a tdt"
         << "\n#  soit une dependance a la phase a la phase de la deformation totale. "
         << "\n#  Dans ce cas, a la suite du parametre Qzero on met le mot cle: avec_phaseDeltaSig ou avec_phaseDeltaSig"
         << "\n#  puis sur la ligne qui suit on met les fonctions de controle de la dependance "
         << "\n# suit un exemple de declaration (il est possible d'ommettre une fonction "
         << "\n#  mais il faut respecter l'ordre ). Comme pour toutes les courbes on peut soit mettre directement"
         << "\n#  la courbe, soit mettre un nom de courbe. Ne pas oublier de passer  a la ligne apres chaque courbe "
         << "\n#  np= 1                   mu= 4000                Qzero= 80   avec_phaseDeltaSig "
         << "\n#  xnp_phase= courbe_xnp_phase "
         << "\n#  xmu_phase= courbe_xmu_phase " 
         << "\n#  Qzero_phase= courbe_Qzero_phase  "
         << "\n# "
         << "\n#-----------------------------------"
         << "\n# il est egalement possible de definir une dependance a la deformation equivalente (cf. doc)"
         << "\n#  il s'agit ici d'une grandeur qui mesure une mesure de def equivalente a un trajet radial pur. "
         << "\n#  Il s'agit :"
         << "\n#     1) d'une dependance du parametre de prager sous la forme suivante:"
         << "\n#        xp = f(eps_equi * Q_deltaSigma_R_tdt * para) tel que para = (2*Qzero^2/(w'*mu). "
         << "\n#     2) d'une dependance de la saturation Qzero sous la forme suivante:"
         << "\n#        Qzero = f(eps_equi) * Qzero  "
         << "\n#  Dans ce cas, a la suite du parametre Qzero (ou des parametres de phase et du type de transport ) "
         << "\n#   on met le mot cle: avec_defEqui . "
         << "\n#  puis sur la ligne qui suit on met la fonctions de controle de la dependance pour xnp et/ou pour Qzero. "
         << "\n#  on peut mettre l'une ou l'autre ou les deux "
         << "\n# suit un exemple de declaration. Comme pour toutes les courbes on peut soit mettre directement"
         << "\n#  la courbe, soit mettre un nom de courbe. Ne pas oublier de passer  a la ligne apres chaque courbe "
         << "\n#  np= 1                   mu= 4000                Qzero= 80   avec_defEqui "
         << "\n#  xnp_phase= courbe_xnp_defEqui Qzero_phase= courbe_Qzero_defEqui"
         << "\n# "
         << "\n#-----------------------------------"
         << "\n# il est egalement possible de definir une dependance a la phase de la deformation totale"
         << "\n#  (cf. doc) pour para = (2*Qzero^2/(w'*mu) . Il s'agit d'une fonction multiplicatrice de para"
         << "\n#  Cette dependance s'utilise donc conjointement avec la dependance a la deformation equivalente "
         << "\n#  Dans le  cas d'une dependance, a la suite de la dependance a la deformation equivalente "
         << "\n#   on met le mot cle: avec_phase_paradefEqui . "
         << "\n#  puis sur la ligne qui suit on met la fonctions de controle de la dependance. "
         << "\n# suit un exemple de declaration. Comme pour toutes les courbes on peut soit mettre directement"
         << "\n#  la courbe, soit mettre un nom de courbe. Ne pas oublier de passer  a la ligne apres chaque courbe "
         << "\n#  np= 1                   mu= 4000                Qzero= 80   avec_defEqui "
         << "\n#  xnp_phase= courbe_xnp_defEqui "
         << "\n#   avec_phase_paradefEqui "
         << "\n#     coef_paradefEqui= courbe_coef_paradefEqui "
         << "\n# "
         << "\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 (si l'on est sans phase) "
         << "\n# ou sur la ligne qui suit le dernier parametre de phase on indique le mot cle: avec_parametres_de_reglage_ "
         << "\n# ensuite on defini (dans un ordre quelconque) les parametres que l'on souhaites "
         << "\n# chaque parametre est precede d'un mot cle, on a donc une succession de mot cle suivi d'une grandeur "
         << "\n# on peut avoir un ou plusieur couple parametre-grandeur sur chaque ligne "
         << "\n# par contre la derniere ligne doit comporter uniquement le mot cle: "
         << "\n#  fin_parametres_reglage_Hysteresis_ "
         << "\n# les differents parametres sont: "
         << "\n# - le type de resolution: par linearisation(1) (valeur par defaut) ou integration directe via Runge_Kutta(2)"
         << "\n# s'il n'y a pas convergence avec (1) arret et generation d'une exception, avec 2, on bascule sur (1) et "
         << "\n# s'il n'y a pas de nouveau convergence on bascule sur un appel directe de kutta"
         << "\n# type (3) = idem que type (2) mais s'il n'y a pas convergence arret et genration d'une exception"
         << "\n# type (4) = idem que type (2) mais s'il n'y a pas convergence bascule sur la linearisation, et s'il n'y"
         << "\n# a pas convergence arret et generation d'une exception"
         << "\n# ex: type_de_resolution_  2 "
         << "\n# - le nombre d'iteration (pour (1)) ex: nb_iteration_maxi_  20 "
         << "\n# - le nombre de dichotomie(pour (1)) ex: nb_dichotomie_maxi_  20 "
         << "\n# - la tolerance absolue sur le residu(pour (1)) ex: tolerance_residu_ 1.e-3 "
         << "\n# - la tolerance relative sur le residu(pour (1)) ex: tolerance_residu_rel_ 1.e-3 "
         << "\n#   signifie que la precision sera tolerance_residu_ + ||sig_tdt|| *  tolerance_residu_rel_"
         << "\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#  si la valeur est negative il s'agit d'une presicion relative: exe -1.e-3  "
//         << "\n# signifie que la precision sera max (0.001*||sig_tdt||,0.001) "
         << "\n# - le type de Runge_kutta (pour (2)): 3 pour une methode imbriquee 2-3, 4 pour 3-4, 5 pour 4-5, "
         << "\n# ex: cas_kutta_  5 "
         << "\n# - l'erreur absolue sur la contrainte finale(pour (2)) ex: erreurAbsolue_  1.e-3"
         << "\n# - l'erreur relative sur la contrainte finale(pour (2)) ex: erreurRelative_ 1.e-5"
         << "\n# - le nombre maxi d'appel de la fonction derivee (sigma_point) (pour (2)) ex: nbMaxiAppel_  100"
         << "\n# "
         << "\n# - la tolerance sur la detection des coincidences ex: tolerance_coincidence_  1.e-3"
         << "\n# si le nombre indique est negatif, cela signifie que la tolerance sera relative a la valeur "
         << "\n# de la norme de la contrainte de reference: exe -0.1 signifie que la tolerance sera "
         << "\n# max (0.1*||sig_R||,0.1) "
         << "\n# "
         << "\n# - la tolerance sur le calcul des hyper-centres de trajet neutre ex: tolerance_centre_  1.e-3"
         << "\n# si le nombre indique est negatif, cela signifie que la tolerance sera relative a la valeur "
         << "\n# de la norme de la contrainte de reference: exe -0.1 signifie que la tolerance sera "
         << "\n# max (0.1*||sig_R||,0.1) "
         << "\n# "
         << "\n# -le mini en dessous duquel on considere delta_O_R et delta_R_Stdt nul ex: mini_rayon_ 1. e-8"
         << "\n# Meme comportement que pour mini_Qsig_pour_phase_sigma_Oi_tdt_, dans le cas ou mini_rayon est negatif"
         << "\n# ce parametre devient un parametre de regularisation "
         << "\n# "
         << "\n# -le maxi d'inversion ou de coincidence que l'on tolere sur un pas "
         << "\n# dans le cas ou ce  maxi est un nombre negatif, on utilise sa valeur absolue et lorsque le maxi "
         << "\n# depasse ce nombre, on retient la valeur final de la contrainte, sinon cas normal: on genere une erreur "
         << "\n# ex nb_maxInvCoinSurUnPas_  -20"
         << "\n# "
         << "\n# - min_angle_trajet_neutre : indique le minimun du cos de  l'angle en dessous duquel le trajet est neutre "
         << "\n# ex min_angle_trajet_neutre_ 0.008"
         << "\n# "
			      << "\n# - possibilite_cosAlphaNegatif : indique si oui (diff de 0) on non (0) on accepte transitoirement une valeur "
			      << "\n# de cosAlpha negative:  ex:  possibilite_cosAlphaNegatif_ 0 , si c'est non, c'est traite comme un cas neutre " 
         << "\n# "
         << "\n#------------- mini_Qsig_pour_phase_sigma_Oi_tdt_ ------------------"
         << "\n# - mini_Qsig_pour_phase_sigma_Oi_tdt : indique le minimum de Qsig en dessous duquel on  "
         << "\n# considere que la phase pour delta sigma de Oi a tdt, est nulle "
         << "\n# ex mini_Qsig_pour_phase_sigma_Oi_tdt_ 1.5 "
         << "\n# Dans le cas ou mini_Qsig_pour_phase_sigma_Oi_tdt_ est negatif, cela devient un parametre de regularisation "
         << "\n# Qsig est alors transforme en (Qsig-mini_Qsig_pour_phase_sigma_Oi_tdt) au niveau des divisions qui servent "
         << "\n# a calculer la phase. Dans ce cas l'angle de phase est toujours calculable, par contre pour les faibles "
         << "\n# valeur de Qsig, on peut avoir angle errone, mais ce n'est peut-etre pas un pb "
         << "\n# "
         << "\n#------------- mini_QepsilonBH_ ------------------"
         << "\n# - mini_QepsilonBH : indique le minimum de QepsilonBH en dessous duquel on  "
         << "\n# considere que la phase pour la deformation totale, est nulle "
         << "\n# ex mini_QepsilonBH_ 1.e-4 "
         << "\n# Meme comportement que pour mini_Qsig_pour_phase_sigma_Oi_tdt_, dans le cas ou mini_QepsilonBH est negatif"
         << "\n# ce parametre devient un parametre de regularisation "
         << "\n# "
         << "\n#------------- force_phi_zero_si_negatif_ ------------------"
         << "\n# - au niveau de l'equation constitutive, phi doit-etre toujours positif, cependant pendant le processus "
         << "\n# de convergence il peut etre transitoirement negatif: on peut neanmoins forcer phi a etre toujours >= 0 "
         << "\n# avec le parametre : force_phi_zero_si_negatif_ "
         << "\n# Par defaut => force_phi_zero_si_negatif_ = 0. : on ne force pas la mise a 0"
         << "\n# si : force_phi_zero_si_negatif_ x , avec x diff de 0 : on force la mise a 0 "
         << "\n#      si phi devient negatif et |phi| < x "
         << "\n#------------- type de transport ------------------"
         << "\n# - il est egalement possible de preciser un type de transport des grandeurs memorises "
         << "\n#  (cf. doc)  "
         << "\n#  Dans ce cas, on met le mot cle: type_de_transport_memorisation_ suivi d'un entier signe 'i' "
         << "\n#   i = 0  : transport historique en mixte  (valeur par defaut pour l'instant) "
         << "\n#   i = -1 : transport incremental ( a la fin de chaque increment) de maniere coherente avec "
         << "\n#            la derivee de Jauman "
         << "\n#--------------- utilisation de la fonction d'aide -----------------"
         << "\n# "
         << "\n# - l'algorithme de gestion de la memorisation discrete s'effectue soit via le rayon des  "
         << "\n# hypersphere representant les tenseurs OiSigma_tdt ceci pour de faibles rayons,  "
         << "\n# soit via une fonction d'aide pour des rayons importants. Le passage entre ces deux modes "
         << "\n# de gestion s'effectue en fonction du parametre niveau_bascule_fct_aide_ qui est compris entre 0 et 1"
         << "\n# ex: niveau_bascule_fct_aide_ 0.5 # signifie que l'on bascule pour un rayon superieur a 50% "
         << "\n#                                  # du rayon maxi "
         << "\n# "
         << "\n# "
         << "\n#-------------- limitation de l'intensite du deviateur ------------------"
         << "\n# "
         << "\n# - normalement l'intensite du deviateur des contraintes Qsig doit etre inferieure a la saturation Q_0 "
         << "\n# le parametre depassement_Q0 donne la valeur toleree de depassement, au-dessus de laquelle "
         << "\n# la contrainte n'est plus recevable "
         << "\n# ex: depassement_Q0_ 1.2 # signifie que l'on tolere 20% de deplacement"
         << "\n# "
         << "\n# "
         << "\n# -------------- calcul du comportement tangent ---------"
         << "\n# - Pour le type de resolution par linearisation, le comportement tangent est calcule par une methode coherente"
         << "\n# differente du cas de type de resolution par Kutta. Il est possible d'indiquer explicitement "
         << "\n# le type de calcul du comportement tangent: deux cas possibles, soit en utilisant l'equation linearise "
         << "\n# (cas = 1), soit en utilisant l'equation exacte sans linearisation (cas 2) "
         << "\n# Pour cela, par exemple apres la definition du cas de resolution , on indique le mot cle"
         << "\n# type_calcul_comportement_tangent_ suivi du cas : 1 ou 2 "
         << "\n# ex type_calcul_comportement_tangent_  2"
         << "\n# Il est possible de tenir compte ou pas de la variation de l'angle de phase et de sa derivee danse le "
         << "\n# calcul du comportement tangent. Par defaut, il n'y a pas de prise en compte de ces variations. Pour "
         << "\n# en tenir compte il faut mettre le mot cle avecVarWprimeS_ suivi de 1 (0 etant la valeur par defaut) "
         << "\n# ex avecVarWprimeS_  1"
         << "\n# "
         << "\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# \n Exemple de declaration: sans la phase "
         << "\n#-------------------------------------------------------------------------"
         << "\n# .......  loi_de_comportement d'hysteresis 3D ........                   |"
         << "\n# para de prager       :         mu         : limite maxi de plasticite   |"
         << "\n#-------------------------------------------------------------------------"
         << "\n#   np= " << setprecision(6) << xnp << "       mu= " << setprecision(6) << xmu 
         << "\n#   Qzero= "<<  setprecision(6) << Qzero << "   avec_parametres_de_reglage_ "
         << "\n#     nb_iteration_maxi_  20  nb_dichotomie_maxi_  20  tolerance_residu_ 1.e-3  tolerance_residu_rel_ 1.e-5  "
         << "\n#     tolerance_coincidence_  1.e-3  mini_rayon_ 1. e-8 tolerance_centre_ 1. e-3 "
         << "\n#     fin_parametres_reglage_Hysteresis_ "
         << "\n# "
         << "\n# \n Exemple de declaration pour une resolution avec une methode de Runge_Kutta: "
         << "\n#-------------------------------------------------------------------------"
         << "\n# .......  loi_de_comportement d'hysteresis 3D ........                   |"
         << "\n# para de prager       :         mu         : limite maxi de plasticite   |"
         << "\n#-------------------------------------------------------------------------"
         << "\n#   np= " << setprecision(6) << xnp << "       mu= " << setprecision(6) << xmu 
         << "\n#     Qzero= "<<  setprecision(6) << Qzero << "   avec_parametres_de_reglage_ "
         << "\n#       type_de_resolution_  2 " 
         << "\n#       cas_kutta_  5  erreurAbsolue_  1.e-3  erreurRelative_ 1.e-5  nbMaxiAppel_  100"
         << "\n#      tolerance_coincidence_  1.e-3   nb_maxInvCoinSurUnPas_  20 min_angle_trajet_neutre_ 0.008"
         << "\n#      possibilite_cosAlphaNegatif_ 0  mini_Qsig_pour_phase_sigma_Oi_tdt_ 1.5 "
         << "\n#       fin_parametres_reglage_Hysteresis_ ";
       }
    else
      {sort
         << "\n# \n Exemple de declaration pour une resolution avec une methode de Runge_Kutta: "
         << "\n#-------------------------------------------------------------------------"
         << "\n# .......  loi_de_comportement d'hysteresis 3D ........                   |"
         << "\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_ "
         << "\n      type_de_resolution_  2 " 
         << "\n      cas_kutta_  5  erreurAbsolue_  1.e-3  erreurRelative_ 1.e-5  nbMaxiAppel_  3000"
         << "\n     tolerance_coincidence_  1.e-3   nb_maxInvCoinSurUnPas_  20 min_angle_trajet_neutre_ 0.008"
         << "\n     possibilite_cosAlphaNegatif_ 0  mini_Qsig_pour_phase_sigma_Oi_tdt_ 1.5 "
         << "\n      fin_parametres_reglage_Hysteresis_ ";
       };
    sort << endl;
    // appel de la classe mère
    Loi_comp_abstraite::Info_commande_don_LoisDeComp(entreePrinc);     
  };  		  	  

 // test si la loi est complete
int Hysteresis3D::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 == NULL) && (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 == NULL) && (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 Hysteresis3D::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 Hysteresis3D::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
            { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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 HYPER_CENTRE_HYSTERESIS:
           // b) ----- cas du centre du cercle actuelle de référence
            { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) saveDon);
              Tab_Grandeur_TenseurBH& tyTQ= *((Tab_Grandeur_TenseurBH*) (*itq).Grandeur_pointee()); // pour simplifier
              if (save_resul.oc_BH_R.size() != 0)
                {tyTQ(1+(*idecal))= *(save_resul.oc_BH_R.begin());}
              else
                {tyTQ(1+(*idecal)).Inita(0.);}
              (*idecal)++; break;
            }
          case SIGMA_REF:
           // c) ----- cas de la contrainte de référence actuelle
            { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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;
            }
           // d) ----- Q_sigma actuel de Oi à T
          case Q_SIG_HYST_Oi_A_R:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             Tenseur3BH delta__sigma_barre_BH_OiaR; // a priori le centre et la référence = 0: cas du début
             if (save_resul.sigma_barre_BH_R.size() != 0) delta__sigma_barre_BH_OiaR=(*(save_resul.sigma_barre_BH_R.begin())); 
             if (save_resul.oc_BH_R.size() != 0) delta__sigma_barre_BH_OiaR -= *(save_resul.oc_BH_R.begin());
             tyTQ(1+(*idecal)) = sqrt(delta__sigma_barre_BH_OiaR.II());
             (*idecal)++; break;
           }
           // e) ----- Q_sigma actuel de R à T
          case Q_SIG_HYST_R_A_T:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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;
           }
           // f) ----- COS_ALPHA_HYSTERESIS actuel
          case COS_ALPHA_HYSTERESIS:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             // le plus simple est de recalculer 
             double w__prime,w__prime_point; // grandeurs de retour
             bool trajet_neutre=false;
             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());
             double Q__deltaSiRatdt = sqrt(delta__sigma_barre_BH_Ratdt.II());
             Tenseur3BH delta__sigma_barre_BH_OiaR; // a priori le centre et la référence = 0: cas du début
             if (save_resul.sigma_barre_BH_R.size() != 0) delta__sigma_barre_BH_OiaR=(*(save_resul.sigma_barre_BH_R.begin())); 
             if (save_resul.oc_BH_R.size() != 0) delta__sigma_barre_BH_OiaR -= *(save_resul.oc_BH_R.begin());
             double Q__OiaR = sqrt(delta__sigma_barre_BH_OiaR.II());
             Cal_wprime(Q__deltaSiRatdt,delta__sigma_barre_BH_Ratdt,Q__OiaR,delta__sigma_barre_BH_OiaR 
                              ,save_resul.wBase_tdt,ZeroBH3,w__prime,w__prime_point,trajet_neutre);
             tyTQ(1+(*idecal))=w__prime/save_resul.wBase_tdt;
             (*idecal)++; break;
           }
           // g) ----- cos_3phi actuel pour la contrainte totale d'hystérésis
          case COS3PHI_SIG_HYSTERESIS:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) saveDon);
             Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             double Qsig =  sqrt(Dabs(save_resul.sigma_barre_BH_tdt.II()));
             double Qsig3 = Qsig * Qsig * Qsig;
     //	     if (Qsig > mini_Qsig_pour_phase_sigma_Oi_tdt )
              { // on peut calculer un cos3phi pas débile
                double bIIIb = save_resul.sigma_barre_BH_tdt.III() / 3.;
                if (mini_Qsig_pour_phase_sigma_Oi_tdt > 0.)
                   tyTQ(1+(*idecal)) = 3. * sqrt(6.)  * bIIIb/ Qsig3;
                else
                   tyTQ(1+(*idecal)) = 3. * sqrt(6.)  * bIIIb/ (Qsig3-mini_Qsig_pour_phase_sigma_Oi_tdt);
              };
     //			    else tyTQ=0.; // sinon on le met à 0 
             (*idecal)++; break;
           }
           // h) ----- cos_3phi actuel pour l'incrément de contrainte totale d'hystérésis
          case COS3PHI_DELTA_SIG_HYSTERESIS:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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);
             double Qsig =  sqrt(delta__sigma_barre_BH_tatdt.II());
             double Qsig3 = Qsig * Qsig * Qsig;
     //	     if (Qsig > mini_Qsig_pour_phase_sigma_Oi_tdt )
              { // on peut calculer un cos3phi pas débile
                double bIIIb = delta__sigma_barre_BH_tatdt.III() / 3.;
                if (mini_Qsig_pour_phase_sigma_Oi_tdt > 0.)
                   tyTQ(1+(*idecal)) = 3. * sqrt(6.)  * bIIIb/ Qsig3;
                else
                   tyTQ(1+(*idecal)) = 3. * sqrt(6.)  * bIIIb/ (Qsig3-mini_Qsig_pour_phase_sigma_Oi_tdt);
              }
     //			    else tyTQ=0.; // sinon on le met à 0 
             (*idecal)++; break;
           }
           // i) ----- Q_delta_sig  d'hystérésis
          case Q_DELTA_SIG_HYST:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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:
           { SaveResulHysteresis3D & save_resul = *((SaveResulHysteresis3D*) 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 Hysteresis3D::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);
     };
  };
  // b) $$$ cas du centre du cercle actuelle de référence
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == HYPER_CENTRE_HYSTERESIS)
      {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(HYPER_CENTRE_HYSTERESIS,SIG11,sigrefBH);
      liTQ.push_back(typQ);
      delete tens; // car on n'en a plus besoin
     };
  };
  // 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
    };
  };
  // d) $$$ Q_sigma actuel de Oi à R
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == Q_SIG_HYST_Oi_A_R)
      {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_Oi_A_R,SIG11,grand_courant);
        liTQ.push_back(typQ1);
     };
  };
  // 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);
     };
  };
  // f) $$$ cos_alpha actuel
  {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == COS_ALPHA_HYSTERESIS)
      {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(COS_ALPHA_HYSTERESIS,SIG11,grand_courant);
        liTQ.push_back(typQ1);
     };
  };
  // g) ----- cos_3phi actuel pour la contrainte totale 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() == COS3PHI_SIG_HYSTERESIS)
      {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(COS3PHI_SIG_HYSTERESIS,SIG11,grand_courant);
        liTQ.push_back(typQ1);
     };
  };
  // h) ----- cos_3phi actuel pour l'incrément de contrainte totale 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() == COS3PHI_DELTA_SIG_HYSTERESIS)
      {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(COS3PHI_DELTA_SIG_HYSTERESIS,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:================
	 
	   //----- 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 Hysteresis3D::Lecture_base_info_loi(istream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
{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); };
    // --- dépendance à la phase éventuelle 
    ent >> nom; 
    if (nom == "avec_phaseDeltaSig") {avec_phaseDeltaSig = true; avec_phaseEps = false; }
    else if (nom == "avec_phaseEps") {avec_phaseDeltaSig = false; avec_phaseEps = true; }
    else  {avec_phaseDeltaSig = false; avec_phaseEps = false; };
    if (avec_phaseDeltaSig || avec_phaseEps)
     {// param_prager_(np)
      ent >> nom >> test;
      if (!test)
        { if (xnp_phase != NULL) {if (xnp_phase->NomCourbe() == "_") delete xnp_phase; 
                                  xnp_phase = NULL;
                                 };
        }
      else
        { ent >> nom; xnp_phase = lesCourbes1D.Lecture_pour_base_info(ent,cas,xnp_phase); };
         // xmu
      ent >> nom >> test;
      if (!test)
        { if (xmu_phase != NULL) {if (xmu_phase->NomCourbe() == "_") delete xmu_phase; 
                                  xmu_phase = NULL;
                                 };
        }
      else
        { ent >> nom; xmu_phase = lesCourbes1D.Lecture_pour_base_info(ent,cas,xmu_phase); };
         // Qzero
      ent >> nom >> test;
      if (!test)
        { if (Qzero_phase != NULL) {if (Qzero_phase->NomCourbe() == "_") delete Qzero_phase; 
                                    Qzero_phase = NULL;
                                   };
        }
      else
        { ent >> nom; Qzero_phase = lesCourbes1D.Lecture_pour_base_info(ent,cas,Qzero_phase); };
     };

    // --- dépendance à la def Equi éventuelle 
    ent >> nom; 
    if (nom == "avec_defEqui")
    	{ // param_prager_(np)
	     ent  >> test >> nom;
	     if ((!test) && (nom == "pas_de_fct_xnp_defEqui_"))
	       { // pas de dépendance de xn à la defEqui
			       if (xnp_defEqui != NULL) {if (xnp_defEqui->NomCourbe() == "_") delete xnp_defEqui; 
												                        xnp_defEqui = NULL;
                                   };
			     }
		    else if (test)
	       { ent >> nom; 
			       if (nom == "fonction_xnp_defEqui")			 
			        {xnp_defEqui = lesCourbes1D.Lecture_pour_base_info(ent,cas,xnp_defEqui);};
			     }
		    else 
		      { cout << "\n erreur en lecture de xnp_defEqui, on attendait de lire la chaine: pas_de_fct_xnp_defEqui_ et on a lue " 
			            << nom  << endl;
		        Sortie(1);			 
			     };

    	  // dépendance de Qzero 
	     ent  >> test >> nom;
	     if ((!test) && (nom == "pas_de_fct_Qzero_defEqui_"))
	       { // pas de dépendance de Qzero à la defEqui
			       if (Qzero_defEqui != NULL) {if (Qzero_defEqui->NomCourbe() == "_") delete Qzero_defEqui; 
	                                     Qzero_defEqui = NULL;
                                     };
			     }
		    else if (test)
	       { ent >> nom; 
			       if (nom == "fonction_Qzero_defEqui")			 
			         {Qzero_defEqui = lesCourbes1D.Lecture_pour_base_info(ent,cas,Qzero_defEqui);};
			     }
		    else 
		      { cout << "\n erreur en lecture de Qzero_defEqui, on attendait de lire la chaine: pas_de_fct_Qzero_defEqui_ et on a lue " 
			            << nom  << endl;
		        Sortie(1);			 
			     };
					
    	};

    // --- dépendance à la phase de la déformation totale
    ent >> nom;
    if (nom == "avec_phase_paradefEqui")
    	{ent >> nom >> test;
	     // coef_paradefEqui
	     if (!test)
	       { if (coef_paradefEqui != NULL) {if (coef_paradefEqui->NomCourbe() == "_") delete coef_paradefEqui; 
	                                        coef_paradefEqui = NULL;
                                        };
        }
	     else
	       { ent >> nom; coef_paradefEqui = lesCourbes1D.Lecture_pour_base_info(ent,cas,coef_paradefEqui); };
    	};

	   // 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 >> nb_dichotomie 
        >>  nom >> mini_rayon
        >>  nom >> tolerance_coincidence
        >>  nom >> tolerance_centre;
    ent >>  nom >> type_resolution_equa_constitutive
        >>  nom >> type_calcul_comportement_tangent
        >>  nom >> avecVarWprimeS
        >>  nom >>  cas_kutta >> nom >>  erreurAbsolue >> nom >>  erreurRelative; 
    ent >>  nom >> nb_maxInvCoinSurUnPas >> nom >> min_angle_trajet_neutre >> nom >> possibilite_cosAlphaNegatif
        >>  nom >> mini_Qsig_pour_phase_sigma_Oi_tdt                   
        >>  nom >> mini_QepsilonBH
			     >>  nom >> force_phi_zero_si_negatif                   
        >>  nom >> depassement_Q0
        >>  nom >> type_de_transport_memorisation
        >>  nom >> niveau_bascule_fct_aide;
    // 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 Hysteresis3D::Ecriture_base_info_loi(ostream& sort,const int cas)
  { if (cas == 1) 
     { sort << "  HYSTERESIS_3D ";
       sort << "  param_prager_(np) "; 
       if (xnp_temperature == NULL)
        { sort << false << " " << xnp_lue << " ";}
       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_lue << " ";}
       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_lue << " ";}
       else 
        { sort << true << " fonction_xmu_temperature ";
          LesCourbes1D::Ecriture_pour_base_info(sort,cas,xmu_temperature);
        };
       // --- dépendance à la phase éventuelle  
       if (avec_phaseDeltaSig || avec_phaseEps)
        {if (avec_phaseDeltaSig == 1) {sort << " avec_phaseDeltaSig ";}
         else {sort << " avec_phaseEps ";}; 
         if (xnp_phase == NULL)
          { sort << false << " " ;}
         else 
          { sort << true << " fonction_xnp_phase ";
            LesCourbes1D::Ecriture_pour_base_info(sort,cas,xnp_phase);
          };
         if (xmu_phase == NULL)
          { sort << false << " " ;}
         else 
          { sort << true << " fonction_xmu_phase ";
            LesCourbes1D::Ecriture_pour_base_info(sort,cas,xmu_phase);
          };
         if (Qzero_phase == NULL)
          { sort << false << " " ;}
         else 
          { sort << true << " fonction_Qzero_phase ";
            LesCourbes1D::Ecriture_pour_base_info(sort,cas,Qzero_phase);
          };
        }
       else
		      {sort << " sans_phase ";};
       
       // --- dépendance à la def Equi éventuelle  
       if (avec_defEqui)
    	   {sort << " avec_defEqui ";
         if (xnp_defEqui == NULL)
          { sort << false << " pas_de_fct_xnp_defEqui_ " ;}
         else 
          { sort << true << " fonction_xnp_defEqui ";
            LesCourbes1D::Ecriture_pour_base_info(sort,cas,xnp_defEqui);
          };
         if (Qzero_defEqui == NULL)
          { sort << false << " pas_de_fct_Qzero_defEqui_ " ;}
         else 
          { sort << true << " fonction_Qzero_defEqui ";
            LesCourbes1D::Ecriture_pour_base_info(sort,cas,Qzero_defEqui);
          };
		      }
       else 
       	{sort << " sans_defEqui ";};       
       
       // --- dépendance à la phase de la déformation totale pour paradefEqui 
       if (avec_phase_paradefEqui)
    	  {sort << " avec_phase_paradefEqui ";
         if (coef_paradefEqui == NULL)
          { sort << false << " " ;}
         else 
          { sort << true << " fonction_coef_paradefEqui ";
            LesCourbes1D::Ecriture_pour_base_info(sort,cas,coef_paradefEqui);
          };
    	  }
       else 
       	{sort << " sans_phaseEps ";};
       
       // --- paramètre de réglage
       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
            << " nb_dichotomie " << nb_dichotomie
            << " tolerance_coincidence " << tolerance_coincidence
            << " tolerance_centre " << tolerance_centre
            << " mini_rayon " << mini_rayon; 
       sort << "\n type_resolution_equa_constitutive " << type_resolution_equa_constitutive
            << " type_calcul_comportement_tangent " << type_calcul_comportement_tangent
            << " avecVarWprimeS " << avecVarWprimeS
            << " cas_kutta " << cas_kutta 
            << " erreurAbsolue " << erreurAbsolue << " erreurRelative " << erreurRelative << " "; 
       sort << " nb_maxInvCoinSurUnPas " << nb_maxInvCoinSurUnPas 
            << " min_angle_trajet_neutre " << min_angle_trajet_neutre
				        << " possibilite_cosAlphaNegatif " << possibilite_cosAlphaNegatif 
            << " mini_Qsig_pour_phase_sigma_Oi_tdt " << mini_Qsig_pour_phase_sigma_Oi_tdt 
            << " mini_QepsilonBH " << mini_QepsilonBH 
				        << " force_phi_zero_si_negatif " << force_phi_zero_si_negatif
            << " depassement_Q0 " << depassement_Q0
            << " type_de_transport_memorisation "<< type_de_transport_memorisation
            << " niveau_bascule_fct_aide "<< niveau_bascule_fct_aide;
       // 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);  
  }; 

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

// --------------- méthodes internes ---------------:
// 1)  affinage d'un point de coincidence à l'aide des rayons
// ramène true si le traitement est exactement terminé, sinon false, ce qui signifie qu'il
// faut encore continuer à utiliser l'équation d'évolution
// pt_sur_principal : indique si oui ou non le pointeur iatens pointe sur sa liste principale
// oi_sur_principal : indique si oui ou non le pointeur iaOi pointe sur sa liste principale
// iatens_princ et iaOi_princ: pointeurs sur les listes principales
// force_coincidence : on force la coincidence à la position actuelle
// le rayon peut-être modifié dans le cas particulier d'une coincidence à la précision près
bool Hysteresis3D::Coincidence(bool bascule_fct_aide,double& unSur_wBaseCarre
                              ,const Tenseur3HH & gijHH,const Tenseur3BB & gijBB
                              ,SaveResulHysteresis3D & save_resul,double& W_a
                              ,List_io <Tenseur3BH>::iterator& iatens
	                             ,List_io <double>::iterator& iadef_equi
                              ,List_io <double>::iterator& iafct
                              ,bool& pt_sur_principal
                              ,List_io <Tenseur3BH>::iterator& iaOi,bool& oi_sur_principal
                              ,List_io <Tenseur3BH>::iterator& iatens_princ
	                             ,List_io <double>::iterator& iadef_equi_princ
                              ,List_io <Tenseur3BH>::iterator& iaOi_princ
                              ,List_io <double>::iterator& iafct_princ
                              ,const double& rayon_tdt,bool force_coincidence)
 { // tout d'abord on vérifie que l'on n'est pas exactement à un point de
   // coincidence à la précision près
  
   // -- modif 10 juillet 2014:
   // on calcul la grandeur cc qui est un des coef de l'équation du second degré permettant
   // de trouver la coïncidence (voir après)
   Tenseur3BH delta_sigma_oi_a_t_BH = sigma_i_barre_BH - oc_BH_R; // OB
   double cc = (delta_sigma_oi_a_t_BH && delta_sigma_oi_a_t_BH) - Q_OiaR * Q_OiaR; // cc=OB*OB - r^2
   // si cc est positif, cela signifie qu'au pas précédent on n'a pas bien détecté une coincidence
   // ou que c'est un pb de zero
   // on considère alors que le point actuel est un point de coïncidence à la précision près et donc
   // on finit le traitement
  
   double tol_coincidence_reelle = tolerance_coincidence;
   if (tolerance_coincidence < 0) // si l'indication est négative , cela veut dire que l'on veut une grandeur relative
     tol_coincidence_reelle = MaX(-tolerance_coincidence * Q_OiaR,-tolerance_coincidence);
   // -- fin modif
  
   if ((Abs(rayon_tdt - Q_OiaR) <= tol_coincidence_reelle) || force_coincidence
//       || ((cc >= 0.) && (sqrt(Dabs(cc)) <=  tol_coincidence_reelle)) ) // -- ajout 10 juillet 2014:
       || (cc >= 0.) ) // -- ajout 11 juillet 2014: on ne peut plus revenir sur les grandeurs à t
                // donc le mieux est de valider la coïncidence ce qui simplifiera la suite du traitement
     { // on est dans le cas où l'on a une coïncidence exacte à la précision "tolerance_coincidence" près
       // mais dans tous les cas on a rayon_tdt > Q_OiaR sinon on n'aurait pas de coïncidence
       // on signale qu'il y a une coincidence exacte (pour le retour de la méthode Coincidence)   
       // gestion des pointeurs
       do
        {Gestion_pointeur_coincidence(unSur_wBaseCarre,save_resul,W_a
	                    ,iatens,iadef_equi,iafct,pt_sur_principal,iaOi,oi_sur_principal
	                    ,iatens_princ,iadef_equi_princ,iaOi_princ,iafct_princ);
        }// on traite le cas où des autres coincidences existent à la précision près               
       while (Autre_coincidence_a_la_tolerance_pres(bascule_fct_aide,gijHH,gijBB
                                            ,pt_sur_principal,oi_sur_principal,iatens,iaOi));
       return true;
     };   
   // --- sinon on continue mais le traitement ne sera pas fini !! 
 
   // dans une première étape on tente de calculer plus précisemment le point d'inversion,
   //  en supposant une approximation linéaire  de l'évolution de sigma sur le pas de temps: 
   bool bon_calcul = false; // permet de savoir si le calcul précis est correcte, 
                            // pour l'instant on dit que non  au niveau de l'init
   // a-- calcul des coefficients de l'équation du second degré qui gère le point exact
   double aa = delta_sigma_barre_tdt_BH && delta_sigma_barre_tdt_BH; // BA*BA
   // aa doit être sup à 0, si ce n'est pas le cas du à des arrondis ou des pb de transport on le met à 0
   if (aa < ConstMath::pasmalpetit)
    { aa = 0.;
      if (Permet_affichage() > 0)
          cout << "\n warning algo coincidence, dans la recherche des racines de l'equa 2 degre "
               << " on a sig_tdt : sig_tdt qui est negatif !! =  " << aa <<" on le met a 0 mais ce n'est pas normal "
               << "\n  Hysteresis3D::Coincidence(... ";
    };
  
   // delta_sigma_oi_a_tdt_BH c'est  OA
   double bb = 2. * (delta_sigma_oi_a_t_BH && delta_sigma_barre_tdt_BH); // OB*BA
//   bb *=  2. * bb; // 2 (OB*BA)^2
//   double cc = (delta_sigma_oi_a_t_BH && delta_sigma_oi_a_t_BH) - Q_OiaR * Q_OiaR; // OB*OB - r^2
//   #ifdef MISE_AU_POINT
//**** le test qui suit ne sert plus compte tenu du choix fait plus haut sur cc
//   if(!aucun_pt_inversion)
//    if (cc > 0.) // signifie qu'au pas précédent on n'a pas bien détecté une coincidence
//                  // ou que c'est un pb de zero
//        { // les 4 lignes qui suivent n'ont plus lieu d'être : -- modif 10 juillet 2014
////       if (Dabs(cc) <= tolerance_coincidence)
////        { cc = 0.;
////         }
////       else
//        { if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 0)) || (Permet_affichage() > 0))
//            cout << "\n erreur algo coincidence : 1 : cc positif ! "
//                 << "\n  Hysteresis3D::Coincidence(... " << endl;
//          if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 2)) || (Permet_affichage() > 2))
//            { cout << "\n aa= " << aa << " bb= " << bb << " cc= " << cc;}; 
//          if ( ((Permet_affichage()==0) && (ParaGlob::NiveauImpression() > 4)) || (Permet_affichage() > 4))
//            { Affiche_debug(unSur_wBaseCarre,save_resul,iatens,iadef_equi,pt_sur_principal
//                              ,iaOi,oi_sur_principal,iatens_princ,iadef_equi_princ,iaOi_princ);
//            };
//          // on génère une exception
//          throw ErrNonConvergence_loiDeComportement();
////          Sortie(1);
//        };
//       };
//  
//****
//   #endif
   // b-- recherche de racine
   double racine1,racine2; int cas;
   alg_zero.SecondDegre(aa,bb,cc,racine1,racine2,cas);
   // --- traitement suivant les différents cas de la résolution de l'équation du second degré ---
   switch (cas)
    { case 1: // deux racines distinctes
       { // normalement les deux racines sont de signe opposé, seule la positive <=1 est recevable
         if (racine1*racine2 <=0.)
           {// on regarde si racine2 <= 1 ce qui est le cas normal
            if (racine2 <= 1.) // racine2 est la plus grande donc positive
              // cas normal, on valide la procédure
              { bon_calcul = true;}
            #ifdef MISE_AU_POINT
            else // sinon cela signifie que la méthode n'est pas bonne
               { if (Permet_affichage() > 0)
                   cout << "\n warning algo coincidence, dans la recherche des racines de l'equa 2 degre "
                      << " la seconde racine " << racine2 <<" est superieur a 1"
                      << "\n  Hysteresis3D::Coincidence(... ";
                }       
            #endif
            }
         else 
          {  
           #ifdef MISE_AU_POINT
           // normalement aa >=0 donc avec cc <0 on ne doit pas avoir 2 racines du même signe
           if(!aucun_pt_inversion) // sauf dans le cas de la première charge
            {  if (Permet_affichage() > 0)
                 cout << "\n erreur algo coincidence, dans la recherche des racines de l'equa 2 degre "
                      << " les deux racines sont du meme signe ??, a= " <<aa<<" c= " << cc << " racine1= "
                      << racine1 << "  racine2= " << racine1
                      << "\n  Hysteresis3D::Coincidence(... ";
             }       
           #endif
           // on regarde si une des racines convient
           // a priori on garde la plus grande, si les deux conviennent
           double la_plus_grande = MaX(racine1,racine2);
           if ((la_plus_grande>0.) && (la_plus_grande<1.))
             { racine2=la_plus_grande; bon_calcul = true;}
           else // sinon on test l'autre
            { double la_plus_petite = MiN(racine1,racine2);
              if ((la_plus_petite>0.) && (la_plus_petite<1.))
                { racine2=la_plus_petite; bon_calcul = true;}
              // sinon rien tous les autres cas sont mauvais
             };    
          };
         break;
        }
      case 2: // deux racines identiques
       { // normalement la racine doit être comprise entre 0 et 1, sinon non recevable
         if ((racine2>=0.) && (racine2 <= 1.))
            // cas normal, on valide la procédure
            { bon_calcul = true;};
         // tous les autres cas sont mauvais               
         break;
        }
      case -3: // une racine simple
       { // normalement la racine doit être comprise entre 0 et 1, sinon non recevable
         if ((racine1>=0.) && (racine1 <= 1.))
            // cas normal, on valide la procédure
            { bon_calcul = true; 
              racine2=racine1; // pour la suite
              };
         // tous les autres cas sont mauvais               
         break;
        }
     // tous les autres cas sont mauvais donc la variable bon_calcul sera fausse
     // et on utilisera une autre procedure de calcul par la suite   
    }; //-- fin du switch
   // --- fin du traitement suivant les différents cas de la résolution de l'équation du second degré ---
   if (!bon_calcul)
    // cas où la recherche fine avec la résolution de l'équat du second degré n'a pas marché
    { // on utilise une interpolation plus grossière à l'aide de la fonction de charge
      if (Permet_affichage() > 4)
        cout << "\n (algo hysteresis) on passe par l'interpolation lineaire de l'equation du second degre";
      double delta_r2 = rayon_tdt - Q_OiaR;
      double delta_r1 = Q_OiaR - sqrt(delta_sigma_oi_a_t_BH.II());
      racine2 = delta_r1 / (delta_r1 + delta_r2);
      // normalement racine2 est compris entre 0 et 1
      if ( (racine2 < 0.) || (racine2 > 1.))
          { if (Permet_affichage() > 0)
              cout << "\n erreur algo coincidence, dans la recherche de racine2 simplifiee"
                 << "\n racine2= " << racine2 << " delta_r2= " << delta_r2 << " delta_r1= " << delta_r1 
                 << " Q_OiaR= " << Q_OiaR << " -> divergence ! "
                 << "\n  Hysteresis3D::Coincidence(... " << endl;
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();
           };       
    };
   // c-- maintenant on traite les infos 
   
  
   //  comme racine2 appartient à [0,1], que OiR > Oisigma_t et que OiR < Oisigma_tdt, normalement on doit avoir
   //  Oisigma_tdt > Oisigma_coinci
   
   // -- cas où à l'issue du calcul racines est très proche de 1 --- 
   // dans ce cas on considère que la coïncidence est exacte 
   if (sqrt(((1.-racine2)*delta_sigma_barre_tdt_BH).II()) <= tol_coincidence_reelle)
     { // on est dans le cas où l'on a une coïncidence exacte à la précision "tolerance_coincidence" près
       // mais dans tous les cas on a rayon_tdt > Q_OiaR sinon on n'aurait pas de coïncidence
       // on signale qu'il y a une coincidence exacte (pour le retour de la méthode Coincidence)   
       // gestion des pointeurs
       do
        {Gestion_pointeur_coincidence(unSur_wBaseCarre,save_resul,W_a
	                    ,iatens,iadef_equi,iafct,pt_sur_principal,iaOi,oi_sur_principal
	                    ,iatens_princ,iadef_equi_princ,iaOi_princ,iafct_princ);
        }// on traite le cas où des autres coincidences existent à la précision près               
       while (Autre_coincidence_a_la_tolerance_pres(bascule_fct_aide,gijHH,gijBB
                                            ,pt_sur_principal,oi_sur_principal,iatens,iaOi));
       return true;
     };   
   
   // calcul de la valeur de sigma au point de coincidence, qui servira pour un nouveau calcul
   sigma_i_barre_BH +=  racine2 * delta_sigma_barre_tdt_BH;
   // donc à partir d'ici on considère que l'on va valider la coïncidence, il faut donc que
   // la contrainte au point de conïncidence corresponde "exactement" à celle correspondante au critère de
   // coïncidence, on va donc vérifier que  "racine2" est correcte
   double nouveau_rayon_tdt = sqrt((sigma_i_barre_BH - oc_BH_R).II()); // Q_OiaR
   if ((Abs(nouveau_rayon_tdt - Q_OiaR) > tol_coincidence_reelle) )
      if (Permet_affichage() > 4)
           { cout << "\n erreur2 algo coincidence, dans la recherche de racine2 "
                 << "\n racine2= " << racine2 << " nouveau_rayon_tdt= " << nouveau_rayon_tdt
                 << " Q_OiaR= " << Q_OiaR << " -> divergence ! "
                 << "\n  Hysteresis3D::Coincidence(... " << endl;
              // on génère une exception
              throw ErrNonConvergence_loiDeComportement();
           };       
  
   // calcul du reste d'incrément de déformation qu'il faut utiliser pour la suite
   delta_barre_epsBH *= (1.-racine2); // (1.-racine2) est >= 0
   // mise à jour des différents pointeurs 
   Gestion_pointeur_coincidence(unSur_wBaseCarre,save_resul,W_a
	                    ,iatens,iadef_equi,iafct,pt_sur_principal,iaOi,oi_sur_principal
	                    ,iatens_princ,iadef_equi_princ,iaOi_princ,iafct_princ);
  
   // fin et retour, comme le calcul n'est pas fini on retourne false
   return false;   
  };

// traitement des cas où des autres coincidences existent à la précision près               
// ramène true si effectivement il y a une nouvelle coincidence               
bool Hysteresis3D::Autre_coincidence_a_la_tolerance_pres(bool bascule_fct_aide
                      ,const Tenseur3HH & gijHH,const Tenseur3BB & gijBB
                      ,const bool& pt_sur_principal,const bool& oi_sur_principal
	                     ,List_io <Tenseur3BH>::iterator& iatens
	                     ,List_io <Tenseur3BH>::iterator& iaOi)
 { // choix entre gestion avec rayons ou avec fonction d'aide
   if (!bascule_fct_aide)
     {// on va calculer le nouveau rayon et voir s'il y a de nouveau coincidence ou pas
      // -- 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
                              };
      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());};
     
      // calcul du rayon actuelle, avec le nouveau centre éventuelle
      Tenseur3BH delta_sigma_oi_a_tdt_BH = sigma_t_barre_tdt - oc_BH_R; // OA
      double nouveau_rayon_tdt = sqrt(delta_sigma_oi_a_tdt_BH.II());
      
      // on test
      bool retour;
      if (nouveau_rayon_tdt < Q_OiaR)   {retour = false;}     // cas normal
      else                       {retour = true;	};    // cas où il y a une nouvelle coincidence
      // une nouvelle coincidence est possible si l'ancien rayon de référence et le nouveau ont une
      // différence inférieure à la précision de la coincidence !!
  //--------débug- traçage
      #ifdef MISE_AU_POINT
      if ((Permet_affichage() == -77)&&retour)
         { cout << "\n nouvelle coïncidence: cas de points tres rapprochees "
                << endl ;
         };
      #endif
  //----- fin débug
      
      return retour;
     }
   else // cas d'une gestion avec la fonction d'aide
     {// pour l'instant on ne fait rien, s'il y a plusieurs coïncidence à suivre
      // on passera plusieurs fois dans l'algo coïncidence
      return false;
     };
 };

	 // 2) affinage d'un point de coincidence à l'aide de la fonction d'aide
// ramène true si le traitement est exactement terminé, sinon false, ce qui signifie qu'il
// faut encore continuer à utiliser l'équation d'évolution
// premiere_charge : indique si c'est oui ou non une coincidence avec la première charge
// pt_sur_principal : indique si oui ou non les pointeurs iafct et iatens pointent sur les listes
// principales
// iatens_princ et iafct_princ: pointeurs sur les listes principales
bool Hysteresis3D::Coincidence(bool bascule_fct_aide,double& unSur_wBaseCarre
                               ,const Tenseur3HH & gijHH,const Tenseur3BB & gijBB
                               ,SaveResulHysteresis3D & save_resul,double& W_a
                               ,List_io <Tenseur3BH>::iterator& iatens
                               ,List_io <double>::iterator& iadef_equi
                               ,List_io <double>::iterator& iafct
                               ,bool& pt_sur_principal
                               ,List_io <Tenseur3BH>::iterator& iaOi,bool& oi_sur_principal
                               ,List_io <Tenseur3BH>::iterator& iatens_princ
                               ,List_io <double>::iterator& iadef_equi_princ
                               ,double& position_coincidence
                               ,List_io <Tenseur3BH>::iterator& iaOi_princ
                               ,List_io <double>::iterator& iafct_princ
                               ,double& delta_W_a,bool force_coincidence)
 { // tout d'abord on vérifie que l'on n'est pas exactement à un point de
   // coincidence à la précision près
   double c =   (W_a - delta_W_a)  -  *iafct;
   bool coin_exacte = false; // drapeau indiquant si l'on a une coincidence exacte ou pas
   // calcul de la précision
   double tol_coincidence_reelle = tolerance_coincidence;
   if (tolerance_coincidence < 0) // si l'indication est négative , cela veut dire que l'on veut une grandeur négative
     tol_coincidence_reelle = MaX(-tolerance_coincidence * W_a,-tolerance_coincidence);
   if ((Abs(W_a - *iafct) <= tol_coincidence_reelle) || force_coincidence
       || (c >= 0.) ) // on ne peut plus revenir sur les grandeurs à t
                      // donc le mieux est de valider la coïncidence ce qui simplifiera la suite du traitement
     { // on est dans le cas où l'on a une coïncidence exacte à la précision "tolerance_coincidence" près
       // mais dans tous les cas on a rayon_tdt > Q_OiaR sinon on n'aurait pas de coïncidence
       // on signale qu'il y a une coincidence exacte (pour le retour de la méthode Coincidence)   
       // gestion des pointeurs
       do
        { // on prend pour W_a la valeur au moment de la coïncidence ce qui permet d'éviter des approximations futures
          W_a = *iafct;
        
          Gestion_pointeur_coincidence(unSur_wBaseCarre,save_resul,W_a
	                    ,iatens,iadef_equi,iafct,pt_sur_principal,iaOi,oi_sur_principal
	                    ,iatens_princ,iadef_equi_princ,iaOi_princ,iafct_princ);
        }// on traite le cas où des autres coincidences existent à la précision près               
       while (Autre_coincidence_a_la_tolerance_pres(bascule_fct_aide,gijHH,gijBB,pt_sur_principal
                                            ,oi_sur_principal,iatens,iaOi));
       coin_exacte = true;position_coincidence=1.;
       return coin_exacte;
     };   
   // --- sinon on continue
   // recherche de racine
   double racine2;

//   // c doit-être négatif, à la limite nul
//   if (c >= 0.)
//    {// on détermine la proportion de déformation qu'il faut faire pour être exactement à la coïncidence
//      double W_t=W_a - delta_W_a;
//      racine2 = (W_a -  *iafct) / delta_W_a;
//    }
//   else
    { // on utilise une interpolation assez grossière à l'aide de la fonction de charge
 //     cout << "\n on passe par l'interpolation de la fonction d'aide";
      double W_t=W_a - delta_W_a;
      racine2 = (*iafct - W_t) / delta_W_a;
      #ifdef MISE_AU_POINT
      // normalement racine2 est compris entre 0 et 1
      if ( (racine2 < 0.) || (racine2 > 1.))
          { cout << "\n erreur algo coincidence, dans la recherche de racine2 a l'aide de la fonction de charge "
                 << " W_ref= " <<*iafct<<" W_t= " << W_t << " delta_W_a= " << delta_W_a
                 << "\n  Hysteresis1D::Coincidence(... ";
            Sortie(1);        
           }       
      #endif
     }

   // -- maintenant on traite les infos
  
   //  comme racine2 appartient à [0,1], que OiR > Oisigma_t et que OiR < Oisigma_tdt, normalement on doit avoir
   //  Oisigma_tdt > Oisigma_coinci
   
   // -- cas où à l'issue du calcul racines est très proche de 1 --- 
   // dans ce cas on considère que la coïncidence est exacte 
   if (sqrt(((1.-racine2)*delta_sigma_barre_tdt_BH).II()) <= tol_coincidence_reelle)
     { // on est dans le cas où l'on a une coïncidence exacte à la précision "tolerance_coincidence" près
       // mais dans tous les cas on a rayon_tdt > Q_OiaR sinon on n'aurait pas de coïncidence
       // on signale qu'il y a une coincidence exacte (pour le retour de la méthode Coincidence)   
       // gestion des pointeurs
       do
        {// on prend pour W_a la valeur au moment de la coïncidence ce qui permet d'éviter des approximations futures
          W_a = *iafct;
        
         Gestion_pointeur_coincidence(unSur_wBaseCarre,save_resul,W_a
	                    ,iatens,iadef_equi,iafct,pt_sur_principal,iaOi,oi_sur_principal
	                    ,iatens_princ,iadef_equi_princ,iaOi_princ,iafct_princ);
        }// on traite le cas où des autres coincidences existent à la précision près               
       while (Autre_coincidence_a_la_tolerance_pres(bascule_fct_aide,gijHH,gijBB
                                            ,pt_sur_principal,oi_sur_principal,iatens,iaOi));
       coin_exacte = true;position_coincidence=1.;
       return coin_exacte;
     };
  
   // -- sinon cela veut dire que la coïncidence n'est pas précise, au lieu de chercher à calculer
   // le tenseur sigma à l'aide d'une péréquation, on ne valide pas la coïncidence, par contre
   // on ramène la valeur de la proportion racine2 indiquant la position approximative de l'inversion exacte
   
//   // calcul de la valeur de sigma au point de coincidence, qui servira pour un nouveau calcul
//   sigma_i_barre_BH +=  racine2 * delta_sigma_barre_tdt_BH;
//   
//   // calcul du reste d'incrément de déformation qu'il faut utiliser pour la suite
//   delta_barre_epsBH *= (1.-racine2); // (1.-racine2) est >= 0
//   // mise à jour des différents pointeurs 
//   Gestion_pointeur_coincidence(unSur_wBaseCarre,save_resul
//	                    ,iatens,iadef_equi,iafct,pt_sur_principal,iaOi,oi_sur_principal
//	                    ,iatens_princ,iadef_equi_princ,iaOi_princ,iafct_princ);
//          
//   // fin et retour, comme le calcul n'est pas fini on retourne false
       coin_exacte = false;position_coincidence=racine2;
       return coin_exacte;
  };

// calcul de wprime en fonction de grandeurs supposées déjà calculées
// --- méthode indépendante -----
// utilise : Q_OiaR, QdeltaSigmaRatdt, 
//           delta_sigma_barre_BH_Ratdt, delta_sigma_barre_BH_OiaR
//           wBase
// trajet_neutre: indique si oui ou non, on est dans un chargement neutre à la précision près
void Hysteresis3D::Cal_wprime(const double& Q__deltaSiRatdt,const Tenseur3BH& delta__sig_barre_BH_Ratdt
                              ,const double& Q__OiaR,const Tenseur3BH& delta__sig_barre_BH_OiaR 
                              ,const double& w__Base,Tenseur3BH& delta__sig_barre_BH_tatdt
                              , double& w__prime, double& w__prime_point,bool& trajet_neut) const
{ // -- calculs relatifs aux angles de phases
  // ces calculs ne sont nécessaires que si l'on n'est pas sur une première charge
  if (w__Base!=1) 
     {// si l'intensité du rayon est nulle, celui de seconde charge doit
      // être également nulle, on considére un alpha nulle donc un cos = 1 d'où w__prime = 2.
      if (Q__OiaR >= mini_rayon) // si mini_rayon est négatif (=> régularisation), l'expression est tjs vrai
       {// si l'intensité de l'accroissement du déviateur de contrainte est nulle, 
        // on considére un alpha nulle donc un cos = 1 d'où w__prime = 2.
        if (Q__deltaSiRatdt >= mini_rayon) // idem test si dessus pour le cas où mini_rayon est négatif
          {// cas où on peut calculer l'angle
           // -- calcul de w__prime
           double unSurQ__OiaR ; //= 1./Q__OiaR;
           double unSurQ__deltaSiRatdt ;//= 1./Q__deltaSiRatdt;
           if (mini_rayon > 0.) // cas historique
            { unSurQ__OiaR = 1./Q__OiaR;
              unSurQ__deltaSiRatdt = 1./Q__deltaSiRatdt;
            }
           else // cas avec régularisation
            { unSurQ__OiaR = 1./(Q__OiaR-mini_rayon);
              unSurQ__deltaSiRatdt = 1./(Q__deltaSiRatdt-mini_rayon);
            };

           double cos_alpha = - (delta__sig_barre_BH_Ratdt && delta__sig_barre_BH_OiaR)
                                * unSurQ__OiaR * unSurQ__deltaSiRatdt;
//           if (Dabs(cos_alpha)<= ConstMath::pasmalpetit) 
           if (Dabs(cos_alpha)<= min_angle_trajet_neutre) 
           	{ // dans ce cas il s'agit d'un trajet neutre
           	  // le cos_alpha, sa dérivée, les w_prime et w_prime_point n'auront pas au final d'importance
           	  trajet_neut=true;
           	  w__prime=0.; w__prime_point=0.;
           	}
           else if ((cos_alpha <= - min_angle_trajet_neutre) && (!possibilite_cosAlphaNegatif))
				        { // cas ou cos_alpha est négatif et que l'on veut traiter ce cas comme un cas neutre 
				          // le cos_alpha, sa dérivée, les w_prime et w_prime_point n'auront pas au final d'importance
              trajet_neut=true;
              w__prime=0.; w__prime_point=0.;
           	}
           else
            { // chargement non neutre
              trajet_neut = false;
              w__prime = w__Base * cos_alpha;
              if ((w__prime <= 0) && (possibilite_cosAlphaNegatif))
           	  { // dans le cas où cos_alpha est négatif et que l'on admet "transitoirement" que le cos_alpha puisse
				            // être négatif, on lui change de signe (cf. les anciens commentaires qui suivent)
				  
				  
                // C1- il y a problème car cela signifie que cos_alpha est négatif donc que les cercles s'accroissent
                // C1- ceci peut être du à une erreur d'arrondi
           	    // C1-  on considère alors que l'on est au cas limite de cos_alpha = 0`
                // C2-- non en fait ça peut-être tout-à-fait normale, juste avant une inversion on a un angle négatif et c'est normale
                // C2--  pour éviter d'avoir des pb le plus simple est de considérer la partie positive de l'angle           	  
           	  
    // --        	  if (MaX(ParaGlob::NiveauImpression(),Permet_affichage()) >= 3)
    // --        	     cout << "\n attention, angle de phase negatif en hysteresis ! ,";
    //       	          << " on le met a 0";
    //       	  if (MaX(ParaGlob::NiveauImpression(),Permet_affichage()) >= 4)
    //       	     cout << " Q__deltaSiRatdt= " << Q__deltaSiRatdt << " w__prime= " << w__prime;
    //       	  w__prime = 2.;w__prime_point=0.;    
           	  
                w__prime = - w__prime;
                double Rsig_point_scalaire_Rsig = delta__sig_barre_BH_tatdt && delta__sig_barre_BH_Ratdt;
                double ee = Rsig_point_scalaire_Rsig * unSurQ__deltaSiRatdt * unSurQ__deltaSiRatdt;
                double cos_alpha_point =  - unSurQ__OiaR * unSurQ__deltaSiRatdt 
                                          * (delta__sig_barre_BH_OiaR && 
                                              (delta__sig_barre_BH_tatdt - ee *  delta__sig_barre_BH_Ratdt )) ; 
                w__prime_point = - w__Base * cos_alpha_point;
           	  
              	}
              else	
               {// -- calcul de w__prime_point
                double Rsig_point_scalaire_Rsig = delta__sig_barre_BH_tatdt && delta__sig_barre_BH_Ratdt;
                double ee = Rsig_point_scalaire_Rsig * unSurQ__deltaSiRatdt * unSurQ__deltaSiRatdt;
                double cos_alpha_point =  - unSurQ__OiaR * unSurQ__deltaSiRatdt 
                                          * (delta__sig_barre_BH_OiaR && 
                                              (delta__sig_barre_BH_tatdt - ee *  delta__sig_barre_BH_Ratdt )) ; 
                w__prime_point = w__Base * cos_alpha_point;
               };
            }; // fin du cas non neutre
          } // fin du cas où on peut calculer l'angle
        else  
         // cas ou l'intensité de l'accroissement du déviateur de contrainte est nulle
         {w__prime = 2.;w__prime_point=0.;trajet_neut = false;}; // cas de cos(alpha)=1.
      	}
      else 
       // cas ou l'intensité du déviateur de référence est nulle
       {w__prime = 2.;w__prime_point=0.;trajet_neut = false;}; // cas de cos(alpha)=1.
     }
    else 
     // cas d'une première charge
     {w__prime=1.;w__prime_point=0.;trajet_neut = false;};
};

// calcul de wprime et de sa variation par rapport aux coordonnées de delta sigma barre
// en fonction de grandeurs supposées déjà calculées
// utilise : Q_OiaR, QdeltaSigmaRatdt, 
//           delta_sigma_barre_BH_Ratdt, delta_sigma_barre_BH_OiaR
//           wBase
// trajet_neut: indique si oui ou non, on est dans un chargement neutre à la précision près
// --- méthode indépendante -----
void Hysteresis3D::Cal_wprime_et_der(const double& Q__deltaSiRatdt,const Tenseur3BH& delta__sig_barre_BH_Ratdt
                              ,const double& Q__OiaR,const Tenseur3BH& delta__sig_barre_BH_OiaR 
                              ,const double& w__Base,Tenseur3BH& delta__sig_barre_BH_tatdt 
                              ,double& w__prime, Tenseur3BH& d_w__prime
                              ,double& w__prime_point,Tenseur3BH& d_w__prime_point,bool& trajet_neut) const
{ // -- calculs relatifs aux angles de phases
  static const double untiers=1./3.;static const double troisRacineDe6=3.*sqrt(6.);
  // ces calculs ne sont nécessaires que si l'on n'est pas sur une première charge
  d_w__prime.Inita(0.); // init pour tous les cas ou d_w__prime n'est pas calculée
                      // cf les différents cas qui suivent
  d_w__prime_point.Inita(0.); // idem pour le w__prime_point                    
  if (w__Base!=1) 
     {// si l'intensité du rayon est nulle, celui de seconde charge doit
      // être également nulle, on considére un alpha nulle donc un cos = 1 d'où w__prime = 2.
      // d'où des variations nulles
      if (Q__OiaR >= mini_rayon) // si mini_rayon est négatif (=> régularisation), l'expression est tjs vrai
       {// si l'intensité de l'accroissement du déviateur de contrainte est nulle, 
        // on considére un alpha nulle donc un cos = 1 d'où w__prime = 2.
        if (Q__deltaSiRatdt >= mini_rayon) // idem test si dessus pour le cas où mini_rayon est négatif
          {// cas où on peut calculer l'angle
           double unSurQ__OiaR ;//= 1./Q__OiaR;
           double unSurQ__deltaSiRatdt;// = 1./Q__deltaSiRatdt;
           if (mini_rayon > 0.) // cas historique
            { unSurQ__OiaR = 1./Q__OiaR;
              unSurQ__deltaSiRatdt = 1./Q__deltaSiRatdt;
            }
           else // cas avec régularisation
            { unSurQ__OiaR = 1./(Q__OiaR-mini_rayon);
              unSurQ__deltaSiRatdt = 1./(Q__deltaSiRatdt-mini_rayon);
            }
           double x1 = delta__sig_barre_BH_Ratdt && delta__sig_barre_BH_OiaR;
           double cos_alpha = - x1* unSurQ__OiaR * unSurQ__deltaSiRatdt;;
//           if (Dabs(cos_alpha)<= ConstMath::pasmalpetit) 
           if (Dabs(cos_alpha)<= min_angle_trajet_neutre) 
           	{ // dans ce cas il s'agit d'un trajet neutre
           	  // le cos_alpha, sa dérivée, les w_prime et w_prime_point n'auront pas au final d'importance
           	  trajet_neut=true;
           	  w__prime=0.; w__prime_point=0.;
           	}
           else if ((cos_alpha <= - min_angle_trajet_neutre) && (!possibilite_cosAlphaNegatif))
             { // cas ou cos_alpha est négatif et que l'on veut traiter ce cas comme un cas neutre
               // le cos_alpha, sa dérivée, les w_prime et w_prime_point n'auront pas au final d'importance
           	   trajet_neut=true;
           	   w__prime=0.; w__prime_point=0.;
           	 }
           else
             { // chargement non neutre
               trajet_neut = false;
               w__prime = w__Base * cos_alpha;                     
               if ((w__prime <= 0) && (possibilite_cosAlphaNegatif))
                { // dans le cas où cos_alpha est négatif et que l'on admet "transitoirement" que le cos_alpha puisse
          // être négatif, on lui change de signe (cf. les anciens commentaires qui suivent)
        
                  // C1- il y a problème car cela signifie que cos_alpha est négatif donc que les cercles s'accroissent
                  // C1- ceci peut être du à une erreur d'arrondi
                  // C1-  on considère alors que l'on est au cas limite de cos_alpha = 0`
                  // C2-- non en fait ça peut-être tout-à-fait normale, juste avant une inversion on a un angle négatif et c'est normale
                  // C2--  pour éviter d'avoir des pb le plus simple est de considérer la partie positive de l'angle           	  
         //    	  if (MaX(ParaGlob::NiveauImpression(),Permet_affichage()) >= 3)
         //    	     cout << "\n attention, angle de phase negatif en hysteresis ! ,";
       //      	          << " on le met a 0";
       //      	  if (MaX(ParaGlob::NiveauImpression(),Permet_affichage()) >= 6)
       //      	     cout << " Q__deltaSiRatdt= " << Q__deltaSiRatdt ;
       //      	   w__prime = 2.;w__prime_point=0.;  */  
                 
                 
                  w__prime = - w__prime;
                  // -- calcul de w__prime_point
                  double a ;//= Q__deltaSiRatdt * Q__deltaSiRatdt;
                  if (mini_rayon > 0.) // cas historique
                    { a = Q__deltaSiRatdt * Q__deltaSiRatdt;}
                  else // cas avec régularisation
                    { a = Q__deltaSiRatdt * Q__deltaSiRatdt-mini_rayon;};
                  double b = delta__sig_barre_BH_tatdt && delta__sig_barre_BH_Ratdt;
                  double ee = b/a;

                  double C = delta__sig_barre_BH_OiaR && (delta__sig_barre_BH_tatdt - ee * delta__sig_barre_BH_Ratdt);
                  double cos_alpha_point = (- unSurQ__OiaR * unSurQ__deltaSiRatdt) * C;
                  w__prime_point = - w__Base * cos_alpha_point;                                                 
                  // calcul de la variation de  cos_alpha et donc de w__prime
                  Tenseur3BH d_aSur2_BH(delta__sig_barre_BH_Ratdt);
                  d_aSur2_BH.PermuteHautBas();
                  Tenseur3BH num_cos_BH(delta__sig_barre_BH_OiaR);num_cos_BH.PermuteHautBas();
                  d_w__prime =  d_aSur2_BH * (cos_alpha * unSurQ__deltaSiRatdt * unSurQ__deltaSiRatdt*w__Base)
                               + num_cos_BH * (unSurQ__deltaSiRatdt * unSurQ__OiaR*w__Base);
  //                d_w__prime = d_a_BH;
     //             d_w__prime *= (x1/(Q__deltaSiRatdt*Q__deltaSiRatdt)-1)/(Q__deltaSiRatdt*Q__OiaR);
                  // calcul de la variation de cos_alpha_point
                  Tenseur3BH d_b_BH(delta__sig_barre_BH_tatdt);
                  d_b_BH.PermuteHautBas();
                  d_b_BH += d_aSur2_BH;
                  double unSur_a2 = 1./(a*a);
                  Tenseur3BH d_e_BH = d_b_BH / a - (2.* b*unSur_a2)*d_aSur2_BH;
                  d_w__prime_point = (w__Base * unSurQ__OiaR) * 
                                                ( (- unSurQ__deltaSiRatdt / a * C)*d_aSur2_BH
                                                 + ((1.-ee)*unSurQ__deltaSiRatdt) * num_cos_BH 
                                                 + (-unSurQ__deltaSiRatdt * x1)* d_e_BH
                                                 );
                 }
               else
                {// -- calcul de w__prime_point
                 double a ;//= Q__deltaSiRatdt * Q__deltaSiRatdt;
                 if (mini_rayon > 0.) // cas historique
                   { a = Q__deltaSiRatdt * Q__deltaSiRatdt;}
                 else // cas avec régularisation
                   { a = Q__deltaSiRatdt * Q__deltaSiRatdt-mini_rayon;};
                 double b = delta__sig_barre_BH_tatdt && delta__sig_barre_BH_Ratdt;
                 double ee = b/a;
                 double C = delta__sig_barre_BH_OiaR && (delta__sig_barre_BH_tatdt - ee * delta__sig_barre_BH_Ratdt);
                 double cos_alpha_point = (- unSurQ__OiaR * unSurQ__deltaSiRatdt) * C;
                 w__prime_point = w__Base * cos_alpha_point;                                                 
                 // calcul de la variation de  cos_alpha et donc de w__prime
                 Tenseur3BH d_aSur2_BH(delta__sig_barre_BH_Ratdt);
                 d_aSur2_BH.PermuteHautBas();
                 Tenseur3BH num_cos_BH(delta__sig_barre_BH_OiaR);num_cos_BH.PermuteHautBas();
                 d_w__prime = d_aSur2_BH * (- cos_alpha * unSurQ__deltaSiRatdt * unSurQ__deltaSiRatdt*w__Base)
                              - num_cos_BH * (unSurQ__deltaSiRatdt * unSurQ__OiaR*w__Base);
 //                d_w__prime = d_a_BH;
 //                d_w__prime *= (x1/(Q__deltaSiRatdt*Q__deltaSiRatdt)-1)/(Q__deltaSiRatdt*Q__OiaR);
                 // calcul de la variation de cos_alpha_point
                 Tenseur3BH d_b_BH(delta__sig_barre_BH_tatdt);
                 d_b_BH.PermuteHautBas(); d_b_BH += d_aSur2_BH;
                 double unSur_a2 = 1./(a*a);
                 Tenseur3BH d_e_BH = d_b_BH / a - (2.*b*unSur_a2)*d_aSur2_BH;
                 d_w__prime_point =  (-w__Base * unSurQ__OiaR) * 
                                           (  (- unSurQ__deltaSiRatdt / a * C)*d_aSur2_BH
                                              + ((1.-ee)*unSurQ__deltaSiRatdt) * num_cos_BH 
                                              + (-unSurQ__deltaSiRatdt * x1)* d_e_BH
                                            );
                };
            }// fin du cas non neutre
          }// fin du cas où on peut calculer l'angle
        else  
         // cas ou l'intensité de l'accroissement du déviateur de contrainte est nulle
         {w__prime = 2.;w__prime_point=0.;trajet_neut = false;}; // cas de cos(alpha)=1.
      	}
      else 
       // cas ou l'intensité du déviateur de référence est nulle
       {w__prime = 2.;w__prime_point=0.;trajet_neut = false;}; // cas de cos(alpha)=1.
     }
    else 
     // cas d'une première charge
     {w__prime=1.;w__prime_point=0.;trajet_neut = false;};		
};

// calcul du centre d'inversion avec les données actuelles
// ramène un indicateur informant comment l'opération s'est passé et si elle est valide (= 0)
int Hysteresis3D::CentreCercle(Tenseur3BH& sig0i_BH,const Tenseur3BH& oc_BH_R
                                ,const Tenseur3BH & delta_sigma_barre_BH_OiaR
                                ,const Tenseur3BH& delta_sigma_barre_BH_Rat)
{ // on part du principe que c'est le point à t qui est le point d'inversion
  // ceci a été déterminé par le fait que le rayon à tdt a été trouvé plus petit que celui a t
  double rayon_t = sqrt((delta_sigma_barre_BH_OiaR + delta_sigma_barre_BH_Rat).II());
  double delta_rayon2 = (rayon_t*rayon_t - Q_OiaR*Q_OiaR);
  // ici ce n'est pas le vrai cos, mais le cos * les deux normes, mais le signe est le même
  double cos_alpha_a_t = (delta_sigma_barre_BH_OiaR && delta_sigma_barre_BH_Rat);
//  double gamma = 0.5 * (rayon_t*rayon_t - Q_OiaR*Q_OiaR) 
//                    / (delta_sigma_barre_BH_OiaR && delta_sigma_barre_BH_Rat);
 
  int retour = 0; // init du retour a priori
  // --- mise à jour précision éventuelle
  double tol_centre_reelle = tolerance_centre;
  if (tolerance_centre < 0) // si l'indication est négative , cela veut dire que l'on veut une grandeur relative
      tol_centre_reelle = MaX(-tolerance_centre * Q_OiaR,-tolerance_centre);
  // ---
 
  // en fait peut-être très proche de 0 du aux erreurs d'arrondi
  if (Dabs(delta_rayon2) < tol_centre_reelle)
    // à la tolérance près on a le même rayon, cela veut dire qu'à l'incrément précédent on était sur un trajet
    // neutre à la précision près, donc pas de nouveau centre à calculer
    {retour = 1;}
  else if (delta_rayon2 > 0.) // et donc sup aussi à tol_centre_reelle compte tenu du test plus haut
    // là il s'agit d'un comportement qui n'est pas normal, car normalement le nouveau rayon doit-être plus petit
    // que l'ancien donc on n'a pas de point d'inversion probant (ce serait plutôt une coïncidence mal déterminée)
    //  il vaut mieux attendre un incrément de charge supérieure qui permettra d'avoir
    // un point d'inversion correctement déterminé
    {retour = 1;} // on signale que ce n'est pas la peine de calculer un nouveau centre
  else if (Dabs(cos_alpha_a_t) < min_angle_trajet_neutre)
     // maintenant il faut que le cos_alpha ne soit pas trop petit
     // si oui on était alors sur un trajet neutre qui s'ignorait, là encore le point d'inversion n'est pas probant
     // il vaut mieux attendre un incrément de charge supérieure qui permettra d'avoir
     // un point d'inversion correctement déterminé
    {retour = 1;} // on signale que ce n'est pas la peine de calculer un nouveau centre
  else if (cos_alpha_a_t > 0.) // et donc sup aussi à min_angle_trajet_neutre compte tenu du test plus haut
     // c'est pas non plus normal, cela veut dire que l'on se déplace vers l'extérieur de la sphére de ref
     // donc ce n'est pas un point d'inversion correct
    {retour = 1;} // on signale que ce n'est pas la peine de calculer un nouveau centre
  else
     // arrivée ici toutes les conditions sont bonnes pour calculer un point d'inversion correct
    {double gamma = 0.5 * delta_rayon2 / cos_alpha_a_t;
     sig0i_BH =  oc_BH_R + gamma * delta_sigma_barre_BH_OiaR;
    };

  // message d'info au cas où
  if (retour)
    if (Permet_affichage() > 5)
      { double cosalpha = (delta_sigma_barre_BH_OiaR && delta_sigma_barre_BH_Rat)
                        /sqrt((delta_sigma_barre_BH_OiaR.II()*delta_sigma_barre_BH_Rat.II()));
      
       cout << "\n info concernant le calcul de centre, le centre ne peut-etre calcule ce qui n'est peut-etre pas normal !! "
            << "\n Hysteresis3D::CentreCercle(..."
            << " rayon_t= " << rayon_t << " Q_OiaR= " <<Q_OiaR
            << " cos_alpha_a_t= cos (delta_sigma_barre_BH_OiaR, delta_sigma_barre_BH_Rat) "
            << cosalpha << endl;
//// -- debug
//   cout << "\n debug Hysteresis3D::CentreCercle( ";
//   Q_OiaR = sqrt(delta_sigma_barre_BH_OiaR.II());
//   double delta_RT2 = delta_sigma_barre_BH_Rat && delta_sigma_barre_BH_Rat;
//   double delta_oiaR2 = delta_sigma_barre_BH_OiaR && delta_sigma_barre_BH_OiaR;
//   double oiaRfoisRat = delta_sigma_barre_BH_OiaR && delta_sigma_barre_BH_Rat;
//   double rayont2 = (delta_sigma_barre_BH_OiaR + delta_sigma_barre_BH_Rat) && (delta_sigma_barre_BH_OiaR + delta_sigma_barre_BH_Rat);
//   cout << "\n nouvelle valeur Q_OiaR = " << Q_OiaR << endl;
//// -- fin debug
      };
 
 
  // retour
  return retour;
 
};

// gestion d'un dépilement des pointeurs dans les listes, dans le cas d'une coïncidence
// met à jour les booléens interne à l'instance : aucun_pt_inversion et centre_initial
void Hysteresis3D::Gestion_pointeur_coincidence(double& unSur_wBaseCarre
	                    ,SaveResulHysteresis3D & save_resul,double& W_a
	                    ,List_io <Tenseur3BH>::iterator& iatens
	                    ,List_io <double>::iterator& iadef_equi
                     ,List_io <double>::iterator& iafct
                     ,bool& pt_sur_principal
	                    ,List_io <Tenseur3BH>::iterator& iaOi,bool& oi_sur_principal
	                    ,List_io <Tenseur3BH>::iterator& iatens_princ
	                    ,List_io <double>::iterator& iadef_equi_princ
	                    ,List_io <Tenseur3BH>::iterator& iaOi_princ
                     ,List_io <double>::iterator& iafct_princ)

	{  // 1-- cas de pt de ref: si on pointe sur la liste secondaire on retire le dernier élément
    if (!pt_sur_principal)
    	{ 
       if (iatens != save_resul.sigma_barre_BH_R_t_a_tdt.begin()) 
          { if (Permet_affichage() > 0)
              cout << "\n incoherence, on devrait avoir ici le premier element de la liste secondaire"
                   << " des sig d'inversion"
                   << "\n Hysteresis3D::Gestion_pointeur_coïncidence(..."<< endl; 
            if (Permet_affichage() > 4)
              Affiche_debug(unSur_wBaseCarre,save_resul,iatens,iadef_equi,pt_sur_principal
                           ,iaOi,oi_sur_principal,iatens_princ,iadef_equi_princ,iaOi_princ);
            // on génère une exception
            throw ErrNonConvergence_loiDeComportement();
          };

    	  // comme on est sur la liste secondaire, cela signifie qu'elle n'est pas vide en point d'inversion
    	  // donc on peut supprimer une contrainte d'inversion     
       save_resul.sigma_barre_BH_R_t_a_tdt.erase(iatens); // normalement c'est le premier de la liste!
       save_resul.def_equi_t_a_tdt.erase(iadef_equi); // idem pour def_equi qui suit la même logique
       save_resul.fct_aide_t_a_tdt.erase(iafct); // idem pour la fonction d'aide
//       save_resul.nb_coincidence--; // on dépile également le nombre de coïncidence active
       if (save_resul.sigma_barre_BH_R_t_a_tdt.size()==0)
        {// il ne reste plus d'élément on revient sur la liste principal
         pt_sur_principal = true;
         iatens = iatens_princ; iadef_equi=iadef_equi_princ;iafct=iafct_princ;
         // on regarde si le pointeur est valide
	        if (iatens != save_resul.sigma_barre_BH_R.end())
	              {aucun_pt_inversion = false;}
	        else  {aucun_pt_inversion = true;};
        }
       else // cas où il reste des éléments sur les listes secondaires
        {iatens = save_resul.sigma_barre_BH_R_t_a_tdt.begin();aucun_pt_inversion = false;
         iadef_equi = save_resul.def_equi_t_a_tdt.begin();
         iafct = save_resul.fct_aide_t_a_tdt.begin();
        };
    	}
    else // cas où on pointe sur la liste principal, on se déplace dans la liste principal,
     { //  sans éliminer d'élément : on update le pointage
          if (iatens != save_resul.sigma_barre_BH_R.end())
            {iatens++;iadef_equi++;// idem pour def_equi et iafct qui suivent une même logique
             // mais il faut mettre à jour la fonction d'aide par rapport à la valeur
             // qu'elle avait au point d'inversion précédent sinon, c'est perdue
             W_a = *iafct;
             iafct++; // idem pour def_equi et iafct qui suivent une même logique
             // on regarde si le pointeur est valide
	            if (iatens != save_resul.sigma_barre_BH_R.end()) {aucun_pt_inversion = false;} 
	            else                                             {aucun_pt_inversion = true;};
	            save_resul.nb_coincidence++; // on acte la coïncidence
             // comme on est sur la liste principale, on met à jour les pointeurs de la liste principale
             iatens_princ = iatens;iadef_equi_princ=iadef_equi;iafct_princ = iafct;
            }
          else // sinon il y a un pb car comme c'est une coïncidence il devrait rester un pointeur valide
            {if (Permet_affichage() > 0)
                cout << "\n incoherence, il devrait rester un pointeur de valide sur la liste de pt de ref"
                     << "\n Hysteresis3D::Gestion_pointeur_coincidence(..." << endl;
				         if (Permet_affichage() > 4)
                Affiche_debug(unSur_wBaseCarre,save_resul,iatens,iadef_equi,pt_sur_principal
                              ,iaOi,oi_sur_principal,iatens_princ,iadef_equi_princ,iaOi_princ);
//                cout << "\n tapper quelque chose ";
//                string toto; cin >> toto;              
              // on génère une exception
				        throw ErrNonConvergence_loiDeComportement();
				        }; 
        };
     
    // 2-- cas des centres : si on pointe sur la liste secondaire on retire le dernier élément
    if (!oi_sur_principal)
    	{ 
          if (iaOi != save_resul.oc_BH_t_a_tdt.begin()) 
             { if (Permet_affichage() > 0)
                cout << "\n incoherence, on devrait avoir ici le premier element de la liste secondaire des centres"
                     << "\n Hysteresis3D::Gestion_pointeur_coïncidence(..."<< endl; 
               if (Permet_affichage() > 4)
                   Affiche_debug(unSur_wBaseCarre,save_resul,iatens,iadef_equi,pt_sur_principal
                              ,iaOi,oi_sur_principal,iatens_princ,iadef_equi_princ,iaOi_princ);
               // on génère une exception
               throw ErrNonConvergence_loiDeComportement();
             }; 
          // on regarde si on peut supprimer un centre
          if (iaOi != save_resul.oc_BH_t_a_tdt.end()) // dans le cas où l'origine est 0, il n'y a rien de sauvegardé
       	       save_resul.oc_BH_t_a_tdt.erase(iaOi); // sinon normalement c'est le premier de la liste!
          if (save_resul.oc_BH_t_a_tdt.size()==0)
           {// il ne reste plus d'élément on revient sur la liste principal
            oi_sur_principal = true; iaOi = iaOi_princ;
       	    // on regarde de nouveau si le pointeur de centre est valide 
       	    if ((iaOi != save_resul.oc_BH_R.end())) {centre_initial=false;} else {centre_initial=true;};
           }
          else // cas où il reste des éléments sur les nouvelles listes
           {iaOi = save_resul.oc_BH_t_a_tdt.begin(); centre_initial = false;
           };
       	}
    else // cas où on pointe sur la liste principal, on se déplace dans la liste principal,
     { //  sans éliminer d'élément : on update le pointage
          if (iaOi != save_resul.oc_BH_R.end()) // si la liste est vide, c-a-d le centre est le tenseur nulle
              iaOi++;                           // on n'avance pas
       	  // on regarde de nouveau si le pointeur de centre est valide 
       	  if ((iaOi != save_resul.oc_BH_R.end())) {centre_initial=false;} else {centre_initial=true;};
          // comme on est sur la liste principale, on met à jour les pointeurs de la liste principale
          iaOi_princ=iaOi;
     };

    // 3-- traitement particulier dans le cas où on a rejoint la première charge
    if (aucun_pt_inversion) // cas où l'on est sur la courbe de première charge
     { wBase = 1; unSur_wBaseCarre = 1./(wBase*wBase);
     }
    else
      // on met à jour le centre du cercle de référence, en indiquant que l'on a rattrapé une courbe
     { wBase = 2; unSur_wBaseCarre = 1./(wBase*wBase);
     };
  
    // gestion du paramètre "modif" de saveresult
    bool inversion = false;
    Gestion_para_Saveresult_Modif(pt_sur_principal,save_resul,inversion);
  
//--------débug- traçage
    #ifdef MISE_AU_POINT
    if (Permet_affichage() == -77)
       { cout << "\ngestion de pointeur de coïncidence ";
         cout << " aucun_pt_inversion= " << aucun_pt_inversion
              << " save_resul.nb_coincidence= " << save_resul.nb_coincidence;
         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
               << endl ;
       };
    #endif
//----- fin débug


	};

/*          // **********calcul d'une dérivée numérique-------------
          double peti= 1.E-10;
          double lambda_ver = lambda+peti;
          double un_sur_1_plus_2_G_lambda_ver = 1. / (1. + deux_G*lambda_ver);
          double un_sur_1_plus_2_G_lambda2_ver = 
                    un_sur_1_plus_2_G_lambda_ver * un_sur_1_plus_2_G_lambda_ver;
          double alphaa_ver = un_sur_1_plus_2_G_lambda_ver*deux_G;
          double alphaa2_ver = un_sur_1_plus_2_G_lambda2_ver * deux_G_carre;
          double omega_ver = alphaa_ver*K/(alphaa_ver+2.*K); double omega2_ver = omega_ver*omega_ver; 
          // a moins que lambda soit très grand on  considère qu'omega est positif
          // par contre lambda peut-être négatif
  //        if (lambda >= 0)
          double   delta_eps_equi_ver = 2.*lambda_ver*omega_ver * eps_elasBH(1,1);
 //         delta_eps_equi = 2.*lambda*omega * sqrt(c_c);
          double epsilon_barre_ver = epsilon_barre_t +  // def plastique cumulée
                            delta_eps_equi_ver; 
          // nouvelle valeur de la variation de sigma_barre
          // et valeur de la tangente de la courbe d'écrouissage
          Courbe1D::ValDer valder_ver = f_ecrouissage->Valeur_Et_derivee(epsilon_barre_ver);
          double sig_equi_ver = valder_ver.valeur;
                                      
          // calcul du résidu
          double res_plas_ver = 3.*c_c*omega2_ver - sig_equi_ver * sig_equi_ver * un_tiers;
          double der1 = 3.*c_c*(omega2_ver-omega2)/peti;
          double dereps_barre = (epsilon_barre_ver -epsilon_barre)/peti;
          double der2 = un_tiers*(- sig_equi_ver * sig_equi_ver - - sig_equi * sig_equi)/peti;
          double der = (res_plas_ver - res_plas)/peti;
          double delta_lambda_ver = - res_plas/der ; 
          // **********fin du calcul de la dérivée numérique------- */
          
        // affichage des informations pour le débug
        void Hysteresis3D::Affiche_debug(double& unSur_wBaseCarre
                                         ,SaveResulHysteresis3D & save_resul
                                         ,List_io <Tenseur3BH>::iterator& iatens
                                         ,List_io <double>::iterator& iadef_equi,bool& pt_sur_principal
                                         ,List_io <Tenseur3BH>::iterator& iaOi,bool& oi_sur_principal
                                         ,const List_io <Tenseur3BH>::iterator& iatens_princ
                                         ,const List_io <double>::iterator& iadef_equi_princ
                                         ,const List_io <Tenseur3BH>::iterator& iaOi_princ)
        	{ // affichage de la loi
        	  Affiche();
           // départ
           cout << "\n -- valeurs initiales -- ";
           cout << "\n sigma_barre_BH_t= " << save_resul.sigma_barre_BH_t; // sigma à t 
           cout << "\n def_equi_at= " << save_resul.def_equi_at; // sigma à t 
        	  // variables actuelles
           cout << "\n -- variables actuelles  -- ";
        	  cout << "\n sigma_t_barre_tdt= " << sigma_t_barre_tdt; // sigma barre finale
	  	       cout << "\n sigma_i_barre_BH= " << sigma_i_barre_BH;   // sigma barre de début de calcul (à t au début)      	    
	  	       cout << "\n sigma_barre_BH_R= " << sigma_barre_BH_R;   // sigma barre de Référence  en cours
           cout << "\n def_equi_R= " << def_equi_R; // déformation équivalente à R
	  	       cout << "\n def_i_equi= " << def_i_equi; // dernière déformation équivalente  à t
	  	       cout << "\n defEqui_maxi= " << defEqui_maxi; // déformation équivalente maxi sur la courbe de première charge
	  	       cout << "\n def_equi_atdt= " << def_equi_atdt; // déformation équivalente  à tdt
	  	       cout << "\n delta_sigma_barre_BH_Rat= " << delta_sigma_barre_BH_Rat;  // deltat sigma barre de R a t
	  	       cout << "\n delta_sigma_barre_BH_Ratdt= " << delta_sigma_barre_BH_Ratdt;  // deltat sigma barre de R a tdt
	  	       cout << "\n delta_sigma_barre_tdt_BH= " << delta_sigma_barre_tdt_BH;  // delta sigma barre de t à tdt
	  	      
	  	       cout << "\n delta_sigma_barre_BH_OiaR= " << delta_sigma_barre_BH_OiaR; // delta sigma barre de Oi à R
	  	       cout << "\n Q_OiaR= " << Q_OiaR; // norme de delta_sigma_barre_BH_OiaR
	  	       cout << "\n QdeltaSigmaRatdt= " << QdeltaSigmaRatdt; // norme de rdelta_sigma_barre_BH_Ratdt
	  	       cout << "\n oc_BH_R= " << oc_BH_R;
	  	       cout << "\n unSur_wBaseCarre= " << unSur_wBaseCarre;
	  	      
	  	      
	  	       cout << "\n centre_initial= " << centre_initial; // pour gérer le fait qu'au début le centre initial = tenseur nul
	  	       cout << "\n aucun_pt_inversion= " << aucun_pt_inversion; // pour gérer le fait qu'au début il n'y a pas de pt d'inversion !
	          // variables de liste
           cout << "\n -- variables de liste  -- ";
	          cout << "\n *iatens= " << *iatens;
	          cout << "\n *iadef_equi= " << *iadef_equi;
	          cout << "\n pt_sur_principal= " << pt_sur_principal;
	          cout << "\n *iaOi= " << *iaOi;
	          cout << "\n oi_sur_principal= " << oi_sur_principal;
	          cout << "\n *iatens_princ= " << *iatens_princ;
	          cout << "\n *iadef_equi_princ= " << *iadef_equi_princ;
	          cout << "\n *iaOi_princ= " << *iaOi_princ;
	          // les listes 
           cout << "\n -- les listes  -- ";
	          cout << "\n save_resul.sigma_barre_BH_R_t_a_tdt= " << save_resul.sigma_barre_BH_R_t_a_tdt;
	          cout << "\n save_resul.sigma_barre_BH_R= " << save_resul.sigma_barre_BH_R;
	          cout << "\n save_resul.oc_BH_t_a_tdt= " << save_resul.oc_BH_t_a_tdt;
	          cout << "\n save_resul.oc_BH_R= " << save_resul.oc_BH_R;
	          // on vide le buffer
	          cout << endl;
        	}; 

