// FICHIER : LoiAdditiveEnSigma.cp
// CLASSE : LoiAdditiveEnSigma


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


//#include "Debug.h"
#include "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 "CharUtil.h"

#include "LoiAdditiveEnSigma.h"


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

// constructeur  par défaut à ne pas utiliser
LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma() :
	liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t(),l_energ(),l_energ_t(),f_ponder(),f_ponder_t() 
  { cout << "\n erreur, le constructeur par defaut ne doit pas etre utilise !"
	        << "\n LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma()";
	   cout << "\n LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma()";     
    Sortie(1);
   }; 

// le constructeur courant
LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma
                        (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):
	       liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t(),l_energ(l_energ_),l_energ_t(l_energ_t_)
	       ,f_ponder(),f_ponder_t()
	 { 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.);};  
//---debug
//cout << "\n  constructeurcourant LoiAdditiveEnSigma : taille_l_energ= " << l_energ.size() << "  taille_l_energ_t= " << l_energ_t.size()<< endl;
//this->Affiche(); cout << "\n" << endl;
//---fin debug
         };
//---debug
//ofstream fichier("toto", ios::app);
//fichier << "\n un saveresult de loi additive : constructeur courant ";
//this->Ecriture_base_info(fichier,1);        
//---fin debug
  }; 

// constructeur de copie 
LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma
                                         (const LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma& 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)
	 { 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);
//---debug
//ofstream fichier("toto", ios::app);
//fichier << "\n un constructeur de copie ";
//fichier << "\n ------ save result interne : ";
//if (nevez_save_result != NULL) nevez_save_result->Ecriture_base_info(fichier,1);
//fichier << endl;
//---fin debug
			  
           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);
         };
//---debug
//ofstream fichier("toto", ios::app);
//fichier << "\n un saveresult de loi additive : constructeur de copie ";
//fichier << "\n ------ le saveresult passé en paramètre : ";
//LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma* savons =  ( LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma*) &sav ;
//savons->Ecriture_base_info(fichier,1);
//
//fichier << "\n ------- le saveresult this : ";
//this->Ecriture_base_info(fichier,1);        
//---fin debug
  }; 
	        // destructeur
LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::~SaveResul_LoiAdditiveEnSigma()
	 { 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);
         };
  }; 
  
// affectation
Loi_comp_abstraite::SaveResul &
     LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma& sav = *((LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma*) &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++)
            { if ((*ili) != NULL) // cas où il y a effectivement un conteneur non nul dans sav
                  // normalement les tailles sont déjà bonnes
                  (*(*jli))=(*(*ili)); // on peut directement affecter
              // pour les autres conteneurs, ils doivent toujours exister
              (*(*jsig))=(*(*isig));(*(*jsig_t))=(*(*isig_t));
            };
      };
    // // 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;
    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 LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::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_LoiAdSig")
          { cout << "\n erreur en lecture du conteneur pour la loi additive"
                 << " \n LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::Lecture_base_info(..";
            Sortie(1);     
          }
     #endif
     // 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 additive, 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 LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::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)
         {f_ponder.resize(nb_loi);
          f_ponder_t.resize(nb_loi);
         };
		    };
     
     // 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);
       };
     // on met les grandeurs de t vers tdt
     TversTdt();
  };

// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::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_LoiAdSig  ";
	    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); 			 
       };
	  }; 
	        
	        // mise à jour des informations transitoires en définitif s'il y a convergence 
	        // par exemple (pour la plasticité par exemple)
void LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::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++)
     {if ((*ili) != NULL) (*ili)->TdtversT();
      (*(*isig_t)) = (*(*isig));
      (*ienerg_t)=(*ienerg);
			   if (avec_ponderation)
			     {(*ifo_t) = (*ifo);
			      ifo++; ifo_t++;
				    }; 
     }; 
	 }; 

void LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::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++;
         }; 
     }; 
	 }; 
			  
// affichage à l'écran des infos
void LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::Affiche() const 
{ cout << "\n SaveResul_LoiAdditiveEnSigma: " ; 
  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 additive: ";
  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);};

  cout << "\n .. fin SaveResul_LoiAdditiveEnSigma:.. \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 LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::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);
  };
};

// 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* LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma
         ::Complete_SaveResul(const BlocGen & bloc, const Tableau <Coordonnee>& tab_coor
                             ,const Loi_comp_abstraite* loi)
  {// on transmet au conteneur 3D interne
   const LoiAdditiveEnSigma * loi_CPtt = (const LoiAdditiveEnSigma*) loi;
   // loi_CPtt : est un nom quelconque
   // récup de la liste de loi
   list <Loi_comp_abstraite *>::const_iterator ili,ilifin=loi_CPtt->lois_internes.end();
   // récup des infos pour chaque loi
   list <SaveResul*>::iterator ia=liste_des_SaveResul.begin();
   for (ili = loi_CPtt->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 LoiAdditiveEnSigma::SaveResul_LoiAdditiveEnSigma::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_LoiAdditiveEnSigma::Deformation_plastique()";
     Sortie(1);
     return 0.; // pour taire le warning, mais on ne passe jamais là
   };

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

LoiAdditiveEnSigma::LoiAdditiveEnSigma ()  : // Constructeur par defaut
  Loi_comp_abstraite(LOI_ADDITIVE_EN_SIGMA,RIEN_CATEGORIE_LOI_COMP,0),lois_internes()
  ,list_completude_calcul(),d_sigma_deps_inter(NULL)
  ,d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt(NULL)
  ,avec_ponderation(false),list_ponderation()
  ,list_ponderation_nD_quelconque()
  ,d_sigtotalHH()
  ,type_calcul(1),tangent_ddl_via_eps(0)
    {};
	
// Constructeur de copie
LoiAdditiveEnSigma::LoiAdditiveEnSigma (const LoiAdditiveEnSigma& loi) :
   Loi_comp_abstraite(loi),lois_internes(),list_completude_calcul()
   ,d_sigma_deps_inter(NULL),d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt(NULL)
   ,avec_ponderation(loi.avec_ponderation),list_ponderation(loi.list_ponderation)
   ,d_sigtotalHH()
   ,list_ponderation_nD_quelconque()
   ,type_calcul(loi.type_calcul),tangent_ddl_via_eps(loi.tangent_ddl_via_eps)

     { list <Loi_comp_abstraite *>::const_iterator ili,ilifin=loi.lois_internes.end();
       list <Enumcompletudecalcul>::const_iterator ic,icfin=loi.list_completude_calcul.end();
       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);
         };
       // pondération nD quelconques -> création de pondérations identiques
       list <Ponderation_TypeQuelconque* >::const_iterator it,itfin = loi.list_ponderation_nD_quelconque.end();
       if (!(loi.list_ponderation_nD_quelconque.empty()))
        {for (it = loi.list_ponderation_nD_quelconque.begin(); it != itfin; it++)
          if (*it != NULL)
            { Ponderation_TypeQuelconque* pt = new Ponderation_TypeQuelconque(*(*it));
              list_ponderation_nD_quelconque.push_back(pt);
            }
          else list_ponderation_nD_quelconque.push_back(NULL);
        };
     };

LoiAdditiveEnSigma::~LoiAdditiveEnSigma ()
// 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_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt != NULL)
          delete d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt;
       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);
        };
       // pondération nD quelconques
       list <Ponderation_TypeQuelconque* >::iterator it,itfin = list_ponderation_nD_quelconque.end();
       if (list_ponderation_nD_quelconque.size() != 0)
         {for (it = list_ponderation_nD_quelconque.begin(); it != itfin; it++)
           if (*it != NULL)
             delete *it;
         };
      
     };

// def d'une instance de données spécifiques, et initialisation
// valable une fois que les différentes lois internes sont définit
LoiAdditiveEnSigma::SaveResul * LoiAdditiveEnSigma::LoiAdditiveEnSigma::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
     // 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++)
        { SaveResul * nevez_save_result=NULL;
          if ((*ili) != NULL)
            nevez_save_result = (*ili)->New_et_Initialise();  
          liste_des_SaveResul.push_back(nevez_save_result);
          // 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
     LoiAdditiveEnSigma::SaveResul * retour = new SaveResul_LoiAdditiveEnSigma(liste_des_SaveResul,l_sigoHH,l_sigoHH_t
                                              ,l_energ,l_energ_t,avec_ponderation);
     // 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);
        };
     // retour
	    return retour;
	  };

// Lecture des lois de comportement
void LoiAdditiveEnSigma::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { // tout d'abord on regarde si on utilise ou pas des fonctions de pondération
    bool passerUneLigne = false;
    if (strstr(entreePrinc->tablcar,"avec_fonction_de_ponderation_")!=NULL)
      { // lecture du mot clé
        string st2;
        *(entreePrinc->entree)  >> st2;
        // vérification 
        if (st2 != "avec_fonction_de_ponderation_") 
               { cout << "\n erreur en lecture, on aurait du lire le mot cle avec_fonction_de_ponderation_"
                      << " alors qu'on a lu " << st2;
                 cout << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";     
                 entreePrinc->MessageBuffer("**erreur01**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);     
                };
        // on enregistre
        avec_ponderation = true;
        passerUneLigne = true;
      }
    else // sinon on n'a pas de fonction de pondération
		    {avec_ponderation = false;};
    // maintenant on regarde si le type de calcul est spécifié
    if (strstr(entreePrinc->tablcar,"type_calcul=")!=NULL)
      { // lecture du mot clé
        string st2;
        *(entreePrinc->entree)  >> st2 >> type_calcul;
        // vérification 
        if (st2 != "type_calcul=") 
               { cout << "\n erreur en lecture, on aurait du lire le mot cle type_calcul="
                      << " alors qu'on a lu " << st2;
                 cout << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";     
                 entreePrinc->MessageBuffer("**erreur02**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);     
                };
        // on enregistre
        if ((type_calcul != 1) && (type_calcul != 2))
               { cout << "\n erreur en lecture, on aurait du lire type_calcul= 1 ou 2"
                      << " alors qu'on a lu " << type_calcul;
                 cout << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";     
                 entreePrinc->MessageBuffer("**erreur03**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);     
                };
       passerUneLigne = true;
      }
    else // sinon valeur par défaut
		    {type_calcul = 1;};
   
    // maintenant on regarde si tangent_ddl_via_eps est spécifié
    if (strstr(entreePrinc->tablcar,"tangent_ddl_via_eps=")!=NULL)
      { // lecture du mot clé
        string st2;
        *(entreePrinc->entree)  >> st2 >> tangent_ddl_via_eps;
        // vérification
        if (st2 != "tangent_ddl_via_eps=")
               { cout << "\n erreur en lecture, on aurait du lire le mot cle tangent_ddl_via_eps="
                      << " alors qu'on a lu " << st2;
                 cout << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";
                 entreePrinc->MessageBuffer("**erreur10**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);
                };
        // on enregistre
        if ((tangent_ddl_via_eps != 1) && (tangent_ddl_via_eps != 0))
               { cout << "\n erreur en lecture, on aurait du lire tangent_ddl_via_eps= 1 ou 0"
                      << " alors qu'on a lu " << tangent_ddl_via_eps;
                 cout << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";
                 entreePrinc->MessageBuffer("**erreur010**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);
                };
       passerUneLigne = true;
      }
    else // sinon valeur par défaut
      {tangent_ddl_via_eps = 0;};


	   // on passe à la ligne éventuellement, s'il y a des fonctions de pondération et/ou un type de calcul spécifié
	   if (passerUneLigne)
	     entreePrinc->NouvelleDonnee();
    
    // lecture jusque l'on trouve le mot clé signalant la fin de la liste des loi élémentaires
    bool trouve_ponder_grandeur_locale = false; // pour la gestion de  list_ponderation_nD_quelconque
    bool premier_lecture = true;
    int dim_lois=0; Enum_categorie_loi_comp categ=RIEN_CATEGORIE_LOI_COMP;
    string st1,st2;
    while (strstr(entreePrinc->tablcar,"fin_liste_lois_elementaires")==NULL)
      { // dans le cas de l'existence de fonction de pondération, on lit les infos
		      if (avec_ponderation)
         { Ponderation ponder; // un élément courant
           // on doit commencer par lire les grandeurs des fonctions de pondération
           *(entreePrinc->entree)  >> st1;
           if ((st1 != "les_grandeur_ponderation=") && (st1 != "avec_ponder_grandeur_locale_"))
               { cout << "\n erreur en lecture, on aurait du lire le mot cle les_grandeur_ponderation="
                      << " ou le mot cle avec_ponder_grandeur_locale_ "
                      << " alors qu'on a lu " << st1;
                 cout << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";     
                 entreePrinc->MessageBuffer("**erreur04**");
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);     
               };
               
           
           // 1) cas de l'utilisation de courbes 1D
           if (st1 == "les_grandeur_ponderation=")
             {int compteur = 1; // pour éviter une boucle infinie
              Ddl_enum_etendu typecourant; // inter
              List_io < Ddl_enum_etendu > listddlenum;
              List_io <bool> listbool;
              while (st1 != "fin_grandeur_ponderation_")
               {*(entreePrinc->entree)  >> st1 >> st2;
                if (st1 == "fin_grandeur_ponderation_") break; // pas terrible mais c'est ce qui me vient à l'idée !
                // cas de la grandeur
                if (!(Ddl_enum_etendu::VerifExistence(st1)))
                  { cout << "\n erreur en lecture, le type de grandeur lu" << st1 << " n'est pas acceptable  "
                         << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";
                    entreePrinc->MessageBuffer("**erreur05**");
                    throw (UtilLecture::ErrNouvelleDonnee(-1));
                    Sortie(1);
                  }
                else {typecourant=Ddl_enum_etendu::RecupDdl_enum_etendu(st1);};
                listddlenum.push_back(typecourant); // sauvegarde
                // cas du positionnement de la grandeur
                if (st2 == "AuxNoeuds_")  {listbool.push_back(1);}
                else if (st2 == "AuPti_") {listbool.push_back(0);}
                else
                  { cout << "\n erreur en lecture, de positionnement de la grandeur qui doit etre AuxNoeuds_ ou AuPti_ "
                         << " et on a  lu" << st2 << " qui n'est pas acceptable  "
                         << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";
                    entreePrinc->MessageBuffer("**erreur06**");
                    throw (UtilLecture::ErrNouvelleDonnee(-1));
                    Sortie(1);
                  };
                // vérif que l'on n'a pas dépasser le maxi autorisé
                if (compteur > 11)
                  { cout << "\n erreur en lecture, on a lu plus de 11 types de grandeurs pour les fonctions de ponderations "
                         << " il y a un probleme dans le fichier de donnee !! "
                         << "\n valeurs actuellement lue: " << listddlenum;
                    cout << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";
                    entreePrinc->MessageBuffer("**erreur07**");
                    throw (UtilLecture::ErrNouvelleDonnee(-1));
                    Sortie(1);
                  }
                else {compteur++;};
               };
              // maintenant on peut définir le nombre de fonctions 1D
              int taille = listddlenum.size();
              ponder.Type_grandeur().Change_taille(taille);
              ponder.Valeur_aux_noeuds().Change_taille(taille);
              ponder.C_proport().Change_taille(taille);
              // on transfert les Ddl_enum_etendu et les positionnements
              int i=1; List_io < Ddl_enum_etendu >::iterator il,ilfin=listddlenum.end();
              List_io < bool >::iterator ip = listbool.begin();
              for (il=listddlenum.begin();il != ilfin; il++,i++,ip++)
                {ponder.Type_grandeur()(i) = (*il);
                 ponder.Valeur_aux_noeuds()(i) = (*ip);
                };
              // maintenant la lecture des fonctions de pondération
              entreePrinc->NouvelleDonnee();
              *(entreePrinc->entree)  >> st1; // le mot clé
              if (st1 != "deb_fonct_ponder=")
                { cout << "\n erreur en lecture, on attendait le mot cle deb_fonct_ponder= et on a lu  " << st1
                       << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";
                  entreePrinc->MessageBuffer("**erreur08**");
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie(1);
                };
              for (int j=1;j<=taille;j++)
                { *(entreePrinc->entree) >> st2; // lecture de l'identificateur de la courbe
                  // on regarde si la courbe existe, si oui on récupère la référence
                  if (lesCourbes1D.Existe(st2))
                      { ponder.C_proport()(j) = lesCourbes1D.Trouve(st2);}
                  else // sinon il faut la lire maintenant
                      { string non_courbe("_");
                        ponder.C_proport()(j) = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (st2.c_str()));
                        // lecture de la courbe
                        ponder.C_proport()(j)->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
                        entreePrinc->NouvelleDonnee(); // préparation du flux
                      };
                };
              *(entreePrinc->entree)  >> st1; // le mot clé de la fin
              if (st1 != "fin_fonct_ponder_")
                  { cout << "\n erreur en lecture, on attendait le mot cle fin_fonct_ponder_ et on a lu  " << st1
                         << "\n LoiAdditiveEnSigma::LectureDonneesParticulieres (...";
                    entreePrinc->MessageBuffer("**erreur09**");
                    throw (UtilLecture::ErrNouvelleDonnee(-1));
                    Sortie(1);
                  };
              // enregistrement des infos
              list_ponderation.push_back(ponder);
              entreePrinc->NouvelleDonnee(); // prepa du flot de lecture pour la suite
              *(entreePrinc->entree)  >> st1; // on lit le prochain mot clé

             }; // fin du cas de l'utilisation de courbes 1D
          
           // 2) cas de l'utilisation d'une fonction nD
           // cas où il existe une pondération additionnelle via des grandeurs
           // quelconque locales
           // mais en fait cela permet de définir une fonction nD qui
           // peut alors contenir toutes les grandeurs possibles: locales et globales
           if (st1 == "avec_ponder_grandeur_locale_")
//           if (strstr(entreePrinc->tablcar,"avec_ponder_grandeur_locale_")!=NULL)
             { Ponderation_TypeQuelconque ponderQuelc; // un élément courant
               entreePrinc->NouvelleDonnee(); // prepa du flot de lecture pour la suite
               // on doit commencer par lire les grandeurs des fonctions de niveau
               string mot_cle="les_grandeurs_=";
               string nom_class_methode("LoiAdditiveEnSigma::LectureDonneesParticulieres");
               
               List_io <string> list_id_grand; //liste de travail
               if (strstr(entreePrinc->tablcar,"les_grandeurs_=")!=NULL)
                  // cas où il y a des grandeurs à lire
                 {entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
                  int compteur = 1; // pour éviter une boucle infinie
                  // on lit les grandeurs pour l'instant en string
                  int nb_grandeurs_locales = 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
                    if (Existe_typeQuelconque(st1))
                      {list_id_grand.push_back(st1);
                       nb_grandeurs_locales++;
                      }
                    else
                      { cout << "\n erreur en lecture, le type de grandeur lu" << st1
                             << " n'est pas acceptable  "
                             << "\n "<<nom_class_methode<<"(...";
                        entreePrinc->MessageBuffer("**erreur05**");
                        throw (UtilLecture::ErrNouvelleDonnee(-1));
                        Sortie(1);
                      };
                   };
                  };
                  
               // --- maintenant on va lire la fonction nD
               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);
               // on crée le conteneur de pondération
               Ponderation_TypeQuelconque* ptnD = new Ponderation_TypeQuelconque;
               // lecture sur le flot d'entrée
               // si list_id_grand n'est pas vide, on vérifie que les grandeurs passées en paramètre
               // sont bien des variables de la fonction (locale ou globale)
               ptnD->LecturePonderation(list_id_grand,entreePrinc,lesFonctionsnD);

               trouve_ponder_grandeur_locale=true; // on valide l'existence au moins d'une fct nD
               // on ajoute dans la liste des fct nD
               list_ponderation_nD_quelconque.push_back(ptnD);
               // 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);
               entreePrinc->NouvelleDonnee(); // prepa du flot de lecture pour la suite
               *(entreePrinc->entree)  >> st1; // on lit le prochain mot clé
//               cout << "\n debug lecture donnée loi additive en sigma "
//                    << "\n st1= "<< st1 << flush;
             }
           else // sinon pour l'instant on rempli de pointeurs nulles
             {list_ponderation_nD_quelconque.push_back(NULL);
             };
         }
        else // si on n'est pas avec ponderation il faut lire le nom de la loi
         {*(entreePrinc->entree)  >> st1;
         } ;
        // --- lecture de la loi individuelle ---------
        // lecture du nom de la loi
        st2=st1; // c'est st1 qui contient le dernier nom lu
//        *(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 LoiAdditiveEnSigma::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 LoiAdditiveEnSigma::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 additive, 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 LoiAdditiveEnSigma"
                     << "\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 LoiAdditiveEnSigma::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 LoiAdditiveEnSigma"
                   << "\n la loi lue: " << pt->Nom_comport() << " n'a pas la meme dimension que la premier loi lue";
              entreePrinc->MessageBuffer("lecture  LoiAdditiveEnSigma"); 
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1); 
            }
           if (!GroupeMecanique(pt->Id_categorie()))
              { cout << "\n erreur en lecture des lois constitutives elementaire d'une loi LoiAdditiveEnSigma"
                     << "\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 LoiAdditiveEnSigma::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 additive l'est aussi
        if (((Loi_comp_abstraite*)pt)->ThermoDependante()) this->thermo_dependant = true;
      };
    // gestion de list_ponderation_nD_quelconque
    // dans le cas où aucune fct_nD n'a été trouvé, on vide la liste qui n'est remplie que de nul
    if (!trouve_ponder_grandeur_locale)
      list_ponderation_nD_quelconque.clear();
   
    // au contraire s'il y a pondération avec des grandeurs locales, on va vérifier que ces grandeurs
    // sont dispo et on va préparer l'accès à ces grandeurs
    if (trouve_ponder_grandeur_locale)
      Verif_et_preparation_acces_grandeurs_locale();
   
    // appel au niveau de la classe mère, avec preparation du flot de lecture
    Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire
                 (*entreePrinc,lesFonctionsnD,true);
//    // prepa du flot de lecture pour d'autre loi éventuellement
//    entreePrinc->NouvelleDonnee();
  };

// affichage de la loi
void LoiAdditiveEnSigma::Affiche() const 
  {cout << "\n .......  loi de comportement loiAdditiveEnSigma ........";
	  cout << "\n calcul additif ";
	  if (type_calcul) {cout << " sur les contraintes ";} else { cout << " sur les increments de contraintes ";};
   if (tangent_ddl_via_eps) cout << "\n utilisation du comportement tangent dsig/deps pour calculer le comportement tangent en ddl ";
	  if (avec_ponderation) {cout << "\n avec ponderation " ;} else {cout << "\n 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  
         	};
      };
     cout << "\n .......  fin de la loi de comportement loiAdditiveEnSigma ........";     
  };
            
// affichage et definition interactive des commandes particulières à chaques lois
void LoiAdditiveEnSigma::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
 {  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
	   cout << "\n definition standart (rep o) ou exemples exhaustifs (rep n'importe quoi) ? ";
	   string rep = "_";     // procédure de lecture avec prise en charge d'un retour chariot
    rep = lect_return_defaut(true,"o");

    sort << "\n# .......  loi de comportement loiAdditiveEnSigma ........"
         << "\n#  il faut donner le nom de chaque loi suivi des parametres sur les lignes suivantes"
         << "\n#  puis terminer avec le mot cle: fin_liste_lois_elementaires "
         << "\n# exemple de deux lois elastiques ";
    // definition de la loi
    string internom("ISOELAS");
    LoiAbstraiteGeneral * pt = LesLoisDeComp::Def_loi(internom);
    sort << "\n      ISOELAS # premiere loi isoelas 3D";
    pt->Info_commande_LoisDeComp(entreePrinc);     
    sort << "\n      ISOELAS # seconde loi isoelas 3D";
    pt->Info_commande_LoisDeComp(entreePrinc);     
    sort  << "\n          fin_liste_lois_elementaires   # ----- fin de loiAdditiveEnSigma" << 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_  "
          << "\n#  exemple de deux lois elastiques ";
         sort << "\n#      ISOELAS  tangent_seulement_ # premiere loi isoelas 3D dont on retiens que le comportement tangent";
         pt->Info_commande_LoisDeComp(entreePrinc);     
         sort << "\n#      ISOELAS  tangent_seulement_  # seconde loi isoelas 3D dont on retiens que les contraintes ";
         pt->Info_commande_LoisDeComp(entreePrinc);     
         sort  << "\n#          fin_liste_lois_elementaires   # ----- fin de loiAdditiveEnSigma" << endl;
         sort  << "\n\n \n ";
         sort << "\n# .......  cas particulier 2) ........"
          << "\n#  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_ADDITIVE_EN_SIGMA) 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_ADDITIVE_EN_SIGMA   "
          << "\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#  "
          << "\n#  Cas particulier: a la suite du mot cle eventuel type_calcul= suivi de sa valeur "
          << "\n#  on peut indiquer le mot cle tangent_ddl_via_eps= suivi de 1 ou 0 (valeur par defaut) "
          << "\n#  une valeur de 1 indique que l'on souhaite calculer l'operateur tangent dsig/d_ddl "
          << "\n#  via l'operation composee: dsig/deps * deps/d_ddl (ce qui n'est pas le cas par defaut)"
          << "\n#  "
          << "\n#  " << endl;
       };
  };  		  	  

// test si la loi est complete
int LoiAdditiveEnSigma::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();
          }
     return ret; 
    }; 
		          
// calcul d'un module d'young équivalent à la loi, ceci pour un
// chargement nul
double LoiAdditiveEnSigma::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();
    // on balaie les infos de chaque loi
    SaveResul_LoiAdditiveEnSigma & save_resul = *((SaveResul_LoiAdditiveEnSigma*) saveResul_ex);
    list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
	   // cas éventuelle des fonctions de pondération
	   list <double>::iterator ipfonc;
	   if (avec_ponderation) ipfonc = save_resul.f_ponder.begin();
     for (ili=lois_internes.begin(),ic=list_completude_calcul.begin();ili!=ilifin;ili++,ic++,isave++)
      { if (*ic != TANGENT_UNIQUEMENT)
         {if ((avec_ponderation)&&((*ipfonc) != 1.))
            {E +=(*ili)->Module_young_equivalent(temps,def,*isave)  * (*ipfonc);}
          else
            {E +=(*ili)->Module_young_equivalent(temps,def,*isave);};
         };
        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 LoiAdditiveEnSigma::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();
    // on balaie les infos de chaque loi
    SaveResul_LoiAdditiveEnSigma & save_resul = *((SaveResul_LoiAdditiveEnSigma*) saveResul_ex);
    list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
	   // cas éventuelle des fonctions de pondération
	   list <double>::iterator ipfonc;
	   if (avec_ponderation) ipfonc = save_resul.f_ponder.begin();
     for (ili=lois_internes.begin(),ic=list_completude_calcul.begin();ili!=ilifin;ili++,ic++)
         { if (*ic != TANGENT_UNIQUEMENT)
             {if ((avec_ponderation)&&((*ipfonc) != 1.))
               {module_compressibilite +=(*ili)->Module_compressibilite_equivalent(temps,def,*isave) * (*ipfonc);}
				          else
				           {module_compressibilite +=(*ili)->Module_compressibilite_equivalent(temps,def,*isave);};
				         };
			        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 LoiAdditiveEnSigma::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_enu=1;i_enu<= taille; i_enu++)
           { // 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_enu))
              {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_enu).Enum()))
                  {tabnoeud(i)->Met_en_service(ponder.Type_grandeur()(i_enu).Enum());}
                 else
                  { cout << "\n erreur: la grandeur " << ponder.Type_grandeur()(i) << " n'existe pas "
                     << " il n'est pas possible d'utiliser une loi additive ponderee avec cette grandeur "
                     << " il manque sans doute des donnees aux noeuds !!! "
                     << "\n LoiAdditiveEnSigma::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 additive ponderee ne peut pas s'utiliser ici telle quelle ***"
                   << " demander une modification ! ";
                  cout << "\n 	LoiAdditiveEnSigma::Activation_donnees(.. " << endl;
                  Sortie(1);
                };	 		 
               // cas normal
               switch (ponder.Type_grandeur()(i_enu).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:
                   { Enum_ddl enu = ponder.Type_grandeur()(i_enu).Enum(); // pour simplifier
                     // si c'est EPS11, c'est ok, on n'a rien à faire car c'est directement dispo sinon les autres cas sont pb
                     if (enu != EPS11)
                       {cout << "\n erreur, le type de proportion " << ponder.Type_grandeur()(i_enu) << " n'est pas disponible "
                             << " pour l'instant au point d'integration ! "
                             << "\n LoiAdditiveEnSigma::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 LoiAdditiveEnSigma::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_LoiAdditiveEnSigma & save_resul = *((SaveResul_LoiAdditiveEnSigma*) saveDon);
   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();
   int dim = ParaGlob::Dimension();
   // maintenant on s'occupe des grandeurs de la loi additive elle même,
   List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
   list<int>::iterator idecal=decal.begin();
   for (itq=liTQ.begin();itq!=itqfin;itq++,idecal++)
    {TypeQuelconque& tipParticu = (*itq); // pour simplifier
     if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
     { EnumTypeQuelconque enuTQ = tipParticu.EnuTypeQuelconque().EnumTQ();

       // 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;

//--debug
//			 cout << "\n taille " << save_resul.l_sigoHH_t.size() << endl;
//			 for (ili=lois_internes.begin(),isig_t = save_resul.l_sigoHH_t.begin();
//               ili!=ilifin;ili++,isig_t++)
//				(*(isig_t))->Ecriture(cout);
//			 cout << endl;		
//          Sortie(1);
//--fin debug
			 
          for (ili=lois_internes.begin(),isig_t = save_resul.l_sigoHH_t.begin();
               ili!=ilifin;ili++,isig_t++)
                {TenseurHH* sigHH = (*(isig_t)); // pour simplifier
                 if (Dabs(sigHH->Dimension()) != dim)
                   {tyTQ(1+(*idecal)).Affectation_trans_dimension(*sigHH,true);
                   }
                 else // cas même dimension
                   {tyTQ(1+(*idecal)) = *(*(isig_t));
                   };
                 (*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 = save_resul.f_ponder_t.end();
           for (ipfonc=save_resul.f_ponder_t.begin();ipfonc != ipfonc_fin;ipfonc++)
             {tyTQ(1+(*idecal)) = (*ipfonc);  (*idecal)++;};
         };
       };
     };
   // puis appel des lois élémentaires
   for (ili=lois_internes.begin();ili!=ilifin;ili++,isave++)
        (*ili)->Grandeur_particuliere(absolue,liTQ,*isave,decal);
  };

// 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 LoiAdditiveEnSigma::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);
      };
   // maintenant on s'occupe des grandeurs de la loi additive elle même,
   
   // 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  LoiAdditiveEnSigma::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 LoiAdditiveEnSigma::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 >>  tangent_ddl_via_eps
           >> st1 >> type_calcul >> st1 >> avec_ponderation >> st2;
       // on regarde s'il y a une pondération nD également
       bool avec_nD;
       // on vide la liste au cas où
       {if (!list_ponderation_nD_quelconque.empty())
         {list <Ponderation_TypeQuelconque* >::iterator il, ilfin= list_ponderation_nD_quelconque.end();
          // on commence par supprimer les grandeurs pointées
          for (il = list_ponderation_nD_quelconque.begin();il != ilfin; il++)
            if (*il != NULL)
              delete (*il);
          list_ponderation_nD_quelconque.clear(); // puis on vide
         };
       };
       ent >> st1 >> avec_nD; // lecture du fait qu'il y a ou non du nD

       // 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);
       // on boucle sur le nombre de loi
       for (int i=1;i<= nb_loi; i++)
        { string toto;
          ent >> toto >> toto ; // passage de "===>sous_loi nb "
          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);
             // cas éventuel des fonctions nD
             if (avec_nD)
              {bool existe_fct;
               ent >> st1 >> existe_fct;
               if (existe_fct) // cas où il y a une fonction
                {Ponderation_TypeQuelconque* pt = new Ponderation_TypeQuelconque();
                 pt->Lecture_base_info(ent, cas, lesFonctionsnD);
                 list_ponderation_nD_quelconque.push_back(pt);
                }
               else list_ponderation_nD_quelconque.push_back(NULL);
              };
            };

          //------ 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 lu " << nom_completude_calcul
                   << " au lieu d'un des noms suivants CONTRAINTE_ET_TANGENT CONTRAINTE_UNIQUEMENT TANGENT_UNIQUEMENT ";
              cout << "\n LoiAdditiveEnSigma::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);
        };
       // s'il y a pondération avec des grandeurs locales, on va vérifier que ces grandeurs
       // sont dispo et on va préparer l'accès à ces grandeurs
       if (!list_ponderation_nD_quelconque.empty())
         Verif_et_preparation_acces_grandeurs_locale();
      }
    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 LoiAdditiveEnSigma::Ecriture_base_info_loi(ofstream& sort,const int cas)
  { if (cas == 1) 
     { sort << "\n  loiAdditiveEnSigma " << lois_internes.size()
            << " tangent_ddl_via_eps= "<< tangent_ddl_via_eps <<" ";
		     sort << "\n   type_calcul_additif " << type_calcul;
		     sort << " avec_ponderation ";
	      if (avec_ponderation) {sort << 1 ;} else {sort << 0;};
       // on regarde s'il y a une pondération nD également
       bool avec_nD = false;
       if ( list_ponderation_nD_quelconque.empty())
          {sort << " nD=  0 ";}
       else // cas avec nD
          {sort << " nD=  1 ";
           avec_nD = true;
          };

	      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;
       list <Ponderation_TypeQuelconque* >::const_iterator ipon_nD;
       if ( avec_nD)
          ipon_nD= list_ponderation_nD_quelconque.begin();
      
	      if (avec_ponderation)
         ipon = list_ponderation.begin();
       int compteur_loi = 1; // init
       for (ili=lois_internes.begin(),ic=list_completude_calcul.begin();
            ili!=ilifin;ili++,ic++,compteur_loi++)
         {sort << "\n ===>sous_loi "<< compteur_loi << " ";
          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++;
               // cas éventuel des fonctions nD
               if (avec_nD)
                {if (*ipon_nD != NULL)
                  {bool sans_courbe = false;
                   sort << " fct_nD  1 ";
                   (*ipon_nD)->Ecriture_base_info(sort,cas,sans_courbe);
                  }
                 else {sort << " fct_nD  0 ";};
                 ipon_nD++; // on avance pour la loi suivante
                };
				         };
			
			        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);
         };
     }
    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);
     };
   }; 
            

 // ========== codage des METHODES VIRTUELLES  protegees:================
        // calcul des contraintes a t+dt
void LoiAdditiveEnSigma::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_LoiAdditiveEnSigma & save_resul = *((SaveResul_LoiAdditiveEnSigma*) 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 = save_resul.f_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
         // 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);
////----- debug
////if (((*(*isig))(1,1) < 0.) && ((*ipfonc) != 0.))
// { cout << "\n debug LoiAdditiveEnSigma::Calcul_SigmaHH "
//        << " (*(*isig))(1,1)= "<<(*(*isig))(1,1)<< ", (*ipfonc)= "<< (*ipfonc)
//        << endl;
// };
////--- fin debug
             if ((avec_ponderation)&&((*ipfonc) != 1.))
                {
//                 double coef = (*ipfonc); // coef sans le local
//                 if (avec_fctnD_quelc) coef *= (*ipfonc_nD); // + le local
//                 switch(type_calcul) // choix en fonction du type
//                  { case 1 : // cas où les proportions s'appliquent à la totalité
//                     {module_compressibilite += coef*compress_inter;
//                      module_cisaillement +=  coef*cisaill_inter;
//                      energ += (*ienerg) * coef; // update des énergies totales
//                      (*sigtotalHH) += coef*(*(*isig)); // on ajoute la contrainte au total
//                      break;
//                     }
//                    case 2 : // cas où les proportions s'appliquent aux deltats
//                     {module_compressibilite += coef*compress_inter;
//                      module_cisaillement +=  coef*cisaill_inter;
//                      energ += (*ienerg) * coef; // update des énergies totales
//                      (*sigtotalHH) += (*(*isig_t)) + coef*((*(*isig))-(*(*isig_t))); // on ajoute la contrainte au total
//                      break;
//                     }
                
                 double coef = (*ipfonc);
//                 if (avec_fctnD_quelc) coef *= (*ipfonc_nD);
                 module_compressibilite += coef*compress_inter;
                 module_cisaillement +=  coef*cisaill_inter;
                 energ += (*ienerg) * coef; // update des énergies totales
                 (*sigtotalHH) += coef*(*(*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++;
//                if (avec_fctnD_quelc) ipfonc_nD++;
               };
           };
      };
//////----- debug
//if (((*sigtotalHH)(1,1) < 0.) && (Dabs(*ipfonc) > ConstMath::petit))
// { cout << "\n **** erreur debug LoiAdditiveEnSigma::Calcul_SigmaHH "
//        << "(*sigtotalHH)(1,1)= " << (*sigtotalHH)(1,1) << " (*ipfonc)= "<< (*ipfonc);
// };
// 
// { cout << "\n debug LoiAdditiveEnSigma::Calcul_SigmaHH "
//        << " (*sigtotalHH)(1,1)="<<(*sigtotalHH)(1,1)
//        << endl;
// };
//////--- fin debug
  
    // recopie du résultat
    sigHH = (*sigtotalHH);
    delete sigtotalHH; delete zeroHH;
    LibereTenseur();   
 };
        
        // calcul des contraintes a t+dt et de ses variations  
void LoiAdditiveEnSigma::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 & energ_t
		  	,double& module_compressibilite,double&  module_cisaillement
		  	,const Met_abstraite::Impli& ex )
 { // dans le cas très particulier ou on veut un opérateur tangent via dsig/deps on appelle
   // une routine particulière
   if (tangent_ddl_via_eps)
     {Calcul_DsigmaHH_via_eps_tdt
         (sigHH_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,energ,energ_t
          ,module_compressibilite,module_cisaillement,ex );
      return;
     };
   // 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_LoiAdditiveEnSigma & save_resul = *((SaveResul_LoiAdditiveEnSigma*) saveResul);
////---debug
//
//ofstream fichier("toto", ios::app);
//this->Ecriture_base_info_loi(fichier,1);        // calcul de la contrainte résultante
//
//cout << "\n nb loi= " << save_resul.liste_des_SaveResul.size() << endl;
////---fin debug
   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 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 = save_resul.f_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
//---debug
//cout << "\n  isave = " << ( (*isave) == NULL ) << endl;
//---fin debug
        // calcul de la contrainte résultante
        (*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);
         // --- traitement en fonction du type de calcul
//cout << "\n ipfonc= " << (*ipfonc) << endl;
////------- debug ------
//            { cout << "\n debug LoiAdditiveEnSigma: contrainte et variation d'une loi individuelle ";
//              cout << "\n contrainte "; sigHH_tdt.Ecriture(cout);
//					         cout << "\n variation contrainte/ddl ";
//              for (int i=1;i<=taille;i++)
//                 d_sigHH(i)->Ecriture(cout);
//					         cout << " \n -- fin  contrainte et variation d'une loi individuelle --- "<< endl ;
//            };       
////------- fin debug ------
         switch (*ic)
          { case CONTRAINTE_ET_TANGENT:  // cas normal
             {if ((avec_ponderation)&&((*ipfonc) != 1.))
               {double coef = (*ipfonc);
 //               if (avec_fctnD_quelc) coef *= (*ipfonc_nD);
 ////------- debug ------
 //            { cout << "\n debug LoiAdditiveEnSigma::Calcul_DsigmaHH_tdt ";
 //              cout << "\n (*ipfonc)= "<< (*ipfonc) ;
 //					         cout << "(*ipfonc_nD)= " << (*ipfonc_nD) << endl ;
 //            };
 ////------- fin debug ------
                module_compressibilite += coef * compress_inter;
                module_cisaillement +=  coef * cisaill_inter;
                energ +=   (*ienerg) * coef; // update des énergies totales
                (*sigtotalHH) += coef * (sigHH_tdt); // on ajoute la contrainte au total
                (*(*isig)) = sigHH_tdt; // on sauvegarde la contrainte partielle
 //cout << "\n ipfonc= " << (*ipfonc) << " ";
                // récup de l'opérateur tangent
                for (int j=1;j<=taille;j++)
                  { (*d_SigtotalHH(j)) += coef * (*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.))
               {double coef = (*ipfonc);
 //               if (avec_fctnD_quelc) coef *= (*ipfonc_nD);
                module_compressibilite += coef * compress_inter;
                module_cisaillement +=  coef * cisaill_inter;
                energ +=   (*ienerg) * coef; // update des énergies totales
                (*sigtotalHH) += coef * (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.))
                {double coef = (*ipfonc);
         //        if (avec_fctnD_quelc) coef *= (*ipfonc_nD);
                 // récup de l'opérateur tangent
                 for (int j=1;j<=taille;j++)
                   { (*d_SigtotalHH(j)) += coef * (*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++;
//            if (avec_fctnD_quelc) ipfonc_nD++;
           };
       
      }; // 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 a t+dt et de ses variations
void LoiAdditiveEnSigma::Calcul_DsigmaHH_via_eps_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 & energ_t
            ,double& module_compressibilite,double&  module_cisaillement
            ,const Met_abstraite::Impli& ex )
 {
   //il nous faut une Met_abstraite::Umat_cont
   Met_abstraite::Umat_cont umat; // def
   ex.Recup_Umat_cont(umat); // récup des grandeurs ad hoc d'Impli
  
      // redimentionnement éventuel pour le comportement tangent
   if (d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt != NULL)
    { int dim_HHHH = d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt->Dimension();
      switch (Abs(sigHH_t.Dimension()))
       {case 3:
         if (dim_HHHH != 33)
            {delete d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt;
             d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt = NevezTenseurHHHH(33);
            };
         break;
        case 2:
         if (dim_HHHH != 22)
            {delete d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt;
             d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt = NevezTenseurHHHH(22);
            };
         break;
        case 1:
         if (dim_HHHH != 11)
            {delete d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt;
             d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt = NevezTenseurHHHH(11);
            };
         break;
        default:
          cout << "\n *** dimensiont incorrecte !!! on arrete "
               << "\n LoiAdditiveEnSigma::Calcul_DsigmaHH_via_eps_tdt(...";
          Sortie(1);
       };
    }
   else
    { switch (Abs(sigHH_t.Dimension()))
       {case 3:
         d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt = NevezTenseurHHHH(33);
// on essaie avec un tenseur général, pas de symétrie prise en compte
//         d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt = NevezTenseurHHHH(30);
         break;
        case 2:
         d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt = NevezTenseurHHHH(22);
         break;
        case 1:
         d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt = NevezTenseurHHHH(11);
         break;
        default:
          cout << "\n *** dimensiont incorrecte !!! on arrete "
               << "\n LoiAdditiveEnSigma::Calcul_DsigmaHH_via_eps_tdt(...";
          Sortie(1);
       };
    }

   // appel de Calcul_dsigma_deps
   bool en_base_orthonormee = false; // on est en curviligne
   Calcul_dsigma_deps
            (en_base_orthonormee,sigHH_t,DepsBB
            ,epsBB_tdt,delta_epsBB,jacobien_0,jacobien
            ,sigHH_tdt
            ,*d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt
            ,energ,energ_t,module_compressibilite,module_cisaillement
            ,umat);
 
   // maintenant on peut calculer l'opérateur tangent / ddl
   int nbddl = d_gijBB_tdt.Taille();
   for (int i = 1; i<= nbddl; i++)
     {  *(d_sigHH(i)) = (*d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt) && (*(d_epsBB(i)));
     };
//      for (int i = 1; i<= nbddl; i++)
//        {  Tenseur3HH & dsigHH = *((Tenseur3HH*) (d_sigHH(i)));  // passage en dim 3
//           const Tenseur3BB & depsBB = *((Tenseur3BB *) (d_epsBB(i))); //    "
//           dsigHH = (*d_sigma_deps_pourCalcul_DsigmaHH_via_eps_tdt) && depsBB;
//        };


    LibereTenseur();LibereTenseurQ();
 };
        // calcul des contraintes et ses variations  par rapport aux déformations a t+dt
        // en_base_orthonormee:  le tenseur de contrainte en entrée est  en orthonormee
        //                  le tenseur de déformation et son incrémentsont également en orthonormees
        //                 si = false: les bases transmises sont utilisées
        // ex: contient les éléments de métrique relativement au paramétrage matériel = X_(0)^a
void LoiAdditiveEnSigma::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_LoiAdditiveEnSigma & save_resul = *((SaveResul_LoiAdditiveEnSigma*) 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);};
   // 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 = save_resul.f_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
        // calcul de la contrainte résultante
//cout << "\n boucle 100000 pour debug LoiAdditiveEnSigma::Calcul_dsigma_deps "<<endl;
//for (int jj=1;jj<=100000;jj++)
        (*ili)->Calcul_dsigma_deps (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,ex);

         // --- traitement en fonction du type de calcul
         switch (*ic)
          { case CONTRAINTE_ET_TANGENT:  // cas normal
             {if ((avec_ponderation)&&((*ipfonc) != 1.))
                 {double coef = (*ipfonc);
//                  if (avec_fctnD_quelc) coef *= (*ipfonc_nD);
                  module_compressibilite += coef * compress_inter;
                  module_cisaillement +=  coef * cisaill_inter;
                  energ +=   (*ienerg) * coef; // update des énergies totales
                  (*sigtotalHH) += coef * (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  * coef ;
                 }
              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.))
                 {double coef = (*ipfonc);
//                  if (avec_fctnD_quelc) coef *= (*ipfonc_nD);
                  module_compressibilite += coef * compress_inter;
                  module_cisaillement +=  coef * cisaill_inter;
                  energ +=   (*ienerg) * coef; // update des énergies totales
                  (*sigtotalHH) += coef * (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.))
                 {double coef = (*ipfonc);
//                  if (avec_fctnD_quelc) coef *= (*ipfonc_nD);
                  // récup de l'opérateur tangent
                  d_sigma_deps += *d_sigma_deps_inter  * coef ;
                 }
              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++;
//            if (avec_fctnD_quelc) ipfonc_nD++;
           };

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

       // fonction interne utilisée par les classes dérivées de Loi_comp_abstraite
       // pour répercuter les modifications de la température
       // ici utiliser pour modifier la température des lois élémentaires
       // l'Enum_dure: indique quel est la température courante : 0 t ou tdt
 void LoiAdditiveEnSigma::RepercuteChangeTemperature(Enum_dure temps)
  { list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
    for (ili=lois_internes.begin();ili!=ilifin;ili++) 
        {(*ili)->temperature_0 = this->temperature_0;
         (*ili)->temperature_t = this->temperature_t;
         (*ili)->temperature_tdt = this->temperature_tdt;
         (*ili)->dilatation=dilatation;
         
         // on répercute également les déformations thermiques, qui ne sont utilisées
         // telles quelles que pour certaines lois: ex: loi hyper-élastique
         if (dilatation)
          {//  a- dimensionnement des tenseurs intermédiaires 
           int dim_tens = epsBB_therm->Dimension();
               // -- cas de la déformation
           if ((*ili)->epsBB_therm == NULL) { (*ili)->epsBB_therm = NevezTenseurBB(dim_tens);}
           else if ((*ili)->epsBB_therm->Dimension() != dim_tens)
              { delete (*ili)->epsBB_therm;(*ili)->epsBB_therm = NevezTenseurBB(dim_tens);};
               // -- cas de la vitesse de déformation
           if ((*ili)->DepsBB_therm == NULL) { (*ili)->DepsBB_therm = NevezTenseurBB(dim_tens);}
           else if ((*ili)->DepsBB_therm->Dimension() != dim_tens)
            { delete (*ili)->DepsBB_therm;(*ili)->DepsBB_totale = NevezTenseurBB(dim_tens);};
           // b- affectation des tenseurs
           (*(*ili)->epsBB_therm)=(*epsBB_therm);
           (*(*ili)->DepsBB_therm)=(*DepsBB_therm);
          };
         // on répercute sur les lois internes
         (*ili)->RepercuteChangeTemperature(temps);
         Loi_comp_abstraite * loi_ili = (*ili); // pour le débug
         
         switch (temps)
          { case TEMPS_0: {(*ili)->temperature = &(*ili)->temperature_0; break;}
            case TEMPS_t: {(*ili)->temperature = &(*ili)->temperature_t; break;}
            case TEMPS_tdt: {(*ili)->temperature = &(*ili)->temperature_tdt; break;}
            default:
              { cout << "\n erreur, cas de temps non prevu !! "
                     << "\n LoiAdditiveEnSigma::RepercuteChangeTemperature(...";
                Sortie(1);      
              };
           }; 
         #ifdef MISE_AU_POINT
         if (((ParaGlob::NiveauImpression() > 8) && (Permet_affichage() == 0))
             || (Permet_affichage() > 7)
            )
              { cout << "\n init temperatures:\n "
                     << " loi_ili->temperature_0= " << loi_ili->temperature_0
                     << " loi_ili->temperature_t= " << loi_ili->temperature_t
                     << " loi_ili->temperature_tdt= " << loi_ili->temperature_tdt
                     << " loi_ili->temperature= " << *(loi_ili->temperature)
                     << " \n LoiAdditiveEnSigma::RepercuteChangeTemperature(.."
                     << endl;
              };
         #endif
        };
  }; 
   
// fonction surchargée dans les classes dérivée si besoin est
void LoiAdditiveEnSigma::CalculGrandeurTravail
          (const PtIntegMecaInterne& ptintmeca
           ,const Deformation & def,Enum_dure temps,const ThermoDonnee& dTP
           ,const Met_abstraite::Impli* ex_impli
           ,const Met_abstraite::Expli_t_tdt* ex_expli_tdt
           ,const Met_abstraite::Umat_cont* ex_umat
           ,const List_io<Ddl_etendu>* exclure_dd_etend
           ,const List_io<const TypeQuelconque *>* exclure_Q
          )
{ // récup et enregistrement dans les variables spécifiques au point calculé
  SaveResul_LoiAdditiveEnSigma & save_resul = *((SaveResul_LoiAdditiveEnSigma*) saveResul);
  if (avec_ponderation)
    { // on passe en revue les grandeurs servant au calcul des fonctions de proportion
	     {list <Ponderation >::iterator il,ilfin=list_ponderation.end();
       list <double>::iterator ipfonc = save_resul.f_ponder.begin();
       for (il=list_ponderation.begin();il != ilfin;il++,ipfonc++)
        { Ponderation& ponder = (*il); // pour simplifier
          (*ipfonc)=1.; // init
          int taille = ponder.Type_grandeur().Taille();
          for (int i=1;i<= taille; i++)
           { // calcul des pondérations
             if (ponder.Valeur_aux_noeuds()(i)) // pour l'instant que des ddl patentés !
              // cas d'une proportion provenant d'une interpolation aux noeuds
              { double grand = def.DonneeInterpoleeScalaire(ponder.Type_grandeur()(i).Enum(),temps);
                double fonc = ponder.C_proport()(i)->Valeur(grand);
                (*ipfonc) *= fonc; // on accumule multiplicativement
              }
             else
              // sinon il s'agit d'une grandeur directement accessible au point d'intégration
              // pour l'instant il n'y a pas de procédure générale de récupération, seulement des cas particuliers
              { 
                // deux cas suivant que l'on a affaire à un ddl de base ou à un vrai ddl étendu
                if (ponder.Type_grandeur()(i).Nom_vide())
                  {Enum_ddl enu = ponder.Type_grandeur()(i).Enum(); // pour simplifier
                   switch (enu)
                    { case PROP_CRISTA:
                       { const double* taux_crita = dTP.TauxCrista();
                         if (taux_crita != NULL)
                          {	double fonc = ponder.C_proport()(i)->Valeur(*taux_crita);
                            (*ipfonc) *= fonc; // on accumule multiplicativement
                          }
                         else
                          {cout << "\n erreur, le taux de cristalinite n'est pas disponible au point d'integration "
                                << " il n'est pas possible de calculer la proportion pour la loi des melanges "
                                << "\n LoiAdditiveEnSigma::CalculGrandeurTravail(.... ";
                          }; 	
                         break;
                       }
                      case EPS11:
                       { double eps11 = (ptintmeca.EpsBB_const())(1,1);
                         double fonc = ponder.C_proport()(i)->Valeur(eps11);
                         (*ipfonc) *= fonc; // on accumule multiplicativement
 ////----- debug
 ////if ((spherique_sig < 0.) && (fonc != 0.))
 // { cout << "\n debug LoiAdditiveEnSigma::CalculGrandeurTravail "
 //        <<  " EPS11= "<<EPS11<< ", fonc= "<< fonc
 //        << endl;
 // };
 ////--- fin debug
                         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 LoiAdditiveEnSigma::CalculGrandeurTravail(.... ";
                       }
                    };
                  }
                else
                  {// cas d'un vrai ddl étendue
                   switch (ponder.Type_grandeur()(i).Position()-NbEnum_ddl())
                    {case 87: // cas de "def_equivalente"
                      {const double def_equivalente  =  ptintmeca.Deformation_equi_const()(1); // recup de la def equi
                       double fonc = ponder.C_proport()(i)->Valeur(def_equivalente);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
             //cout << "\n defEqui= " << def_equivalente << " fonct= " << fonc << " ";									 
                       break;
                      }
                     case 88: // cas de "def_duale_mises_maxi"
                      {const double def_duale_mises_maxi  =  ptintmeca.Deformation_equi_const()(3); // recup de la def equi
                       double fonc = ponder.C_proport()(i)->Valeur(def_duale_mises_maxi);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       break;
                      }
                     case 89: // cas de "vitesse_def_equivalente"
                      {const double delta_def_equivalente  =  ptintmeca.Deformation_equi_const()(4); // recup du delta def equi
                       // recup de l'incrément de temps
                       double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
                       double unSurDeltat=0;    
                       if (Abs(deltat) >= ConstMath::trespetit)
                       {unSurDeltat = 1./deltat;}
                       else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
                       { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
                         if (unSurDeltat < 0)
                         { cout << "\n le pas de temps est négatif !! "; };
                         unSurDeltat = ConstMath::tresgrand;
                       };
                       double vitesse_def_equi = 	delta_def_equivalente * unSurDeltat;
                       double fonc = ponder.C_proport()(i)->Valeur(vitesse_def_equi);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
             //cout << "\n vit= " << vitesse_def_equi << " f= " << fonc << endl;									 
                       break;
                      }
                     case 77: // cas de "def_duale_mises"
                      {const double def_duale_mises  =  ptintmeca.Deformation_equi_const()(2); // recup de la def equi
                       double fonc = ponder.C_proport()(i)->Valeur(def_duale_mises);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       break;
                      }
                     case 78: // cas de "Spherique_eps"
                      {const Vecteur &  epsInvar   = ptintmeca.EpsInvar_const(); // recup des invariants
                       double spherique_eps = epsInvar(1); 
                       double fonc = ponder.C_proport()(i)->Valeur(spherique_eps);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       break;
                      }
                     case 81: // cas de "Spherique_sig"
                      {const Vecteur &  sigInvar   = ptintmeca.SigInvar_const(); // recup des invariants
                       double spherique_sig = sigInvar(1); 
                       double fonc = ponder.C_proport()(i)->Valeur(spherique_sig);
 ////----- debug
 ////if ((spherique_sig < 0.) && (fonc != 0.))
 // { cout << "\n debug LoiAdditiveEnSigma::CalculGrandeurTravail "
 //        << " i="<< i << " spherique_sig= "<<spherique_sig<< ", fonc= "<< fonc
 //        << endl;
 // };
 ////--- fin debug
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       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 LoiAdditiveEnSigma::CalculGrandeurTravail(.... ";
                     break;
                     };
                  };
              };
           };
        };
      };

      // dans le cas où il y a une dépendance à des grandeurs locales
      if (!list_ponderation_nD_quelconque.empty())
       {
        list <Ponderation_TypeQuelconque* >::iterator il,ilfin=list_ponderation_nD_quelconque.end();
//        // on reparcourt les pondérations
        list <double>::iterator ipfonc = save_resul.f_ponder.begin();
        
        for (il=list_ponderation_nD_quelconque.begin();il != ilfin;il++,ipfonc++)
         {//(*ipfonc)=1.; // init
          if (*il != NULL)
           {Ponderation_TypeQuelconque& pondnD = *(*il);
            // on utilise la méthode générique de loi abstraite
            Tableau <double> & tab_val = Loi_comp_abstraite::Loi_comp_Valeur_FnD_Evoluee
                (pondnD.C_proport(),1 // une seule valeur attendue en retour
                 ,ex_impli,ex_expli_tdt,ex_umat
                 ,exclure_dd_etend
                 ,exclure_Q
                 ,&(save_resul.liste_des_SaveResul)
                );
            (*ipfonc) *= tab_val(1); // on accumule multiplicativement

////------- debug ------
//            { cout << "\n debug LoiAdditiveEnSigma::CalculGrandeurTravail ";
//              cout << "\n argument "<< pondnD.Tab_argument() ;
//					         cout << "(*ipfonc_nD)= " << (*ipfonc) << endl ;
//            };       
////------- fin debug ------
           };
         };
       };
	   };
 
  // répercution sur les classes dérivées si besoin est
  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();
	 for (ili=lois_internes.begin();ili!=ilifin;ili++,isave++) 
    {// 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
		   (*ili)->CalculGrandeurTravail(ptintmeca,def,temps,dTP
                             ,ex_impli,ex_expli_tdt,ex_umat,exclure_dd_etend,exclure_Q);
    };
};


 
// vérification et préparation de l'acces aux grandeurs locales
void  LoiAdditiveEnSigma::Verif_et_preparation_acces_grandeurs_locale()
  {// 1) on demande aux lois de prendre en compte éventuellement les grandeurs locales nécessaires
   list <EnumTypeQuelconque > listEnuQuelc; // def de la liste des grandeurs quelconque
   // récup des grandeurs quelconques nécessaires
   if (!list_ponderation_nD_quelconque.empty())
    {
     list <Ponderation_TypeQuelconque* >::iterator il,ilfin=list_ponderation_nD_quelconque.end();
     for (il = list_ponderation_nD_quelconque.begin();il != ilfin;il++)
      if ((*il)!= NULL)
       {const Tableau <EnumTypeQuelconque>& tab_enu_quelc = (*il)->C_proport()->Tab_enu_quelconque();
        int tail = tab_enu_quelc.Taille();
        if (tail)
         {for (int i = 1; i<= tail; i++)
            listEnuQuelc.push_back(tab_enu_quelc(i));
         };
       };
      
     listEnuQuelc.sort();
     listEnuQuelc.unique();

     // 2) on vérifie qu'une des lois au moins produira la grandeur quelconque
     list <Loi_comp_abstraite *>::iterator kk,kkfin=lois_internes.end();
     list <EnumTypeQuelconque >::iterator jj,jjfin=listEnuQuelc.end();
     for (jj=listEnuQuelc.begin();jj != jjfin; jj++)
       {bool existe = false; // par défaut pb
        for (kk=lois_internes.begin();kk != kkfin;kk++)
           {if(((*kk)->Existe_stockage_grandeurs_quelconques((*jj))))
             existe = true;
////--- debug
//cout << "\n debug LoiAdditiveEnSigma::Verif_et_preparation_acces_grandeurs_locale() ";
//cout <<"\n nom_loi: "<< (*kk)->Nom_comport() <<", ce que l'on regarde: "<< NomTypeQuelconque(*jj) << ", existe= "<< existe << "\n ";
//const list <EnumTypeQuelconque >& liinter = (*kk)->ListdeTouslesQuelc_dispo_localement();
//
//if (!(liinter.empty()))
// {list <EnumTypeQuelconque >::const_iterator hh,hfin=liinter.end();
//  for (hh=liinter.begin();hh!=hfin;hh++)
//    cout << NomTypeQuelconque(*hh) << " ";
// };
//
//
////--- fin debug
//            
           };
        if (!existe)
           { cout << "\n *** erreur d'utilisation de grandeur locale "
                  << " la grandeur "<<NomTypeQuelconque(*jj)
                  << " n'est pas disponible au niveau des differentes lois de comportement "
                  << endl;
             Sortie(1);
           };
       };

     // activation dans les lois de la demande des grandeurs quelconques
     for (kk=lois_internes.begin();kk != kkfin;kk++)
  //   for (Loi_comp_abstraite * loii : lois_internes)
  //      loii->Activation_stockage_grandeurs_quelconques(listEnuQuelc);
       (*kk)->Activation_stockage_grandeurs_quelconques(listEnuQuelc);


   
//   for (EnumTypeQuelconque enu : listEnuQuelc)
//      for (Loi_comp_abstraite * loii : lois_internes)
//         if(!(loii->Existe_stockage_grandeurs_quelconques(enu)))
//           { cout << "\n *** erreur d'utilisation de grandeur locale "
//                  << " la grandeur "<<NomTypeQuelconque(enu)
//                  << " n'est pas disponible au niveau des differentes lois de comportement "
//                  << endl;
//             Sortie(1);
//           };
    };
  };









   
