// FICHIER : LoiCritere.cp
// CLASSE : LoiCritere


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

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

#include "LoiCritere.h"
#include "LoiContraintesPlanesDouble.h"
#include "LoiContraintesPlanes.h"
#include "Util.h"
#include "CharUtil.h"



//==================== cas de la class de sauvegarde SaveResul ===================

// constructeur  par défaut à ne pas utiliser
LoiCritere::SaveResul_LoiCritere::SaveResul_LoiCritere() :
	liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t(),l_energ(),l_energ_t(),f_ponder(),f_ponder_t()
 ,V_P_sig(NULL),V_P_sig_t(NULL),save_result_1DCP2(NULL)
 ,eps_pli(),eps_pli_t(),niveau_declenchement_critere(-ConstMath::petit)
 ,le_type_critere(AUCUN_CRITERE)
 ,cas_cal_plis(0),cas_cal_plis_t(0)
 ,map_type_quelconque()
  { cout << "\n erreur, le constructeur par defaut ne doit pas etre utilise !"
	        << "\n LoiCritere::SaveResul_LoiCritere::SaveResul_LoiCritere()";
	   cout << "\n LoiCritere::SaveResul_LoiCritere::SaveResul_LoiCritere()";
    Sortie(1);
   }; 

// le constructeur courant
LoiCritere::SaveResul_LoiCritere::SaveResul_LoiCritere
                        (list <SaveResul*>& l_des_SaveResul,list <TenseurHH* >& l_siHH
	                        ,list <TenseurHH* >& l_siHH_t
	                        ,list <EnergieMeca >& l_energ_,list <EnergieMeca >& l_energ_t_
								                 ,bool avec_ponderation,Enum_Critere_Loi type_crite):
	       liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t(),l_energ(l_energ_),l_energ_t(l_energ_t_)
	       ,f_ponder(),f_ponder_t(),V_P_sig(NULL),V_P_sig_t(NULL),save_result_1DCP2(NULL)
        ,eps_pli(),eps_pli_t(),niveau_declenchement_critere(-ConstMath::petit)
        ,le_type_critere(type_crite)
        ,cas_cal_plis(0),cas_cal_plis_t(0)
        ,map_type_quelconque()

	 { list <SaveResul *>::const_iterator ili,ilifin=l_des_SaveResul.end();
	   list <TenseurHH* >::const_iterator isig,isig_t;
    for (ili=l_des_SaveResul.begin(),isig = l_siHH.begin(),isig_t = l_siHH_t.begin();
            ili!=ilifin;ili++,isig++,isig_t++)
         { SaveResul * nevez_save_result=NULL;
           if ((*ili) != NULL) nevez_save_result = (*ili)->Nevez_SaveResul();
           liste_des_SaveResul.push_back(nevez_save_result);
           TenseurHH * interHH=NULL;
           // dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*isig) != NULL) {interHH=NevezTenseurHH(*(*isig));};
           l_sigoHH.push_back(interHH);
           TenseurHH * interHH_t=NULL;
           // idem interHH, dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*isig_t) != NULL) {interHH_t =NevezTenseurHH(*(*isig_t));};
           l_sigoHH_t.push_back(interHH_t);
			        if (avec_ponderation) // on fait de la place
			           {f_ponder.push_back(1.);f_ponder_t.push_back(1.);};  
         };
  };

// constructeur de copie 
LoiCritere::SaveResul_LoiCritere::SaveResul_LoiCritere
                                         (const LoiCritere::SaveResul_LoiCritere& sav ):
	       liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t()
	       ,l_energ(sav.l_energ),l_energ_t(sav.l_energ_t)
	       ,f_ponder(sav.f_ponder),f_ponder_t(sav.f_ponder_t),V_P_sig(NULL),V_P_sig_t(NULL)
        ,save_result_1DCP2(NULL)
        ,eps_pli(sav.eps_pli),eps_pli_t(sav.eps_pli_t)
        ,niveau_declenchement_critere(sav.niveau_declenchement_critere)
        ,le_type_critere(sav.le_type_critere)
        ,cas_cal_plis(sav.cas_cal_plis),cas_cal_plis_t(sav.cas_cal_plis_t)
        ,map_type_quelconque(sav.map_type_quelconque)
	 { list <SaveResul *>::const_iterator ili,ilifin=sav.liste_des_SaveResul.end();
	   list <TenseurHH* >::const_iterator isig,isig_t;
    for (ili=sav.liste_des_SaveResul.begin(),isig = sav.l_sigoHH.begin(),isig_t = sav.l_sigoHH_t.begin();
            ili!=ilifin;ili++,isig++,isig_t++)
         { SaveResul * nevez_save_result = NULL;
           if ((*ili) != NULL) nevez_save_result = (*ili)->Nevez_SaveResul();
           liste_des_SaveResul.push_back(nevez_save_result);
           TenseurHH * interHH=NULL;
           // dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*isig) != NULL) {interHH=NevezTenseurHH(*(*isig));};
           l_sigoHH.push_back(interHH);
           TenseurHH * interHH_t=NULL;
           // idem interHH, dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*isig_t) != NULL) {interHH_t =NevezTenseurHH(*(*isig_t));};
           l_sigoHH_t.push_back(interHH_t);
         };
    // les vecteurs propres éventuelles
    if (sav.V_P_sig != NULL)
      V_P_sig = new Tableau < Coordonnee >(*(sav.V_P_sig));
    if (sav.V_P_sig_t != NULL)
      V_P_sig_t = new Tableau < Coordonnee >(*(sav.V_P_sig_t));
    // le pointeur de travail pour les plis
    if (sav.save_result_1DCP2 != NULL)
      { SaveResul * inter = sav.save_result_1DCP2->Nevez_SaveResul();
        save_result_1DCP2 = ((LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble*) inter);
      };
  };
	        // destructeur
LoiCritere::SaveResul_LoiCritere::~SaveResul_LoiCritere()
	 { list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	   list <TenseurHH* >::iterator isig,isig_t;
    for (ili=liste_des_SaveResul.begin(),isig = l_sigoHH.begin(),isig_t = l_sigoHH_t.begin();
         ili!=ilifin;ili++,isig++,isig_t++)
         {if ((*ili) != NULL) delete (*ili); //liste_des_SaveResul.erase(ili); 
          if((*isig) != NULL) delete (*isig); if((*isig_t) != NULL) delete (*isig_t);
         };
    // car des vecteurs propres de contrainte
    if (V_P_sig != NULL) delete V_P_sig;
    if (V_P_sig_t != NULL) delete V_P_sig_t;
    if (save_result_1DCP2 != NULL) delete save_result_1DCP2;
  }; 
  
// affectation
Loi_comp_abstraite::SaveResul &
     LoiCritere::SaveResul_LoiCritere::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { LoiCritere::SaveResul_LoiCritere& sav = *((LoiCritere::SaveResul_LoiCritere*) &a);

    // on regarde si les listes sont de même tailles, si oui on considère qu'elle sont des conteneurs identiques
    // sinon on les crée
    list <SaveResul *>::const_iterator ili,ilifin=sav.liste_des_SaveResul.end();
	   list <TenseurHH* >::const_iterator isig = sav.l_sigoHH.begin();
    list <TenseurHH* >::const_iterator isig_t = sav.l_sigoHH_t.begin();
    if (liste_des_SaveResul.size() != sav.liste_des_SaveResul.size())
     
     {// 1) on vide la liste: tout d'abord les grandeurs pointées sont supprimées
      list <SaveResul *>::iterator jli,jlifin=liste_des_SaveResul.end();
	     list <TenseurHH* >::iterator jsig  = l_sigoHH.begin();
      list <TenseurHH* >::iterator jsig_t = l_sigoHH_t.begin();
      for (jli=liste_des_SaveResul.begin();jli!=jlifin;jli++,jsig++,jsig_t++)
         {if ((*jli) != NULL) delete (*jli); //liste_des_SaveResul.erase(ili);
          if((*jsig) != NULL) delete (*jsig); if((*jsig_t) != NULL) delete (*jsig_t);
         };
      // on vide les listes
      liste_des_SaveResul.clear();l_sigoHH.clear();l_sigoHH_t.clear();
      
      // 2) on recrée à la bonne taille
      for (ili=sav.liste_des_SaveResul.begin(),isig = sav.l_sigoHH.begin(),isig_t = sav.l_sigoHH_t.begin();
            ili!=ilifin;ili++,isig++,isig_t++)
         { SaveResul * nevez_save_result = NULL;
           if ((*ili) != NULL) nevez_save_result = (*ili)->Nevez_SaveResul();
           liste_des_SaveResul.push_back(nevez_save_result);
           TenseurHH * interHH=NULL;
           // dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*isig) != NULL) {interHH=NevezTenseurHH(*(*isig));};
           l_sigoHH.push_back(interHH);
           TenseurHH * interHH_t=NULL;
           // idem interHH, dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*isig_t) != NULL) {interHH_t =NevezTenseurHH(*(*isig_t));};
           l_sigoHH_t.push_back(interHH_t);
         };
     }
    else // sinon on affecte les conteneurs
      {
        list <SaveResul *>::iterator jli=liste_des_SaveResul.begin();
	       list <TenseurHH* >::iterator jsig=l_sigoHH.begin();
	       list <TenseurHH* >::iterator jsig_t=l_sigoHH_t.begin();
        for (ili=sav.liste_des_SaveResul.begin(),isig = sav.l_sigoHH.begin(),isig_t = sav.l_sigoHH_t.begin();
            ili!=ilifin;ili++,isig++,isig_t++,jli++,jsig++,jsig_t++)
            { (*(*jli))=(*(*ili)); (*(*jsig))=(*(*isig));(*(*jsig_t))=(*(*isig_t));};
      };
    // les vecteurs propres éventuelles
    if (sav.V_P_sig != NULL)
     { if (V_P_sig == NULL)
            { V_P_sig = new Tableau < Coordonnee >(*(sav.V_P_sig));}
       else {*V_P_sig = *(sav.V_P_sig);};
     }
    else // les vecteurs sont nulles donc on supprime
     { if (V_P_sig != NULL)
         {delete V_P_sig; V_P_sig=NULL;};
     };

    if (sav.V_P_sig_t != NULL)
     { if (V_P_sig_t == NULL)
            { V_P_sig_t = new Tableau < Coordonnee >(*(sav.V_P_sig_t));}
       else {*V_P_sig_t = *(sav.V_P_sig_t);};
     }
    else // les vecteurs sont nulles donc on supprime
     {if (V_P_sig_t != NULL)
        {delete V_P_sig_t; V_P_sig_t=NULL;};
     };
   
    // le pointeur de travail pour les plis
    if (sav.save_result_1DCP2 != NULL)
     {if (save_result_1DCP2 == NULL)
       { SaveResul * inter = sav.save_result_1DCP2->Nevez_SaveResul();
         save_result_1DCP2 = ((LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble*) inter);
       }
      else // sinon on peut affecter directement
       { *save_result_1DCP2 = *((Loi_comp_abstraite::SaveResul *) sav.save_result_1DCP2);
       };
     }
    else
     { if (save_result_1DCP2 != NULL)
         {delete save_result_1DCP2;save_result_1DCP2=NULL;};
     };
    // // pour les autres conteneurs internes, affectation directe, car a priori pas de pb
    l_energ = sav.l_energ;
    l_energ_t = sav.l_energ_t;
    f_ponder = sav.f_ponder;
    eps_pli = sav.eps_pli;
    eps_pli_t = sav.eps_pli_t;
    // le niveau de déclenchement
    niveau_declenchement_critere = sav.niveau_declenchement_critere;
    le_type_critere = sav.le_type_critere;
    cas_cal_plis = sav.cas_cal_plis;
    cas_cal_plis_t = sav.cas_cal_plis_t;
    map_type_quelconque = sav.map_type_quelconque;
    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 LoiCritere::SaveResul_LoiCritere::Lecture_base_info
                                                 (ifstream& ent,const int cas)
  {  // ici toutes les données sont toujours a priori variables
     // ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
     string toto; ent >> toto;
     #ifdef MISE_AU_POINT	 	 
      if (toto != "S_R_LoiCrit")
          { cout << "\n erreur en lecture du conteneur pour la loi critere"
                 << " \n LoiCritere::SaveResul_LoiCritere::Lecture_base_info(..";
            Sortie(1);     
          }
     #endif
     // niveau du critère
     ent >> toto >>   niveau_declenchement_critere;
     ent >> toto >> le_type_critere;
     // indicateur concernant le calcul des directions de plis
     ent >> toto >> cas_cal_plis_t;
     cas_cal_plis = cas_cal_plis_t;
     // on regarde s'il s'agit d'une lecture avec fonction de pondération ou non
     bool avec_ponderation=false;
     ent >> toto >> avec_ponderation;
     // lecture du nombre de loi
     int nb_loi; ent >> toto >> nb_loi;
     // Dans le cas où le nombre de loi n'est pas identique au cas actuel 
     // cela signifie que l'instance est mal déclaré -> pb on arrête
     // sinon on lit uniquement
     #ifdef MISE_AU_POINT	 	 
      if (nb_loi != liste_des_SaveResul.size())
       { cout << "\n erreur en lecture du conteneur pour la loi critere, cas des infos specifiques a chaque loi"
              << "\n le nombre de loi definit est different de celui lu donc il y a un pb d'initialisation"
              << " \n LoiCritere::SaveResul_LoiCritere::Lecture_base_info(..";
         Sortie(1);
       };
     #endif
     // on vérifie que la taille de f_ponder_t est correcte, sinon on redimentionne
     if (avec_ponderation)
      {if (f_ponder_t.size() != nb_loi)
		     {// on efface les listes
        list <double>::iterator ieefin=f_ponder.end();
        list <double>::iterator ieedeb=f_ponder.begin();
        f_ponder.erase(ieedeb,ieefin);
	       f_ponder.insert(ieedeb,nb_loi,1.);
        ieefin=f_ponder_t.end();
        ieedeb=f_ponder_t.begin();
        f_ponder_t.erase(ieedeb,ieefin);
		      // on les définit la place
		      f_ponder_t.insert(ieedeb,nb_loi,1.);
       };
		    };
     
     // on itère sur ces grandeurs
     list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
     list <TenseurHH* >::iterator isig_t;
     list <EnergieMeca >::iterator ienerg_t=l_energ_t.begin();
     string nom_num_loi;int num_loi;
     list <double>::iterator ifo;
     if (avec_ponderation) ifo = f_ponder_t.begin(); 
     for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin();
          ili!=ilifin;ili++,isig_t++,ienerg_t++)
       { ent >> nom_num_loi>>num_loi;
		       if (avec_ponderation)
			       { ent >> (*ifo); ifo++;};
         // données de chaque loi
         if((*ili) != NULL) (*ili)->Lecture_base_info(ent,cas);
         // lecture de la contrainte sauvegardée 
         (*isig_t)->Lecture(ent); // lecture du tenseur
         // lecture des énergies
         ent >> (*ienerg_t);
       };
     // cas des directions des vecteurs propres
     int test;
     ent >> toto >> test;
     if (test)
      { // cas de l'existence de vecteurs propres
        if (V_P_sig_t == NULL) V_P_sig_t = new Tableau <Coordonnee>;
        if (V_P_sig == NULL) V_P_sig = new Tableau <Coordonnee>;
        ent >> (*V_P_sig_t); (*V_P_sig)=(*V_P_sig_t);
      }
     else
      { // cas où il n'y a pas de vecteurs propres en sauvegarde
        if (V_P_sig_t != NULL)
           {delete V_P_sig_t; V_P_sig_t=NULL;};
        if (V_P_sig != NULL)
           { delete V_P_sig; V_P_sig=NULL;};
      };
     // cas des plis
     ent >> toto >>  eps_pli_t; eps_pli=eps_pli_t;

  };

// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LoiCritere::SaveResul_LoiCritere::Ecriture_base_info
                                                 (ofstream& sort,const int cas)
   { // ici toutes les données sont toujours a priori variables
     // ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
     sort << "\n S_R_LoiCrit  ";
     // niveau du critère
     sort << "\n niv_declenche_= " <<  niveau_declenchement_critere ;
     sort << "\n type_de_critere= " << le_type_critere;
     // indicateur concernant le calcul des directions de plis
     sort << " cas_cal_plis= "<< cas_cal_plis_t ;
     // pondération ?
	    bool avec_ponderation = (f_ponder_t.size() != 0);
	    sort << " Pond= "<< avec_ponderation << " ";
     // on sort  le nombre de grandeur à sauvegarde
     sort << "nbS= "<< liste_des_SaveResul.size();
     // on itère sur ces grandeurs
	    list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	    list <TenseurHH* >::iterator isig_t; int nb_loi=1;
	    list <EnergieMeca >::iterator ienerg_t=l_energ_t.begin();
     list <double>::iterator ifo;
	    if (avec_ponderation) ifo=f_ponder_t.begin();
     for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin();ili!=ilifin;
                 ili++,isig_t++,nb_loi++,ienerg_t++)
       { // données de chaque loi
         sort << "\n --loi_nb " << nb_loi << " ";
			      // les pondérations éventuelles
			      if (avec_ponderation)
			       { sort << " " << (*ifo) << " ";
			         ifo++;
          };

         if ((*ili) != NULL) (*ili)->Ecriture_base_info(sort,cas);sort << "  ";
         // la contrainte sauvegardée est celle stable uniquement
         (*isig_t)->Ecriture(sort); // écriture du tenseur
         sort << " " << (*ienerg_t); 			 
       };
     // cas des directions des vecteurs propres
     if (V_P_sig_t == NULL)
       {sort << " V_P_sig= 0 ";}
     else
       {sort << " V_P_sig= 1 "<< (*V_P_sig_t)<<" ";};
     // cas des plis
     sort << "\n eps_pli= " << eps_pli_t;
	  };
	        
	        // mise à jour des informations transitoires en définitif s'il y a convergence 
	        // par exemple (pour la plasticité par exemple)
void LoiCritere::SaveResul_LoiCritere::TdtversT()
  {list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	  list <TenseurHH* >::iterator isig_t,isig;
	  list <EnergieMeca >::iterator ienerg,ienerg_t;
	  bool avec_ponderation = (f_ponder_t.size() != 0);
	  list <double>::iterator ifo,ifo_t;
	  if (avec_ponderation) {ifo=f_ponder.begin();ifo_t=f_ponder_t.begin();};
   for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin(),isig = l_sigoHH.begin()
          ,ienerg=l_energ.begin(),ienerg_t=l_energ_t.begin();
          ili!=ilifin;ili++,isig_t++,isig++,ienerg++,ienerg_t++)
     {// dans le cas d'un critère plis, on a utiliser un conteneur intermédiaire:
// il faut mettre à jour le conteneur 3D à minima avec les résultats du calcul 1D
// *** pour l'instant il n'y a rien de fait donc cela signifie, que le save_result de la loi 3D
// correspond à celui du comportement sans plis.
// ça c'est ok s'il n'y a finalement pas de plis, mais pas du tout ok, s'il y a des plis
// avec une loi incrémental de type hystérésis, c'est catastrophique !!
//$$$$$$$$$$$$$$$$ il faut changer $$$$$$$$$$$$$$$$$$
     
     
      if ((*ili) != NULL) (*ili)->TdtversT();
      (*(*isig_t)) = (*(*isig));
      (*ienerg_t)=(*ienerg);
			   if (avec_ponderation)
			     {(*ifo_t) = (*ifo);
			      ifo++; ifo_t++;
				    }; 
     }; 
   // cas des directions des vecteurs propres
   if (V_P_sig != NULL)
    { // cas de l'existence de vecteurs propres
      if (V_P_sig_t == NULL) V_P_sig_t = new Tableau <Coordonnee>;
      (*V_P_sig_t)=(*V_P_sig);
    }
   else
    { // cas où il n'y a pas de vecteurs propres en sauvegarde
      if (V_P_sig_t != NULL) {delete V_P_sig_t; V_P_sig_t=NULL;};
    };
   // cas des plis
   eps_pli_t = eps_pli;
   cas_cal_plis_t = cas_cal_plis;
   // mise à jour de la liste des grandeurs quelconques internes
   Mise_a_jour_map_type_quelconque();

	 };

void LoiCritere::SaveResul_LoiCritere::TversTdt()
  {list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	  list <TenseurHH* >::iterator isig_t,isig;
	  list <EnergieMeca >::iterator ienerg,ienerg_t;
	  bool avec_ponderation = (f_ponder_t.size() != 0);
	  list <double>::iterator ifo,ifo_t;
	  if (avec_ponderation) {ifo=f_ponder.begin();ifo_t=f_ponder_t.begin();};
   for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin(),isig = l_sigoHH.begin()
          ,ienerg=l_energ.begin(),ienerg_t=l_energ_t.begin();
          ili!=ilifin;ili++,isig_t++,isig++,ienerg++,ienerg_t++)
     { if ((*ili) != NULL) (*ili)->TversTdt();
       (*(*isig)) = (*(*isig_t));
       (*ienerg)=(*ienerg_t);
			    if (avec_ponderation)
			      {(*ifo) = (*ifo_t);
			       ifo++; ifo_t++;
         }; 
     }; 
   // cas des directions des vecteurs propres
   if (V_P_sig_t != NULL)
    { // cas de l'existence de vecteurs propres
      if (V_P_sig == NULL) V_P_sig = new Tableau <Coordonnee>;
      (*V_P_sig)=(*V_P_sig_t);
    }
   else
    { // cas où il n'y a pas de vecteurs propres en sauvegarde
      if (V_P_sig != NULL) {delete V_P_sig; V_P_sig=NULL;};
    };
   // cas des plis
   eps_pli = eps_pli_t;
   cas_cal_plis = cas_cal_plis_t;
   // mise à jour de la liste des grandeurs quelconques internes
   Mise_a_jour_map_type_quelconque();
	 };
			  
// affichage à l'écran des infos
void LoiCritere::SaveResul_LoiCritere::Affiche() const
{ cout << "\n SaveResul_LoiCritere: " ;
  list <SaveResul *>::const_iterator ili,ilifin=liste_des_SaveResul.end();
  list <TenseurHH* >::const_iterator isig,isigfin=l_sigoHH.end();
  list <TenseurHH* >::const_iterator isig_t,isig_tfin=l_sigoHH_t.end();
  list <EnergieMeca >::const_iterator ienerg,ienergfin = l_energ.end();
  list <EnergieMeca >::const_iterator ienerg_t,ienerg_tfin = l_energ_t.end();
  list <double>::const_iterator i_ponder, i_ponderfin = f_ponder.end();
  list <double>::const_iterator i_ponder_t,i_ponder_tfin = f_ponder_t.end();
  cout << "\n -- partie relative aux lois internes: ";
  cout << "\n liste_des_SaveResul: ";
  int i=1;
  for (ili=liste_des_SaveResul.begin();ili!=ilifin;ili++,i++)
         {cout << "\n  loi nb: " << i <<" ";
          if ((*ili) != NULL) { (*ili)->Affiche();};
         };
  cout << "\n -- partie specifique loi critere: ";
  cout << "\n l_sigoHH: ";
  for (isig = l_sigoHH.begin();isig!=isigfin;isig++)
         { (*isig)->Ecriture(cout);};
  cout << "\n l_sigoHH_t: ";
  for (isig_t = l_sigoHH_t.begin();isig_t!=isig_tfin;isig_t++)
         { (*isig_t)->Ecriture(cout);};
  cout << "\n l_energ: ";
  for (ienerg = l_energ.begin();ienerg!=ienergfin;ienerg++)
         { cout << (*ienerg);};
  cout << "\n l_energ_t: ";
  for (ienerg_t = l_energ_t.begin();ienerg_t!=ienerg_tfin;ienerg_t++)
         { cout << (*ienerg_t);};
  cout << "\n f_ponder: ";
  for (i_ponder = f_ponder.begin();i_ponder!=i_ponderfin;i_ponder++)
         { cout << " " << (*i_ponder);};
  cout << "\n f_ponder_t: ";
  for (i_ponder_t = f_ponder_t.begin();i_ponder_t!=i_ponder_tfin;i_ponder_t++)
         { cout << " " << (*i_ponder_t);};
  // cas d'existence et sauvegarde de vecteurs propres de contrainte
  if (V_P_sig != NULL)
    cout << "\n V_P_sig= " << (*V_P_sig)<<" ";
  // cas du pointeur 1D de plis
  if (save_result_1DCP2 != NULL)
   {cout << "\n conteneur1D_pour plis: ";
    save_result_1DCP2->Affiche();
   };
  // cas des plis
  cout << "\n eps_pli= " << eps_pli_t;
  // déclenchement du critère
  cout << "\n niveau_declenchement_critere= "<<niveau_declenchement_critere;
  cout << "\n le type de critere= " <<le_type_critere;
  // dernier type de calcul des directions de plis
  cout << "\n type enregistre de calcul de direction de plis: cas_cal_plis_t= "
       << cas_cal_plis_t << ", cas_cal_plis= "<<cas_cal_plis;
  cout << "\n .. fin SaveResul_LoiCritere:.. \n" ;
};

//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 LoiCritere::SaveResul_LoiCritere::ChBase_des_grandeurs(const Mat_pleine& beta,const Mat_pleine& gamma)
{ // on ne s'intéresse qu'aux grandeurs tensorielles
  // encapsulage pour utiliser deux fois les mêmes itérators
  { List_io <SaveResul*>::iterator lit(liste_des_SaveResul.begin()),
                                   lend(liste_des_SaveResul.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
      if ((*lit) != NULL) // s'il y a un conteneur non nul
       (*lit)->ChBase_des_grandeurs(beta,gamma);
  };
  { List_io <TenseurHH*>::iterator lit(l_sigoHH.begin()),
                                   lend(l_sigoHH.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit)->ChBase(gamma);
  };
  { List_io <TenseurHH*>::iterator lit(l_sigoHH_t.begin()),
                                   lend(l_sigoHH_t.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit)->ChBase(gamma);
  };
  // les vecteurs donnant les directions principales sont exprimés dans la base orthonormee
  // ils ne sont pas concernés par cette méthode !
};

// procedure permettant de completer éventuellement les données particulières
// de la loi stockées
// au niveau du point d'intégration par exemple: exemple: un repère d'anisotropie
// completer est appelé apres sa creation avec les donnees du bloc transmis
// peut etre appeler plusieurs fois
Loi_comp_abstraite::SaveResul* LoiCritere::SaveResul_LoiCritere
         ::Complete_SaveResul(const BlocGen & bloc, const Tableau <Coordonnee>& tab_coor
                             ,const Loi_comp_abstraite* loi)
  {// on transmet au conteneur 3D interne
   const LoiCritere * loi_CP = (const LoiCritere*) loi;
   // récup de la liste de loi
   list <Loi_comp_abstraite *>::const_iterator ili,ilifin=loi_CP->lois_internes.end();
   // récup des infos pour chaque loi
   list <SaveResul*>::iterator ia=liste_des_SaveResul.begin();
   for (ili = loi_CP->lois_internes.begin(); ili != ilifin; ili++,ia++)
     {// on intervient que si le conteneur n'est pas vide
      if ((*ia)!= NULL)
        (*ia)->Complete_SaveResul(bloc,tab_coor,(*ili));
     };
   return this;
  };
	        // ---- récupération d'information: spécifique à certaine classe dérivée
double LoiCritere::SaveResul_LoiCritere::Deformation_plastique()
   { cout << "\n pour l'instant cette option n'est pas implante dans le cas d'une loi"
          << "\n additive en contrainte"
          << "\n double Loi_comp_abstraite::SaveResul_LoiCritere::Deformation_plastique()";
     Sortie(1);
     return 0.; // pour taire le warning, mais on ne passe jamais là
   };

// mise à jour de la liste des grandeurs quelconques internes
void LoiCritere::SaveResul_LoiCritere::Mise_a_jour_map_type_quelconque()
 { map <  EnumTypeQuelconque , TypeQuelconque, std::less < EnumTypeQuelconque> >::iterator il
      ,ilfin=map_type_quelconque.end();
   int dim_espace = ParaGlob::Dimension();
   for (il=map_type_quelconque.begin();il != ilfin;il++)
     {EnumTypeQuelconque enu = (*il).first;
       switch (enu)
        {// -----cas de la direction de pli éventuelle
         case DIRECTION_PLI:
          { Tab_Grandeur_Coordonnee& gr= *((Tab_Grandeur_Coordonnee*) map_type_quelconque[DIRECTION_PLI].Grandeur_pointee()); // pour simplifier
            switch (le_type_critere)
              {  case PLISSEMENT_MEMBRANE:
                   {// tout d'abord on regarde s'il y des vecteurs propres
                     if (((cas_cal_plis == 2)|| (cas_cal_plis == 3))
                        && (V_P_sig != NULL))
                     // cas où il y a des vecteurs propres, la direction des plis est le premier vecteur, + éventuellement
                     // le deuxième s'il y a deux plis
                     { gr(1) = eps_pli(1) * (*V_P_sig)(1);
                       gr(2) = eps_pli(2) * (*V_P_sig)(2);
                     }
                    else // sinon cela veut dire qu'il n'y a pas de pli, on sort un vecteur nul
                     {Coordonnee coor(dim_espace); // un type coordonnee typique
                      gr(1) = coor; gr(2) = coor;
                     };
                    break;
                   }
                 case PLISSEMENT_BIEL:
                  {// tout d'abord on regarde s'il y des vecteurs propres
                   if (V_P_sig != NULL)
                    // cas où il y a des vecteurs propres, la direction des plis est le premier vecteur, + éventuellement
                    // le deuxième s'il y a deux plis
                    {gr(1) = eps_pli(1) * (*V_P_sig)(1);
                     Coordonnee coor(dim_espace);
                     gr(2) = coor;
                    }
                   else // sinon cela veut dire qu'il n'y a pas de pli, on sort un vecteur nul
                    {Coordonnee coor(dim_espace); // un type coordonnee typique
                     gr(1) = coor; gr(2) = coor;
                    };
                   break;
                  }
                 default :
                   cout << "\nErreur : valeur non prise en compte du type de critere defini= " << le_type_critere
                        << "  !\n";
                   cout << "\n LoiCritere::SaveResul_LoiCritere::Mise_a_jour_map_type_quelconque(...";
                   Sortie(1);
               };
             break;
          }
         case INDIC_CAL_PLIS:
          { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) map_type_quelconque[DIRECTION_PLI].Grandeur_pointee()); // pour simplifier
            switch (le_type_critere)
              {  case PLISSEMENT_MEMBRANE: case PLISSEMENT_BIEL: // pour les biels on ne sait pas encore !!
                  {*(gr.ConteneurEntier()) = cas_cal_plis;
                   break;
                  }
                 default :
                   cout << "\nErreur : valeur non prise en compte du type de critere defini= " << le_type_critere
                        << "  !\n";
                   cout << "\n LoiCritere::SaveResul_LoiCritere::Mise_a_jour_map_type_quelconque(...";
                   Sortie(1);
              };
            break;
           }
         default:; // on ne fait rien sinon
        };
      };
 };


//==================== fin du cas de la class de sauvegarde SaveResul ============

LoiCritere::LoiCritere ()  : // Constructeur par defaut
  Loi_comp_abstraite(LOI_CRITERE,RIEN_CATEGORIE_LOI_COMP,0)
  ,type_critere(AUCUN_CRITERE),lois_internes()
  ,list_completude_calcul(),d_sigma_deps_inter(NULL),d_sig_deps_3D_HHHH()
  ,avec_ponderation(false),list_ponderation(),fonc_ponder(),type_calcul(1)
  ,d_sigtotalHH()
  ,ordre_criteres()
  // -- pour PLISSEMENT_MEMBRANE
  ,loi_2DCP_de_3D(NULL),loi_1DCP2_de_3D(NULL),niveau_declenchement_critere(-ConstMath::petit)
  ,avecNiveauSigmaI_mini_pour_plis(false)
  ,niveauF_fct_nD(NULL),niveauF_grandeurConsultable(NULL)
  ,niveauF_ddlEtendu(NULL),niveauF_temps(NULL)
  ,choix_calcul_epaisseur_si_relachement_complet(1),recalcul_dir_plis(NULL)
  // -- pour RUPTURE_SIGMA_PRINC et RUPTURE_EPS_PRINC
  ,loi_2DCP_pour_rupture(NULL),loi_1DCP2_pour_rupture(NULL)
  // -- grandeurs de travail
  // un conteneur d'un point d'intégration courant
  ,ptintmeca(3)
  // métriques
  ,giB_0_1D(3,1),giH_0_1D(3,1),giB_t_1D(3,1),giH_t_1D(3,1),giB_tdt_1D(3,1),giH_tdt_1D(3,1)
  ,gijBB_0_1D(),gijHH_0_1D(),gijBB_t_1D(),gijHH_t_1D(),gijBB_tdt_1D(),gijHH_tdt_1D()
  ,gradVmoyBB_t_1D_P(NULL),gradVmoyBB_t_1D()
  ,gradVmoyBB_tdt_1D_P(NULL),gradVmoyBB_tdt_1D()
  ,gradVBB_tdt_1D_P(NULL),gradVBB_tdt_1D()
  ,jacobien_tdt_1D(0.),jacobien_t_1D(0.),jacobien_0_1D(0.),d_jacobien_tdt_1D()
  ,d_giB_tdt_1D(),d_giH_tdt_1D(),d_gijBB_tdt_1D_P(NULL),d_gijBB_tdt_1D()
  ,d2_gijBB_tdt_1D_P(NULL),d2_gijBB_tdt_1D()
  ,d_gijHH_tdt_1D_P(NULL),d_gijHH_tdt_1D()
  ,d_gradVmoyBB_t_1D_P(NULL),d_gradVmoyBB_t_1D()
  ,d_gradVmoyBB_tdt_1D_P(NULL),d_gradVmoyBB_tdt_1D()
  ,d_gradVBB_t_1D_P(NULL),d_gradVBB_t_1D()
  ,d_gradVBB_tdt_1D_P(NULL),d_gradVBB_tdt_1D()
		,sig_HH_t_1D(),sig_HH_1D(),Deps_BB_1D(),eps_BB_1D(),delta_eps_BB_1D()
  ,d_eps_BB_1D_P(),d_eps_BB_1D(),d_sig_HH_1D_P(NULL),d_sig_HH_1D()
  ,d_sigma_deps_1D_P(NULL),d_sigma_deps_1D()
  ,eps_BB_2D_t(),delta_eps_BB_2D(),eps_HH_2D_t()
  ,ViB(ParaGlob::Dimension(),ParaGlob::Dimension()),ViH(ParaGlob::Dimension(),ParaGlob::Dimension())
  // puis les grandeurs hors métriques
  ,sig_HH_t_3D(),sig_HH_3D(),Deps_BB_3D(),eps_BB_3D(),delta_eps_BB_3D()

  // paramètres
  ,choix_methode_cal_plis_memb(1)
    { // conteneurs des métriques
	     // a priori seules les grandeurs principales sont affecté
	     expli_1D = new Met_abstraite::Expli_t_tdt  // constructeur normal
                          (&giB_0_1D,&giH_0_1D,&giB_t_1D,&giH_t_1D,&giB_tdt_1D,&giH_tdt_1D
                          ,&gijBB_0_1D,&gijHH_0_1D,&gijBB_t_1D,&gijHH_t_1D
                          ,&gijBB_tdt_1D,&gijHH_tdt_1D
                          ,gradVmoyBB_t_1D_P,gradVmoyBB_tdt_1D_P,gradVBB_tdt_1D_P // pas affecté par défaut
                          ,&d_gijBB_tdt_1D_P,&jacobien_tdt_1D,&jacobien_t_1D,&jacobien_0_1D);
      impli_1D = new  Met_abstraite::Impli  // constructeur normal
                       (&giB_0_1D,&giH_0_1D,&giB_t_1D,&giH_t_1D,&giB_tdt_1D,&d_giB_tdt_1D,&giH_tdt_1D,&d_giH_tdt_1D
                        ,&gijBB_0_1D,&gijHH_0_1D,&gijBB_t_1D,&gijHH_t_1D,&gijBB_tdt_1D,&gijHH_tdt_1D
                        ,gradVmoyBB_t_1D_P,gradVmoyBB_tdt_1D_P,gradVBB_tdt_1D_P // pas affecté par défaut
                        ,&d_gijBB_tdt_1D_P
								                ,d2_gijBB_tdt_1D_P // pas affecté par défaut
								                ,&d_gijHH_tdt_1D_P
                        ,&jacobien_tdt_1D,&jacobien_t_1D,&jacobien_0_1D,&d_jacobien_tdt_1D
                        ,d_gradVmoyBB_t_1D_P,d_gradVmoyBB_tdt_1D_P     // pas affecté par défaut
		  	               ,d_gradVBB_t_1D_P,d_gradVBB_tdt_1D_P);	        // pas affecté par défaut
	     umat_cont_1D = new Met_abstraite::Umat_cont  // constructeur normal
                          (&giB_0_1D,&giH_0_1D,&giB_t_1D,&giH_t_1D,&giB_tdt_1D,&giH_tdt_1D
                          ,&gijBB_0_1D,&gijHH_0_1D,&gijBB_t_1D,&gijHH_t_1D
                          ,&gijBB_tdt_1D,&gijHH_tdt_1D
                          ,gradVmoyBB_t_1D_P,gradVmoyBB_tdt_1D_P,gradVBB_tdt_1D_P      // pas affecté par défaut
                          ,&jacobien_tdt_1D,&jacobien_t_1D,&jacobien_0_1D);
		    // on ajoute les invariants au pt integ courant
		    ptintmeca.Change_statut_Invariants_contrainte (true);
      d_sigma_deps_1D_P = & d_sigma_deps_1D;
	   };

// Constructeur de copie
LoiCritere::LoiCritere (const LoiCritere& loi) :
  Loi_comp_abstraite(loi),lois_internes()
  ,type_critere(loi.type_critere),list_completude_calcul(),d_sigma_deps_inter(NULL)
  ,d_sig_deps_3D_HHHH(loi.d_sig_deps_3D_HHHH)
  ,avec_ponderation(loi.avec_ponderation),list_ponderation(loi.list_ponderation)
	 ,fonc_ponder(loi.fonc_ponder),type_calcul(loi.type_calcul),d_sigtotalHH()
  ,ordre_criteres(loi.ordre_criteres)
  // -- pour PLISSEMENT_MEMBRANE
  ,loi_2DCP_de_3D(NULL),loi_1DCP2_de_3D(NULL)
  ,niveau_declenchement_critere(loi.niveau_declenchement_critere)
  ,avecNiveauSigmaI_mini_pour_plis(loi.avecNiveauSigmaI_mini_pour_plis)
  ,niveauF_fct_nD(NULL),niveauF_grandeurConsultable(NULL)
  ,niveauF_ddlEtendu(NULL),niveauF_temps(loi.niveauF_temps)
  ,choix_calcul_epaisseur_si_relachement_complet(loi.choix_calcul_epaisseur_si_relachement_complet)
  ,recalcul_dir_plis(NULL)
  // -- pour RUPTURE_SIGMA_PRINC et RUPTURE_EPS_PRINC
  ,loi_2DCP_pour_rupture(NULL),loi_1DCP2_pour_rupture(NULL)
     // un conteneur d'un point d'intégration courant
  ,ptintmeca(loi.ptintmeca)
  // métriques
  ,giB_0_1D(1),giH_0_1D(1),giB_t_1D(1),giH_t_1D(1),giB_tdt_1D(1),giH_tdt_1D(1)
  ,gijBB_0_1D(),gijHH_0_1D(),gijBB_t_1D(),gijHH_t_1D(),gijBB_tdt_1D(),gijHH_tdt_1D()
  ,gradVmoyBB_t_1D_P(NULL),gradVmoyBB_t_1D()
  ,gradVmoyBB_tdt_1D_P(NULL),gradVmoyBB_tdt_1D()
  ,gradVBB_tdt_1D_P(NULL),gradVBB_tdt_1D()
  ,jacobien_tdt_1D(0.),jacobien_t_1D(0.),jacobien_0_1D(0.),d_jacobien_tdt_1D()
  ,d_giB_tdt_1D(),d_giH_tdt_1D(),d_gijBB_tdt_1D_P(NULL),d_gijBB_tdt_1D()
  ,d2_gijBB_tdt_1D_P(NULL),d2_gijBB_tdt_1D()
  ,d_gijHH_tdt_1D_P(NULL),d_gijHH_tdt_1D()
  ,d_gradVmoyBB_t_1D_P(NULL),d_gradVmoyBB_t_1D()
  ,d_gradVmoyBB_tdt_1D_P(NULL),d_gradVmoyBB_tdt_1D()
  ,d_gradVBB_t_1D_P(NULL),d_gradVBB_t_1D()
  ,d_gradVBB_tdt_1D_P(NULL),d_gradVBB_tdt_1D()
		,sig_HH_t_1D(),sig_HH_1D(),Deps_BB_1D(),eps_BB_1D(),delta_eps_BB_1D()
  ,d_eps_BB_1D_P(),d_eps_BB_1D(),d_sig_HH_1D_P(NULL),d_sig_HH_1D()
  ,d_sigma_deps_1D_P(NULL),d_sigma_deps_1D()
  ,eps_BB_2D_t(),delta_eps_BB_2D(),eps_HH_2D_t()
  ,ViB(ParaGlob::Dimension(),ParaGlob::Dimension()),ViH(ParaGlob::Dimension(),ParaGlob::Dimension())
  // puis les grandeurs hors métriques, pour les tableaux de pointeurs, c'est uniquement du dimensionnement
  ,sig_HH_t_3D(loi.sig_HH_t_3D),sig_HH_3D(loi.sig_HH_3D),Deps_BB_3D(loi.Deps_BB_3D)
  ,eps_BB_3D(loi.eps_BB_3D),delta_eps_BB_3D(loi.delta_eps_BB_3D)
  // paramètres
  ,choix_methode_cal_plis_memb(loi.choix_methode_cal_plis_memb)
     { list <Loi_comp_abstraite *>::const_iterator ili,ilifin=loi.lois_internes.end();
       list <Enumcompletudecalcul>::const_iterator ic;
       for (ili=loi.lois_internes.begin(),ic=loi.list_completude_calcul.begin();ili!=ilifin;ili++,ic++)
         { Loi_comp_abstraite * nouvelle_loi = (*ili)->Nouvelle_loi_identique();
           lois_internes.push_back(nouvelle_loi);
           list_completude_calcul.push_back(*ic);
         };
       Loi_comp_abstraite * loi_inter = *(lois_internes.begin()); // pour simplifier
       switch (type_critere)
        {		case PLISSEMENT_MEMBRANE:
             {// -- pour PLISSEMENT_MEMBRANE
              loi_2DCP_de_3D = (LoiContraintesPlanes*) loi_inter;
              // on construit une loi interne en contraintes planes double qui servira de support
              bool calcul_en_3D_via_direction_quelconque=false; // init
              if (choix_methode_cal_plis_memb == 2)
                 calcul_en_3D_via_direction_quelconque = true;
              loi_1DCP2_de_3D = new LoiContraintesPlanesDouble(*loi_2DCP_de_3D,calcul_en_3D_via_direction_quelconque);
              // cas des fonctions éventuelles pour le niveau de détection

              // -- cas de niveauF_temps
              // on regarde s'il s'agit d'une courbe locale ou d'une courbe globale
              if (niveauF_temps != NULL)
               if (niveauF_temps->NomCourbe() == "_")
                 {// comme il s'agit d'une courbe locale on la redéfinie (sinon pb lors du destructeur de loi)
                  string non_courbe("_");   
                  niveauF_temps = Courbe1D::New_Courbe1D(*loi.niveauF_temps);
                 };
              // -- pour les pondérations à base de ddl étendue et pour les grandeurs globale
              // tout est déjà fait dans les constructeurs de copie des class
              // Ponderation_GGlobal et Ponderation
              // --- pilotage recalcul des directions des plis
              // on regarde s'il s'agit d'une fonction locale ou d'une fonction globale
              if (recalcul_dir_plis != NULL)
                if (recalcul_dir_plis->NomFonction() == "_")
                  {// comme il s'agit d'une fonction locale on la redéfinie
                   // (sinon pb lors du destructeur de loi)
                   string non_courbe("_");
                   recalcul_dir_plis = Fonction_nD::New_Fonction_nD(*loi.recalcul_dir_plis);
                  };

              break;
             }
           case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
             {loi_2DCP_pour_rupture = new LoiContraintesPlanes(*(loi.loi_2DCP_pour_rupture));
              loi_1DCP2_pour_rupture = new LoiContraintesPlanesDouble(*(loi.loi_1DCP2_pour_rupture));
              break;
             }
     
           default :
             cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
                  << "  !\n";
             cout << "\n LoiCritere::LoiCritere (const LoiCritere& loi)";
             Sortie(1);
        };

	      // association des pointeurs de grandeurs si nécessaire
	      if (loi.gradVmoyBB_t_1D_P != NULL) {gradVmoyBB_t_1D_P = &gradVmoyBB_t_1D;};
	      if (loi.gradVmoyBB_tdt_1D_P != NULL) {gradVmoyBB_tdt_1D_P = &gradVmoyBB_tdt_1D;};
	      if (loi.gradVBB_tdt_1D_P != NULL) {gradVBB_tdt_1D_P = &gradVBB_tdt_1D;};
		 
	      // def des tableaux de pointeurs pour les conteneurs de métriques
		
       // -- cas des tableaux de pointeurs, ils ont déjà la bonne dimension
	      int ta_d_gijBB_tdt_1D = loi.d_gijBB_tdt_1D.Taille();
	      for (int i=1;i<= ta_d_gijBB_tdt_1D;i++)
	      		d_gijBB_tdt_1D_P(i) = &(d_gijBB_tdt_1D(i));

	      if (loi.d2_gijBB_tdt_1D_P!= NULL)
	       { int tai_d2_gijBB_tdt_1D = d2_gijBB_tdt_1D.Taille1();
	         d2_gijBB_tdt_1D_P = new Tableau2<TenseurBB *> (tai_d2_gijBB_tdt_1D);
	         int taj_d2_gijBB_tdt_1D = d2_gijBB_tdt_1D.Taille2();
	         for (int i=1;i<= tai_d2_gijBB_tdt_1D;i++)
	           for (int j=1;j<= taj_d2_gijBB_tdt_1D;j++)
	             (*d2_gijBB_tdt_1D_P)(i,j) = &(d2_gijBB_tdt_1D(i,j));
	       };
			 
	      int ta_d_gijHH_tdt_1D = d_gijHH_tdt_1D.Taille();
	      for (int i=1;i<= ta_d_gijHH_tdt_1D;i++)
	      		d_gijHH_tdt_1D_P(i) = &(d_gijHH_tdt_1D(i));
	     
	      if (loi.d_gradVmoyBB_t_1D_P != NULL)
	       { int ta_d_gradVmoyBB_t_1D = d_gradVmoyBB_t_1D.Taille();
	         d_gradVmoyBB_t_1D_P = new Tableau<TenseurBB *> (ta_d_gradVmoyBB_t_1D);
	      	for (int i=1;i<= ta_d_gradVmoyBB_t_1D;i++)
	      		(*d_gradVmoyBB_t_1D_P)(i) = &(d_gradVmoyBB_t_1D(i));
	       };
			 
	      if (loi.d_gradVmoyBB_tdt_1D_P != NULL)
	       { int ta_d_gradVmoyBB_tdt_1D = d_gradVmoyBB_tdt_1D.Taille();
	         d_gradVmoyBB_tdt_1D_P = new Tableau<TenseurBB *> (ta_d_gradVmoyBB_tdt_1D);
	      	  for (int i=1;i<= ta_d_gradVmoyBB_tdt_1D;i++)
	      		   (*d_gradVmoyBB_tdt_1D_P)(i) = &(d_gradVmoyBB_tdt_1D(i));
	       };		 
		    
	      if (loi.d_gradVBB_t_1D_P != NULL)
	       { int ta_d_gradVBB_t_1D = d_gradVBB_t_1D.Taille();
	         d_gradVBB_t_1D_P = new Tableau<TenseurBB *> (ta_d_gradVBB_t_1D);
	      	  for (int i=1;i<= ta_d_gradVBB_t_1D;i++)
	      		  (*d_gradVBB_t_1D_P)(i) = &(d_gradVBB_t_1D(i));
	       };
			 
	      if (loi.d_gradVBB_tdt_1D_P != NULL)
	       { int ta_d_gradVBB_tdt_1D = d_gradVBB_tdt_1D.Taille();
	         d_gradVBB_tdt_1D_P = new Tableau<TenseurBB *> (ta_d_gradVBB_tdt_1D);
	      	  for (int i=1;i<= ta_d_gradVBB_tdt_1D;i++)
	      		   (*d_gradVBB_tdt_1D_P)(i) = &(d_gradVBB_tdt_1D(i));
	       };		 
		
	      // conteneurs des métriques
	      // a priori seules les grandeurs principales sont affecté
	      expli_1D = new Met_abstraite::Expli_t_tdt  // constructeur normal
                          (&giB_0_1D,&giH_0_1D,&giB_t_1D,&giH_t_1D,&giB_tdt_1D,&giH_tdt_1D
                          ,&gijBB_0_1D,&gijHH_0_1D,&gijBB_t_1D,&gijHH_t_1D
                          ,&gijBB_tdt_1D,&gijHH_tdt_1D
                          ,gradVmoyBB_t_1D_P,gradVmoyBB_tdt_1D_P,gradVBB_tdt_1D_P // pas affecté par défaut
                          ,&d_gijBB_tdt_1D_P,&jacobien_tdt_1D,&jacobien_t_1D,&jacobien_0_1D);
       impli_1D = new  Met_abstraite::Impli  // constructeur normal
                       (&giB_0_1D,&giH_0_1D,&giB_t_1D,&giH_t_1D,&giB_tdt_1D,&d_giB_tdt_1D,&giH_tdt_1D,&d_giH_tdt_1D
                        ,&gijBB_0_1D,&gijHH_0_1D,&gijBB_t_1D,&gijHH_t_1D,&gijBB_tdt_1D,&gijHH_tdt_1D
                        ,gradVmoyBB_t_1D_P,gradVmoyBB_tdt_1D_P,gradVBB_tdt_1D_P // pas affecté par défaut
                        ,&d_gijBB_tdt_1D_P
								                ,d2_gijBB_tdt_1D_P // pas affecté par défaut
								                ,&d_gijHH_tdt_1D_P
                        ,&jacobien_tdt_1D,&jacobien_t_1D,&jacobien_0_1D,&d_jacobien_tdt_1D
                        ,d_gradVmoyBB_t_1D_P,d_gradVmoyBB_tdt_1D_P     // pas affecté par défaut
		  	               ,d_gradVBB_t_1D_P,d_gradVBB_tdt_1D_P);	        // pas affecté par défaut
	      umat_cont_1D = new Met_abstraite::Umat_cont  // constructeur normal
                          (&giB_0_1D,&giH_0_1D,&giB_t_1D,&giH_t_1D,&giB_tdt_1D,&giH_tdt_1D
                          ,&gijBB_0_1D,&gijHH_0_1D,&gijBB_t_1D,&gijHH_t_1D
                          ,&gijBB_tdt_1D,&gijHH_tdt_1D
                          ,gradVmoyBB_t_1D_P,gradVmoyBB_tdt_1D_P,gradVBB_tdt_1D_P      // pas affecté par défaut
                          ,&jacobien_tdt_1D,&jacobien_t_1D,&jacobien_0_1D);
			 
	      // puis les tableaux de pointeurs de grandeurs hors métriques
	      int ta_d_eps_BB_1D = d_eps_BB_1D.Taille();
	      for (int i=1;i<= ta_d_eps_BB_1D;i++)
	          d_eps_BB_1D_P(i) = &(d_eps_BB_1D(i));
			 
	      int ta_d_sig_HH_1D = d_sig_HH_1D.Taille();
	      for (int i=1;i<= ta_d_sig_HH_1D;i++)
	          d_sig_HH_1D_P(i) = &(d_sig_HH_1D(i));
       d_sigma_deps_1D_P = & d_sigma_deps_1D;
       // traitement des pondérations
       if (loi.niveauF_fct_nD != NULL)
         niveauF_fct_nD = new Ponderation_TypeQuelconque(*(loi.niveauF_fct_nD));
       if (loi.niveauF_ddlEtendu != NULL)
         niveauF_ddlEtendu = new Ponderation(*(loi.niveauF_ddlEtendu));
       if (loi.niveauF_temps != NULL)
         {if (loi.niveauF_temps->NomCourbe() == "_")
            niveauF_temps = Courbe1D::New_Courbe1D(*(loi.niveauF_temps));;
         };
       if (loi.niveauF_grandeurConsultable != NULL)
         niveauF_grandeurConsultable = new Ponderation_Consultable(*(loi.niveauF_grandeurConsultable));
      
   		};

LoiCritere::~LoiCritere ()
// Destructeur 
     { list <Loi_comp_abstraite *>::iterator ili,ilifin=lois_internes.end();
       for (ili=lois_internes.begin();ili!=ilifin;ili++)
         { lois_internes.erase(ili);
         };
       if (d_sigma_deps_inter != NULL)  
          delete d_sigma_deps_inter; 
       if (d_sigtotalHH.Taille() != 0)
        { int taille = d_sigtotalHH.Taille();
          for (int i=1; i<= taille; i++)
            if (d_sigtotalHH(i) != NULL) delete d_sigtotalHH(i);
        };
       // -- pour les plis
       if (loi_1DCP2_de_3D != NULL) delete loi_1DCP2_de_3D;
       // on regarde s'il s'agit d'une fonction locale ou d'une fonction globale
       if (recalcul_dir_plis != NULL)
          if (recalcul_dir_plis->NomFonction() == "_") delete recalcul_dir_plis;
      
       // -- pour RUPTURE_SIGMA_PRINC et RUPTURE_EPS_PRINC
       if (loi_2DCP_pour_rupture != NULL) delete loi_2DCP_pour_rupture;
       if (loi_1DCP2_pour_rupture != NULL) delete loi_1DCP2_pour_rupture;

       // les conteneurs de pointeurs:
       delete expli_1D;delete  impli_1D; delete umat_cont_1D;
		 
       // pour les grandeurs de base, pas de new, donc pas de delete
		 
       // pour les tableaux de pointeurs, idem s'ils ne sont pas addressé par un pointeur
       // sinon il faut détruire le tableau

       if (d2_gijBB_tdt_1D_P!= NULL) delete d2_gijBB_tdt_1D_P;
       if (d_gradVmoyBB_t_1D_P!= NULL) delete d_gradVmoyBB_t_1D_P;
       if (d_gradVmoyBB_tdt_1D_P!= NULL) delete d_gradVmoyBB_tdt_1D_P;
       if (d_gradVBB_t_1D_P!= NULL) delete d_gradVBB_t_1D_P;
       if (d_gradVBB_tdt_1D_P!= NULL) delete d_gradVBB_tdt_1D_P;
      
       // cas des pondérations
       if (niveauF_fct_nD != NULL)
          delete niveauF_fct_nD;
       if (niveauF_ddlEtendu != NULL)
          delete niveauF_ddlEtendu;
       if (niveauF_temps != NULL)
         {if (niveauF_temps->NomCourbe() == "_")
            // comme il s'agit d'une courbe locale on doit la détruire localement
            delete niveauF_temps;
         };

	    };		    

// def d'une instance de données spécifiques, et initialisation
// valable une fois que les différentes lois internes sont définit
LoiCritere::SaveResul * LoiCritere::LoiCritere::New_et_Initialise()
   { // on crée les différentes listes
     list <SaveResul*> liste_des_SaveResul; // data pour chaque loi
	    list <TenseurHH* > l_sigoHH,l_sigoHH_t; // gestion des contraintes pour chaque loi
     list <EnergieMeca > l_energ,l_energ_t; // idem pour les énergies
     // le traitement est différent suivant les types de critères
     Loi_comp_abstraite * loi_inter = *(lois_internes.begin()); // pour simplifier
     switch (type_critere)
       {	case PLISSEMENT_MEMBRANE:
          { // -- pour PLISSEMENT_MEMBRANE
            // ici seule la première loi est utilisée et il s'agit forcément d'une loi de contrainte plane
            // on définit un conteneur de CP double qui contient lui-même un conteneur de CP ce qui permettra
            // de passer de l'un à l'autre sans pb
            SaveResul * nevez_save_result=NULL;
            // si on utilise la V2 plis, il faut en avertir la loi 1D
           
            nevez_save_result = loi_1DCP2_de_3D->New_et_Initialise();
            liste_des_SaveResul.push_back(nevez_save_result);
            break;
          }
        case PLISSEMENT_BIEL:
          { // -- pour plissement 1D
            // ici seule la première loi est utilisée et il s'agit forcément d'une loi 1D
            SaveResul * nevez_save_result=loi_inter->New_et_Initialise();
            liste_des_SaveResul.push_back(nevez_save_result);
            break;
          }
         case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
           {// pour l'instant on ne fait rien
            break;
           }
     
         default :
           cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
                << "  !\n";
           cout << "\n LoiCritere::LoiCritere::New_et_Initialise()";
            Sortie(1);
        };
     // pour le reste on balaie l'ensemble des lois
     list <Loi_comp_abstraite *>::iterator ili,ilifin=lois_internes.end();
     list <TenseurHH* >::iterator isig,isig_t;
     for (ili=lois_internes.begin();ili!=ilifin;ili++)
        { // pour l'instant on définit des pointeurs de tenseurs qui ont la  dimension de la loi,
          // ensuite au moment de l'utilisation on les initialisera correctement si besoin
          TenseurHH * interHH = NevezTenseurHH(dim,0.);l_sigoHH.push_back(interHH);
          TenseurHH * interHH_t = NevezTenseurHH(dim,0.);l_sigoHH_t.push_back(interHH_t);
          // on définit les conteneurs pour les énergies
          l_energ.push_back(EnergieMeca());l_energ_t.push_back(EnergieMeca());
        };
     // on ramène la bonne instance
     LoiCritere::SaveResul * retour = new SaveResul_LoiCritere(liste_des_SaveResul,l_sigoHH,l_sigoHH_t
                                              ,l_energ,l_energ_t,avec_ponderation,type_critere);
     // on supprime les grandeurs locales qui ont été crées par des new
     list <SaveResul*>::iterator ils, ilsfin= liste_des_SaveResul.end(); 
     list <TenseurHH* >::iterator isib = l_sigoHH.begin();
     list <TenseurHH* >::iterator isib_t = l_sigoHH_t.begin();
     for (ils=liste_des_SaveResul.begin();ils!=ilsfin;ils++,isib++,isib_t++)
        { if ((*ils) != NULL) delete (*ils);
		        if ((*isib) != NULL) delete (*isib);
			       if ((*isib_t) != NULL) delete (*isib_t);
        };
     // insertion éventuelle de conteneurs de grandeurs quelconque
     Insertion_conteneur_dans_save_result(retour);
     // retour
	    return retour;
	  };

// Lecture des lois de comportement
void LoiCritere::LectureDonneesParticulieres(UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { // on commence par lire le type de critère qui devra être considéré
    // pour l'instant on suppose qu'il n'y a qu'un seul critère actif
    string nom_class_methode("LoiCritere::LectureDonneesParticulieres");
    string mot_cle("TYPE_DE_CRITERE_");
    entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
    // lecture du critère
    *(entreePrinc->entree)  >> type_critere;
    // on regarde si on compte utiliser une fonction de contrôle du niveau
    // d'apparition des plis
    bool passerUneLigne = false;
    if (strstr(entreePrinc->tablcar,"avecNiveauSigmaI_mini_pour_plis_")!=NULL)
      { // lecture du mot clé
        string st2;
        *(entreePrinc->entree)  >> st2;
        // vérification 
        if (st2 != "avecNiveauSigmaI_mini_pour_plis_")
               { cout << "\n erreur en lecture, on aurait du lire le mot cle avecNiveauSigmaI_mini_pour_plis_"
                      << " alors qu'on a lu " << st2;
                 cout << "\n LoiCritere::LectureDonneesParticulieres(...";
                 entreePrinc->MessageBuffer("**erreur01**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);     
                };
        // on enregistre
        avecNiveauSigmaI_mini_pour_plis = true;
        passerUneLigne = true;
      }
    else // sinon on n'a pas de fonction de contrôle
		    {avecNiveauSigmaI_mini_pour_plis = false;};

    // passage éventuel de ligne
//    if (passerUneLigne)
    entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
   
    // lecture jusque l'on trouve le mot clé signalant la fin de la liste des loi élémentaires
    bool premier_lecture = true;
    int dim_lois=0; Enum_categorie_loi_comp categ=RIEN_CATEGORIE_LOI_COMP;
    while (strstr(entreePrinc->tablcar,"fin_loi_interne")==NULL)
     { // dans le cas de l'existence de fonction de niveau, on lit les infos
       bool use_temps=false;
       if (avecNiveauSigmaI_mini_pour_plis)
         { Ponderation ponder; // un élément courant
           // on doit commencer par lire les grandeurs des fonctions de niveau
           mot_cle="les_grandeurs_de_controle_=";string st1,st2;
           entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
//           entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle,st2);
           int compteur = 1; // pour éviter une boucle infinie
           List_io < Ddl_enum_etendu > listddlenum;
           List_io <bool> listbool;
          
           // on lit les grandeurs pour l'instant en string
           List_io <string> list_id_grand; //liste de travail
           List_io <string> list_id_grand_glob; //liste des grandeurs globales
           int nb_grandeurs_globales = 0; // init
           while (st1 != "fin_grandeurs_")
            {*(entreePrinc->entree)  >> st1 ;
             if (st1 == "fin_grandeurs_") break; // pas terrible mais c'est ce qui me vient à l'idée !
             // on vérifie que le mot clé lu est exploitable
             string minus = Minuscules(st1); // la forme minuscules
             if ((st1=="TEMPS") || (Ddl_enum_etendu::VerifExistence(st1))
                 || EstUneGrandeurGlobale(minus)
                )
               {list_id_grand.push_back(st1);
                if (EstUneGrandeurGlobale(minus)) // si c'est une grandeur globale on cumule le compteur
                   {nb_grandeurs_globales++;
                    list_id_grand_glob.push_back(st1);
                   };
               }
             else
               { cout << "\n erreur en lecture, le type de grandeur lu" << st1
                      << " n'est pas acceptable  "
                      << "\n LoiCritere::LectureDonneesParticulieres (...";
                 entreePrinc->MessageBuffer("**erreur05**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);     
               };
            };
           // --- maintenant on va lire les fonctions
           entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
           mot_cle="deb_fonct_="; // le début des fonctions
           entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
           List_io <string>::iterator ili,ilifin = list_id_grand.end();
           List_io <Courbe1D*> li_courbe_globale; // inter
           List_io <bool> val_aux_noeuds; // inter
           int nb_GGlob=0;int nb_enum_etendu = 0; // compteur pour le dimensionnement
           // premier passage on crée les fonctions
           for (ili=list_id_grand.begin();ili != ilifin;ili++)
             {string minus = Minuscules(*ili); // la forme minuscules
              if ((*ili)=="TEMPS") // cas de la fonction du temps
                { // lecture de la loi d'évolution
                  *(entreePrinc->entree) >>  st1;
                  val_aux_noeuds.push_back(false); // sert à rien, mais permet
                       // de garder le même ordre de rangement que list_id_grand
                  // on regarde si la courbe existe, si oui on récupère la référence
                  if (lesCourbes1D.Existe(st1))
                   { niveauF_temps = lesCourbes1D.Trouve(st1);
                   }
                  else
                   { // sinon il faut la lire maintenant
                     string non_courbe("_");
                     niveauF_temps = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (st1.c_str()));
                     // lecture de la courbe
                     niveauF_temps->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
                   };
                }
               else if (EstUneGrandeurGlobale(minus))
                { val_aux_noeuds.push_back(false); // sert à rien, mais permet
                  nb_GGlob++;             // de garder le même ordre de rangement que list_id_grand
                  // pour le premier élément de la liste on lit la fonction
                  // pour les autres, on ne fait rien (la fct est déjà lue)
                  if (nb_GGlob == 1)
                   {// création de la pondération si nécessaire
                    if (niveauF_fct_nD == NULL)
                       niveauF_fct_nD = new Ponderation_TypeQuelconque;
                    // on lit la fonction
                    niveauF_fct_nD->LecturePonderation
                              (list_id_grand_glob,entreePrinc,lesFonctionsnD);
                   };
                
                }
               else if (Ddl_enum_etendu::VerifExistence(*ili))
                { nb_enum_etendu++;
                  if (niveauF_ddlEtendu==NULL) // on le crée
                    niveauF_ddlEtendu = new Ponderation;
                  // on lit la courbe
                  *(entreePrinc->entree) >>  st1;
                  Courbe1D* inter=NULL;
                  // on regarde si la courbe existe, si oui on récupère la référence
                  if (lesCourbes1D.Existe(st1))
                   { inter = lesCourbes1D.Trouve(st1);
                   }
                  else
                   { // sinon il faut la lire maintenant
                     string non_courbe("_");
                     inter = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (st1.c_str()));
                     // lecture de la courbe
                     inter->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
                   };
                  li_courbe_globale.push_back(inter);
                  // et il faut lire en plus le fait que ce soit au noeud
                  // ou au pti
                  *(entreePrinc->entree) >> st2;
                  if (st2 == "AuxNoeuds_")  {val_aux_noeuds.push_back(true);}
                  else if (st2 == "AuPti_") {val_aux_noeuds.push_back(false);}
                  else
                    { cout << "\n erreur en lecture, de positionnement de la grandeur: "
                           << (*ili) << " qui doit etre AuxNoeuds_ ou AuPti_ "
                           << " et on a  lu" << st2 << " qui n'est pas acceptable  "
                           << "\n" <<  nom_class_methode<<"(...";
                      entreePrinc->MessageBuffer("**erreur06**");
                      throw (UtilLecture::ErrNouvelleDonnee(-1));
                      Sortie(1);
                    };
                };
             };
           // on passe le mot clé de fin
           mot_cle="fin_fonct_"; // la fin des fonctions
           entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
          
          
// *** à changer en fonction de l'utilisation
           // deuxième passage on met à jour les conteneurs
//           niveauF_fct_nD->type_grandeur_GGlob.Change_taille(nb_GGlob);
//           niveauF_fct_nD->c_proport.Change_taille(nb_GGlob);
          
           // on intervient sur les ddlEtendu que s'il en existe
           if (niveauF_ddlEtendu != NULL)
             { niveauF_ddlEtendu->Type_grandeur().Change_taille(nb_enum_etendu);
               niveauF_ddlEtendu->Valeur_aux_noeuds().Change_taille(nb_enum_etendu);
               niveauF_ddlEtendu->C_proport().Change_taille(nb_enum_etendu);
             };
           List_io <Courbe1D*>::iterator  i_courbe=li_courbe_globale.begin(); // inter
           List_io <bool>::iterator i_val= val_aux_noeuds.begin(); // inter
           // re_init des numéros
           nb_enum_etendu = 1; // compteur pour le dimensionnement
           for (ili=list_id_grand.begin();ili != ilifin;ili++,i_courbe++, i_val++)
             { if ((*ili)=="TEMPS") // cas de la fonction du temps
                { // on passe car l'affectation a déjà été faite
                }
               else if (EstUneGrandeurGlobale((*ili)))
                { // on passe car l'affectation a déjà été faite
                }
               else if (Ddl_enum_etendu::VerifExistence(*ili))
                {(niveauF_ddlEtendu->Type_grandeur())(nb_enum_etendu)=
                     Ddl_enum_etendu(*ili);
                 (niveauF_ddlEtendu->Valeur_aux_noeuds())(nb_enum_etendu)=(*i_val);
                 (niveauF_ddlEtendu->C_proport())(nb_enum_etendu)=(*i_courbe);
                 nb_enum_etendu++;
                };
             };
           entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
         };
     
       // --- lecture de la loi individuelle ---------
       // lecture du nom de la loi
       string st2;
       *(entreePrinc->entree)  >> st2;
       // --- définition de list_completude_calcul, 
       // on regarde si éventuellement on utilise seulement une partie de la loi
       string toto;
       if(strstr(entreePrinc->tablcar,"sigma_seulement_")!=0)
        { *(entreePrinc->entree) >> toto; // on passe la chaine de caractere
          // on vérifie que le mot clé est bien positionné
          if (toto != "sigma_seulement_") 
           { cout << "\n erreur en lecture, on aurait du lire le mot cle sigma_seulement_"
                  << " alors qu'on a lu " << toto;
             cout << "\n LoiCritere::LectureDonneesParticulieres (...";
             entreePrinc->MessageBuffer("**erreur2**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
           };
          // on enregistre
          list_completude_calcul.push_back(CONTRAINTE_UNIQUEMENT);
        }
       else if(strstr(entreePrinc->tablcar,"tangent_seulement_")!=0)
        { *(entreePrinc->entree) >> toto; // on passe la chaine de caractere
          // on vérifie que le mot clé est bien positionné
          if (toto != "tangent_seulement_") 
           { cout << "\n erreur en lecture, on aurait du lire le mot cle tangent_seulement_"
                  << " alors qu'on a lu " << toto;
             cout << "\n LoiCritere::LectureDonneesParticulieres (...";
             entreePrinc->MessageBuffer("**erreur3**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
           };
          // on enregistre
          list_completude_calcul.push_back(TANGENT_UNIQUEMENT);
        }
       else // cas par défaut
        { list_completude_calcul.push_back(CONTRAINTE_ET_TANGENT);         		
        };
       // --- definition de la loi
       LoiAbstraiteGeneral * pt = LesLoisDeComp::Def_loi(st2);
       // enregistrement de la loi
       lois_internes.push_back((Loi_comp_abstraite*)pt);
       // lecture des informations particulières propres à la  loi   
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
       pt->LectureDonneesParticulieres (entreePrinc,lesCourbes1D,lesFonctionsnD);
   
       // dans le cas de la première loi on enregistre la dimension
       // on s'occupe de la catégorie et de la dimension de la loi, après la lecture des informations particulières 
       // pour le cas où  ce serait une loi critere, car dans ce dernier cas, c'est après la lecture que l'on peut
       // définir la catégorie dans le cas de la première loi on enregistre la dimension
       if (premier_lecture)
        {  premier_lecture=false;
           dim_lois=pt->Dimension_loi();categ = pt->Id_categorie();
           // on met à jour la dimension et la catégorie
           dim = dim_lois; categorie_loi_comp = categ;
           if (!GroupeMecanique(categorie_loi_comp))
             { cout << "\n erreur1 en lecture des lois constitutives elementaire d'une loi LoiCritere"
                    << "\n la loi lue: " << pt->Nom_comport() << " n'est pas une loi mecanique, elle fait partie "
                    << " de la categorie: "<< Nom_categorie_loi_comp(categorie_loi_comp);
               entreePrinc->MessageBuffer("**erreur LoiCritere::LectureDonneesParticulieres (...**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);     
             };
        }
       else // sinon on vérifie que les lois ont la bonne dimension et la bonne catégorie
        { if (pt->Dimension_loi() !=  dim_lois) 
           { cout << "\n erreur en lecture des lois constitutives elementaire d'une loi LoiCritere"
                  << "\n la loi lue: " << pt->Nom_comport() << " n'a pas la meme dimension que la premier loi lue";
             entreePrinc->MessageBuffer("lecture  LoiCritere");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1); 
           }
          if (!GroupeMecanique(pt->Id_categorie()))
             { cout << "\n erreur en lecture des lois constitutives elementaire d'une loi LoiCritere"
                    << "\n la loi lue: " << pt->Nom_comport() << " n'est pas une loi mecanique, elle fait partie "
                    << " de la categorie: "<< Nom_categorie_loi_comp(categorie_loi_comp);
               entreePrinc->MessageBuffer("**erreur2 LoiCritere::LectureDonneesParticulieres (...**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);     
             };
          // on enregistre la catégorie la plus complète    
          categorie_loi_comp = Categorie_loi_comp_la_plus_complete(categorie_loi_comp,pt->Id_categorie());  
        };
   
       // si la loi est thermo dépendante on indique que la loi critère l'est aussi
       if (((Loi_comp_abstraite*)pt)->ThermoDependante()) this->thermo_dependant = true;
     };
    //   préparation lecture éventuelle de paramètres additionnels
    entreePrinc->NouvelleDonnee();
   
    // vérification en fonction du type de critère
    switch (type_critere)
     {		case PLISSEMENT_MEMBRANE:
          {// on vérifie qu'il n'y a qu'une seule loi élémentaire
           if (lois_internes.size() != 1)
             { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " une seule loi interne est autorise alors qu'ici il y a "
                    << lois_internes.size() << " loi(s) definie(s), revoir les donnees d'entree ";
               cout << "\n LoiCritere::LectureDonneesParticulieres (...";
               entreePrinc->MessageBuffer("**erreur3**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);
             };
           // on vérifie qu'il s'agit d'une loi de 2D contraintes planes venant du 3D
           Loi_comp_abstraite * loi = *(lois_internes.begin()); // pour simplifier
           if (!(loi->Contraintes_planes_de_3D()))
             { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " la loi de comportement ne provient pas d'une loi 3D, on ne peut pas l'utiliser ! ";
               cout << "\n LoiCritere::LectureDonneesParticulieres (...";
               entreePrinc->MessageBuffer("**erreur4**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);
             }
           else // sinon on définit la loi 2D contraintes planes support, puis la 1D
            {loi_2DCP_de_3D = (LoiContraintesPlanes*) loi;
             // on construit une loi interne en contraintes planes double qui servira de support
             bool calcul_en_3D_via_direction_quelconque=false; // init
             if (choix_methode_cal_plis_memb == 2)
                 calcul_en_3D_via_direction_quelconque = true;
             loi_1DCP2_de_3D = new LoiContraintesPlanesDouble(*loi_2DCP_de_3D,calcul_en_3D_via_direction_quelconque);
             // on regarde s'il faut lire des paramètres particuliers à la loi contraintes planes double
             string toto;
             if(strstr(entreePrinc->tablcar,"parametres_controle_pour_contraintes_planes_double_")!=0)
              { *(entreePrinc->entree) >> toto; // on passe la chaine de caractere
                // on vérifie que le mot clé est bien positionné
                if (toto != "parametres_controle_pour_contraintes_planes_double_")
                 { cout << "\n erreur en lecture, on aurait du lire le mot cle parametres_controle_pour_contraintes_planes_double_"
                        << " alors qu'on a lu " << toto;
                   cout << "\n LoiCritere::LectureDonneesParticulieres (...";
                   entreePrinc->MessageBuffer("**erreur41**");
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);
                 };
                entreePrinc->NouvelleDonnee(); //   on passe le mot clé
                // on appelle la méthode
                loi_1DCP2_de_3D->LectureParametres_controles(entreePrinc,lesCourbes1D,lesFonctionsnD);
                // lecture du mot clé de fin des paramètres de controle
                *(entreePrinc->entree) >> toto; // on passe la chaine de caractere
                // on vérifie que le mot clé est bien positionné
                if (toto != "fin_parametres_controle_pour_contraintes_planes_double_")
                 { cout << "\n erreur en lecture, on aurait du lire le mot cle fin_parametres_controle_pour_contraintes_planes_double_"
                        << " alors qu'on a lu " << toto;
                   cout << "\n LoiCritere::LectureDonneesParticulieres (...";
                   entreePrinc->MessageBuffer("**erreur42**");
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);
                 };

              };
             // on dimensionne éventuellement
             if (d_sigma_deps_inter == NULL)
               d_sigma_deps_inter = NevezTenseurHHHH(22);
            };
           // on met à jour l'indicateur    calcul_en_3D_via_direction_quelconque_ de la loi 1D
           bool calcul_en_3D_via_direction_quelconque=false; // init
           if (choix_methode_cal_plis_memb == 2)
              calcul_en_3D_via_direction_quelconque = true;
           loi_1DCP2_de_3D->Change_calcul_en_3D_via_direction_quelconque (calcul_en_3D_via_direction_quelconque);
			        break;
          }
        case PLISSEMENT_BIEL:
          {// on vérifie qu'il n'y a qu'une seule loi élémentaire
           if (lois_internes.size() != 1)
             { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " une seule loi interne est autorise alors qu'ici il y a "
                    << lois_internes.size() << " loi(s) definie(s), revoir les donnees d'entree ";
               cout << "\n LoiCritere::LectureDonneesParticulieres (...";
               entreePrinc->MessageBuffer("**erreur3**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);
             };
           // on vérifie qu'il s'agit d'une loi de 1D 
           Loi_comp_abstraite * loi = *(lois_internes.begin()); // pour simplifier
           if ((loi->Dimension_loi() != 1) && (loi->Dimension_loi() != 4))
             { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " la loi de comportement doit etre de type 1D, on ne peut pas l'utiliser ! ";
               cout << "\n LoiCritere::LectureDonneesParticulieres (...";
               entreePrinc->MessageBuffer("**erreur4**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);
             };
           // on dimensionne éventuellement
           if (d_sigma_deps_inter == NULL)
             d_sigma_deps_inter = NevezTenseurHHHH(11);
			        break;
          }
  
        case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
          {// on vérifie qu'il n'y a qu'une seule loi élémentaire
           if (lois_internes.size() != 1)
             { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " une seule loi interne est autorise alors qu'ici il y a "
                    << lois_internes.size() << " loi(s) definie(s), revoir les donnees d'entree ";
               cout << "\n LoiCritere::LectureDonneesParticulieres (...";
               entreePrinc->MessageBuffer("**erreur3**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);
             };
           // pour l'instant seule les lois 3D sont autorisées
           Loi_comp_abstraite * loi = *(lois_internes.begin()); // pour simplifier
           if (Comp_3D_CP_DP_1D(loi->Id_comport()) != COMP_3D)
             { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " la loi de comportement n'est pas une loi 3D, on ne peut pas l'utiliser ! ";
               cout << "\n LoiCritere::LectureDonneesParticulieres (...";
               entreePrinc->MessageBuffer("**erreur5**");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);
             };
           // on définit les lois supports en contraintes planes
           loi_2DCP_pour_rupture = (LoiContraintesPlanes*) loi;
           // on construit une loi interne en contraintes planes double qui servira de support
           bool calcul_en_3D_via_direction_quelconque=false; // init
           if (choix_methode_cal_plis_memb == 2)
               calcul_en_3D_via_direction_quelconque = true;
           loi_1DCP2_de_3D = new LoiContraintesPlanesDouble(*loi_2DCP_de_3D,calcul_en_3D_via_direction_quelconque);
			        break;
          }
       
		      default :
          cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
               << "  !\n";
          cout << "\n LoiCritere::LectureDonneesParticulieres (...";
          entreePrinc->MessageBuffer("**erreur4**");
          throw (UtilLecture::ErrNouvelleDonnee(-1));
          Sortie(1);
     };
    // prepa du flot de lecture pour d'autre loi éventuellement et
    //    lecture éventuelle du mot clé de fin de la loi
    if((strstr(entreePrinc->tablcar,"fin_loi_critere")==0)
       && (strstr(entreePrinc->tablcar,"avec_parametres_controle_pour_loi_critere_")==0)
      )
      entreePrinc->NouvelleDonnee();

    // --- lecture éventuelle des paramètres de réglage ----
    if(strstr(entreePrinc->tablcar,"avec_parametres_controle_pour_loi_critere_")!=0)
     {string nom;
      entreePrinc->NouvelleDonnee(); // on se positionne sur un nouvel enreg
      // on lit tant que l'on ne rencontre pas la ligne contenant "fin_parametres_controle_pour_loi_critere_"
      // ou un nouveau mot clé global auquel cas il y a pb !!
      MotCle motCle; // ref aux mots cle
      while (strstr(entreePrinc->tablcar,"fin_parametres_controle_pour_loi_critere_")==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 : on n'a pas trouve le mot cle "
                << " fin_parametres_controle_pour_loi_critere_ et par contre la ligne courante contient un mot cle global  ";
           entreePrinc->MessageBuffer("** erreur5 des parametres de reglage de la loi de comportement de LoiCritere::LectureDonneesParticulieres( **");
           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_controle_pour_loi_critere_")
              {entreePrinc->NouvelleDonnee(); *(entreePrinc->entree) >> nom;};
          }
        #endif
        else // cas d'une erreur de lecture
         { cout << "\n erreur de lecture inconnue  ";
           entreePrinc->MessageBuffer("** erreur4 des parametres de reglage de la loi de comportement de LoiCritere::LectureDonneesParticulieres( **");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         };
        
        // forcer un affichage particulier pour les méthodes
        if (nom == "permet_affichage_")
         { Lecture_permet_affichage(entreePrinc,lesFonctionsnD);
         }
        // choix entre la première ou deuxième méthode pour le calcul des plis en membrane
        else if (nom == "choix_methode_cal_plis_memb_")
         { *(entreePrinc->entree) >> choix_methode_cal_plis_memb;
           // on met à jour l'indicateur    calcul_en_3D_via_direction_quelconque_ de la loi 1D
           bool calcul_en_3D_via_direction_quelconque=false; // init
           if (choix_methode_cal_plis_memb == 2)
              calcul_en_3D_via_direction_quelconque = true;
           loi_1DCP2_de_3D->Change_calcul_en_3D_via_direction_quelconque (calcul_en_3D_via_direction_quelconque);
         }
        // traitement des épaisseurs si relachement_complet
        else if (nom == "choix_calcul_epaisseur_si_relachement_complet_")
         { *(entreePrinc->entree) >> choix_calcul_epaisseur_si_relachement_complet;
         }
        //paramètres de controle du recalcul de la direction des plis
         // utilisation d'une fonction nD
        else if (nom == "recalcul_dir_plis_")
         { // --- lecture du nom de la fonction nD
           mot_cle="recalcul_dir_plis_";
           string nom_fonct; // init
           *(entreePrinc->entree) >> nom_fonct;
           // maintenant on définit la fonction
           if (lesFonctionsnD.Existe(nom_fonct))
             {recalcul_dir_plis = lesFonctionsnD.Trouve(nom_fonct);
             }
           else
             {// sinon il faut la lire maintenant
              string non("_");
              recalcul_dir_plis = Fonction_nD::New_Fonction_nD(non, Id_Nom_Fonction_nD(nom_fonct));
              // lecture de la courbe
              recalcul_dir_plis->LectDonnParticulieres_Fonction_nD (non,entreePrinc);
              // maintenant on vérifie que la fonction est utilisable
              if (recalcul_dir_plis->NbComposante() != 1 )
               { cout << "\n erreur en lecture, la fonction " << nom_fonct
                      << " est une fonction vectorielle a   " << recalcul_dir_plis->NbComposante()
                      << " composante alors qu'elle devrait etre scalaire ! "
                      << " elle n'est donc pas utilisable !! ";
                 string message("\n**erreur** \n"+nom_class_methode+"(...");
                 entreePrinc->MessageBuffer(message);
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);
               };
            };
          }
//        // niveau du critère
//        if (nom == "niv_declenche_")
//         {*(entreePrinc->entree) >> niveau_declenchement_critere;
//         }

        // sinon ce n'est pas un mot clé connu, on le signale
        else if (nom != "fin_parametres_controle_pour_loi_critere_")
         { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu "
                << " on a lu : " << nom << endl;
           if (ParaGlob::NiveauImpression()>3)
                cout << "\n LoiCritere::LectureDonneesParticulieres((UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         }
       }; //-- fin du while
      }; //-- fin de la lecture des paramètres de réglage
    // préparation de la lecture
    entreePrinc->NouvelleDonnee();
    if(strstr(entreePrinc->tablcar,"fin_loi_critere")!=0)
      entreePrinc->NouvelleDonnee();
    // appel au niveau de la classe mère
    Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire
                 (*entreePrinc,lesFonctionsnD,false);

   
  };


// affichage de la loi
void LoiCritere::Affiche() const
 { cout << "\n .......  loi de comportement LOI_CRITERE ........";
   cout << "\n type de critere: " << type_critere;
   cout << "\n   type_calcul_additif " ;
	  if (type_calcul) {cout << " sur les contraintes ";} else { cout << " sur les increments de contraintes ";};
	  if (avec_ponderation) {cout << " avec ponderation " ;} else {cout << " sans ponderation ";};
   list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
   list <Enumcompletudecalcul>::const_iterator ic,icfin=list_completude_calcul.end();
	  list <Ponderation >::const_iterator ipon;
	  if (avec_ponderation) ipon = list_ponderation.begin();
     for (ili=lois_internes.begin(),ic=list_completude_calcul.begin();ili!=ilifin;ili++,ic++)
      {if (avec_ponderation)
		       { cout << "\n avec fonctions de ponderation des grandeurs: ";
           const Ponderation& ponder = (*ipon); // pour simplifier
           int taille = (ponder.Const_Type_grandeur()).Taille();
           for (int i=1;i<=taille;i++) 
             {cout << (ponder.Const_Type_grandeur())(i) << " ";
              if ((ponder.Const_Valeur_aux_noeuds())(i)) {cout << "AuxNoeuds ";} else {cout << "AuPti ";};
             };
           // les courbes
           cout << "\n les courbes: ";
           for (int i=1;i<=taille;i++)
				        {cout <<  (ponder.Const_C_proport())(i)->NomCourbe() <<" ";};
				       ipon++;
				     };
			    // affichage de la loi
       (*ili)->Affiche();
       // affichage du type d'utilisation de la loi
       switch (*ic)
         	{case CONTRAINTE_ET_TANGENT:
         	   cout << "\n utilisation complete de la loi (contraintes et comportement tangent)";
         	   break;
         	 case CONTRAINTE_UNIQUEMENT:
         	   cout << "\n utilisation uniquement des contraintes calculees par cette loi";
         	   break;
         	 case TANGENT_UNIQUEMENT:
         	   cout << "\n utilisation uniquement de l'operateur tangent  calcules par cette loi";
         	   break;
         	 // le type énuméré ne contenant que ces valeurs, on ne peut pas avoir d'autres cas  
         	};
      };
   // niveau d'affichage
   Affiche_niveau_affichage();

   // affichage
   switch (type_critere)
     {  case PLISSEMENT_MEMBRANE:
          {//affichage de la loi CP2
           cout << "\n loi 1D CP2: ";
           loi_1DCP2_de_3D->Affiche();
           // choix entre la première ou deuxième méthode pour le calcul des plis en membrane
           cout << "\n choix_methode_cal_plis_memb= " << choix_methode_cal_plis_memb;
           // cas de recalcul_dir_plis
           cout << "\n recalcul_dir_plis= ";
           if (recalcul_dir_plis == NULL)
             {cout << " 0 ";}
           else
             {if (recalcul_dir_plis->NomFonction() != "_")
                   cout << recalcul_dir_plis->NomFonction();
              else
                   recalcul_dir_plis->Affiche();
              cout << "\n";
             };
           break;
          }
        case PLISSEMENT_BIEL:
          {           break;
          }
  
        case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
          {           break;
          }
       
        default : break; // déjà vue
     };

  
  
   cout << "\n .......  fin de la loi de comportement LOI_CRITERE ........";
 };
            
// affichage et definition interactive des commandes particulières à chaques lois
void LoiCritere::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
 {  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
	   cout << "\n definition standart pour critere plis (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");

    sort << "\n# .......  loi de comportement avec critere(s) ........"
         << "\n#  on commence par indiquer le type de critere, par exemple: "
         << "\n#  TYPE_DE_CRITERE_  PLISSEMENT_MEMBRANE  "
         << "\n#  il faut donner le nom d'une (ou plusieurs, cela depend du critere) loi(s) "
         << "\n#  suivi des parametres sur les lignes suivantes"
         << "\n#  puis terminer avec le mot cle: fin_loi_interne "
         << "\n#  puis def eventuel des grandeurs associees au(x) critere(s) sur les lignes suivantes"
         << "\n#  puis terminer avec le mot cle: fin_loi_critere "
         << "\n#  "
         << "\n# exemple avec une loi elastique et un critere de plissement  ";
  
    // definition de la loi
    sort << "\n#     TYPE_DE_CRITERE_  PLISSEMENT_MEMBRANE ";
    string internom("LOI_CONTRAINTES_PLANES");
    LoiAbstraiteGeneral * pt = LesLoisDeComp::Def_loi(internom);
    sort << "\n#      LOI_CONTRAINTES_PLANES # loi de contrainte plane ";
    pt->Info_commande_LoisDeComp(entreePrinc);     
    sort  << "\n          fin_loi_critere   # ----- fin de LOI_CRITERE" << endl;
    // cas particulier
    if ((rep != "o") && (rep != "O" ) && (rep != "0") )
       { sort << "\n# .......  cas particulier 1) ........"
          << "\n#  il est possible de ne retenir de la loi que les contraintes, ou que le comportement tangent "
          << "\n#  ceci peut-etre utile dans le cas d'un comportement tangent singulier par exemple "
          << "\n#  pour cela on indique apres le nom de la loi, un des mots cles suivant:  "
          << "\n#  sigma_seulement_  tangent_seulement_  ";
         sort << "\n# .......  cas particulier 2) ........"
          << "\n#   --- cas d'un critere de plissement sur des membrannes --- "
          << "\n#   la loi de comportement doit etre de type contrainte plane, "
          << "\n#   qui utilise une loi 3D. Cette loi 3D est utilisee directement par "
          << "\n#   le critere (cf. doc). "
          << "\n#   Seule une seule loi est autorisee "
          << "\n#   "
          << "\n#   --- exemple de declaration pour une loi elastique --- "
          << "\n#   "
          << "\n#   "
          << "\n#   toto          LOI_CRITERE  "
          << "\n#     TYPE_DE_CRITERE_  PLISSEMENT_MEMBRANE "
          << "\n#     LOI_CONTRAINTES_PLANES    "
          << "\n#        NEWTON_LOCAL 	avec_parametres_de_reglage_   "
          << "\n#                    nb_iteration_maxi_  20   "
          << "\n#                    nb_dichotomie_maxi_  20   "
          << "\n#                    tolerance_residu_ 1.e-3   "
          << "\n#                 fin_parametres_reglage_Algo_Newton_   "
          << "\n#   "
          << "\n#     ISOELAS   "
          << "\n#       200000  0.3   "
          << "\n#       fin_loi_contrainte_plane  # --- fin de la loi de contrainte plane  "
          << "\n#     fin_loi_interne # --- fin des lois internes"
          << "\n#   fin_loi_critere   # --- fin de la loi critere "
          << "\n\n \n ";
         sort << "\n# .......  cas particulier 3) ........"
          << "\n#   --- cas d'un critere de plissement sur des elements 1D type biel (sans flexion) --- "
          << "\n#   la loi de comportement doit etre de type 1D quelconque "
          << "\n#   Seule une seule loi est autorisee "
          << "\n#   "
          << "\n#   --- exemple de declaration pour une loi elastique --- "
          << "\n#   "
          << "\n#   "
          << "\n#   toto          LOI_CRITERE  "
          << "\n#     TYPE_DE_CRITERE_  PLISSEMENT_BIEL "
          << "\n#       ISOELAS1D   "
          << "\n#         200000  0.3   "
          << "\n#       fin_loi_interne # --- fin des lois internes"
          << "\n#     fin_loi_critere   # --- fin de la loi critere "
          << "\n\n \n "

          << "\n# -------------- parametres particuliers pour les plis ------ "
          << "\n#  il est possible d'indiquer les parametres particuliers qui controles "
          << "\n#  la loi de comportement doublement planes, pour cela apres la declaration "
          << "\n#  de la loi de contrainte plane, on indique : "
          << "\n#  parametres_controle_pour_contraintes_planes_double_ "
          << "\n#   - puis les parametres specifique de pilotage des contraintes planes double"
          << "\n#   cf. la loi "
          << "\n#   - pui le mot cle "
          << "\n#  fin_parametres_controle_pour_contraintes_planes_double_"
          << "\n#  "
          << "\n#  Exemple de declaration: "
          << "\n#  "
          << "\n#   toto          LOI_CRITERE  "
          << "\n#     TYPE_DE_CRITERE_  PLISSEMENT_MEMBRANE "
          << "\n#     LOI_CONTRAINTES_PLANES    "
          << "\n#        NEWTON_LOCAL  avec_parametres_de_reglage_   "
          << "\n#                    nb_iteration_maxi_  20   "
          << "\n#                    nb_dichotomie_maxi_  20   "
          << "\n#                    tolerance_residu_ 1.e-3   "
          << "\n#                 fin_parametres_reglage_Algo_Newton_   "
          << "\n#   "
          << "\n#     ISOELAS   "
          << "\n#       200000  0.3   "
          << "\n#       fin_loi_contrainte_plane  # --- fin de la loi de contrainte plane  "
          << "\n#     fin_loi_interne # --- fin des lois internes"
          << "\n#     parametres_controle_pour_contraintes_planes_double_"
          << "\n#      NEWTON_LOCAL avec_parametres_de_reglage_"
          << "\n#                    nb_iteration_maxi_  20 "
          << "\n#                    nb_dichotomie_maxi_  20 "
          << "\n#                    tolerance_residu_ 5.e-3 "
          << "\n#                    tolerance_residu_rel_ 1.e-4 "
          << "\n#                    mini_hsurh0_ 1.e-4 "
          << "\n#                    mini_bsurb0_ 1.e-4 "
          << "\n#                    maxi_hsurh0_ 1.2 "
          << "\n#                    maxi_bsurb0_ 1.2 "
          << "\n#                    sortie_post_ 1 "
          << "\n#                    permet_affichage_ 3 "
          << "\n#                    choix_methode_cal_plis_memb_ 1 "
          << "\n#                   fin_parametres_reglage_Algo_Newton_ "
          << "\n#     fin_parametres_controle_pour_contraintes_planes_double_"
          << "\n#  "
          << "\n# -------------- parametres de controle   ------ "
          << "\n# parametres a mettre en dernier entre les deux mots clefs: "
          << "\n#  avec_parametres_controle_pour_loi_critere_  et fin_parametres_controle_pour_loi_critere_"
          << "\n# "
          << "\n# 1) controle de l'affichage: "
          << "\n# - l'affichage normale est fonction du parametre global d'affichage gerer "
          << "\n#  par le niveau d'affichage cependant  il est possible de permettre l'affichage "
          << "\n#  a un niveau particulier (mot cle : permet_affichage_ suivi d'un nombre entier)  "
          << "\n#  l'affichage s'effectuera donc en fonction de l'affichage normale et de l'affichage "
          << "\n#  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), "
          << "\n# 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 "
          << "\n# uniquement de n "
          << "\n# "
          << "\n# ex: permet_affichage_ 5  "
          << "\n# "
          << "\n# 2) gestion eventuelle  du recalcul des directions des plis "
          << "\n# - par defaut la direction des plis est recalculee a chaque iteration "
          << "\n#  il est possible de changer ce comportement a l'aide de la definition d'une fonction nD "
          << "\n#  qui doit renvoyer une valeur qui est transformee en entier:    "
          << "\n#     si == 0 on utilise la valeur stockee actuelle (== celle de l'iter precedente),  "
          << "\n#        si aucun calcul de direction n'a ete effectue, un premier calcul est fait "
          << "\n#     si == 1 on recalcule les directions des plis,  "
          << "\n#     si == 2 on recalcule les directions des plis uniquement pour la zone "
          << "\n#          non completement relachee a t, pour cette derniere on maintient le relachement,  "
          << "\n#     si == -1 on utilise la valeur stockee a t (celle precedente qui a convergee),  "
          << "\n#        si aucun calcul de direction n'a ete effectue, un premier calcul est fait "
          << "\n#     si == -2 idem -1 , sauf que s'il n'y a pas de direction existante, on ne recalcule pas une "
          << "\n#                 nouvelle direction, on continue avec un calcul sans plis "
          << "\n#          --> cela signifie que la zone de plis est totalement figee / au precedent incr"
          << "\n#     si == -3 idem 0 , sauf que s'il n'y a pas de direction existante, on ne recalcule pas une "
          << "\n#                 nouvelle direction, on continue avec un calcul sans plis "
          << "\n#          --> cela signifie que la zone de plis est totalement figee  / a la precedente iter"
          << "\n#   "
          << "\n#  Pour cela on utilise le mot cle: recalcul_dir_plis_ suivi du nom de la fonction "
          << "\n#  (ou eventuellement en declarant directement la fonction localement, "
          << "\n#   et alors on passe une ligne apres la definition) "
          << "\n#   "
          << "\n#  exemple de mise en donnees: "
          << "\n#  "
          << "\n# recalcul_dir_plis_  f_recalcul_pli "
          << "\n# "
          << "\n# dans cet exemple f_recalcul_pli est le nom d'une fonction qui doit avoir ete definie "
          << "\n#  "
          << "\n#  3) une nouvelle methode de calcul des plis sur membrane est disponible "
          << "\n#  le choix de la methode s'effectue via le mot cle : choix_methode_cal_plis_memb_ "
          << "\n#  valeur par defaut: 1, nouvelle methode : 2 "
          << "\n#  exemple de mise en donnees: "
          << "\n#  choix_methode_cal_plis_memb_ 2 "
          << "\n#  .... "
          << "\n#   fin_loi_critere   # --- fin de la loi critere "
          << "\n\n \n "
          << "\n#  "
          << "\n#  "
          << "\n\n \n ";

//         sort << "\n# .......  cas particulier 4) ........"
//          << "\n#  Dans le cas d'un critere de membrane, il est possible de ponderer chaque terme de la somme de contrainte. La contrainte finale sera alors: "
//          << "\n#  sigma = f1*sigma1+ f2*sigma2 + ..."
//          << "\n#  Les facteurs de ponderation, sont des fonctions de grandeurs disponibles pendant le calcul: i.e.: deformation equivalente, "
//          << "\n#  temperature, etc.  "
//          << "\n#  Pour ce faire, on indique sur la premiere ligne (apres la ligne contenant le mot cle LOI_CRITERE) le mot cle:  "
//          << "\n#   avec_fonction_de_ponderation_ suivit optionnellement (sur la meme ligne)"
//          << "\n#  du type de calcul (mot cle: type_calcul= ) (1 ou 2) cf. expli si dessous, puis on passe a la ligne suivante  "
//          << "\n#  et on definit successivement chaque lois de la maniere suivante: "
//          << "\n#  avant le mot cle definissant la loi , on indique le mot cle les_grandeur_ponderation= suivit de m (m < 11 maxi) couples  "
//          << "\n#  (un nomDeGrandeur A_k suivi de l'une des deux chaines: AuxNoeuds_ ou AuPti_ , indiquant ou est definit la grandeur) "
//          << "\n#   L'ensemble des couples est terminer  par le mot cle  fin_grandeur_ponderation_ "
//          << "\n#     On peut utiliser n'importe quelle grandeur definie (mais qui doit exister par ailleurs) "
//          << "\n#     aux noeuds ou au point d'integration, cf. documentation "
//          << "\n#  ensuite sur la ligne suivante on definit la fonction de ponderation f, qui est produit de fonction 1D g(A_k) :"
//          << "\n#   f = Produit_{k=1}^m [ g_k(A_k)] "
//          << "\n#  On doit donc definir m fonction 1D, d'où un mot cle: deb_fonct_ponder=  "
//          << "\n#  les noms de fonctions deja definies, ou alors la definition directe de la fonction (apres la def directe d'une"
//          << "\n#  fonction, on passe a la ligne suivante pour continuer)"
//          << "\n#  et enfin le mot cle: fin_fonct_ponder_ puis sur la ligne suivante: le nom de la loi"
//          << "\n#    optionnellement, apres le nom de la loi, on peut indiquer (cf. expli si dessus) un des deux mots cle suivant: "
//          << "\n#    sigma_seulement_  ou tangent_seulement_  "
//          << "\n#  ensuite suivent les informations specifiques a la loi"
//          << "\n#  sur la derniere ligne on doit indiquer le mot cle: fin_liste_lois_elementaires "
//          << "\n# "
//          << "\n#  NB:  option type_calcul= : en fait il y a deux type de loi  possibles:  "
//          << "\n#  soit : sigma = somme_{i=1}^n ( f_i * sigma(loi_i)) , ce qui est le type 1 (par defaut) "
//          << "\n#  soit : delta sigma = somme_{i=1}^n (f_i * delta sigma(loi_i))  , ce qui est le type 2"
//          << "\n#         en tenant compte que les contraintes sont cumulees dans le type 2. "
//          << "\n#  "
//          << "\n#  exemple d'un somme ponderee de deux lois elastique, chacune ponderee de fonctions dependantes "
//          << "\n#  de la vitesse de deformation equivalente  et de la temperature, "
//          << "\n#  "
//          << "\n#		metal  LOI_CRITERE   "
//          << "\n#		 avec_fonction_de_ponderation_ "
//          << "\n#		 les_grandeur_ponderation= def_equivalente  AuPti_ TEMP AuxNoeuds_  fin_grandeur_ponderation_ "
//          << "\n#		 deb_fonct_ponder=   nom_fonc_1  nom_fonc_2  fin_fonct_ponder_   "
//          << "\n#		ISOELAS  "
//          << "\n#			210000  0.3 "
//          << "\n#		  les_grandeur_ponderation= def_equivalente AuPti_ TEMP  AuxNoeuds_ fin_grandeur_ponderation_ "
//          << "\n#		  deb_fonct_ponder=   nom_fonc_3  nom_fonc_4  fin_fonct_ponder_   "
//          << "\n#		ISOELAS  "
//          << "\n#			300  0.1 "
//          << "\n#  fin_liste_lois_elementaires  "
//          << "\n#  " << endl;
       };
  };  		  	  

// test si la loi est complete
int LoiCritere::TestComplet()
  {int ret = LoiAbstraiteGeneral::TestComplet();
   list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
   for (ili=lois_internes.begin();ili!=ilifin;ili++)
      ret *=(*ili)->TestComplet();
    switch (type_critere)
     {		case PLISSEMENT_MEMBRANE:
          {// on vérifie que les lois supports sont définies
           if ((loi_2DCP_de_3D == NULL) || (loi_1DCP2_de_3D == NULL))
            { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " le lois internes supports ne sont pas definies ... la loi n'est pas exploitable ";
               cout << "\n LoiCritere::TestComplet()";
               ret = 0;
            }
			        break;
          }
        case PLISSEMENT_BIEL:
          {// rien n'a vérifier
			        break;
          }
        case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
          {// on vérifie que les lois supports sont définies
           if ((loi_2DCP_pour_rupture == NULL) || (loi_1DCP2_pour_rupture == NULL))
            { cout << "\n erreur : dans le cas d'un critere " << Nom_Critere_Loi(type_critere)
                    << " le lois internes supports ne sont pas definies ... la loi n'est pas exploitable ";
               cout << "\n LoiCritere::TestComplet()";
               ret = 0;
            }
			        break;
          }
  
		      default :
          cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
               << "  !\n";
          cout << "\n LoiCritere::TestComplet()";
          ret = 0;
     };
   return ret;
  };
		          
// calcul d'un module d'young équivalent à la loi, ceci pour un
// chargement nul
double LoiCritere::Module_young_equivalent(Enum_dure temps,const Deformation & def ,SaveResul * saveResul_ex)
  { double E=0.; 
    list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
    list <Enumcompletudecalcul>::const_iterator ic,icfin=list_completude_calcul.end();
    // récup des infos spécifiques
    SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul_ex);
	   list <SaveResul*>::iterator lisave =  save_resul.liste_des_SaveResul.begin();

    // cas éventuelle des fonctions de pondération
    list <double>::iterator ipfonc;
    if (avec_ponderation) ipfonc = fonc_ponder.begin();
    for (ili=lois_internes.begin(),ic=list_completude_calcul.begin();ili!=ilifin;ili++,ic++,lisave++)
     {if (*ic != TANGENT_UNIQUEMENT)
			     {if ((avec_ponderation)&&((*ipfonc) != 1.))
           {E +=(*ili)->Module_young_equivalent(temps,def,*lisave)  * (*ipfonc);}
				     else
				       {E +=(*ili)->Module_young_equivalent(temps,def,*lisave);};
				    };
			   if (avec_ponderation) // on incrémente si on a de la pondération
			    ipfonc++;
     };
//cout << "\n E= " << E;			 
    return E;
  };
    
// récupération d'un module de compressibilité équivalent à la loi, ceci pour un chargement nul
// il s'agit ici de la relation -pression = sigma_trace/3. = module de compressibilité * I_eps
double LoiCritere::Module_compressibilite_equivalent(Enum_dure temps,const Deformation & def,SaveResul * saveResul_ex)
  { double module_compressibilite=0.; 
    list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
    list <Enumcompletudecalcul>::const_iterator ic,icfin=list_completude_calcul.end();
    // récup des infos spécifiques
    SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul_ex);
	   list <SaveResul*>::iterator lisave =  save_resul.liste_des_SaveResul.begin();

    // cas éventuelle des fonctions de pondération
    list <double>::iterator ipfonc;
    if (avec_ponderation) ipfonc = fonc_ponder.begin();
    for (ili=lois_internes.begin(),ic=list_completude_calcul.begin();ili!=ilifin;ili++,ic++,lisave++)
      {if (*ic != TANGENT_UNIQUEMENT)
         {if ((avec_ponderation)&&((*ipfonc) != 1.))
            {module_compressibilite +=(*ili)->Module_compressibilite_equivalent(temps,def,*lisave) * (*ipfonc);}
				      else
				        {module_compressibilite +=(*ili)->Module_compressibilite_equivalent(temps,def,*lisave);};
				     };
       if (avec_ponderation) // on incrémente si on a de la pondération
       ipfonc++;
      };
    return module_compressibilite;
  };
		  	
// activation des données des noeuds et/ou elements nécessaires au fonctionnement de la loi
// exemple: mise en service des ddl de température aux noeuds
// ici la grandeur qui sert de proportion entre la première loi et la seconde
void LoiCritere::Activation_donnees(Tableau<Noeud *>& tabnoeud,bool dilatation,LesPtIntegMecaInterne& lesPtMecaInt)
  { if (avec_ponderation)
     { // on passe en revue les grandeurs servant au calcul des fonctions de proportion
       list <Ponderation >::iterator il,ilfin=list_ponderation.end();
       for (il=list_ponderation.begin();il != ilfin;il++)
        { Ponderation& ponder = (*il); // pour simplifier
          int taille = ponder.Type_grandeur().Taille();
          for (int i=1;i<= taille; i++)
           { // dans le cas de fonction de pondération  venant des noeuds par interpolation
             // on active les ddl correspondant à la grandeur qui règle la proportion
             if (ponder.Valeur_aux_noeuds()(i))
              {int nbnoeud = tabnoeud.Taille();
               for (int i=1;i<=nbnoeud;i++)
                {  // on vérifie que la variable type_grandeur existe sinon erreur
                 if (tabnoeud(i)->Existe_ici(ponder.Type_grandeur()(i).Enum()))
                  {tabnoeud(i)->Met_en_service(ponder.Type_grandeur()(i).Enum());}
                 else
                  { cout << "\n erreur: la grandeur " << ponder.Type_grandeur()(i) << " n'existe pas "
                         << " il n'est pas possible d'utiliser une loi critere ponderee avec cette grandeur "
                         << " il manque sans doute des donnees aux noeuds !!! "
                         << "\n LoiCritere::Activation_donnees(...";
                    Sortie(1);
                  };     
                };
              }
             else
              {	// cas d'un vrai ddl étendue
               // on commence par regarder si les pt meca int existent
               if ( ((LesPtIntegMecaInterne*) &lesPtMecaInt) == NULL)
                { cout << "\n *** erreur la loi critere ponderee ne peut pas s'utiliser ici telle quelle ***"
                   << " demander une modification ! ";
                  cout << "\n 	LoiCritere::Activation_donnees(.. " << endl;
                  Sortie(1);
                };	 		 
               // cas normal
               switch (ponder.Type_grandeur()(i).Position()-NbEnum_ddl())
                {case 77: case 78: case 87: case 88: case 89: // cas de "def_duale_mises", cas de "Spherique_eps", cas de "def_duale_mises_maxi"
                  {// et vitesse_def_equi// il faut que l'on active le calcul des invariants de déformations
                   int nbpti = lesPtMecaInt.NbPti();
                   for (int i= 1;i<= nbpti;i++)
                   lesPtMecaInt(i).Change_statut_Invariants_deformation (true);
                   break;
                  }
                 case 81: // cas de "Spherique_sig"
                  {// il faut que l'on active le calcul des invariants des contraintes
                   int nbpti = lesPtMecaInt.NbPti();
                   for (int i= 1;i<= nbpti;i++)
                   lesPtMecaInt(i).Change_statut_Invariants_contrainte (true);
                   break;
                  }
                 default:
                  cout << "\n erreur, le type de proportion " << ponder.Type_grandeur()(i) << " n'est pas disponible "
                       << " pour l'instant au point d'integration ! "
                       << "\n LoiCritere::Activation_donnees(.... ";
                  break;
                };
              };
           };
        };
     };
    // ---maintenant appel des lois élémentaires
    list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
    for (ili=lois_internes.begin();ili!=ilifin;ili++)
      (*ili)->Activation_donnees(tabnoeud,dilatation,lesPtMecaInt);

    // appel de la méthode de la classe mère
    Loi_comp_abstraite::Activ_donnees(tabnoeud,dilatation,lesPtMecaInt);     
  };
   
// 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 LoiCritere::Grandeur_particuliere
              (bool absolue, List_io<TypeQuelconque>& liTQ,Loi_comp_abstraite::SaveResul * saveDon,list<int>& decal) const
 { // tout d'abord on récupère le conteneur
   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveDon);
   int dim = ParaGlob::Dimension();
   list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
   list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
   // maintenant on s'occupe des grandeurs de la loi critere elle même,
   List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
   list<int>::iterator idecal=decal.begin();
   int dim_espace = ParaGlob::Dimension();
   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
     { EnumTypeQuelconque enuTQ = tipParticu.EnuTypeQuelconque().EnumTQ();

       // -----cas de la direction de pli éventuelle
       if (enuTQ == DIRECTION_PLI)
        { Tab_Grandeur_Coordonnee& gr= *((Tab_Grandeur_Coordonnee*) (*itq).Grandeur_pointee()); // pour simplifier
          switch (type_critere)
            {		case PLISSEMENT_MEMBRANE:
                {// tout d'abord on regarde s'il y des vecteurs propres
//                 if (((save_resul.cas_cal_plis == 1)|| (save_resul.cas_cal_plis == 2)|| (save_resul.cas_cal_plis == 3))
                  if (((save_resul.cas_cal_plis == 2)|| (save_resul.cas_cal_plis == 3))
                     && (save_resul.V_P_sig != NULL))
                  // cas où il y a des vecteurs propres, la direction des plis est le premier vecteur, + éventuellement
                  // le deuxième s'il y a deux plis
                  { gr(1) = save_resul.eps_pli(1) * (*save_resul.V_P_sig)(1);
                    gr(2) = save_resul.eps_pli(2) * (*save_resul.V_P_sig)(2);
                  }
                 else // sinon cela veut dire qu'il n'y a pas de pli, on sort un vecteur nul
                  {Coordonnee coor(dim_espace); // un type coordonnee typique
                   gr(1) = coor; gr(2) = coor;
                  };
                 break;
                }
               case PLISSEMENT_BIEL:
                {// tout d'abord on regarde s'il y des vecteurs propres
                 if (save_resul.V_P_sig != NULL)
                  // cas où il y a des vecteurs propres, la direction des plis est le premier vecteur, + éventuellement
                  // le deuxième s'il y a deux plis
                  {gr(1) = save_resul.eps_pli(1) * (*save_resul.V_P_sig)(1);
                   Coordonnee coor(dim_espace);
                   gr(2) = coor;
                  }
                 else // sinon cela veut dire qu'il n'y a pas de pli, on sort un vecteur nul
                  {Coordonnee coor(dim_espace); // un type coordonnee typique
                   gr(1) = coor; gr(2) = coor;
                  };
                 break;
                }
               default :
                 cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
                      << "  !\n";
                 cout << "\n LoiCritere::Grandeur_particuliere(...";
                 Sortie(1);
            };
        };
       if (enuTQ == DIRECTION_PLI_NORMEE) // ici il s'agit uniquement des vecteurs normés
        { Tab_Grandeur_Coordonnee& gr= *((Tab_Grandeur_Coordonnee*) (*itq).Grandeur_pointee()); // pour simplifier
          switch (type_critere)
            {  case PLISSEMENT_MEMBRANE:
//                {if (((save_resul.cas_cal_plis == 1)|| (save_resul.cas_cal_plis == 2)|| (save_resul.cas_cal_plis == 3))
                {if (( (save_resul.cas_cal_plis == 2)|| (save_resul.cas_cal_plis == 3))
                     && (save_resul.V_P_sig != NULL))
                  // cas où il y a des plis correctement calculés
                 // on regarde s'il y des vecteurs propres: normalement il devrait en avoir
 //                if (save_resul.V_P_sig != NULL)
                  // cas où il y a des vecteurs propres, la direction des plis est le premier vecteur, + éventuellement
                  // le deuxième s'il y a deux plis
                  { gr(1) = (*save_resul.V_P_sig)(1);
                    gr(2) = (*save_resul.V_P_sig)(2);
                  }
                 else // sinon cela veut dire qu'il n'y a pas de pli, on sort un vecteur nul
                  // ou que l'on n'a pas pu les calculer
                  {Coordonnee coor(dim_espace); // un type coordonnee typique
                   gr(1) = coor; gr(2) = coor;
                  };
                 break;
                }
               case PLISSEMENT_BIEL:
                {// tout d'abord on regarde s'il y des vecteurs propres
                 if (save_resul.V_P_sig != NULL)
                  // cas où il y a des vecteurs propres, la direction des plis est le premier vecteur, + éventuellement
                  // le deuxième s'il y a deux plis
                  {gr(1) = (*save_resul.V_P_sig)(1);
                   Coordonnee coor(dim_espace);
                   gr(2) = coor;
                  }
                 else // sinon cela veut dire qu'il n'y a pas de pli, on sort un vecteur nul
                  {Coordonnee coor(dim_espace); // un type coordonnee typique
                   gr(1) = coor; gr(2) = coor;
                  };
                 break;
                }
               default :
                 cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
                      << "  !\n";
                 cout << "\n LoiCritere::Grandeur_particuliere(...";
                 Sortie(1);
            };
        };
       if (enuTQ == INDIC_CAL_PLIS) // ici il s'agit d'un scalaire
        { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) (*itq).Grandeur_pointee()); // pour simplifier
          switch (type_critere)
            {  case PLISSEMENT_MEMBRANE: case PLISSEMENT_BIEL: // pour les biels on ne sait pas encore !!
                {*(gr.ConteneurEntier()) = save_resul.cas_cal_plis;
                 break;
                }
               default :
                 // on annule car l'info ne correspond a priori à rien
                 // donc a priori pas de calcul effectué
                 *(gr.ConteneurEntier()) = 0;
            };
        };

//-------- la suite est identique aux lois additives, devra être modifié sans doute ---------
   
       // 2) -----cas des contraintes individuelles à chaque loi à t
       if (enuTQ == CONTRAINTE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
        { Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
          // on boucle sur les lois
          list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
          list <TenseurHH* >::iterator isig_t;
          for (ili=lois_internes.begin(),isig_t = save_resul.l_sigoHH_t.begin();
               ili!=ilifin;ili++,isig_t++)
              {// dans le cas des plis, la loi principale est 2D ou 1D alors que
               // le conteneur est un tenseur d'ordre 3, on transfert en fonction
               TenseurHH* sigHH = (*(isig_t)); // pour simplifier
               if (Dabs(sigHH->Dimension()) != dim)
                {tyTQ(1+(*idecal)).Affectation_trans_dimension(*sigHH,true);
                }
               else // cas ordre 3
                {tyTQ(1+(*idecal)) = *(*(isig_t));
                };
               // puis on décale
               (*idecal)++;
              };
        };
       // 3) -----cas de l'énergie élastique individuelles à chaque loi à t 
       if (enuTQ == ENERGIE_ELASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          // on boucle sur les lois
          list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
          list <EnergieMeca >::iterator ienerg_t; 
          for (ili=lois_internes.begin(),ienerg_t = save_resul.l_energ_t.begin();
               ili!=ilifin;ili++,ienerg_t++)
              { tyTQ(1+(*idecal)) = (*ienerg_t).EnergieElastique(); (*idecal)++;
                };  
        };
       // 4) -----cas de l'énergie plastique individuelles à chaque loi à t 
       if (enuTQ == ENERGIE_PLASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          // on boucle sur les lois
          list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
          list <EnergieMeca >::iterator ienerg_t; 
          for (ili=lois_internes.begin(),ienerg_t = save_resul.l_energ_t.begin();
               ili!=ilifin;ili++,ienerg_t++)
              { tyTQ(1+(*idecal)) = (*ienerg_t).DissipationPlastique(); (*idecal)++;
                };  
        };
       // 5) -----cas de l'énergie visqueuse individuelles à chaque loi à t 
       if (enuTQ == ENERGIE_VISQUEUSE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          // on boucle sur les lois
          list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
          list <EnergieMeca >::iterator ienerg_t; 
          for (ili=lois_internes.begin(),ienerg_t = save_resul.l_energ_t.begin();
               ili!=ilifin;ili++,ienerg_t++)
              { tyTQ(1+(*idecal)) = (*ienerg_t).DissipationVisqueuse(); (*idecal)++;
                };  
        };
       // 6) -----cas de fonction de ponderation des lois 
       if(avec_ponderation)
         if (enuTQ == FONC_PONDERATION)
           { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             // on boucle sur les lois
             list <double>::const_iterator ipfonc, ipfonc_fin = fonc_ponder.end();
             list <double>::const_iterator ifo = save_resul.f_ponder_t.begin();
             for (ipfonc=fonc_ponder.begin();ipfonc != ipfonc_fin;ipfonc++,ifo++)
               { tyTQ(1+(*idecal)) = (*ifo);  (*idecal)++;
               };
           };
      };
     };
   // puis appel des lois élémentaires générales
   for (ili=lois_internes.begin();ili!=ilifin;ili++,isave++)
      (*ili)->Grandeur_particuliere(absolue,liTQ,*isave,decal);
   // puis on examine le cas des différents critères et on récupère les infos internes associées
   switch (type_critere)
     {		case PLISSEMENT_MEMBRANE: //
         {// on récupère les infos pour la loi 1D, dans le cas où il y a des plis
          // si pas de plis, la loi loi_1DCP2_de_3D n'a pas été sollicité, dans ce cas on ne sort rien
          if (save_resul.V_P_sig != NULL)
            loi_1DCP2_de_3D->Grandeur_particuliere(absolue,liTQ,*(save_resul.liste_des_SaveResul.begin()),decal);
          break;
         }
        case PLISSEMENT_BIEL:
         {// ici il n'y a rien pour l'instant à récupérer
          break;
         }
        case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
         {cout << "\nwarning : pour l'instant rien il n'y a rien de prevu en sortie "
               << " de specifique pour les criteres: RUPTURE_SIGMA_PRINC et RUPTURE_EPS_PRINC, a completer !!!\n";
          cout << "\n LoiCritere::Grandeur_particuliere(...";
          Sortie(1);
          break;
         }
		      default :
          cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
               << "  !\n";
          cout << "\n LoiCritere::Grandeur_particuliere(...";
          Sortie(1);
     };
  };

// récupération 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 LoiCritere::ListeGrandeurs_particulieres(bool absolue,List_io<TypeQuelconque>& liTQ) const
 { // tout d'abord on passe en revue les grandeurs des lois associées
   // ** au niveau de l'exécution ce sera l'inverse de cette ordre: on s'occupera d'abord de this puis les lois internes
	  // ** mais a priori cela n'a pas d'importance
   // appel des lois élémentaires
   list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
	  int nb_loi = lois_internes.size();
   for (ili=lois_internes.begin();ili!=ilifin;ili++)
      (*ili)->ListeGrandeurs_particulieres(absolue,liTQ);
   // on examine le cas des différents critères et on récupère les infos internes associées
   switch (type_critere)
     {		case PLISSEMENT_MEMBRANE: //
         {// la partie loi 2D CP a déjà été traité, car il s'agit de la première loi interne
          loi_1DCP2_de_3D->ListeGrandeurs_particulieres(absolue,liTQ);
          break;
         }
        case PLISSEMENT_BIEL:
         {// ici il n'y a rien pour l'instant à récupérer
          break;
         }
        case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
         {// la partie loi 2D CP a déjà été traité, car il s'agit de la première loi interne
          loi_1DCP2_pour_rupture->ListeGrandeurs_particulieres(absolue,liTQ);
          break;
         }
		      default :
          cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
               << "  !\n";
          cout << "\n LoiCritere::ListeGrandeurs_particulieres(...";
          Sortie(1);
     };
  
   // maintenant on s'occupe des grandeurs de la loi critère elle même,
   int dim_espace = ParaGlob::Dimension();
  
   switch (type_critere)
     {		case PLISSEMENT_MEMBRANE: //
         { // -----cas de la direction de pli éventuelle
           Coordonnee coor(dim_espace); // un type coordonnee typique
           Tab_Grandeur_Coordonnee grand5(coor,2); // deux plis maxi
           // la direction des plis dont l'intensité = la norme des vecteurs
           // sous forme d'un vecteur, exprimée aux pti
           TypeQuelconque typQ(DIRECTION_PLI,SIG11,grand5);liTQ.push_back(typQ);
           // idem mais avec des vecteurs normés
           TypeQuelconque typQN(DIRECTION_PLI_NORMEE,SIG11,grand5);liTQ.push_back(typQN);
           // L'indicateur de calcul de plis
           Grandeur_scalaire_entier gscal;
           TypeQuelconque typGI(INDIC_CAL_PLIS,SIG11,gscal);liTQ.push_back(typGI);
          break;
         }
        case PLISSEMENT_BIEL:
         { // -----cas de la direction de pli éventuelle
           Coordonnee coor(dim_espace); // un type coordonnee typique
           Tab_Grandeur_Coordonnee grand5(coor,2); // ne seule direction de pli
           // **** mais  pour l'instant j'en mets 2 de manière à être cohérent avec les membranes
           // sinon pb en sortie des grandeurs
           // la direction des plis, sous forme d'un vecteur, exprimée aux pti
           TypeQuelconque typQ(DIRECTION_PLI,SIG11,grand5);liTQ.push_back(typQ);
           // idem mais avec des vecteurs normés
           TypeQuelconque typQN(DIRECTION_PLI_NORMEE,SIG11,grand5);liTQ.push_back(typQN);
          break;
         }
		      default : break; // rien car on a déjà traité ce cas
     };
  
//-------- la suite est identique aux lois additives, devra être modifié sans doute ---------
   
   // 2) -----cas des contraintes individuelles à chaque loi à t uniquement
   {// ici il s'agit du tenseur des contraintes du pas précédent ou du pas actuel
    //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
    List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
      if ((*itq).EnuTypeQuelconque() == CONTRAINTE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
       { Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
         int taille = tyTQ.Taille()+nb_loi;
         tyTQ.Change_taille(taille); nexistePas = false;
       };
      if (nexistePas)
       {TenseurHH* tens = NevezTenseurHH(ParaGlob::Dimension()); // un tenseur typique
         // en fait on utilise systématiquement un tenseur d'ordre le + élevé, car c'est le conteneur le plus générique
         // et Tab_Grandeur_TenseurHH ne supporte que des tenseurs du même ordre donc s'il y a un tenseur élevé
         // interne il faut que tous les tenseurs soient du même ordre
        Tab_Grandeur_TenseurHH gtHH(*tens,nb_loi);
        // def d'un type quelconque représentatif 
        TypeQuelconque typQ(CONTRAINTE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,gtHH);
        liTQ.push_back(typQ);
        delete tens; // car on n'en a plus besoin
       };
   };

   // pour toutes les énergies
   Tableau <double> tab_double(nb_loi);   
   Tab_Grandeur_scalaire_double grand_courant(tab_double); 
   // 3) -----cas de l'énergie élastique individuelles à chaque loi à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
      if ((*itq).EnuTypeQuelconque() == ENERGIE_ELASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          int taille = tyTQ.Taille()+nb_loi;
          tyTQ.Change_taille(taille); nexistePas = false;
        };
    if (nexistePas)
      {TypeQuelconque typQ1(ENERGIE_ELASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,grand_courant);
       liTQ.push_back(typQ1);
      };
   };
   // 4) -----cas de l'énergie plastique individuelles à chaque loi à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
      if ((*itq).EnuTypeQuelconque() == ENERGIE_PLASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          int taille = tyTQ.Taille()+nb_loi;
          tyTQ.Change_taille(taille); nexistePas = false;
        };
    if (nexistePas)
     { TypeQuelconque typQ1(ENERGIE_PLASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,grand_courant);
       liTQ.push_back(typQ1);
     };
   };
   // 5) -----cas de l'énergie visqueuse individuelles à chaque loi à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
      if ((*itq).EnuTypeQuelconque() == ENERGIE_VISQUEUSE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          int taille = tyTQ.Taille()+nb_loi;
          tyTQ.Change_taille(taille); nexistePas = false;
        };
    if (nexistePas)
     { TypeQuelconque typQ1(ENERGIE_VISQUEUSE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,grand_courant);
       liTQ.push_back(typQ1);
     };
   };
   // 6) -----cas de fonction de ponderation des lois
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == FONC_PONDERATION)
      { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
        int taille = tyTQ.Taille()+nb_loi;
        tyTQ.Change_taille(taille); nexistePas = false;
      };
    if (nexistePas)
     {TypeQuelconque typQ1(FONC_PONDERATION,SIG11,grand_courant);
        liTQ.push_back(typQ1);
     };
   };

 };

// indique le type Enum_comp_3D_CP_DP_1D correspondant à une  loi de comportement
// la fonction est simple dans le cas d'une loi basique, par contre dans le cas
// d'une loi combinée, la réponse dépend des lois internes donc c'est redéfini
// dans les classes dérivées
Enum_comp_3D_CP_DP_1D  LoiCritere::Comportement_3D_CP_DP_1D()
  { // si la liste des lois internes n'est pas nulle, on ramène le cas de la première loi
    if (lois_internes.size() != 0)
      {return (*(lois_internes.begin()))->Comportement_3D_CP_DP_1D();}
    else // sinon on ramène le cas non défini
      {return RIEN_COMP_3D_CP_DP_1D;};

  };

	   //----- 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 LoiCritere::Lecture_base_info_loi(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { if (cas == 1) 
     { string st1,st2,nom_completude_calcul; int nb_loi;
       ent >> st1 >> nb_loi >> st1 >> type_calcul >> st1 >> avec_ponderation >> st2;
       // on supprime la liste de loi actuellement présente par sécurité
       list <Loi_comp_abstraite *>::iterator ilifin=lois_internes.end();
       list <Loi_comp_abstraite *>::iterator ilideb=lois_internes.begin();
       lois_internes.erase(ilideb,ilifin);
       // idem pour list_completude_calcul
       list <Enumcompletudecalcul>::iterator icfin=list_completude_calcul.end();
       list <Enumcompletudecalcul>::iterator icdeb=list_completude_calcul.begin();
       list_completude_calcul.erase(icdeb,icfin);
		 // idem pour la liste  list_ponderation
       list <Ponderation>::iterator iefin=list_ponderation.end();
       list <Ponderation>::iterator iedeb=list_ponderation.begin();
       list_ponderation.erase(iedeb,iefin);
		 // idem pour la liste fonc_ponder
       list <double>::iterator ieefin=fonc_ponder.end();
       list <double>::iterator ieedeb=fonc_ponder.begin();
       fonc_ponder.erase(ieedeb,ieefin);
       // on boucle sur le nombre de loi
       for (int i=1;i<= nb_loi; i++)
        { if (avec_ponderation)
          {ent >> st1;int taille;
           ent >> taille;
           Ponderation ponder; // inter
           ponder.Type_grandeur().Change_taille(taille);
           ponder.Valeur_aux_noeuds().Change_taille(taille);
           ponder.C_proport().Change_taille(taille);
           for (int i=1;i<=taille;i++)
             ent >> ponder.Type_grandeur()(i) >> ponder.Valeur_aux_noeuds()(i);
           // les courbes
           ent >> st1;
           for (int i=1;i<=taille;i++)
             ponder.C_proport()(i) = lesCourbes1D.Lecture_pour_base_info(ent,cas,ponder.C_proport()(i));
             // enreg
           list_ponderation.push_back(ponder);
           fonc_ponder.push_back(1.); // préparation de la place
          };
          //------ maintenant les lois 
          ent >> st1 >> nom_completude_calcul ; // lecture du nom de la loi et du type d'action
          if (nom_completude_calcul == "CONTRAINTE_ET_TANGENT")
          	{ list_completude_calcul.push_back(CONTRAINTE_ET_TANGENT);}
          else if (nom_completude_calcul == "CONTRAINTE_UNIQUEMENT") 
          	{ list_completude_calcul.push_back(CONTRAINTE_UNIQUEMENT);}
          else if (nom_completude_calcul == "TANGENT_UNIQUEMENT") 
          	{ list_completude_calcul.push_back(TANGENT_UNIQUEMENT);}
          else 
            { cout << "\n  *** erreur en lecture du type d'action a faire avec la loi, on a lue " << nom_completude_calcul
                   << " au lieu d'un des noms suivants CONTRAINTE_ET_TANGENT CONTRAINTE_UNIQUEMENT TANGENT_UNIQUEMENT ";
              cout << "\n LoiCritere::Lecture_base_info_loi(...";
              Sortie(1);    
            };
          // definition de la loi
          LoiAbstraiteGeneral * pt = LesLoisDeComp::Def_loi(st1);
          lois_internes.push_back((Loi_comp_abstraite*) pt); // enregistrement de la loi
          // lecture des informations  propres à la  loi
          pt->Lecture_base_info_loi(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
        };
       // les autres paramètres
       string toto;
       ent >>  toto; // entête
       // le niveau d'affichage
       Lecture_permet_affichage(ent,cas,lesFonctionsnD);
       // choix de la methode pour le calcul de plis
       ent >> st1 >> choix_methode_cal_plis_memb;
       // cas de recalcul_dir_plis
       {int choix;
        ent >> st1 >> choix;
        if (choix)
         recalcul_dir_plis = lesFonctionsnD.Lecture_pour_base_info(ent,cas,recalcul_dir_plis);
       }
     }
    else
     { // on boucle directement sur les lois déjà définis
       list <Loi_comp_abstraite *>::iterator ili,ilifin=lois_internes.end();
       for (ili=lois_internes.begin();ili!=ilifin;ili++)
          (*ili)->Lecture_base_info_loi(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 LoiCritere::Ecriture_base_info_loi(ofstream& sort,const int cas)
  { if (cas == 1) 
     { sort << "\n  LOI_CRITERE " << lois_internes.size() << " ";
		     sort << "\n   type_calcul_additif " << type_calcul;
		     sort << " avec_ponderation ";
	      if (avec_ponderation) {sort << 1 ;} else {sort << 0;};
	      sort <<" ,_les_lois: ";
       list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
       list <Enumcompletudecalcul>::const_iterator ic,icfin=list_completude_calcul.end();
	      list <Ponderation >::const_iterator ipon; 
	      if (avec_ponderation) ipon = list_ponderation.begin();
       for (ili=lois_internes.begin(),ic=list_completude_calcul.begin();ili!=ilifin;ili++,ic++)
         { if (avec_ponderation)
		           { sort << "\n avec_fonctions_de_ponderation_des_grandeurs: ";
				           const Ponderation& ponder = (*ipon); // pour simplifier
				           int taille = (ponder.Const_Type_grandeur()).Taille();
				           sort << taille << " ";
				           for (int i=1;i<=taille;i++) 
                {sort << ponder.Const_Type_grandeur()(i) << " " << ponder.Const_Valeur_aux_noeuds()(i) << " ";};
				           // les courbes
				           sort << "\n les_courbes: ";
               for (int i=1;i<=taille;i++) 
                { LesCourbes1D::Ecriture_pour_base_info(sort,cas,ponder.Const_C_proport()(i));};
				           ipon++;
				         };
			
			        sort << "\n " << (*ili)->Nom_comport() << "  ";
           switch (*ic)
         	  {case CONTRAINTE_ET_TANGENT: sort << " CONTRAINTE_ET_TANGENT "; break;
         	   case CONTRAINTE_UNIQUEMENT: sort << " CONTRAINTE_UNIQUEMENT "; break;
         	   case TANGENT_UNIQUEMENT: sort << " TANGENT_UNIQUEMENT "; break;
         	  };
           (*ili)->Ecriture_base_info_loi(sort,cas);
         };
       // affichage autres paramètre
       sort << "\n autres-parametres_loi_critere:--> ";

       // niveau d'affichage
       Affiche_niveau_affichage(sort,cas);
       // choix de la méthode pour le calcul de plis
       sort << "\n choix_methode_cal_plis_memb= " << choix_methode_cal_plis_memb;
      
       // cas de recalcul_dir_plis
       sort << "\n recalcul_dir_plis= ";
       if (recalcul_dir_plis == NULL)
         {sort << " 0 ";}
       else
         {sort << " 1 ";
          LesFonctions_nD::Ecriture_pour_base_info(sort,cas,recalcul_dir_plis);
         };
     }
    else
     { list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
       for (ili=lois_internes.begin();ili!=ilifin;ili++)
         (*ili)->Ecriture_base_info_loi(sort,cas);
     };
   }; 
            
 
// activation du stockage de grandeurs quelconques qui pourront ensuite être récupéré
// via le conteneur SaveResul, si la grandeur n'existe pas ici, aucune action
void LoiCritere::Activation_stockage_grandeurs_quelconques(list <EnumTypeQuelconque >& listEnuQuelc)
 {  // récup de la liste de stockage
    list <EnumTypeQuelconque >& listlocale = ListQuelc_mis_en_acces_localement();
    // on parcours la liste des grandeurs à activer
    // et on remplit la liste locale
    list <EnumTypeQuelconque >::iterator il, ilfin = listEnuQuelc.end();
    for (il = listEnuQuelc.begin();il != ilfin; il++)
//    for (EnumTypeQuelconque enu : listEnuQuelc)
     // on ne remplit que s'il s'agit d'une grandeur qui peut-être accessible
     {switch (*il)
       {case DIRECTION_PLI : case INDIC_CAL_PLIS:
          listlocale.push_back(*(il));
          break;
        default: ;  // pour les autres cas on ne fait rien
       };
     };
  
    // on supprime les doublons localement
    listlocale.sort(); // on ordonne la liste
    listlocale.unique(); // suppression des doublons
  
 };

// insertion des conteneurs ad hoc concernant le stockage de grandeurs quelconques
// passée en paramètre, dans le save result: ces conteneurs doivent être valides
// c-a-d faire partie de listdeTouslesQuelc_dispo_localement
void LoiCritere::Insertion_conteneur_dans_save_result(SaveResul * sr)
 {
    // récup de la liste de stockage
    list <EnumTypeQuelconque >& listlocale = ListQuelc_mis_en_acces_localement();
    // on spécialise saveresult
    SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) sr);
  
    // -- autre stockage éventuel en fonction des grandeurs quelconques demandées par d'autres lois
    // on va regarder s'il faut activer ou non, pour le cas
    // de la récupération de grandeur quelconque au moment de l'utilisation de la loi
    List_io <EnumTypeQuelconque>::iterator jk,jkfin = listlocale.end();
    int dim_espace = ParaGlob::Dimension();
    for (jk=listlocale.begin();jk != jkfin;jk++)
      {EnumTypeQuelconque enu = *jk;
       switch (enu)
        {case DIRECTION_PLI:
            { // on crée le conteneur ad hoc pour le passage d'info
              // def d'un conteneur de grandeurs quelconques, initialisée à 0
              Coordonnee coor(dim_espace); // un type coordonnee typique
              Tab_Grandeur_Coordonnee grand5(coor,2); // deux plis maxi
              // la direction des plis dont l'intensité = la norme des vecteurs
              // sous forme d'un vecteur, exprimée aux pti
              TypeQuelconque typQ(DIRECTION_PLI,SIG11,grand5);
              save_resul.map_type_quelconque[enu]=(typQ);
              break;
            }
         case INDIC_CAL_PLIS :
            { // on crée le conteneur ad hoc pour le passage d'info
              // def d'un conteneur de grandeurs quelconques, initialisée à 0
              Grandeur_scalaire_entier grand_courant(0);
              TypeQuelconque typQ1(enu,SIG11,grand_courant);
              save_resul.map_type_quelconque[enu]=(typQ1);
              break;
            }
         default:
            cout << "\n *** erreur on demande l'acces  a : "
                 << NomTypeQuelconque(enu)
                 << " or celui-ci n'est pas dispo pour la loi ";
            this->Affiche();
            cout << " revoir la mise en donnees ! " << endl;
            Sortie(1);
        };
     };
 
 };


 // ========== codage des METHODES VIRTUELLES  protegees:================
        // calcul des contraintes a t+dt
void LoiCritere::Calcul_SigmaHH (TenseurHH& sigHH_t,TenseurBB& DepsBB,DdlElement & tab_ddl,
             TenseurBB & gijBB_t,TenseurHH & gijHH_t,BaseB& giB,BaseH& gi_H, TenseurBB & epsBB_,
             TenseurBB & delta_epsBB,
             TenseurBB & gijBB_,TenseurHH & gijHH_,Tableau <TenseurBB *>& d_gijBB_,
             double& jacobien_0,double& jacobien,TenseurHH & sigHH
             ,EnergieMeca & energ,const EnergieMeca &
             ,double& module_compressibilite,double&  module_cisaillement
             ,const Met_abstraite::Expli_t_tdt& ex)
 { // on commence par créer un tenseur contrainte qui totalisera toutes les contraintes
   int dim_tens = sigHH.Dimension();
   TenseurHH* sigtotalHH = (NevezTenseurHH(dim_tens,0.));
   TenseurHH* zeroHH = (NevezTenseurHH(dim_tens,0.));

   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   module_compressibilite=module_cisaillement=0.; // init
   energ.Inita(0.); // initialisation des énergies mises en jeux
   // on balaie l'ensemble des lois
   list <Loi_comp_abstraite *>::iterator ili,ilifin=lois_internes.end();
   list <Enumcompletudecalcul>::const_iterator ic,icfin=list_completude_calcul.end();
   // cas éventuelle des fonctions de pondération
   list <double>::iterator ipfonc;
   if (avec_ponderation) ipfonc = fonc_ponder.begin();
	
   list <TenseurHH* >::iterator isig,isig_t;
   list <EnergieMeca >::iterator ienerg,ienerg_t;
   list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
   for (ili=lois_internes.begin(),isig_t = save_resul.l_sigoHH_t.begin(),isig = save_resul.l_sigoHH.begin()
        ,ienerg = save_resul.l_energ.begin(),ienerg_t = save_resul.l_energ_t.begin(),ic=list_completude_calcul.begin();
        ili!=ilifin;ili++,isig_t++,isig++,isave++,ienerg++,ienerg_t++,ic++)
      {  // dimensionnement si nécessaire
         if ((*isig)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*isig); (*isig)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
         if ((*isig_t)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*isig_t); (*isig_t)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
         // initialisation du tenseurs contrainte pour le prochain calcul de la contrainte
         (*(*isig)) = *zeroHH;
         double compress_inter=0.; double cisaill_inter=0;  // init
         // passage des informations spécifique à la loi liste_des_SaveResul
         (*ili)->IndiqueSaveResult(*isave);
         (*ili)->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
         (*ili)->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours

        // -- première phase: préparation de calcul pour l'application d'un critère
        const Met_abstraite::Expli_t_tdt* ex_expli= (Met_abstraite::Expli_t_tdt*) &ex;
        const Met_abstraite::Impli* ex_impli =NULL;
        const Met_abstraite::Umat_cont* ex_umat = NULL;
        int retour_pre_critere =  Pre_Critere
                      (DepsBB,epsBB_,delta_epsBB,jacobien_0,jacobien
                             ,ex_expli,ex_impli,ex_umat);
       
         // calcul de la contrainte résultante,
         if (*ic != TANGENT_UNIQUEMENT)
           {  (*ili)->Calcul_SigmaHH((*(*isig_t)),DepsBB,tab_ddl,gijBB_t,gijHH_t,giB,gi_H,epsBB_,delta_epsBB,
                               gijBB_,gijHH_,d_gijBB_,jacobien_0,jacobien,(*(*isig))
                               ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,ex);
//if (compress_inter == 0. )
// {cout << "\n debug: LoiCritere::Calcul_SigmaHH:... "
//       << " compress= "<< compress_inter ;
//  TenseurHH* ptHH = NevezTenseurHH((*(*isig)));
//  (*(*isig)).BaseAbsolue(*ptHH,giB);
//  cout << "\n sigHH= en giB "; (*(*isig)).Ecriture(cout);
//  cout << "\n sigma en absolu: ";
//  ptHH->Ecriture(cout);
//  cout << "\n module_compressibilite= "<<compress_inter;
//  delete ptHH;
//  cout << flush;
//  (*ili)->Calcul_SigmaHH((*(*isig_t)),DepsBB,tab_ddl,gijBB_t,gijHH_t,giB,gi_H,epsBB_,delta_epsBB,
//                               gijBB_,gijHH_,d_gijBB_,jacobien_0,jacobien,(*(*isig))
//                               ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,ex);
// }
// if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//    cout << "\n test1: LoiCritere::Calcul_SigmaHH:... " << flush;
              #ifdef MISE_AU_POINT
              // sortie éventuelle d'infos
              if  (Permet_affichage() > 5)
               { cout << "\nLoiCritere::Calcul_SigmaHH: avant critere ";
                 cout << "\n ele= "<< (ptintmeca_en_cours->Nb_ele()) << ", nbpti= "<< (ptintmeca_en_cours->Nb_pti());
                 //if (sigHH.MaxiComposante() > 20.)
                 TenseurBB* ptBB = NevezTenseurBB(epsBB_);
                 epsBB_.BaseAbsolue(*ptBB,(gi_H));
                 cout << "\n eps en absolu: ";
                 ptBB->Ecriture(cout);
                 delta_epsBB.BaseAbsolue(*ptBB,gi_H);
                 cout << "\n delta eps en absolu: ";
                 ptBB->Ecriture(cout);
                 TenseurHH* ptHH = NevezTenseurHH((*(*isig)));
                 (*(*isig)).BaseAbsolue(*ptHH,giB);
                 cout << "\n base giB "<< giB;
                 cout << "\n sigHH= en giB "; (*(*isig)).Ecriture(cout);
                 cout << "\n sigma en absolu: ";
                 ptHH->Ecriture(cout);
                 delete ptBB; delete ptHH;
              };
             #endif
             // -- on applique le critère ce qui peut changer ou pas les résultats précédents
             bool implicit = false;bool en_base_absolu = false;
             Met_abstraite::Umat_cont umat_transfert; // une umat inter
             ex.Recup_Umat_cont(umat_transfert);
//if ((ptintmeca_en_cours->Nb_ele() == 100) && (ptintmeca_en_cours->Nb_pti() == 1))
//  cout << "\n debug: LoiCritere::Calcul_SigmaHH:... " << flush;
             int retour_critere =  Critere
                                 (en_base_absolu, (*(*isig_t)),DepsBB,epsBB_,delta_epsBB,jacobien_0,jacobien
                                  ,(*(*isig)),*d_sigma_deps_inter
                                  ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,implicit,umat_transfert
                                  );
// if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//if (compress_inter == 0. )
// {cout << "\n debug: LoiCritere::Calcul_SigmaHH:... "
//       << " compress= "<< compress_inter ;
//  TenseurHH* ptHH = NevezTenseurHH((*(*isig)));
//  (*(*isig)).BaseAbsolue(*ptHH,giB);
//  cout << "\n sigHH= en giB "; (*(*isig)).Ecriture(cout);
//  cout << "\n sigma en absolu: ";
//  ptHH->Ecriture(cout);
//  cout << "\n module_compressibilite= "<<compress_inter;
//  delete ptHH;
//  cout << "\n ele= "<< (ptintmeca_en_cours->Nb_ele()) << ", nbpti= "<< (ptintmeca_en_cours->Nb_pti());
//  cout << flush;
//  int retour_critere =  Critere
//                                 (en_base_absolu, (*(*isig_t)),DepsBB,epsBB_,delta_epsBB,jacobien_0,jacobien
//                                  ,(*(*isig)),*d_sigma_deps_inter
//                                  ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,implicit,umat_transfert
//                                  );
 
// }
//    cout << "\n test2: LoiCritere::Calcul_SigmaHH:... " << flush;
              #ifdef MISE_AU_POINT
              // sortie éventuelle d'infos après l'application du critère
              if  (Permet_affichage() > 5)
               { cout << "\nLoiCritere::Calcul_SigmaHH: apres l'application du critere: ";
                 TenseurHH* ptHH = NevezTenseurHH((*(*isig)));
                 (*(*isig)).BaseAbsolue(*ptHH,giB);
                 cout << "\n sigHH= en giB "; (*(*isig)).Ecriture(cout);
                 cout << "\n sigma en absolu: ";
                 ptHH->Ecriture(cout);
                 cout << "\n module_compressibilite= "<<compress_inter;
////------ debug
//       if (ptHH->MaxiComposante() > 20.)
//         cout << "\n debug LoiCritere::Calcul_SigmaHH "
//              << "(ptHH->MaxiComposante() > 20.) !! ";
////------ debug
                 delete ptHH;
               };
             #endif

             switch (retour_critere)
              {case 0: // cas d'un pb
                 if (Permet_affichage() > 4)
                    cout << "\n pb dans l'application du critere, on continue sans tenir compte du critere ";
                 if (Permet_affichage() > 5)
                  {cout << "\n **>>  il y a eu un pb que l'on n'a pas pu resoudre, rien n'a ete modifie ";
                   if (ptintmeca_en_cours != NULL) ptintmeca_en_cours->Signature();
                   cout << "\n retour_critere= "<< retour_critere ;
                  };
                 break;
               case 1: break; // le critère n'a rien changé
               case 2: if (Permet_affichage() > 5)
                         {cout << "\n **>> l'application du critere conduit a une contrainte  nulle ";
                          if (ptintmeca_en_cours != NULL) ptintmeca_en_cours->Signature();
                          //cout << "\n retour_critere= "<< retour_critere ;
                         }
               break; // l'application du critère -> tout nul
               case 3: break; // il y a eu des modification
               default: cout << "\n *** cas non prevu ! "
                             << "\n LoiCritere::Calcul_SigmaHH (.." << endl;
                        Sortie(2);
                        break;
              };

             // --- traitement en fonction du type de calcul
//             if (retour_critere != 2) // ==1 signifie que tout est nul, dans ce cas ce n'est pas la peine d'ajouter
// transitoirement on va mettre une petite raideur
//         if (retour_critere == 2)
//          { compress_inter /= 1000.;
//            cisaill_inter /= 1000.;
//          };
               {if ((avec_ponderation)&&((*ipfonc) != 1.))
                         {module_compressibilite += (*ipfonc)*compress_inter;
                          module_cisaillement +=  (*ipfonc)*cisaill_inter;                 
                          energ += (*ienerg) * (*ipfonc); // update des énergies totales
                          (*sigtotalHH) += (*ipfonc)*(*(*isig)); // on ajoute la contrainte au total
                }
                else  						 
                         {module_compressibilite += compress_inter;
                          module_cisaillement +=  cisaill_inter;                 
                          energ += (*ienerg); // update des énergies totales
                          (*sigtotalHH) += (*(*isig)); // on ajoute la contrainte au total
                };
               };
             if (avec_ponderation) // on incrémente si on a de la pondération
			            ipfonc++;
           };
      };
  
    // recopie du résultat
    sigHH = (*sigtotalHH);
    delete sigtotalHH; delete zeroHH;
    LibereTenseur();   
 };
        
        // calcul des contraintes a t+dt et de ses variations  
void LoiCritere::Calcul_DsigmaHH_tdt(TenseurHH& sigHH_t,TenseurBB& DepsBB,DdlElement & tab_ddl
            ,BaseB& giB_t,TenseurBB & gijBB_t,TenseurHH & gijHH_t
            ,BaseB& giB_tdt,Tableau <BaseB> & d_giB_tdt,BaseH& giH_tdt,Tableau <BaseH> & d_giH_tdt
            ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *>& d_epsBB
            ,TenseurBB & delta_epsBB,TenseurBB & gijBB_tdt,TenseurHH & gijHH_tdt
		          ,Tableau <TenseurBB *>& d_gijBB_tdt
		  	       ,Tableau <TenseurHH *>& d_gijHH_tdt,double& jacobien_0,double& jacobien
		  	       ,Vecteur& d_jacobien_tdt,TenseurHH& sigHH_tdt,Tableau <TenseurHH *>& d_sigHH
            ,EnergieMeca & energ,const EnergieMeca &
            ,double& module_compressibilite,double&  module_cisaillement
            ,const Met_abstraite::Impli& ex )
 { // on commence par créer un tenseur contrainte qui totalisera toutes les contraintes
   // le tenseurs est initialisé à 0.
   int dim_tens = sigHH_tdt.Dimension();
   TenseurHH* sigtotalHH = (NevezTenseurHH(dim_tens,0.));
   TenseurHH* zeroHH = (NevezTenseurHH(dim_tens,0.));
   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   module_compressibilite=module_cisaillement=0.; // init
   energ.Inita(0.); // initialisation des énergies mises en jeux
   // on vérifie que le tableau de travail intermédiaire statique est correctement 
   // dimensionné sinon on le modifie   
   int taille = d_sigHH.Taille();
   if (d_sigtotalHH.Taille() == 0) 
     { d_sigtotalHH.Change_taille(taille,NULL);}
   else if ( taille != d_sigtotalHH.Taille()) 
     { int ancienne_taille = d_sigtotalHH.Taille();
       d_sigtotalHH.Change_taille(taille);
       if (ancienne_taille < taille)
         for (int i=ancienne_taille+1;i<=taille;i++) d_sigtotalHH(i)=NULL;
     };
   for (int i=1;i<=taille;i++)
     { // mise à zéro des tenseurs du tableau avec création si nécessaire
       if (d_sigtotalHH(i) == NULL) {d_sigtotalHH(i)=NevezTenseurHH(dim_tens,0.);}
       else if ( d_sigtotalHH(i)->Dimension() != dim_tens)
         { delete d_sigtotalHH(i); d_sigtotalHH(i)=NevezTenseurHH(dim_tens,0.);}
       else // mise à zéro simple
         *(d_sigtotalHH(i))= (*zeroHH);
     };

   // première mise à zéro de d_sigHH
   for (int j1=1;j1<=taille;j1++) *d_sigHH(j1) = (*zeroHH);
        
   Tableau <TenseurHH *>& d_SigtotalHH = d_sigtotalHH; // pour simplifier l'acces
   // maintenant on balaie l'ensemble des lois
   list <Loi_comp_abstraite *>::iterator ili,ilifin=lois_internes.end();
   list <Enumcompletudecalcul>::const_iterator icfin=list_completude_calcul.end();
   list <Enumcompletudecalcul>::const_iterator ic = list_completude_calcul.begin();
   // cas éventuelle des fonctions de pondération
   list <double>::iterator ipfonc;
   if (avec_ponderation) ipfonc = fonc_ponder.begin();
   
   list <TenseurHH* >::iterator isig = save_resul.l_sigoHH.begin();
   list <TenseurHH* >::iterator isig_t = save_resul.l_sigoHH_t.begin();
   list <EnergieMeca >::iterator ienerg  = save_resul.l_energ.begin();
   list <EnergieMeca >::iterator ienerg_t  = save_resul.l_energ_t.begin();
   list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
   for (ili=lois_internes.begin();ili!=ilifin;ili++,isig_t++,isig++,isave++,ienerg++,ienerg_t++,ic++)
      { // initialisation du tenseurs contrainte à chaque début de boucle
        sigHH_tdt = (*zeroHH);
        // dimensionnement si nécessaire
        if ((*isig)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*isig); (*isig)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        if ((*isig_t)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*isig_t); (*isig_t)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        double compress_inter=0.; double cisaill_inter=0;  // init
        // passage des informations spécifique à la loi liste_des_SaveResul
        (*ili)->IndiqueSaveResult(*isave);  
        (*ili)->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
        (*ili)->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours

        // -- première phase: préparation de calcul pour l'application d'un critère
        const Met_abstraite::Expli_t_tdt* ex_expli= NULL;
        const Met_abstraite::Impli* ex_impli = (Met_abstraite::Impli*) &ex;
        const Met_abstraite::Umat_cont* ex_umat = NULL;
        int retour_pre_critere =  Pre_Critere
                      (DepsBB,epsBB_tdt,delta_epsBB,jacobien_0,jacobien
                             ,ex_expli,ex_impli,ex_umat);
       
        // -- calcul initial de la contrainte résultante, pour l'instant sans tenir compte de critère
        (*ili)->Calcul_DsigmaHH_tdt((*(*isig_t)),DepsBB,tab_ddl,giB_t,gijBB_t,gijHH_t,giB_tdt
                                      ,d_giB_tdt,giH_tdt,d_giH_tdt,epsBB_tdt,d_epsBB,delta_epsBB
                                      ,gijBB_tdt,gijHH_tdt,d_gijBB_tdt,d_gijHH_tdt,jacobien_0
                                      ,jacobien,d_jacobien_tdt,sigHH_tdt,d_sigHH,(*ienerg)
                                      ,(*ienerg_t),compress_inter,cisaill_inter,ex);

         #ifdef MISE_AU_POINT
         // sortie éventuelle d'infos
         if  (Permet_affichage() > 5)
          { cout << "\nLoiCritere::Calcul_DSigmaHH_tdt:  avant critere  ";
            //if (sigHH.MaxiComposante() > 20.)
            TenseurBB* ptBB = NevezTenseurBB(epsBB_tdt);
            epsBB_tdt.BaseAbsolue(*ptBB,(giH_tdt));
            cout << "\n eps en absolu: ";
            ptBB->Ecriture(cout);
            delta_epsBB.BaseAbsolue(*ptBB,giH_tdt);
            cout << "\n delta eps en absolu: ";
            ptBB->Ecriture(cout);
            TenseurHH* ptHH = NevezTenseurHH(sigHH_tdt);
            sigHH_tdt.BaseAbsolue(*ptHH,giB_tdt);
            cout << "\n base giB "<< giB_tdt;
            cout << "\n sigHH= en giB "; sigHH_tdt.Ecriture(cout);
            cout << "\n sigma en absolu: ";
            ptHH->Ecriture(cout);
            delete ptBB; delete ptHH;
            if (Permet_affichage() > 6)
               {int nbddl = d_gijBB_tdt.Taille();
                cout << "\n operateur tangent avant critere: " ;
                for (int i = 1; i<= nbddl; i++)
                  {cout << "\n i= "<< i;
                   (*d_sigHH(i)).Ecriture(cout);
                  };
               };
         };
        #endif
        // -- on applique le critère ce qui peut changer ou pas les résultats précédents
        bool implicit = true;bool en_base_absolu = false;
        Met_abstraite::Umat_cont umat_transfert; // une umat inter
        ex.Recup_Umat_cont(umat_transfert);
        int retour_critere =  Critere (en_base_absolu, (*(*isig_t)),DepsBB,epsBB_tdt,delta_epsBB
                                       ,jacobien_0,jacobien,sigHH_tdt,*d_sigma_deps_inter
		  	                                  ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,implicit
                                       ,umat_transfert);
        #ifdef MISE_AU_POINT
        // sortie éventuelle d'infos après l'application du critère
        if  (Permet_affichage() > 5)
         { cout << "\nLoiCritere::Calcul_DSigmaHH_tdt: apres l'application du critere: ";
           TenseurHH* ptHH = NevezTenseurHH(sigHH_tdt);
           sigHH_tdt.BaseAbsolue(*ptHH,giB_tdt);
           cout << "\n sigHH= en giB "; sigHH_tdt.Ecriture(cout);
           cout << "\n sigma en absolu: ";
           ptHH->Ecriture(cout);
////------ debug
//       if (ptHH->MaxiComposante() > 100.)
//         cout << "\n debug LoiCritere::Calcul_SigmaHH "
//              << "(ptHH->MaxiComposante() > 100.) !! ";
////------ debug
            delete ptHH;
          };
        #endif
        switch (retour_critere)
         {case 0: // cas d'un pb
            if (Permet_affichage() > 4)
                    cout << "\n pb dans l'application du critere, on continue sans tenir compte du critere ";
                 if (Permet_affichage() > 5)
                  {cout << "\n **>> il y a eu un pb que l'on n'a pas pu resoudre, rien n'a ete modifie ";
                   if (ptintmeca_en_cours != NULL) ptintmeca_en_cours->Signature();
                   cout << "\n retour_critere= "<< retour_critere ;
                  };
            break;
          case 1: break; // le critère n'a rien changé
          case 2: if (Permet_affichage() > 5)
                  {//cout << "\n retour_critere= "<< retour_critere ;
                   cout << "\n **>>  l'application du critere conduit a une contrainte et un operateur"
                        << " tangent nul ";
                   if (ptintmeca_en_cours != NULL) ptintmeca_en_cours->Signature();
                  }
          break; // l'application du critère -> tout nul
          case 3: // il y a eu des modification on va recalculer l'opérateur tangent / au ddl
           { int nbddl = d_gijBB_tdt.Taille();
             for (int i = 1; i<= nbddl; i++)
                (*d_sigHH(i)) = (*d_sigma_deps_inter) && (*(d_epsBB(i)));
             if (Permet_affichage() > 6)
               {cout << "\n **>>  retour_critere= "<< retour_critere
                     << " recalcul de l'operateur tangent: " ;
                for (int i = 1; i<= nbddl; i++)
                  {cout << "\n i= "<< i;
                   (*d_sigHH(i)).Ecriture(cout);
                  };
               };
             break;
           }
          default: cout << "\n *** cas non prevu ! "
                        << "\n LoiCritere::Calcul_DsigmaHH_tdt (.." << endl;
                   Sortie(2);
                   break;
         };
       
// application d'un critère
//  0  : il y a eu un pb que l'on n'a pas peu résoudre, rien n'a été modifié
//  1  : le critère n'a rien modifié
//  2  : l'application du critère conduit à une contrainte et un opérateur tangent nul
//  3  : les données d'entrée ont été modifiées: contraintes, opérateur tangent, module, énergies

        // --- traitement en fonction du type de calcul
//        if (retour_critere != 2) // ==2 signifie que tout est nul, dans ce cas ce n'est pas la peine d'ajouter
// non on ne peut pas faire cela car cela conduit à une structure complètement instable
// transitoirement on va mettre une petite raideur
//         if (retour_critere == 2)
//          { compress_inter /= 1000.;
//            cisaill_inter /= 1000.;
//          };
       
         switch (*ic)
          { case CONTRAINTE_ET_TANGENT:  // cas normal
              {if ((avec_ponderation)&&((*ipfonc) != 1.))
                {module_compressibilite += (*ipfonc) * compress_inter;
                 module_cisaillement +=  (*ipfonc) * cisaill_inter;                 
                 energ +=   (*ienerg) * (*ipfonc); // update des énergies totales
                 (*sigtotalHH) += (*ipfonc) * (sigHH_tdt); // on ajoute la contrainte au total
                 (*(*isig)) = sigHH_tdt; // on sauvegarde la contrainte partielle
                 // récup de l'opérateur tangent
                 for (int j=1;j<=taille;j++)
                   { (*d_SigtotalHH(j)) += (*ipfonc) * (*d_sigHH(j));
                     *d_sigHH(j) = (*zeroHH);
                   };
                 }
               else
                {energ += (*ienerg); // update des énergies
                 module_compressibilite += compress_inter;
                 module_cisaillement +=  cisaill_inter;
                 (*sigtotalHH) += sigHH_tdt; // récup du tenseur et on ajoute la contrainte au total
                 (*(*isig))=sigHH_tdt; // on sauvegarde la contrainte partielle
                 // récup de l'opérateur tangent
                 for (int j=1;j<=taille;j++)
                   { (*d_SigtotalHH(j)) += (*d_sigHH(j));
                     *d_sigHH(j) = (*zeroHH);
                   };
                };
                break;
              }
         	  case CONTRAINTE_UNIQUEMENT:
              {if ((avec_ponderation)&&((*ipfonc) != 1.))
                {module_compressibilite += (*ipfonc) * compress_inter;
                 module_cisaillement +=  (*ipfonc) * cisaill_inter;                 
                 energ +=   (*ienerg) * (*ipfonc); // update des énergies totales
                 (*sigtotalHH) += (*ipfonc) * (sigHH_tdt); // on ajoute la contrainte au total
                 (*(*isig)) = sigHH_tdt; // on sauvegarde la contrainte partielle
                 // récup de l'opérateur tangent
                 for (int j=1;j<=taille;j++)
                   { *d_sigHH(j) = (*zeroHH);};
                }
               else
                {energ += (*ienerg); // update des énergies
                 module_compressibilite += compress_inter;
                 module_cisaillement +=  cisaill_inter;                 
                 (*sigtotalHH) += sigHH_tdt; // récup du tenseur et on ajoute la contrainte au total
                 (*(*isig))=sigHH_tdt; // on sauvegarde la contrainte partielle
                 // mise à zéro de l'opérateur tangent pour la suite
                 for (int j=1;j<=taille;j++)
                   { *d_sigHH(j) = (*zeroHH);};
                };
               break;
              }
         	  case TANGENT_UNIQUEMENT:
              {(*ienerg).Inita(0.); // on remet à 0 l'énergie partielle car pas de prise en compte de la contrainte
               (*(*isig))=(*zeroHH); // on remet à 0 la contrainte partielle
               if ((avec_ponderation)&&((*ipfonc) != 1.))
                {// récup de l'opérateur tangent
                 for (int j=1;j<=taille;j++)
                   { (*d_SigtotalHH(j)) += (*ipfonc) * (*d_sigHH(j));
                     *d_sigHH(j) = (*zeroHH);
                   };
                }
               else
                // on ne tiens pas en compte du module de compressibilité ni de cisaillement
                // récup de l'opérateur tangent
                {for (int j=1;j<=taille;j++)
                  { (*d_SigtotalHH(j)) += (*d_sigHH(j));
                    *d_sigHH(j) = (*zeroHH);};
                };
               break;
              }
          };
        if (avec_ponderation) // on incrémente si on a de la pondération
			       ipfonc++;
      }; // fin de la boucle sur les lois
    // recopie du résultat
    sigHH_tdt = (*sigtotalHH);
    for (int k=1;k<=taille;k++)
       (*d_sigHH(k)) = (*d_SigtotalHH(k));
    delete sigtotalHH; delete zeroHH;
    LibereTenseur();   
 };
		  	
        // calcul des contraintes et ses variations  par rapport aux déformations a t+dt
        // en_base_orthonormee:  le tenseur de contrainte en entrée est  en orthonormee
        //                  le tenseur de déformation et son incrémentsont également en orthonormees
        //                 si = false: les bases transmises sont utilisées
        // ex: contient les éléments de métrique relativement au paramétrage matériel = X_(0)^a
void LoiCritere::Calcul_dsigma_deps (bool en_base_orthonormee, TenseurHH & sigHH_t,TenseurBB& DepsBB
            ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB,double& jacobien_0,double& jacobien
            ,TenseurHH& sigHH_tdt,TenseurHHHH& d_sigma_deps
            ,EnergieMeca & energ,const EnergieMeca & 
            ,double& module_compressibilite,double&  module_cisaillement
            ,const Met_abstraite::Umat_cont& ex)
 { // on commence par créer un tenseur contrainte qui totalisera toutes les contraintes
   // le tenseurs est initialisé à 0.
   int dim_tens = sigHH_tdt.Dimension();
   TenseurHH* sigtotalHH = (NevezTenseurHH(dim_tens,0.));
   TenseurHH* zeroHH = (NevezTenseurHH(dim_tens,0.));
   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   module_compressibilite=module_cisaillement=0.; // init
   energ.Inita(0.); // initialisation des énergies mises en jeux
   // redimentionnement éventuel pour le comportement tangent
   if (d_sigma_deps_inter != NULL)
         { if (d_sigma_deps_inter->Dimension() != d_sigma_deps.Dimension())
         	{ delete d_sigma_deps_inter; d_sigma_deps_inter = NevezTenseurHHHH(d_sigma_deps);}
         }
   else {d_sigma_deps_inter = NevezTenseurHHHH(d_sigma_deps);};
//   if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//     {cout << "\n debug: LoiCritere::Calcul_dsigma_deps (... "
//           << " d_sigma_deps_inter: dimension = " << d_sigma_deps_inter->Dimension()
//           << flush;
//     };
   // idem pour le comportement tangent
   d_sigma_deps.Inita(0.);
   // maintenant on balaie l'ensemble des lois
   list <Loi_comp_abstraite *>::iterator ili,ilifin=lois_internes.end();
   list <Enumcompletudecalcul>::const_iterator ic,icfin=list_completude_calcul.end();
	  // cas éventuelle des fonctions de pondération
	  list <double>::iterator ipfonc;
	  if (avec_ponderation) ipfonc = fonc_ponder.begin();

   list <TenseurHH* >::iterator isig,isig_t;
   list <EnergieMeca >::iterator ienerg,ienerg_t;
   list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
   for (ili=lois_internes.begin(),isig_t = save_resul.l_sigoHH_t.begin(),isig = save_resul.l_sigoHH.begin()
        ,ienerg = save_resul.l_energ.begin(),ienerg_t = save_resul.l_energ_t.begin(),ic=list_completude_calcul.begin();
        ili!=ilifin;ili++,isig_t++,isig++,isave++,ienerg++,ienerg_t++,ic++)
      { // initialisation du tenseurs contrainte à chaque début de boucle
        sigHH_tdt = (*zeroHH);
        // initialisation du comportement tangent
        d_sigma_deps_inter->Inita(0.);
        // dimensionnement si nécessaire
        if ((*isig)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*isig); (*isig)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        if ((*isig_t)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*isig_t); (*isig_t)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        double compress_inter=0.; double cisaill_inter=0;  // init
        // passage des informations spécifique à la loi liste_des_SaveResul
        (*ili)->IndiqueSaveResult(*isave);
        (*ili)->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
        (*ili)->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours

        // -- première phase: préparation de calcul pour l'application d'un critère
        const Met_abstraite::Expli_t_tdt* ex_expli= NULL;
        const Met_abstraite::Impli* ex_impli = NULL;
        const Met_abstraite::Umat_cont* ex_umat = (Met_abstraite::Umat_cont*) &ex;
        int retour_pre_critere =  Pre_Critere
                      (DepsBB,epsBB_tdt,delta_epsBB,jacobien_0,jacobien
                             ,ex_expli,ex_impli,ex_umat);
        bool implicit = true;

        // -- prédiction : calcul de la contrainte résultante
        // on passe en paramètre delta_eps_BB_2D à la place de delta_epsBB
        // cet incrément peut avoir été modifié par la méthode Pre_Critere
        (*ili)->Calcul_dsigma_deps (en_base_orthonormee, (*(*isig_t)),DepsBB,epsBB_tdt,delta_eps_BB_2D,jacobien_0,jacobien
		  	                        ,sigHH_tdt,*d_sigma_deps_inter
		  	                        ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,ex);

         #ifdef MISE_AU_POINT
         // sortie éventuelle d'infos
         if  (Permet_affichage() > 5)
          { cout << "\nLoiCritere::Calcul_dsigma_deps:  avant critere  ";
            //if (sigHH.MaxiComposante() > 20.)
            TenseurBB* ptBB = NevezTenseurBB(epsBB_tdt);
            epsBB_tdt.BaseAbsolue(*ptBB,*(ex.giH_tdt));
            cout << "\n eps en absolu: ";
            ptBB->Ecriture(cout);
            delta_epsBB.BaseAbsolue(*ptBB,*(ex.giH_tdt));
            cout << "\n delta eps en absolu: ";
            ptBB->Ecriture(cout);
            TenseurHH* ptHH = NevezTenseurHH(sigHH_tdt);
            sigHH_tdt.BaseAbsolue(*ptHH,*(ex.giB_tdt));
            cout << "\n base giB(1) "<< (*(ex.giB_tdt))(1)
                 << "\n base giB(2) "<< (*(ex.giB_tdt))(2);
            cout << "\n sigHH= en giB "; sigHH_tdt.Ecriture(cout);
            cout << "\n sigma en absolu: ";
            ptHH->Ecriture(cout);
            delete ptBB; delete ptHH;
         };
        #endif
        // -- on applique le critère ce qui peut changer ou pas les résultats précédents
        int retour_critere =  Critere (en_base_orthonormee, (*(*isig_t)),DepsBB,epsBB_tdt,delta_epsBB,jacobien_0,jacobien
		  	                        ,sigHH_tdt,*d_sigma_deps_inter
		  	                        ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,implicit,ex);
        #ifdef MISE_AU_POINT
        // sortie éventuelle d'infos après l'application du critère
        if  (Permet_affichage() > 5)
         { cout << "\nLoiCritere::Calcul_dsigma_deps: apres l'application du critere: ";
           TenseurHH* ptHH = NevezTenseurHH(sigHH_tdt);
           sigHH_tdt.BaseAbsolue(*ptHH,*(ex.giB_tdt));
           cout << "\n sigHH= en giB "; sigHH_tdt.Ecriture(cout);
           cout << "\n sigma en absolu: ";
           ptHH->Ecriture(cout);
////------ debug
//       if (ptHH->MaxiComposante() > 100.)
//         cout << "\n debug LoiCritere::Calcul_SigmaHH "
//              << "(ptHH->MaxiComposante() > 100.) !! ";
////------ debug
            delete ptHH;
          };
        #endif
        switch (retour_critere)
         {case 0: // cas d'un pb
            if (Permet_affichage() > 4)
                    cout << "\n pb dans l'application du critere, on continue sans tenir compte du critere ";
                 if (Permet_affichage() > 5)
                  {cout << "\n **>> il y a eu un pb que l'on n'a pas pu resoudre, rien n'a ete modifie ";
                   if (ptintmeca_en_cours != NULL) ptintmeca_en_cours->Signature();
                   cout << "\n retour_critere= "<< retour_critere ;
                  };
            break;
          case 1: break; // le critère n'a rien changé
          case 2: if (Permet_affichage() > 5)
                  {//cout << "\n retour_critere= "<< retour_critere ;
                   cout << "\n **>>  l'application du critere conduit a une contrainte et un operateur"
                        << " tangent nul ";
                   if (ptintmeca_en_cours != NULL) ptintmeca_en_cours->Signature();
                  }
                  break; // l'application du critère -> tout nul
          case 3: break; // il y a eu des modification
          default: cout << "\n *** cas non prevu ! "
                        << "\n LoiCritere::Calcul_DsigmaHH_tdt (.." << endl;
                   Sortie(2);
                   break;
         };

        // --- traitement en fonction du type de calcul
        if (retour_critere != 1) // ==1 signifie que tout est nul, dans ce cas ce n'est pas la peine d'ajouter
         switch (*ic)
          { case CONTRAINTE_ET_TANGENT:  // cas normal
				         {if ((avec_ponderation)&&((*ipfonc) != 1.))
               {module_compressibilite += (*ipfonc) * compress_inter;
                module_cisaillement +=  (*ipfonc) * cisaill_inter;                 
                energ +=   (*ienerg) * (*ipfonc); // update des énergies totales
                (*sigtotalHH) += (*ipfonc) * (sigHH_tdt); // on ajoute la contrainte au total
                (*(*isig)) = sigHH_tdt; // on sauvegarde la contrainte partielle
                // récup de l'opérateur tangent
                d_sigma_deps += *d_sigma_deps_inter  * (*ipfonc) ;
               }
				          else
               {energ += (*ienerg); // update des énergies
                module_compressibilite += compress_inter;
                module_cisaillement +=  cisaill_inter;                 
                (*sigtotalHH) += sigHH_tdt; // récup du tenseur et on ajoute la contrainte au total
                (*(*isig))=sigHH_tdt; // on sauvegarde la contrainte partielle
                // récup de l'opérateur tangent
                d_sigma_deps += *d_sigma_deps_inter;
					          };
				          break;
             }
         	  case CONTRAINTE_UNIQUEMENT:
				         {if ((avec_ponderation)&&((*ipfonc) != 1.))
               {module_compressibilite += (*ipfonc) * compress_inter;
                module_cisaillement +=  (*ipfonc) * cisaill_inter;                 
                energ +=   (*ienerg) * (*ipfonc); // update des énergies totales
                (*sigtotalHH) += (*ipfonc) * (sigHH_tdt); // on ajoute la contrainte au total
                (*(*isig)) = sigHH_tdt; // on sauvegarde la contrainte partielle
                // on ne récupère pas  l'opérateur tangent 
					          }
				          else
               {energ += (*ienerg); // update des énergies
                module_compressibilite += compress_inter;
                module_cisaillement +=  cisaill_inter;                 
                (*sigtotalHH) += sigHH_tdt; // récup du tenseur et on ajoute la contrainte au total
                (*(*isig))=sigHH_tdt; // on sauvegarde la contrainte partielle
                // on ne récupère pas  l'opérateur tangent 
					          };
				          break;
             }
         	  case TANGENT_UNIQUEMENT:
				         {(*ienerg).Inita(0.); // on remet à 0 l'énergie partielle car pas de prise en compte de la contrainte
				          (*(*isig))=(*zeroHH); // on remet à 0 la contrainte partielle
				          if ((avec_ponderation)&&((*ipfonc) != 1.))
               {// récup de l'opérateur tangent
                d_sigma_deps += *d_sigma_deps_inter  * (*ipfonc) ;
					          }
				          else
               // on ne tiens pas en compte du module de compressibilité ni de cisaillement
               // récup de l'opérateur tangent
               {d_sigma_deps += *d_sigma_deps_inter;};
				          break;
             }
          };
        if (avec_ponderation) // on incrémente si on a de la pondération
			       ipfonc++;

      };
    // recopie du résultat
    sigHH_tdt = (*sigtotalHH);
    delete sigtotalHH; delete zeroHH;
    LibereTenseur();LibereTenseurQ();    
 };

// application d'un critère
//  0  : il y a eu un pb que l'on n'a pas peu résoudre, rien n'a été modifié
//  1  : le critère n'a rien modifié
//  2  : l'application du critère conduit à une contrainte et un opérateur tangent nul
//  3  : les données d'entrée ont été modifiées: contraintes, opérateur tangent, module, énergies
int LoiCritere::Critere(bool en_base_orthonormee,TenseurHH & sigHH_t,TenseurBB& DepsBB
            ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB,double& jacobien_0,double& jacobien
		  	       ,TenseurHH& sigHH,TenseurHHHH& d_sigma_deps_inter
		  	       ,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double&  module_cisaillement
		  	       ,bool implicit,const Met_abstraite::Umat_cont& ex)
   {
    int retour_critere = 1; // init par défaut du retour
// if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//    cout << "\n test1: LoiCritere::Critere(... " << flush;
    switch (type_critere)
     {		case PLISSEMENT_MEMBRANE:
          { int retour_plis_membrane = Critere_plis_membrane(en_base_orthonormee,sigHH_t,DepsBB
                        ,epsBB_tdt,delta_epsBB,jacobien_0,jacobien,sigHH,d_sigma_deps_inter
                        ,energ,energ_t,module_compressibilite,module_cisaillement,implicit,ex
                        );
          
            switch( retour_plis_membrane)
             {
//   = -1 : pas de calcul de valeur propre possible en contrainte
//   =  1 : pas de plis (pas de calcul de nouvelle direction )
//   = -2 : pas de calcul de valeur propre de déformation
//   = -3 : plis dans les deux sens, mais pas de calcul de direction propre valide
//   =  2 : plis dans les deux sens, calcul des directions de plis
//   = -4 : pas de calcul de vecteurs propres possible pour les contraintes
//   =  3 : plis dans une seule directions, calcul ok
             
               case -2: case -1: case -4: retour_critere = 0; break;
               // -3 c'est quand même ok
               case -3: case 2: retour_critere = 2; break;
               default: retour_critere = retour_plis_membrane; break;
             };
			        break;
          }
        case PLISSEMENT_BIEL:
          { int retour_plis_biel = Critere_plis_biel(en_base_orthonormee,sigHH_t,DepsBB
                        ,epsBB_tdt,delta_epsBB,jacobien_0,jacobien,sigHH,d_sigma_deps_inter
                        ,energ,energ_t,module_compressibilite,module_cisaillement,implicit,ex
                        );
          
            switch( retour_plis_biel)
             { case -2: case -1: retour_critere = 0; break;
               default: retour_critere = retour_plis_biel; break;
             };
			        break;
          }
  
        case RUPTURE_SIGMA_PRINC: case RUPTURE_EPS_PRINC:
          {			        break;
          }
  
		      default :
          cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
               << "  !\n";
          cout << "\n LoiCritere::Critere(...";
          Sortie(1);
     };
    // retour
    return retour_critere;
   };

// préparation à l'appel du comportement
//Par exemple dans le cas d'un critère pli (plutôt seconde méthode), l'incrément de déformation
// dépend de la situation précédente: avec pli ou pas
int LoiCritere::Pre_Critere
           (const TenseurBB& DepsBB,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB,double& jacobien_0,double& jacobien,const Met_abstraite::Expli_t_tdt* ex_expli,const Met_abstraite::Impli* ex_impli,const Met_abstraite::Umat_cont* ex_umat
           )
   {
    int retour_pre_critere = 1; // init par défaut du retour
    if (choix_methode_cal_plis_memb == 2)
     switch (type_critere)
       {  case PLISSEMENT_MEMBRANE:
            { Pre_Critere_plis_membrane(epsBB_tdt,delta_epsBB,ex_expli,ex_impli,ex_umat);
              break;
            }
  //        case PLISSEMENT_BIEL:
  //          break
          default :
            cout << "\nErreur : valeur incorrecte du type de critere defini= " << Nom_Critere_Loi(type_critere)
                 << "  !\n";
            cout << "\n LoiCritere::Pre_Critere(...";
            Sortie(1);
       };
    // retour
    return retour_pre_critere;
   };








