

// 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 "LesLoisDeComp.h"
#include "Prandtl_Reuss.h"
#include "Prandtl_Reuss2D_D.h"
#include "Prandtl_Reuss1D.h"
#include "Loi_iso_elas3D.h"
#include "Loi_iso_elas1D.h"
#include "Loi_iso_elas2D_D.h"
#include "Loi_iso_elas2D_C.h"
#include "Iso_elas_expo1D.h"
#include "Iso_elas_expo3D.h"
#include "Iso_elas_SE1D.h"
#include "IsoHyper3DFavier3.h"
#include "IsoHyper3DOrgeas1.h"
#include "IsoHyper3DOrgeas2.h"
#include "IsoHyperBulk3.h"
#include "TreloarN.h"
#include "Loi_newton1D.h"
#include "Loi_newton3D.h"
#include "Loi_newton2D_D.h"
#include "Loi_maxwell1D.h"
#include "Loi_maxwell2D_D.h"
#include "Loi_maxwell2D_C.h"
#include "Loi_maxwell3D.h"
#include "LoiAdditiveEnSigma.h"
#include "LoiDesMelangesEnSigma.h"
#include "LoiContraintesPlanes.h"
#include "LoiContraintesPlanesDouble.h"
#include "LoiDeformationsPlanes.h"
#include "Hysteresis1D.h"
#include "Hysteresis3D.h"
#include "Hysteresis_bulk.h"
#include "Loi_iso_thermo.h"
#include "Loi_de_Tait.h"
#include "MooneyRivlin1D.h"
#include "MooneyRivlin3D.h"
#include "Hart_Smith3D.h"
#include "Poly_hyper3D.h"
#include "Hypo_hooke3D.h"
#include "Hypo_hooke2D_C.h"
#include "Hypo_hooke1D.h"
#include "Loi_Umat.h"
#include "CompFrotCoulomb.h"
#include "Loi_rien1D.h"
#include "Loi_rien2D_D.h"
#include "Loi_rien2D_C.h"
#include "Loi_rien3D.h"
#include "CharUtil.h"
#include "IsoHyperBulk_gene.h"
#include "LoiCritere.h"
#include "Maheo_hyper.h"
#include "Hyper_externe_W.h"
#include "Loi_ortho3D_entrainee.h"
#include "Projection_anisotrope_3D.h"
#include "Hypo_ortho3D_entrainee.h"
#include "Loi_ortho2D_C_entrainee.h"

// grandeurs statiques
list <LoiAbstraiteGeneral *>  LesLoisDeComp::list_de_loi;

LesLoisDeComp::LesLoisDeComp () :  // constructeur par defaut
  tabRefLoi(),tabLoi(),list_de_umat()
    {// on remplit la liste de loi
     LoiAbstraiteGeneral * pt;
     pt = new Loi_iso_elas3D ();list_de_loi.push_back(pt); // ISOELAS
     pt = new Loi_iso_elas1D ();list_de_loi.push_back(pt); // ISOELAS1D
     pt = new Loi_iso_elas2D_D ();list_de_loi.push_back(pt); // ISOELAS2D_D
     pt = new Loi_iso_elas2D_C ();list_de_loi.push_back(pt); // ISOELAS2D_C
     pt = new Iso_elas_expo1D ();list_de_loi.push_back(pt); // ISO_ELAS_ESPO1D
     pt = new Iso_elas_expo3D ();list_de_loi.push_back(pt); // ISO_ELAS_ESPO3D
     pt = new Iso_elas_SE1D ();list_de_loi.push_back(pt); // ISO_ELAS_SE1D
     pt = new IsoHyper3DFavier3 ();list_de_loi.push_back(pt); // ISOHYPER3DFAVIER3
     pt = new IsoHyper3DOrgeas1 ();list_de_loi.push_back(pt); // ISOHYPER3DORGEAS1
     pt = new IsoHyper3DOrgeas2 ();list_de_loi.push_back(pt); // ISOHYPER3DORGEAS2
     pt = new IsoHyperBulk3 ();list_de_loi.push_back(pt); // ISOHYPERBULK3
     pt = new IsoHyperBulk_gene ();list_de_loi.push_back(pt); // ISOHYPERBULK_GENE
     pt = new Prandtl_Reuss ();list_de_loi.push_back(pt); // PRANDTL_REUSS
     pt = new Prandtl_Reuss2D_D ();list_de_loi.push_back(pt); // PRANDTL_REUSS2D_D
     pt = new Prandtl_Reuss1D ();list_de_loi.push_back(pt); // PRANDTL_REUSS1D
     pt = new TreloarN ();list_de_loi.push_back(pt); // TRELOAR
     pt = new Loi_newton1D ();list_de_loi.push_back(pt); // NEWTON1D
     pt = new Loi_newton2D_D ();list_de_loi.push_back(pt); // NEWTON2D_D
     pt = new Loi_newton3D ();list_de_loi.push_back(pt); // NEWTON3D
     pt = new Loi_maxwell1D ();list_de_loi.push_back(pt); // MAXWELL1D
     pt = new Loi_maxwell2D_D ();list_de_loi.push_back(pt); // MAXWELL2D_D
     pt = new Loi_maxwell2D_C ();list_de_loi.push_back(pt); // MAXWELL2D_C
     pt = new Loi_maxwell3D ();list_de_loi.push_back(pt); // MAXWELL3D
     pt = new LoiAdditiveEnSigma ();list_de_loi.push_back(pt); // LOI_ADDITIVE_EN_SIGMA
     pt = new LoiCritere ();list_de_loi.push_back(pt); // LOI_CRITERE
     pt = new LoiDesMelangesEnSigma ();list_de_loi.push_back(pt); // LOI_DES_MELANGES_EN_SIGMA
     pt = new LoiContraintesPlanes ();list_de_loi.push_back(pt); // LOI_CONTRAINTES_PLANES
     pt = new LoiContraintesPlanesDouble ();list_de_loi.push_back(pt); // LOI_CONTRAINTES_PLANES_DOUBLE
     pt = new LoiDeformationsPlanes ();list_de_loi.push_back(pt); // LOI_DEFORMATIONSS_PLANES
     pt = new Hysteresis1D ();list_de_loi.push_back(pt); // HYSTERESIS_1D
     pt = new Hysteresis3D ();list_de_loi.push_back(pt); // HYSTERESIS_3D
     pt = new Hysteresis_bulk ();list_de_loi.push_back(pt); // HYSTERESIS_BULK
     pt = new Loi_iso_thermo ();list_de_loi.push_back(pt); // LOI_ISO_THERMO
     pt = new Loi_de_Tait ();list_de_loi.push_back(pt); // LOI_DE_TAIT
     pt = new MooneyRivlin1D ();list_de_loi.push_back(pt); // MOONEY_RIVLIN_1D
     pt = new MooneyRivlin3D ();list_de_loi.push_back(pt); // MOONEY_RIVLIN_3D
     pt = new Hart_Smith3D ();list_de_loi.push_back(pt); // HART_SMITH3D
     pt = new Poly_hyper3D ();list_de_loi.push_back(pt); // POLY_HYPER3D
     pt = new Maheo_hyper ();list_de_loi.push_back(pt); // MAHEO_HYPER
     pt = new Hyper_externe_W ();list_de_loi.push_back(pt); // HYPER_EXTERNE_W
     pt = new Hypo_hooke3D ();list_de_loi.push_back(pt); // HYPO_ELAS3D
     pt = new Hypo_hooke2D_C ();list_de_loi.push_back(pt); // HYPO_ELAS2D_C
     pt = new Hypo_hooke1D ();list_de_loi.push_back(pt); // HYPO_ELAS1D
     // en dimension 3, on peut avoir des Umat, mais pas dans les autres dimensions
     if (ParaGlob::Dimension() == 3)
        {pt = new Loi_Umat ();list_de_loi.push_back(pt); // LOI_VIA_UMAT
         pt = new Loi_Umat (LOI_VIA_UMAT_CP);list_de_loi.push_back(pt); // LOI_VIA_UMAT_CP
        };
     pt = new CompFrotCoulomb ();list_de_loi.push_back(pt); // LOI_COULOMB
     pt = new Loi_rien1D ();list_de_loi.push_back(pt); // LOI_rien1D
     pt = new Loi_rien2D_C ();list_de_loi.push_back(pt); // LOI_rien2D_C
     pt = new Loi_rien2D_D ();list_de_loi.push_back(pt); // LOI_rien2D_D
     pt = new Loi_rien3D ();list_de_loi.push_back(pt); // LOI_rien3D
     pt = new Loi_ortho_elas3D ();list_de_loi.push_back(pt); // Loi_ortho_elas3D
     pt = new Loi_ortho2D_C_entrainee ();list_de_loi.push_back(pt); // Loi_ortho_elas2D_C
     pt = new Projection_anisotrope_3D ();list_de_loi.push_back(pt); // Loi_ortho_elas3D
     pt = new Hypo_ortho3D_entrainee(); list_de_loi.push_back(pt); // loi hypo-elas3D anisotrope
    };

// lecture des lois de comportement
void LesLoisDeComp::LecturelesLoisDeComp(UtilLecture& entreePrinc,LesReferences& lesRef
                                         ,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
    { if (ParaGlob::NiveauImpression() >= 4) 
         cout << " debut de la lecture des lois de comportement " << endl;
      // lecture des references de materiaux
      if (ParaGlob::NiveauImpression() >= 6) 
         cout << " lecture des references de materiaux " << endl;
      LecRef(entreePrinc,lesRef);
      if (ParaGlob::NiveauImpression() >= 6) 
         cout << " lecture des  materiaux " << endl;
      // lecture des materiaux
      LecMateriaux(entreePrinc,lesRef,lesCourbes1D,lesFonctionsnD);
      // -------- vérification des doublons ------------ 
      // on verifie que l'on n'utilise pas deux fois la meme reference
      // pour deux loi differentes de la même catégorie
      int taille = tabRefLoi.Taille();
      for (int i=1;i<=taille;i++)
       for (int j= i+1;j<=taille;j++)
          if ((tabRefLoi(i).st1 == tabRefLoi(j).st1)  // la référence
           && (tabRefLoi(i).st2 != tabRefLoi(j).st2)  // le nom de la loi de comp
           && ((tabRefLoi(i).nom_maillage == tabRefLoi(j).nom_maillage)               // le maillage
              || (*(tabRefLoi(i).nom_maillage) == *(tabRefLoi(j).nom_maillage))))     // éventuelle
           { // cas ou l'on a 2 fois la même référence et deux lois différentes
             LoiAbstraiteGeneral * pt1 = PtLoi_abstraite(tabRefLoi(i).st2);
             LoiAbstraiteGeneral * pt2 = PtLoi_abstraite(tabRefLoi(j).st2);
             if (MemeCategorie(pt1->Id_categorie(),pt2->Id_categorie()))
               { cout << "\n erreur , un meme nom de reference est utilisee pour"
                         << " deux lois de materiaux de categories differentes \n";
                 if (tabRefLoi(i).nom_maillage != NULL) cout << "nom du maillage " << *(tabRefLoi(i).nom_maillage);
                 cout << "  nom de la ref = " << tabRefLoi(i).st1 << ", nom des deux lois de materiaux ="
                      << tabRefLoi(i).st2 <<", "<< tabRefLoi(j).st2 ;
                 cout << " LesLoisDeComp::LecRef(UtilLecture& entreePrinc,"
                         << "LesReferences& lesRef) " << endl;
                 entreePrinc.MessageBuffer("**** lecture des  lois de comportement ***** ");                     
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie (1);          
                }
             };   
      if (ParaGlob::NiveauImpression() >= 4) 
         cout << " fin de la lecture des lois de comportement " << endl;
     };  
    
// affichage et definition interactive des commandes 
void LesLoisDeComp::Info_commande_lesLoisDeComp(UtilLecture& entreePrinc,LesReferences& )
 {cout << "\n# ----- definition des lois de comportements ----- ";
  bool plusieurs_maillages = false;
  string rep="_";
  list <Trois_String> l_elem_loi; // liste des : nom de loi, nom de ref d'éléments, nom de maillage éventuel
	     
  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
  try 
     {cout << "\n cas d'un seul maillage (par defaut) : rep o "
           << "\n cas de plusieurs maillages          : rep n ";
      
      // procédure de lecture avec prise en charge d'un retour chariot
      rep = lect_return_defaut(true,"o");

      if (rep == "n")
         { plusieurs_maillages = true;};
      rep="_"; // init
      // tout d'abord la définition des listes d'éléments associés à des noms de lois
      while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
       { cout << "\n -- definition des ref d'elements associes a des noms de lois -- "
              << "\n (0 ou f)  (fin)               "
              << "\n (1)  def d'une ref d'elements associe a un nom de loi "
              << "\n (2 ou ? ) exemple - informations  ! "
              << "\n (3) grandeurs types disponibles pour les fct nD utilisees dans les lois "
              << "\n  ";
        
         // procédure de lecture avec prise en charge d'un retour chariot
         rep = lect_return_defaut(false,"f");


         if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
            break;
         int num = ChangeEntier(rep);
         if (Minuscules(rep) == "?")
           num = 3;
         bool choix_valide=false;
         if ((num >= 0)&&(num<=3))
            { choix_valide=true; }
         else { cout << "\n Erreur on attendait un entier entre 0 et 3 !!, "
                     << "\n redonnez une bonne valeur"
                     << "\n ou taper f ou 0 pour arreter le programme"; 
                choix_valide=false;
              };
         switch (num)
           { case 0:  // sortie
               { break;} // normalement cela a déjà été filtré avant
             case 1:  // def d'une liste d'elements associe a un nom de loi
	              { Trois_String t_str; t_str.nom3="_"; // init
                 if (plusieurs_maillages)
                   { cout << "\n nom du maillage ? ";
                     t_str.nom3= lect_chaine(); cout << " nom lu = "<< t_str.nom3;
                   };
                 cout << "\n nom de la reference d'element ? ";
                 t_str.nom2= lect_chaine(); cout << " ref lu = "<< t_str.nom2;
                 if (t_str.nom2[0] != 'E')
                  {cout << "\n Erreur on attendait un identificateur avec une premiere lettre = E !!, "
                        << "\n recommencer"
                        << "\n ou taper f ou 0 pour arreter le programme";
                   choix_valide=false;
                  };
                 cout << "\n nom de la loi associee a "<<t_str.nom2<<"  ? ";
                 t_str.nom1= lect_chaine(); cout << " nom loi lu ="<< t_str.nom1;
                 l_elem_loi.push_back(t_str);
                 cout << "\n";
                 break;
               }		
             case 2:  // exemple - informations
	              {  cout << "\n la definition des lois de comportement s'effectue en deux etapes: "
                       << "\n     1) def de listes d'element associé a des nom(s) de loi "
                       << "\n     2) def des comportements associes au(x) nom(s) de loi precedemment defini(s)"
                       << "\n il s'agit donc ici de la premiere etape, qui consiste a donner successivement "
                       << "\n des refs d'elements associe a des noms de loi, avec les restrictions suivantes:"
                       << "\n - un element ne peut avoir qu'une seule loi d'un type donne (meca ou thermique ou...)"
                       << "\n - tous les elements doivent etre associe a une loi \n";
                 break;
	              };
             case 3:  // grandeurs types disponibles pour les fct nD utilisees dans les lois
               {// affichage de la liste des grandeurs possible à calculer avec
                // Valeur_multi_interpoler_ou_calculer
                Loi_comp_abstraite::Affichage_grandeurs_Valeur_multi_interpoler_ou_calculer();
                // affichage de la liste des grandeurs possible à calculer avec
                // Valeurs_Tensorielles_interpoler_ou_calculer
                Loi_comp_abstraite::Affichage_grandeurs_Valeurs_Tensorielles_interpoler_ou_calculer();
                // cas des grandeurs quelconques
                Loi_comp_abstraite::Affichage_grandeurs_Valeurs_quelconque_interpoler_ou_calculer();
                break;
               };
             default:
               cout << "\n le cas "<<rep<<" n'est pas  traite !!, bizarre, il faut se plaindre !! ";
           };
        };
      
      
      
      
      
     }
  catch (ErrSortieFinale)
       // cas d'une direction voulue vers la sortie
       // on relance l'interuption pour le niveau supérieur
     { ErrSortieFinale toto;
       throw (toto);
     }
  catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
     {  cout << "\n Erreur on attendait un des mots cles proposes !!, "
             << "\n redonnez une bonne valeur"
             << "\n ou taper f ou 0 pour sortir "; 
     };
  // écriture de l'entête des matériaux
  sort << "\n#======================================"
       << "\n#| definition des lois de comportement|" 
       << "\n#--------------------------------------"
       << "\n "
       << "\n            choix_materiaux ----------"
       << "\n#----------------------------------------"
       << "\n# Elements   |   Nom   Materiau         |"
       << "\n#----------------------------------------";
  list <Trois_String>::iterator il,ilfin=l_elem_loi.end();
  // suppression des doublons 
		l_elem_loi.sort(); l_elem_loi.unique();
		tabRefLoi.Change_taille(l_elem_loi.size());
		int iii = 1; 
  for (il = l_elem_loi.begin();il != ilfin; il++,iii++)
    { Trois_String& t_str = (*il); // pour simplifier
      sort << "\n";
      if (t_str.nom3 != "_")
        {sort << "nom_mail= "<< t_str.nom3 << " ";
         tabRefLoi(iii).Change_nom_maillage(t_str.nom3);
        };
      sort << t_str.nom2 << " "<< t_str.nom1 << " ";
      tabRefLoi(iii).st1=t_str.nom2;tabRefLoi(iii).st2=t_str.nom1;
    };

  // -- maintenant on va s'occuper de définir les lois		 
  // sortie des lois de comportements
  // affichage de l'entête
  sort << "\n"
       << "\n        materiaux #----------\n";
  cout << "\n \n definition des lois de comportement associee au(x) materiau(x) precedemment definit";
  // on commence par définir une liste de loi qui ont la bonne dimension
  int dim = ParaGlob::Dimension();
  list <LoiAbstraiteGeneral *> list_de_loi_dim;
  list <LoiAbstraiteGeneral *>::iterator ilit,ilifint = list_de_loi.end();
  for(ilit=list_de_loi.begin();ilit != ilifint;ilit++)
    { if (((*ilit)->Dimension_loi() <= dim)  || ((*ilit)->Dimension_loi() == 4))
         list_de_loi_dim.push_back(*ilit);}
  // maintenant on parcourt les noms de lois  
	 bool choix_valide = false;
  list <Trois_String>::iterator im,imfin=l_elem_loi.end();
  for (im=l_elem_loi.begin();im!=imfin;im++)
   {choix_valide = false;
    Trois_String& t_str = (*im); // pour simplifier
    while (!choix_valide)
     {int nbloi = list_de_loi_dim.size(); 
      try
        { // affichage  des différentes lois de comportement
          list <LoiAbstraiteGeneral *>::iterator ili,ilifin = list_de_loi_dim.end();
          int undeux=0; int num=0;
          Tableau <LoiAbstraiteGeneral *> tab_ili(nbloi);
          cout << "\n (0) fin \n";
          int i=1;
          for(ili=list_de_loi_dim.begin();ili != ilifin;ili++,i++)
            { cout << " (" << i << ") " << setw(nbmax_caractere_Enum_comp+3) 
                   << (*ili)->Nom_comport() <<"  ";
              undeux++;
              if (undeux==2) {cout << "\n";undeux=0;}
              tab_ili(i) = (*ili);
             };
          cout << "\n donnez la loi de comportement pour le materiau: " << t_str.nom1 << " (un numero):   ";
          rep = lect_chaine();
          if (rep == "fin_prog") Sortie(1);
          num = ChangeEntier(rep);  
          choix_valide=false;  
          if (num == 0) 
            { choix_valide=true;}
          else if ((num > 0)&&(num<=nbloi)) 
               { // affichage de la loi
                 sort << "\n#------------------------------------------"
                      << "\n# Nom Materiau    |      Type loi         |"
                      << "\n#------------------------------------------"         
                      << "\n  " 
                      <<  t_str.nom1 << "         " << tab_ili(num)->Nom_comport();
                 // affichage particulier à la loi
                 tab_ili(num)->Info_commande_LoisDeComp(entreePrinc);  
                 choix_valide=true;   
                }
          else { cout << "\n Erreur on attendait un entier entre 0 et "<< nbloi <<" !!, "
                     << "\n redonnez une bonne valeur"
                     << "\n ou taper fin_prog pour arreter le programme"; 
              }
         }      
      catch (ErrSortieFinale)
           // cas d'une direction voulue vers la sortie
           // on relance l'interuption pour le niveau supérieur
         { ErrSortieFinale toto;
           throw (toto);
         }
      catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
       {  cout << "\n Erreur on attendait un entier entre 0 et "<< nbloi <<" !!, "
               << "\n redonnez une bonne valeur"
               << "\n ou taper fin_prog pour arreter le programme"; 
          choix_valide=false;
       }
     }; //-- fin du while
   };		
  
  // fin de la définition des loi
  sort << "\n#--------------------------------------- fin def des lois de comportement ------------------------"
       << endl;
  sort << flush;
		 
 };
          
    
// affichage des lois de comportement
void LesLoisDeComp::Affiche()  const 
   { cout << "\n *** loi de comportement ******** \n";
     cout << tabRefLoi.Taille() << " references de loi de comp lu \n";
     cout << " reference elements :      nom du materiau : \n";
     for (int i = 1;i<=tabRefLoi.Taille();i++)
        cout << tabRefLoi(i).st1 << "  " << tabRefLoi(i).st2 << '\n';
     cout << tabLoi.Taille() << " loi(s) de comp lu \n";
     for (int i = 1;i<=tabLoi.Taille();i++)
        { cout << " nom de la loi = " << (tabLoi(i)).st1 ;
          (tabLoi(i)).pt->Affiche();
          cout << '\n';
         } 
   }; 
     
//------------------------------------ protegees ----------------------
   
    
 // lecture des references de materiaux
void LesLoisDeComp::LecRef(UtilLecture& entreePrinc,LesReferences& lesRef)
  {  
   if (strstr(entreePrinc.tablcar,"choix_materiaux")!=NULL)
        { // lecture des references de materiaux
          list <LesLoisDeComp::RefLoi> lili;
          entreePrinc.NouvelleDonnee();
          MotCle motCle;             
          while (!motCle.SimotCle(entreePrinc.tablcar))
            { // on commence par regarder si le nom du maillage est définit pour le matériau
              string* nom_mail=NULL; string nom; 
              if (strstr(entreePrinc.tablcar,"nom_mail=")!=NULL)
                  { *(entreePrinc.entree) >> nom >> nom; nom_mail = & nom;}
              // st1 = nom d'une reference, st2 = nom d'une loi
              string st1,st2;
              *(entreePrinc.entree) >> st1 >> st2; 
              // on regarde si st1 correspond bien a une reference lue
              if (!lesRef.Existe(st1,nom_mail))
               { cout << "\n erreur, la ref de materiau = " << st1 
                      <<" , ne correspond a aucun element"
                   << " de la liste de reference lue !! \n";
                 cout << " LesLoisDeComp::LecRef(UtilLecture& entreePrinc,"
                      << "LesReferences& lesRef) " 
                   << endl;
                 entreePrinc.MessageBuffer("lecture des references de materiaux");  
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie (1);     
                }
                
               // stockage
               LesLoisDeComp::RefLoi ref(nom_mail,st1,st2);
               lili.push_back(ref);
               entreePrinc.NouvelleDonnee(); 
             } 
           if (lili.size() == 0)
              { cout << "\n erreur, aucune reference de loi de comportement"
                     << " n est defini !! \n";
                cout << " LesLoisDeComp::LecRef(UtilLecture& entreePrinc,"
                      << "LesReferences& lesRef) " << endl;
                entreePrinc.MessageBuffer("lecture des references de materiaux");                       
                throw (UtilLecture::ErrNouvelleDonnee(-1));
                Sortie (1);     
               }
           else
             { // enregistrement des infos 
               tabRefLoi.Change_taille((int)lili.size());
               list <LesLoisDeComp::RefLoi>::iterator i;
               int j;
               for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++)
                  tabRefLoi(j) = *i;              
              }
          }    
         else
           { cout << "\n erreur, le mot cle choix_materiaux n'existe pas !! \n";
             cout << " LesLoisDeComp::LecRef(UtilLecture& entreePrinc,"
                  << "LesReferences& lesRef) " << endl;
             entreePrinc.MessageBuffer("lecture des references de materiaux");                 
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie (1);     
           }
   };

// lecture des  materiaux
void LesLoisDeComp::LecMateriaux(UtilLecture& entreePrinc,LesReferences& 
                                 ,LesCourbes1D& lesCourbes1D,LesFonctions_nD& lesFonctionsnD)
{try
  { if (strstr(entreePrinc.tablcar,"materiaux")!=NULL)
      { // lecture des  materiaux
        list <Loi> lili;
        entreePrinc.NouvelleDonnee();
        MotCle motCle; 
        while (!motCle.SimotCle(entreePrinc.tablcar))
         { // st1 = nom d'une reference de materiau, st2 = nom du type de loi
           string st1,st2;
           *(entreePrinc.entree) >> st1 >> st2;
           // verif que st1 correspond a quelque chose d'utilisable
           bool ex = false;
           for (int i=1;i<= tabRefLoi.Taille(); i++)
                 if(tabRefLoi(i).st2 == st1) ex = true;
              
           // definition de la loi
           LoiAbstraiteGeneral * pt = Def_loi(st2);
           // on verifie que l'on n'utilise pas deux fois la meme reference
           // pour deux lois d'une même catégorie
           list <Loi>::iterator ii;
           for (ii=lili.begin() ; ii != lili.end(); ii++)
              if ((*ii).st1 == st1) //&& (MemeCategorie((*ii).pt->Id_categorie(),pt->Id_categorie())))
                {
                  cout << "\n erreur , une meme reference est utilisee deux fois"
                       << "  nom de la ref = " << st1 << " pour une meme categorie de loi: " 
                       << Nom_categorie_loi_comp(pt->Id_categorie());
                  cout << "\n LesLoisDeComp::LecMateriaux(UtilLecture& "
                       << "entreePrinc,LesReferences& lesRef) " << endl;
                  entreePrinc.MessageBuffer("lecture des  materiaux");                     
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie (1);          
                }
            
           // lecture des informations particulières propres à la  loi
           entreePrinc.NouvelleDonnee(); // prepa du flot de lecture
           pt->LectureDonneesParticulieres (&entreePrinc,lesCourbes1D,lesFonctionsnD);
           // on enregistre et on signale si la loi est inutilisée via un warning
           if (!ex &&  (ParaGlob::NiveauImpression()>1))
             { cout << "\n Warning, le nom de  materiau = " << st1
                    << " ,  ne correspond pas a une"
                    << " reference de la liste des ref de materiau!! ";
               if (ParaGlob::NiveauImpression()>4)
                 {cout << "\n LesLoisDeComp::LecMateriaux(UtilLecture& "
                       << "entreePrinc,LesReferences& lesRef) " << endl;
                  entreePrinc.MessageBuffer("lecture des  materiaux");
                 };
             };
           // enregistrement
           lili.push_back(LesLoisDeComp::Loi(st1,pt));
           // --- on regarde si la loi est à associer avec un critère particulier
           // par exemple un critère de rupture, ou de l'endommagement etc.
           // appelé : un Critere_Loi
          };
        if (lili.size() == 0)
               { cout << "\n erreur, aucune  loi de comportement"
                      << " n est defini !! \n";
                 cout << " LesLoisDeComp::LecMateriaux(UtilLecture& entreePrinc) " 
                      << endl;
                 entreePrinc.MessageBuffer("lecture des  materiaux");                                          
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie (1);     
               }
        else
              { // enregistrement des infos 
                tabLoi.Change_taille((int)lili.size());
                list <Loi>::iterator i;
                int j;
                for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++)
                   tabLoi(j) = *i;              
              }
      }
    else   
      { cout << "\n erreur, le mot cle materiaux n'existe pas !! \n";
        cout << " LesLoisDeComp::LecMateriaux(UtilLecture& entreePrinc) " 
                      << endl;
        entreePrinc.MessageBuffer("lecture des  materiaux");                                    
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie (1);     
      };
    // -- cas particulier de l'utilisation de lois Umat
    int nbloi=tabLoi.Taille();
    for (int i=1; i<= nbloi; i++)
     {if ((tabLoi(i).pt->Id_comport()==LOI_VIA_UMAT)
          || (tabLoi(i).pt->Id_comport()==LOI_VIA_UMAT_CP)
         )
       { Loi_Umat* loi = (Loi_Umat*) tabLoi(i).pt;
         // cas particulier des umat interne on "branche"
         if (loi->Utilise_une_umat_interne())
          {// récup du nom de la loi associée
           const string& nom_loi_associe = loi->NomDeLaLoi();
           // récup de la loi
           LoiAbstraiteGeneral * loi_ext = PtLoi_abstraite(nom_loi_associe); 
           // association avec la loi définit
           loi->DefLoiExt(loi_ext);
          };
         // sauvegarde de la liste des lois umat
         list_de_umat.push_back(tabLoi(i).pt); 
       };
     };
   
    // --- dans le cas où les lois on besoins de grandeurs particulières qui doivent
    // provenir des autres lois on va créer une liste de ces grandeurs
    //Besoin_de_grandeurs_particuliere
    //une fois que l'on a lue toutes les lois
    //Activation_stockage_grandeurs_quelconques
  }
 catch (ErrSortieFinale)
      // cas d'une direction voulue vers la sortie
      // on relance l'interuption pour le niveau supérieur
    { ErrSortieFinale toto;
      throw (toto);
    }
 catch ( ... )
       { cout << "\n **** erreur dans la lecture des materiaux ****" << '\n';
         entreePrinc.MessageBuffer("lecture des  materiaux");
         throw (UtilLecture::ErrNouvelleDonnee(-1));
         Sortie (1);
       };
 
 };
      
// ramene le pointeur de LoiAbstraiteGeneral en fonction 
// 1) du nom de la loi, 2) du nom d'une reference
//  ou null si la recherche n'abouti pas
LoiAbstraiteGeneral * LesLoisDeComp::PtLoi_abstraite(const string& st) const
  { int nbloi=tabLoi.Taille();
    for (int i=1; i<= nbloi; i++)
     if ( st == tabLoi(i).st1)
       return tabLoi(i).pt;
    // normalement la suite ne devrait pas être utilisé !!
    int nbRefLoi= tabRefLoi.Taille();  
    for (int j=1; j<= nbRefLoi; j++)
     if (st == tabRefLoi(j).st1) 
       for (int i=1; i<= nbloi; i++)
         if ( tabRefLoi(j).st2 == tabLoi(i).st1)
           {// dans ce cas l'utilisateur a mis une référence attachée à la loi
            // ce qui n'est pas correct, néanmoins on a trouvé la loi associée
            // on met une info correspondant à la loi
            cout << "\n *** Warning : la syntaxe de l'entree de la loi n'est pas correct (cf. documentation)"
                 << " \n a priori, la loi voulue (et celle qui sera retenue) est $$ "<< tabLoi(i).st1
                 << " $$ au lieu du nom: "<< st << " !! ";
            return tabLoi(i).pt;
           };
    // si l'on n'a pas trouvé de loi de comportement on met un warning
    if (ParaGlob::NiveauImpression() > 0) 
      {cout << "\n *** Warning : on n'a pas trouve de loi de comportement du nom: "
           << st << " peut-etre pb par la suite !! " << endl ;
       if (ParaGlob::NiveauImpression() > 5)
        cout << "\n LesLoisDeComp::PtLoi_abstraite( ... ";     
      };
    return NULL;        
   };
    
// indique aux différentes loi que l'on doit utiliser une loi tangente simplifiée
// ou non suivant la valeur du paramètre de passage
void LesLoisDeComp::Loi_simplifie(bool ordre)
  { int tabloitaille = tabLoi.Taille();
    for (int i=1; i<= tabloitaille; i++)
      tabLoi(i).pt->Modif_comp_tangent_simplifie(ordre);
   };
   
// récup du type de loi: simplifiée ou non
bool LesLoisDeComp::Test_loi_simplife() 
  { bool test = true;
    int tabloitaille = tabLoi.Taille();
    for (int i=1; i<= tabloitaille; i++)
      test = test && tabLoi(i).pt->Test_loi_simplife();
    return test;  
   };
    
//indique aux lois Umat éventuelles le numéro d'itération 
void LesLoisDeComp::MiseAJour_umat_nbiter(const int& num_iter)
 {  if (list_de_umat.size()!= 0)
     {list <LoiAbstraiteGeneral *>::iterator il,ilfin=list_de_umat.end();
      for (il=list_de_umat.begin();il!=ilfin;il++)
         ((Loi_Umat*) (*il))->Mise_a_jour_num_iteration(num_iter);
     };
 };
// ou le numéro d'incrément 
void LesLoisDeComp::MiseAJour_umat_nbincr(const int& num_incr)
 {  if (list_de_umat.size()!= 0)
     {list <LoiAbstraiteGeneral *>::iterator il,ilfin=list_de_umat.end();
      for (il=list_de_umat.begin();il!=ilfin;il++)
         ((Loi_Umat*) (*il))->Mise_a_jour_num_increment(num_incr);
     };
 };
   
//----- 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 LesLoisDeComp::Lecture_base_info
 (ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
 { // deux choses sont a récupérer : 1) la liste des références de loi, 2) les lois
   // tout d'abord la liste des références de loi
   switch (cas)
  { case 1 : // ------- on récupère la liste de référence de loi -------------------------
     { // tout d'abord la taille
       string titi;
       ent >> titi; // lecture entête
       int tabRefLoitaille;
       ent >> titi >> tabRefLoitaille ;
       tabRefLoi.Change_taille(tabRefLoitaille); 
       for (int i=1; i<= tabRefLoitaille; i++)
         {int num;
          ent >> titi >> num;  // num n'est pas utilisé
          tabRefLoi(i).Lecture_base_info(ent,cas);
         };
       // puis les lois elles même
       // tout d'abord la taille
       int tabLoitaille;
       ent >> titi >> tabLoitaille ;
       tabLoi.Change_taille(tabLoitaille);
       // on parcours la liste des lois de comportement et chaque loi se récupère
       for (int i=1; i<= tabLoitaille; i++)
         {int num;
          ent >> titi >> num;  // num n'est pas utilisé
          tabLoi(i).Lecture_base_info(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
         };
       // -- cas particulier de l'utilisation de lois Umat
       int nbloi=tabLoi.Taille();
       list_de_umat.erase(list_de_umat.begin(),list_de_umat.end());
       for (int i=1; i<= nbloi; i++)
        {if ((tabLoi(i).pt->Id_comport()==LOI_VIA_UMAT)
             || (tabLoi(i).pt->Id_comport()==LOI_VIA_UMAT_CP)
            )
          { Loi_Umat* loi = (Loi_Umat*) tabLoi(i).pt;
            // cas particulier des umat interne on "branche"
            if (loi->Utilise_une_umat_interne())
             {// récup du nom de la loi associée
              const string& nom_loi_associe = loi->NomDeLaLoi();
              // récup de la loi
              LoiAbstraiteGeneral * loi_ext = PtLoi_abstraite(nom_loi_associe); 
              // association avec la loi définit
              loi->DefLoiExt(loi_ext);
             };
           // sauvegarde de la liste des lois umat
           list_de_umat.push_back(tabLoi(i).pt); 
          };
        };
       break;
     }
    case  2 : // ----------- on passe en revue toutes les lois --------------------
     { string titi;
       ent >> titi; // lecture entête
       // puis les lois elles même: ici il s'agit uniquement des données génériques mais pas spécifiques aux pti
       int tabLoitaille= tabLoi.Taille();
       // on parcours la liste des lois de comportement et chaque loi se lit elle même
       int itruc;
       for (int i=1; i<= tabLoitaille; i++)
        {ent >> titi >> itruc;
         tabLoi(i).Lecture_base_info(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
        };
      break;
     }
    default :
	    { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
	      cout << "LesLoisDeComp::Lecture_base_info(ifstream& ent,const int cas)"
			         << " cas= " << cas << endl;
	      Sortie(1);
     }
  };
 };
     // cas donne le niveau de sauvegarde
     // = 1 : on sauvegarde tout
     // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LesLoisDeComp::Ecriture_base_info(ofstream& sort,const int cas)
 { // deux choses sont a sauvegarder : 1) la liste des références de loi, 2) les lois
   // tout d'abord la liste des références de loi
   switch (cas)
   { case 1 : // ------- on sauvegarde la liste de référence de loi -------------------------
      { int tabRefLoitaille = tabRefLoi.Taille();
        // tout d'abord la taille
        sort << "\n ****lesLoisDeComp_: "
             << "\n 1)--nombre_de_ref_de_loi " << tabRefLoitaille ;
        for (int i=1; i<= tabRefLoitaille; i++)
           {sort << "\n ref: "<<i<<" ";
            tabRefLoi(i).Ecriture_base_info(sort,cas);
           }
        // puis les lois elles même
        int tabLoitaille= tabLoi.Taille();
        // tout d'abord la taille
        sort << "\n 2)--nombre_de_loi " << tabLoitaille ; 
        // on parcours la liste des lois de comportement et chaque loi se sauvegarde
        for (int i=1; i<= tabLoitaille; i++)
         {sort << "\n loi_numero: "<<i<<" ";
          tabLoi(i).Ecriture_base_info(sort,cas);
         };
        break;
      }
     case  2 : // ----------- on passe en revue toutes les lois --------------------
      { sort << "\n ****lesLoisDeComp_: ";
        // puis les lois elles même: ici il s'agit uniquement des données génériques mais pas spécifiques aux pti
        // par exemple les temps globaux pour chaque lois
        int tabLoitaille= tabLoi.Taille();
        // on parcours la liste des lois de comportement et chaque loi se sauvegarde
        for (int i=1; i<= tabLoitaille; i++)
         {sort << "\n loi_numero: "<<i<<" ";
          tabLoi(i).Ecriture_base_info(sort,cas);
         };
       break;
      }
     default :
	     { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
	       cout << "LesLoisDeComp::Ecriture_base_info(ofstream& sort,int cas)"
			          << " cas= " << cas << endl;
	       Sortie(1);
      };
   };
   sort << endl;
 };
         
      
// sortie sur fichier des temps cpu spécifiques à toutes les lois
void LesLoisDeComp::Sortie_temps_cpu(UtilLecture& entreePrinc)
  {  // on récupère le fichier des temps cpu
     entreePrinc.Ouverture_fichier_temps_cpu(); // ouverture au cas où
     // récupération du fichier des temps cpu
     ofstream & sort_cpu = entreePrinc.Sort_temps_cpu();
     // on concatène la totalité pour ensuite sortir également des pourcentage
     double  total_cpu = 0.;
     int tabLoitaille= tabLoi.Taille();
     for (int i=1; i<= tabLoitaille; i++)
       {// on fait un cast pour récupérer la loi particulière
        Loi_comp_abstraite* pt_loi = (Loi_comp_abstraite*) tabLoi(i).pt;
        total_cpu += pt_loi->Temp_CPU_loi().Temps_CPU_User();
       };
     int nbdigit = 6; // pour le pourcentage
   
   
     // écriture des temps cpu des lois:

     sort_cpu << "\n \n ---------------  partie specifique aux lois de comportement ---------";
     sort_cpu << fixed;
     sort_cpu.precision(2);
     // pour éviter de faire une division par 0
     total_cpu = MaX(ConstMath::trespetit, total_cpu);
     sort_cpu << "\n ---> tps_total_loi "
              << "("<< std::setw(nbdigit) << total_cpu/1000. << " )   ";
              
     for (int i=1; i<= tabLoitaille; i++)
       {// on fait un cast pour récupérer la loi particulière
        Loi_comp_abstraite* pt_loi = (Loi_comp_abstraite*) tabLoi(i).pt;
        double temps_loi = pt_loi->Temp_CPU_loi().Temps_CPU_User();
        sort_cpu << "\n tps_loi: "<< pt_loi->Nom_comport() << " "
                 << "("<< std::setw(nbdigit) << (100*pt_loi->Temp_CPU_loi().Temps_CPU_User()/total_cpu) << " % )   "
                 << pt_loi->Temp_CPU_loi().Temps_CPU_User_milli();
       };
     sort_cpu << "\n";
  };

//--------------- def des lectures/écritures pour les classes loi et refloi ------

//========= cas de refloi====================
	    //----- 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 LesLoisDeComp::RefLoi::Lecture_base_info(ifstream& ent,const int cas)
   { string toto;
     if (cas==1)
        ent >> toto >> st1 >> toto >> st2; 
    };
        // cas donne le niveau de sauvegarde
        // = 1 : on sauvegarde tout
        // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LesLoisDeComp::RefLoi::Ecriture_base_info(ofstream& sort,const int cas) const
   { if (cas==1)
        sort << "\n nom_de_la_reference " << st1 <<" nom_de_loi "<< st2; 
    };

LesLoisDeComp::RefLoi& LesLoisDeComp::RefLoi::operator = (const RefLoi & a)  
    { 	if (a.nom_maillage == NULL)
		      { if (nom_maillage != NULL) {delete nom_maillage;nom_maillage=NULL;}}
		else
		      { if (nom_maillage == NULL) nom_maillage = new string(*(a.nom_maillage));
		        else                      *nom_maillage = *(a.nom_maillage);
		       };   
        st1 = a.st1; st2 = a.st2; return *this; 
     };  
// changement de nom de maillage
void LesLoisDeComp::RefLoi::Change_nom_maillage(const string& nouveau)
  {	if (nouveau.length() == 0)
	   { cout << "\nErreur : reference de nom de maillage non valide  car de longueur nulle ! "
	          << " nom_mail= " << nouveau << "\n";
		 cout << "LesLoisDeComp::RefLoi::Change_nom_maillage(....) \n";
		 Sortie(1);
		}
     if (nom_maillage == NULL)
       { nom_maillage = new string(nouveau);}
     else 
       { *nom_maillage = nouveau;};  	
	};

// surcharge de l'operateur de lecture typée
istream & operator >> (istream & entree, LesLoisDeComp::RefLoi & refloi)
  { // vérification du type
    string type; entree >> type;
    if (type != "LesLoisDeComp::RefLoi")
      {Sortie (1); return entree;
       }
    //  puis les données
    entree >> refloi.st1 >> refloi.st2 ;   
    return entree;      
  };
  
// surcharge de l'operateur d'ecriture typée
ostream & operator << ( ostream & sort,const  LesLoisDeComp::RefLoi & refloi)
  { // un indicateur donnant le type puis les datas
    sort << "LesLoisDeComp::RefLoi " << refloi.st1 << " " << refloi.st2 << "\n" ; 
    return sort;      
  };
    
//========= cas de loi =====================	    
	    //----- 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 LesLoisDeComp::Loi::Lecture_base_info
       (ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
   {  if (cas==1)
        { cout << "== lecture des lois de comportement \n";
          // la référence de la loi, et son identificateur
          string toto,st2;
          ent >> toto >> st1 >> st2 ;
          // la loi elle même
          pt = LesLoisDeComp::Def_loi(st2);
          // lecture des informations particulières propres à la  loi   
          pt->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 LesLoisDeComp::Loi::Ecriture_base_info(ofstream& sort,const int cas)
   { if (cas==1)
        { // la référence de la loi
          sort << "\n nom_de_la_reference_de_la_loi " << st1 << " " ;
          // la loi elle même
          pt->Ecriture_base_info_loi(sort,cas);
         } 
    };
    
// définition d'un pointeur de loi en fonction d'une chaine de caractères
LoiAbstraiteGeneral * LesLoisDeComp::Def_loi(string & nom)
 { LoiAbstraiteGeneral * pt;
   switch (Id_nom_comp (nom))
	   {
      case ISOELAS : pt = new Loi_iso_elas3D (); break;
      case ISOELAS1D : pt = new Loi_iso_elas1D (); break;
      case ISOELAS2D_D : pt = new Loi_iso_elas2D_D (); break;
      case ISOELAS2D_C : pt = new Loi_iso_elas2D_C (); break;
      case ISO_ELAS_ESPO1D : pt = new Iso_elas_expo1D (); break;
      case ISO_ELAS_ESPO3D : pt = new Iso_elas_expo3D (); break;
      case ISO_ELAS_SE1D : pt = new Iso_elas_SE1D (); break;
      case ISOHYPER3DFAVIER3 : pt = new IsoHyper3DFavier3 (); break;
      case ISOHYPER3DORGEAS1 : pt = new IsoHyper3DOrgeas1 (); break;
      case ISOHYPER3DORGEAS2 : pt = new IsoHyper3DOrgeas2 (); break;
      case ISOHYPERBULK3 : pt = new IsoHyperBulk3 (); break;
      case ISOHYPERBULK_GENE : pt = new IsoHyperBulk_gene (); break;
      case PRANDTL_REUSS : pt = new Prandtl_Reuss(); break;
      case PRANDTL_REUSS2D_D : pt = new Prandtl_Reuss2D_D(); break;	
      case PRANDTL_REUSS1D : pt = new Prandtl_Reuss1D(); break;	
      case TRELOAR : pt = new TreloarN(); break;	
      case NEWTON1D : pt = new Loi_newton1D(); break;	
      case NEWTON2D_D : pt = new Loi_newton2D_D(); break;	
      case NEWTON3D : pt = new Loi_newton3D(); break;	
      case MAXWELL1D : pt = new Loi_maxwell1D(); break;	
      case MAXWELL2D_D : pt = new Loi_maxwell2D_D(); break;	
      case MAXWELL2D_C : pt = new Loi_maxwell2D_C(); break;	
      case MAXWELL3D : pt = new Loi_maxwell3D(); break;	
      case LOI_ADDITIVE_EN_SIGMA : pt = new LoiAdditiveEnSigma(); break;	
      case LOI_CRITERE : pt = new LoiCritere(); break;
      case LOI_DES_MELANGES_EN_SIGMA : pt = new LoiDesMelangesEnSigma(); break;
      case LOI_CONTRAINTES_PLANES : pt = new LoiContraintesPlanes(); break;	
      case LOI_CONTRAINTES_PLANES_DOUBLE : pt = new LoiContraintesPlanesDouble(); break;
      case LOI_DEFORMATIONS_PLANES : pt = new LoiDeformationsPlanes(); break;
      case HYSTERESIS_1D : pt = new Hysteresis1D(); break;	
      case HYSTERESIS_3D : pt = new Hysteresis3D(); break;	
      case HYSTERESIS_BULK : pt = new Hysteresis_bulk(); break;
      case LOI_ISO_THERMO : pt = new Loi_iso_thermo(); break;
      case LOI_DE_TAIT : pt = new Loi_de_Tait(); break;	
      case MOONEY_RIVLIN_1D : pt = new MooneyRivlin1D(); break;	
      case MOONEY_RIVLIN_3D : pt = new MooneyRivlin3D(); break;	
      case HART_SMITH3D : pt = new Hart_Smith3D(); break;	
      case POLY_HYPER3D : pt = new Poly_hyper3D(); break;	
      case MAHEO_HYPER : pt = new Maheo_hyper(); break;
      case HYPER_EXTERNE_W : pt = new Hyper_externe_W(); break;
      case HYPO_ELAS3D : pt = new Hypo_hooke3D(); break;
      case HYPO_ELAS2D_C : pt = new Hypo_hooke2D_C(); break;
      case HYPO_ELAS1D : pt = new Hypo_hooke1D(); break;
      // en dimension 3, on peut avoir des Umat, mais pas dans les autres dimensions
      case LOI_VIA_UMAT :
        { if (ParaGlob::Dimension() == 3) {pt = new Loi_Umat();}
          else {cout << "\n erreur dans la definition de la loi de comportement = "
                      << nom << '\n';
              cout << " les loi via umat ne sont disponibles qu'en 3D "  << endl;
              Sortie (1);
             }
          break;
        }
      case LOI_VIA_UMAT_CP :
        { if (ParaGlob::Dimension() == 3) {pt = new Loi_Umat(LOI_VIA_UMAT_CP); }
          else {cout << "\n erreur dans la definition de la loi de comportement = "
                      << nom << '\n';
              cout << " les loi via umat cp ne sont disponibles qu'en 3D "  << endl;
              Sortie (1);
             }
          break;
        }
      case LOI_COULOMB : pt = new CompFrotCoulomb(); break;
      case LOI_RIEN1D : pt = new Loi_rien1D(); break;	
      case LOI_RIEN2D_C : pt = new Loi_rien2D_C(); break;	
      case LOI_RIEN2D_D : pt = new Loi_rien2D_D(); break;	
      case LOI_RIEN3D : pt = new Loi_rien3D(); break;	
      case ORTHOELA3D : pt = new Loi_ortho_elas3D(); break;
      case ORTHOELA2D_C : pt = new Loi_ortho2D_C_entrainee(); break;
      case PROJECTION_ANISOTROPE_3D : pt = new Projection_anisotrope_3D(); break;
      case HYPO_ORTHO3D : pt = new Hypo_ortho3D_entrainee(); break;
      default :
              {  cout << "\n erreur dans la definition de la loi de comportement = "
                      << nom << '\n';
                 cout << " LesLoisDeComp::Def_loi(string & nom) "  << endl;
                 Sortie (1);     
               }
    };
   return pt;
  };


// surcharge de l'operateur de lecture typée
istream & operator >> (istream & entree, LesLoisDeComp::Loi & loi)
  { // vérification du type
    string type; entree >> type;
    if (type != "LesLoisDeComp::Loi")
      {Sortie (1); return entree;
       }
    //  puis les données 
    entree >> loi.st1; loi.pt=NULL;  
    return entree;      
  };
  
// surcharge de l'operateur d'ecriture typée
ostream & operator << ( ostream & sort,const  LesLoisDeComp::Loi & loi)
  { // un indicateur donnant le type puis les datas
    // il n'y a pas sauvegarde du pointeur de loi
    sort << "LesLoisDeComp::Loi " << loi.st1  << "\n" ; 
    return sort;      
  };
