// FICHIER : LoiDesMelangesEnSigma.cp
// CLASSE : LoiDesMelangesEnSigma


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


//#include "Debug.h"
#include "LesLoisDeComp.h"

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

#include "LoiDesMelangesEnSigma.h"


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

// constructeur  par défaut à ne pas utiliser
LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma() :
	liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t(),l_energ(),l_energ_t()
	,J_sigoHH(),J_sigoHH_t(),proportion(1.),proportion_t(1.),type_evolution_proportion(0)
 ,deja_actif_sur_iter1(false),deja_actif_sur_iter2(false)
  { cout << "\n erreur, le constructeur par defaut ne doit pas etre utilise !"
	     << "\n LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma()";
    Sortie(1);
  }; 

// le constructeur courant
LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma
                        (list <SaveResul*>& l_des_SaveResul
                         ,list <TenseurHH* >& l_siHH,list <TenseurHH* >& l_siHH_t
                         ,list <TenseurHH* >& J_siHH,list <TenseurHH* >& J_siHH_t
	                     ,list <EnergieMeca >& l_energ_,list <EnergieMeca >& l_energ_t_
                      ,int type_evol_proportion):
	liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t(),l_energ(l_energ_),l_energ_t(l_energ_t_) 
	,J_sigoHH(),J_sigoHH_t(),proportion(1.),proportion_t(1.)
 ,type_evolution_proportion(type_evol_proportion)
 ,deja_actif_sur_iter1(false),deja_actif_sur_iter2(false)
     { list <SaveResul *>::const_iterator ili,ilifin=l_des_SaveResul.end();
	      list <TenseurHH* >::const_iterator isig,isig_t,jsig,jsig_t;
       for (ili=l_des_SaveResul.begin(),isig = l_siHH.begin(),isig_t = l_siHH_t.begin()
            ,jsig = J_siHH.begin(),jsig_t = J_siHH_t.begin();
            ili!=ilifin;ili++,isig++,isig_t++,jsig++,jsig_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);

           TenseurHH * jnterHH=NULL;
           // dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*jsig) != NULL) {jnterHH=NevezTenseurHH(*(*jsig));};
           J_sigoHH.push_back(jnterHH);
           TenseurHH * jnterHH_t=NULL;
           // idem interHH, dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*jsig_t) != NULL) {jnterHH_t =NevezTenseurHH(*(*jsig_t));};
           J_sigoHH_t.push_back(jnterHH_t);
         };
//---debug
//cout << "\n  constructeur: taille_l_energ= " << l_energ.size() << "  taille_l_energ_t= " << l_energ_t.size()<< endl;
//---fin debug
  }; 

// constructeur de copie 
LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma
                                         (const LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma& sav ):
	liste_des_SaveResul() ,l_sigoHH(),l_sigoHH_t(),J_sigoHH(),J_sigoHH_t()
	,l_energ(sav.l_energ),l_energ_t(sav.l_energ_t)
	,proportion(sav.proportion),proportion_t(sav.proportion_t)
 ,type_evolution_proportion(sav.type_evolution_proportion)
 ,deja_actif_sur_iter1(sav.deja_actif_sur_iter1),deja_actif_sur_iter2(sav.deja_actif_sur_iter2)
	    { list <SaveResul *>::const_iterator ili,ilifin=sav.liste_des_SaveResul.end();
	      list <TenseurHH* >::const_iterator isig,isig_t,jsig,jsig_t;
       for (ili=sav.liste_des_SaveResul.begin(),isig = sav.l_sigoHH.begin(),isig_t = sav.l_sigoHH_t.begin()
            ,jsig = sav.J_sigoHH.begin(),jsig_t = sav.J_sigoHH_t.begin();
            ili!=ilifin;ili++,isig++,isig_t++,jsig++,jsig_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);

           TenseurHH * jnterHH=NULL;
           // dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*jsig) != NULL) {jnterHH=NevezTenseurHH(*(*jsig));};
           J_sigoHH.push_back(jnterHH);
           TenseurHH * jnterHH_t=NULL;
           // idem interHH, dans le cas où le tenseur passé en paramètre est non null on s'en sert
           if ((*jsig_t) != NULL) {jnterHH_t =NevezTenseurHH(*(*jsig_t));};
           J_sigoHH_t.push_back(jnterHH_t);
			  
         };
//---debug
//cout << "\n  constructeur_copie: taille_l_energ= " << l_energ.size() << "  taille_l_energ_t= " << l_energ_t.size()<< endl;
//this->Affiche(); cout << "\n" << endl;
//---fin debug
  }; 
	        // destructeur
LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::~SaveResul_LoiDesMelangesEnSigma()
	 { list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	   list <TenseurHH* >::iterator isig,isig_t,jsig,jsig_t;
       for (ili=liste_des_SaveResul.begin(),isig = l_sigoHH.begin(),isig_t = l_sigoHH_t.begin()
            ,jsig = J_sigoHH.begin(),jsig_t = J_sigoHH_t.begin();
            ili!=ilifin;ili++,isig++,isig_t++,jsig++,jsig_t++)
         {if ((*ili) != NULL) delete (*ili); //liste_des_SaveResul.erase(ili); 
          if((*isig) != NULL) delete (*isig); if((*isig_t) != NULL) delete (*isig_t);
          if((*jsig) != NULL) delete (*jsig); if((*jsig_t) != NULL) delete (*jsig_t);
         };
  }; 
  
// affectation
Loi_comp_abstraite::SaveResul &
     LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma& sav
                      = *((LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma*) &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();
	   list <TenseurHH* >::const_iterator kisig = sav.J_sigoHH.begin();
    list <TenseurHH* >::const_iterator kisig_t = sav.J_sigoHH_t.begin();
    if (liste_des_SaveResul.size() != sav.liste_des_SaveResul.size())
     
     {// 1) on vide la liste
      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();
	     list <TenseurHH* >::iterator ksig  = J_sigoHH.begin();
      list <TenseurHH* >::iterator ksig_t = J_sigoHH_t.begin();
      
      // on supprime les grandeurs pointées
      for (jli=liste_des_SaveResul.begin();jli!=jlifin;
                                 jli++,jsig++,jsig_t++,ksig++,ksig_t++)
         {if ((*jli) != NULL) delete (*jli); //liste_des_SaveResul.erase(ili);
          if((*jsig) != NULL) delete (*jsig); if((*jsig_t) != NULL) delete (*jsig_t);
          if((*ksig) != NULL) delete (*ksig); if((*ksig_t) != NULL) delete (*ksig_t);
         };
      // on vide les listes
      liste_des_SaveResul.clear();l_sigoHH.clear();l_sigoHH_t.clear();
      J_sigoHH.clear();J_sigoHH_t.clear();
      
      // 2) on recrée à la bonne taille
      for (ili=sav.liste_des_SaveResul.begin();
            ili!=ilifin;ili++,isig++,isig_t++,kisig++,kisig_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);
           // idem pour kisig
           if ((*kisig) != NULL) {interHH_t =NevezTenseurHH(*(*kisig));};
           J_sigoHH.push_back(interHH_t);
           // idem pour kisig_t
           if ((*kisig_t) != NULL) {interHH_t =NevezTenseurHH(*(*kisig_t));};
           J_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();
	       list <TenseurHH* >::iterator ksig=J_sigoHH.begin();
	       list <TenseurHH* >::iterator ksig_t=J_sigoHH_t.begin();
        for (ili=sav.liste_des_SaveResul.begin();
            ili!=ilifin;ili++,isig++,isig_t++,kisig++,kisig_t++
                       ,jli++,jsig++,jsig_t++,ksig++,ksig_t++)
            { (*(*jli))=(*(*ili)); (*(*isig))=(*(*jsig));(*(*isig_t))=(*(*jsig_t));
              (*(*ksig))=(*(*kisig));(*(*ksig_t))=(*(*kisig_t));
            };
      };

    // puis les grandeurs qui ne posent pas de pb
    proportion = sav.proportion;
    proportion_t = sav.proportion_t;
    type_evolution_proportion = sav.type_evolution_proportion;
	   l_energ = sav.l_energ;
    l_energ_t = sav.l_energ_t;
    deja_actif_sur_iter1 = sav.deja_actif_sur_iter1;
    deja_actif_sur_iter2 = sav.deja_actif_sur_iter2;
    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 LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::Lecture_base_info 
                                                 (istream& 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_LoiMeSig")
        { cout << "\n erreur en lecture du conteneur pour la loi additive"
               << " \n LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::Lecture_base_info(..";
          Sortie(1);     
        };
   #endif
   // la proportion
   ent >> toto >>  proportion_t ; //proportion = proportion_t;
   if (cas == 1)
     ent >> toto >> type_evolution_proportion; // le type d'évolution
   ent >> toto >> deja_actif_sur_iter1 >> deja_actif_sur_iter2;
   // lecture du nombre de loi
   int nb_loi; ent >> 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 LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::Lecture_base_info(..";
       Sortie(1);
     };
   #endif
   
   // on itère sur ces grandeurs
	  list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	  list <TenseurHH* >::iterator isig_t,jsig_t;
	  list <EnergieMeca >::iterator ienerg_t=l_energ_t.begin();
   for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin(),jsig_t = J_sigoHH_t.begin();
          ili!=ilifin;ili++,isig_t++,ienerg_t++)
       { // 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 de la contrainte sauvegardée 
         (*jsig_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 LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::Ecriture_base_info
                                                 (ostream& sort,const int cas)
 { // ici la majorité des 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_LoiMeSig  ";
   // la proportion
   sort << " prop= " << proportion_t << " ";
   if (cas == 1)
      sort << " type_evol_prop= " << type_evolution_proportion << " ";
   // deja_actif_sur_iter
   sort << " deja_actif_sur_iter= "<<deja_actif_sur_iter1<<" "<<deja_actif_sur_iter2<<" ";
   // on sort enfin le nombre de grandeur à sauvegarde
   sort <<  liste_des_SaveResul.size() << " ";
   // on itère sur ces grandeurs
   list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
   list <TenseurHH* >::iterator isig_t,jsig_t;
   list <EnergieMeca >::iterator ienerg_t=l_energ_t.begin();
   for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin(),jsig_t = J_sigoHH_t.begin();
          ili!=ilifin;ili++,isig_t++,ienerg_t++)
       { // données de chaque loi
         if ((*ili) != NULL) 
         (*ili)->Ecriture_base_info(sort,cas);sort << "  ";
         // la contrainte sauvegardée est celle stable uniquement
         (*isig_t)->Ecriture(sort); sort << " " ;// écriture du tenseur
         // la contrainte sauvegardée est celle stable uniquement
         (*jsig_t)->Ecriture(sort); // écriture du tenseur
         sort << " " << (*ienerg_t); // écriture des énergies
       };
 };
	        
	        // mise à jour des informations transitoires en définitif s'il y a convergence 
	        // par exemple (pour la plasticité par exemple)
void LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::TdtversT() 
  {  list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	 list <TenseurHH* >::iterator isig_t,isig,jsig_t,jsig;
	 list <EnergieMeca >::iterator ienerg,ienerg_t;
     for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin(),isig = l_sigoHH.begin()
          ,jsig_t = J_sigoHH_t.begin(),jsig = J_sigoHH.begin()
          ,ienerg=l_energ.begin(),ienerg_t=l_energ_t.begin();
          ili!=ilifin;ili++,isig_t++,isig++,jsig_t++,jsig++,ienerg++,ienerg_t++)
         {if ((*ili) != NULL) (*ili)->TdtversT();
          (*(*isig_t)) = (*(*isig));(*(*jsig_t)) = (*(*jsig));
          (*ienerg_t)=(*ienerg);
         }; 
     // la proportion
     proportion_t = proportion;
//non, ce n'est pas la bonne solution dans le cas général     proportion = 1.; // on démarre à priori sur la première loi
     // cas où la proportion démarrre à 1 et ne fait que diminuer sur chaque incrément
     // pour le premier incrément, la proportion est initialisée à la valeur par défaut
     if (type_evolution_proportion == 2)
       proportion = 1.;
     // deja_actif_sur_iter: pour l'instant on remet à false car
     // c'est présumé travailler uniquement sur un incrément
     deja_actif_sur_iter1 = deja_actif_sur_iter2 = false;
   
	}; 
void LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::TversTdt()
{ list <SaveResul *>::iterator ili,ilifin=liste_des_SaveResul.end();
	 list <TenseurHH* >::iterator isig_t,isig,jsig_t,jsig;
	 list <EnergieMeca >::iterator ienerg,ienerg_t;
     for (ili=liste_des_SaveResul.begin(),isig_t = l_sigoHH_t.begin(),isig = l_sigoHH.begin()
          ,jsig_t = J_sigoHH_t.begin(),jsig = J_sigoHH.begin()
          ,ienerg=l_energ.begin(),ienerg_t=l_energ_t.begin();
          ili!=ilifin;ili++,isig_t++,isig++,jsig_t++,jsig++,ienerg++,ienerg_t++)
         {if ((*ili) != NULL) (*ili)->TversTdt();
          (*(*isig)) = (*(*isig_t));(*(*jsig)) = (*(*jsig_t));
          (*ienerg)=(*ienerg_t);
         }; 
     // la proportion
     proportion = proportion_t;
     // cas où la proportion démarrre à 1 et ne fait que diminuer sur chaque incrément
     // pour le premier incrément, la proportion est initialisée à la valeur par défaut
     if (type_evolution_proportion == 2)
       proportion = 1.;
     // deja_actif_sur_iter: pour l'instant on remet à false car
     // c'est présumé travailler uniquement sur un incrément
     deja_actif_sur_iter1 = deja_actif_sur_iter2 = false;
};
			  
// affichage à l'écran des infos
void LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::Affiche() const 
{ cout << "\n SaveResul_LoiDesMelangesEnSigma: " ; 
  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 <TenseurHH* >::const_iterator jsig,jsigfin=J_sigoHH.end();
  list <TenseurHH* >::const_iterator jsig_t,jsig_tfin=J_sigoHH_t.end();
  list <EnergieMeca >::const_iterator ienerg,ienergfin = l_energ.end();
  list <EnergieMeca >::const_iterator ienerg_t,ienerg_tfin = l_energ_t.end();
  cout << "\n liste_des_SaveResul: ";
  for (ili=liste_des_SaveResul.begin();ili!=ilifin;ili++)
         {if ((*ili) != NULL) { cout << "\n "; (*ili)->Affiche();};};
  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 J_sigoHH: ";
  for (jsig = J_sigoHH.begin();jsig!=jsigfin;jsig++)
         { (*jsig)->Ecriture(cout);};
  cout << "\n J_sigoHH_t: ";
  for (jsig_t = J_sigoHH_t.begin();jsig_t!=jsig_tfin;jsig_t++)
         { (*jsig_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 proportion= " << proportion << " proportion_t= " << proportion_t << " ";
  cout << "\n deja_actif_sur_iter(1 et 2)= " << deja_actif_sur_iter1 <<" "<<deja_actif_sur_iter2<<" ";
  cout << "\n .. fin SaveResul_LoiDesMelangesEnSigma:.. \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 LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::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);
  };
  { List_io <TenseurHH*>::iterator lit(J_sigoHH.begin()),
                                   lend(J_sigoHH.end());
    for(;lit!=lend;++lit) // ici les bornes ne changent pas
       (*lit)->ChBase(gamma);
  };
  { List_io <TenseurHH*>::iterator lit(J_sigoHH_t.begin()),
                                   lend(J_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* LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma
         ::Complete_SaveResul(const BlocGen & bloc, const Tableau <Coordonnee>& tab_coor
                             ,const Loi_comp_abstraite* loi)
  {// on transmet au conteneur 3D interne
   const LoiDesMelangesEnSigma * loi_CP = (const LoiDesMelangesEnSigma*) loi;
   // récup des conteneurs relatifs à chaque loi
   list <SaveResul*>::iterator ia = liste_des_SaveResul.begin();
   // traitement de la première loi
   (*ia)->Complete_SaveResul(bloc,tab_coor,loi_CP->lois_internes1);
   // traitement de la seconde loi
   ia++;
   (*ia)->Complete_SaveResul(bloc,tab_coor,loi_CP->lois_internes2);
   return this;
  };

	        // ---- récupération d'information: spécifique à certaine classe dérivée
double LoiDesMelangesEnSigma::SaveResul_LoiDesMelangesEnSigma::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_LoiDesMelangesEnSigma::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 ============

LoiDesMelangesEnSigma::LoiDesMelangesEnSigma ()  : // Constructeur par defaut
  Loi_comp_abstraite(LOI_DES_MELANGES_EN_SIGMA,RIEN_CATEGORIE_LOI_COMP,0)
  ,lois_internes1(NULL),lois_internes2(NULL)
  ,calcule_si_prop_non_nulle(),d_sigtotalHH()
  ,type_grandeur(NU_DDL),proportion(1.),d_sigma_deps_inter(NULL)
  ,type_melange(1),valeur_aux_noeuds(true),c_proport(NULL),aA(1.)
  ,niveauF_grandeurND(NULL),niveauF_grandeurConsultable(NULL)
  ,niveauF_ddlEtendu(NULL),niveauF_temps(NULL)
    {};
	
// Constructeur de copie
LoiDesMelangesEnSigma::LoiDesMelangesEnSigma (const LoiDesMelangesEnSigma& loi) :
   Loi_comp_abstraite(loi),type_grandeur(loi.type_grandeur),proportion(loi.proportion)
   ,lois_internes1(NULL),lois_internes2(NULL),calcule_si_prop_non_nulle(loi.calcule_si_prop_non_nulle)
	  ,d_sigma_deps_inter(NULL),d_sigtotalHH()
   ,type_melange(loi.type_melange),valeur_aux_noeuds(loi.valeur_aux_noeuds)
   ,c_proport(loi.c_proport),aA(loi.aA)
   ,niveauF_grandeurND(loi.niveauF_grandeurND)
   ,niveauF_grandeurConsultable(NULL)
   ,niveauF_ddlEtendu(NULL),niveauF_temps(NULL)
     { lois_internes1 = loi.lois_internes1->Nouvelle_loi_identique();
       lois_internes2 = loi.lois_internes2->Nouvelle_loi_identique();
	      // on regarde s'il s'agit d'une courbe locale ou d'une courbe globale
	      if (c_proport != NULL)
	       if (c_proport->NomCourbe() == "_")
         {// comme il s'agit d'une courbe locale on la redéfinie (sinon pb lors du destructeur de loi)
          string non_courbe("_");   
          c_proport = Courbe1D::New_Courbe1D(*loi.c_proport);
         };
       // traitement des pondérations
       if (loi.niveauF_grandeurND != NULL)
         if (loi.niveauF_grandeurND->NomFonction() == "_")
           niveauF_grandeurND = Fonction_nD::New_Fonction_nD(*(loi.niveauF_grandeurND));
       if (loi.niveauF_ddlEtendu != NULL)
         niveauF_ddlEtendu = new Ponderation(*(loi.niveauF_ddlEtendu));
       if (loi.niveauF_temps != NULL)
            niveauF_temps = new Ponderation_temps(*(loi.niveauF_temps));;
       if (loi.niveauF_grandeurConsultable != NULL)
         niveauF_grandeurConsultable = new Ponderation_Consultable(*(loi.niveauF_grandeurConsultable));
		};

LoiDesMelangesEnSigma::~LoiDesMelangesEnSigma ()
// Destructeur 
     { if (lois_internes1 != NULL) delete lois_internes1;
       if (lois_internes2 != NULL) delete lois_internes2;
       if (d_sigma_deps_inter != NULL) delete d_sigma_deps_inter;
       if (d_sigtotalHH.Taille() != 0)
        { int taille = d_sigtotalHH.Taille();
          for (int i=1; i<= taille; i++)
          if (d_sigtotalHH(i) != NULL) delete d_sigtotalHH(i);
        };
       if (c_proport != NULL)
           if (c_proport->NomCourbe() == "_") delete c_proport;
      
       // cas des pondérations
       if (niveauF_grandeurND != NULL)
           if (niveauF_grandeurND->NomFonction() == "_") delete niveauF_grandeurND;

       if (niveauF_ddlEtendu != NULL)
          delete niveauF_ddlEtendu;
       if (niveauF_temps != NULL)
          delete niveauF_temps;
       if (niveauF_grandeurConsultable != NULL)
          delete niveauF_grandeurConsultable;
     };

// def d'une instance de données spécifiques, et initialisation
// valable une fois que les différentes lois internes sont définit
LoiDesMelangesEnSigma::SaveResul * LoiDesMelangesEnSigma::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 <TenseurHH* > J_sigoHH,J_sigoHH_t; // gestion des contraintes pour chaque loi
     list <EnergieMeca > l_energ,l_energ_t; // idem pour les énergies
     list <TenseurHH* >::iterator isig,isig_t;
     // on balaie les deux lois
     { SaveResul * nevez_save_result=NULL;
       if (lois_internes1 != NULL) nevez_save_result = lois_internes1->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);
       TenseurHH * jnterHH = NevezTenseurHH(dim,0.);J_sigoHH.push_back(jnterHH);
       TenseurHH * jnterHH_t = NevezTenseurHH(dim,0.);J_sigoHH_t.push_back(jnterHH_t);
       // on définit les conteneurs pour les énergies
       l_energ.push_back(EnergieMeca());l_energ_t.push_back(EnergieMeca());
      }  
     { SaveResul * nevez_save_result=NULL;
       if (lois_internes2 != NULL) nevez_save_result = lois_internes2->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);
       TenseurHH * jnterHH = NevezTenseurHH(dim,0.);J_sigoHH.push_back(jnterHH);
       TenseurHH * jnterHH_t = NevezTenseurHH(dim,0.);J_sigoHH_t.push_back(jnterHH_t);
       // on définit les conteneurs pour les énergies
       l_energ.push_back(EnergieMeca());l_energ_t.push_back(EnergieMeca());
      }
     // on regarde le type de progressivité de la proportion éventuelle
     int type_evol_proportion = 0; // init par défaut
     if (calcule_si_prop_non_nulle.Taille() == 2)
      {if ((calcule_si_prop_non_nulle(1) == 2) || (calcule_si_prop_non_nulle(2) == 2))
          type_evol_proportion = 1;
       else if ((calcule_si_prop_non_nulle(1) == 3) || (calcule_si_prop_non_nulle(2) == 3))
         type_evol_proportion = 2;
      };
    
     // on ramène la bonne instance
     LoiDesMelangesEnSigma::SaveResul * retour =  new SaveResul_LoiDesMelangesEnSigma
                           (liste_des_SaveResul,l_sigoHH,l_sigoHH_t
                            ,J_sigoHH,J_sigoHH_t,l_energ,l_energ_t,type_evol_proportion);
     // 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();
	    list <TenseurHH* >::iterator jsib = J_sigoHH.begin();
	    list <TenseurHH* >::iterator jsib_t = J_sigoHH_t.begin();
     for (ils=liste_des_SaveResul.begin();ils!=ilsfin;ils++,isib++,isib_t++,jsib++,jsib_t++)
        { if ((*ils) != NULL) delete (*ils);
		        if ((*isib) != NULL) delete (*isib);
          if ((*isib_t) != NULL) delete (*isib_t);
          if ((*jsib) != NULL) delete (*jsib);
          if ((*jsib_t) != NULL) delete (*jsib_t);
        };
     // retour
	  return retour;	  
	};

// Lecture des donnees de la classe sur fichier
void LoiDesMelangesEnSigma::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { // lecture jusque l'on trouve le mot clé signalant la fin de la liste des loi élémentaires
    bool premier_lecture = true;
    // on lit tout d'abord la grandeur qui servira a établir la proportion entre la première loi et la
    // seconde
    string nom; *(entreePrinc->entree)  >> nom;
    bool passer_une_ligne = true;
   
    // choix entre grandeur_proportion= et les_grandeurs_de_controle_=
   
    if ((nom != "grandeur_proportion=") && (nom != "les_grandeurs_de_controle_="))
      { cout << "\n erreur en lecture de la loi des melanges en sigma,"
             << " on attendait le mot cle grandeur_proportion=  "
             << " et un identificateur de grandeur, ou les_grandeurs_de_controle_= "
             << " alors que l'on a lue: " << nom;
        entreePrinc->MessageBuffer("**erreur1 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie(1);
      };
   
    if (nom == "grandeur_proportion=")
     { *(entreePrinc->entree)  >> type_grandeur; // lecture du type enumere de la grandeur
       // on regarde s'il faut lire le type de mélange
       if (strstr(entreePrinc->tablcar,"type_melange=")!=NULL)
        { *(entreePrinc->entree)  >> nom;
          if (nom != "type_melange=")
            { cout << "\n erreur en lecture de la loi des melanges en sigma, on attendait le mot cle type_melange="
                   << " alors que l'on a lue " << nom;
              entreePrinc->MessageBuffer("**erreur11 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
          *(entreePrinc->entree)  >> type_melange;
          if ((type_melange!= 1) && (type_melange != 2))
            { cout << "\n erreur en lecture du type de melange , il doit etre egale a 1 ou 2 alors que l'on a lu "
                   << type_melange;
              entreePrinc->MessageBuffer("**erreur12 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
        }
       else
        { type_melange = 1.;}; 
       
       // on regarde s'il faut lire l'indicateur "valeur_aux_noeuds"
       if (strstr(entreePrinc->tablcar,"valeur_aux_noeuds=")!=NULL)
        { *(entreePrinc->entree)  >> nom;
          if (nom != "valeur_aux_noeuds=")
            { cout << "\n erreur en lecture de la loi des melanges en sigma,"
                   << " on attendait le mot cle valeur_aux_noeuds="
                   << " alors que l'on a lue " << nom;
              entreePrinc->MessageBuffer("**erreur13 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
          *(entreePrinc->entree)  >> valeur_aux_noeuds;
        }
       else
        { valeur_aux_noeuds = 1;};
      
       // **** pour l'instant on ne considère que des grandeurs ddl aux noeuds, mais cela peut-être étendu sans pb
       if (valeur_aux_noeuds && (!type_grandeur.Nom_vide()))	   
         { cout << "\n erreur en lecture de la loi des melanges en sigma, dans le cas d'une proportion en fonction"
                << " de grandeur aux noeuds  pour l'instant seul les ddl de base sont autorises " ;
           entreePrinc->MessageBuffer("**erreur14 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         };
       // --- on regarde le cas d'une somme étendue
       aA=1.; //par défaut
       if (strstr(entreePrinc->tablcar,"somme_pondere_etendue_")!=NULL)
        {string nom;
         *(entreePrinc->entree) >> nom; // lecture d'un identificateur
         if(nom != "somme_pondere_etendue_")
            { cout << "\n erreur en lecture du mot cle somme_pondere_etendue_ "
                   << " on attendait la chaine : somme_pondere_etendue_ et on a lue " << nom;
              entreePrinc->MessageBuffer("**erreur15 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
         entreePrinc->NouvelleDonnee(); // on passe une ligne
         *(entreePrinc->entree) >> nom; // lecture de aA
         if(nom != "A=")
            { cout << "\n erreur en lecture du mot cle A= "
                   << " on attendait la chaine : A= et on a lue " << nom;
              entreePrinc->MessageBuffer("**erreur16 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
         *(entreePrinc->entree) >> aA;	
        };
      
        // --- on regarde s'il y a une fonction d'interface
       if (strstr(entreePrinc->tablcar,"avec_fonction_proportion_")!=NULL)
        {string nom;
         *(entreePrinc->entree) >> nom; // lecture d'un identificateur 
         if(nom != "avec_fonction_proportion_")
           { cout << "\n erreur en lecture du mot cle avec_fonction_proportion_ "
                  << " on attendait la chaine : avec_fonction_proportion_ et on a lue " << nom;
             entreePrinc->MessageBuffer("**erreur17 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);
           };
         entreePrinc->NouvelleDonnee(); // on passe une ligne
         *(entreePrinc->entree) >> nom; // lecture du mot cle
         if(nom != "fonction_prop=")
           { cout << "\n erreur en lecture du mot cle fonction_prop= "
                  << " on attendait la chaine : fonction_prop= et on a lue " << nom;
             entreePrinc->MessageBuffer("**erreur18 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);
           };
         *(entreePrinc->entree) >> nom; // 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(nom)) 
          { c_proport = lesCourbes1D.Trouve(nom);
          }
         else
          { // sinon il faut la lire maintenant
            string non_courbe("_");   
            c_proport = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
            // lecture de la courbe
            c_proport->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
          };
        };
     }
    else if (nom == "les_grandeurs_de_controle_=")
     { Ponderation ponder; // un élément courant
       // on initialise
       string mot_cle, st1,st2;
       string nom_class_methode="LoiDesMelangesEnSigma::LectureDonneesParticulieres (.";
       List_io < Ddl_enum_etendu > listddlenum;
       List_io <bool> listbool;
      
       // on lit les grandeurs pour l'instant en string
       List_io <string> list_id_grand; //liste de travail de toutes les grandeurs
       List_io <string> list_id_grand_glob; //liste des grandeurs globales
       List_io <string> list_id_ddl_etendu; //liste des ddl étendus
      
       int nb_grandeurs_globales = 0; // init
       while (st1 != "fin_grandeurs_")
        {*(entreePrinc->entree)  >> st1 ;
         if (st1 == "fin_grandeurs_") break; // pas terrible mais c'est ce qui me vient à l'idée !
         // on vérifie que le mot clé lu est exploitable
         string minus = Minuscules(st1); // la forme minuscules
         if ((st1=="TEMPS") || (Ddl_enum_etendu::VerifExistence(st1))
             || EstUneGrandeurGlobale(minus)
            )
           {list_id_grand.push_back(st1);
            if (EstUneGrandeurGlobale(minus)) // si c'est une grandeur globale on cumule le compteur
               nb_grandeurs_globales++;
           }
         else
           { cout << "\n erreur en lecture, le type de grandeur lu" << st1
                  << " n'est pas acceptable  "
                  << "\n LoiDesMelangesEnSigma::LectureDonneesParticulieres (...";
             entreePrinc->MessageBuffer("**erreur05**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);     
           };
        // on rempli les listes spécifiques
        if (Ddl_enum_etendu::VerifExistence(st1))
          list_id_ddl_etendu.push_back(st1);
        if (EstUneGrandeurGlobale(minus))
          list_id_grand_glob.push_back(st1);
        };
      
       // --- maintenant on va lire les fonctions
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
       mot_cle="deb_fonct_="; // le début des fonctions
       entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
       List_io <string>::iterator ili,ilifin = list_id_grand.end();
       List_io <Courbe1D*> li_courbe_globale; // inter
       List_io <bool> val_aux_noeuds; // inter
       int nb_GGlob=0;int nb_enum_etendu = 0; // compteur pour le dimensionnement
       // premier passage on crée les fonctions
       for (ili=list_id_grand.begin();ili != ilifin;ili++)
         {string minus = Minuscules(*ili); // la forme minuscules
          if ((*ili)=="TEMPS") // cas de la fonction du temps
            { // lecture de la loi d'évolution
              val_aux_noeuds.push_back(false); // sert à rien, mais permet
                   // de garder le même ordre de rangement que list_id_grand
              if (niveauF_temps == NULL)
                 niveauF_temps = new Ponderation_temps;
              // lecture de la pondération
              niveauF_temps->LectureDonneesPonderation(entreePrinc, lesCourbes1D);
            }
           else if (EstUneGrandeurGlobale(minus))
            { val_aux_noeuds.push_back(false); // sert à rien, mais permet
              nb_GGlob++;             // de garder le même ordre de rangement que list_id_grand
              // pour le premier élément de la liste on lit la fonction
              // pour les autres, on ne fait rien (la fct est déjà lue)
              if (nb_GGlob == 1)
               {// création de la pondération si nécessaire
                string nom_fonction;
                // lecture du nom de la fonction nD
                *(entreePrinc->entree) >>  nom_fonction;
                // on regarde si la fonction existe, si oui on récupère la référence
                if (lesFonctionsnD.Existe(nom_fonction))
                 { niveauF_grandeurND = lesFonctionsnD.Trouve(nom_fonction);
                 }
                else
                 { // sinon il faut la lire maintenant
                   string non_fonction("_");
                   niveauF_grandeurND = Fonction_nD::New_Fonction_nD(non_fonction,Id_Nom_Fonction_nD (non_fonction.c_str()));
                   // lecture de la fonction
                   niveauF_grandeurND->LectDonnParticulieres_Fonction_nD (non_fonction,entreePrinc);
                  };
               };
            }
           else if (Ddl_enum_etendu::VerifExistence(*ili))
            { nb_enum_etendu++;
              // pour le premier élément de la liste on lit la pondération
              // pour les autres, on ne fait rien (la pondération est déjà lue)
              if (nb_enum_etendu == 1)
               { if (niveauF_ddlEtendu==NULL) // on le crée
                    niveauF_ddlEtendu = new Ponderation;
                 // lecture
                 niveauF_ddlEtendu->LectureDonneesPonderation
                                (list_id_ddl_etendu,entreePrinc,lesCourbes1D);
               };
            };
         };
       // on passe le mot clé de fin
       mot_cle="fin_fonct_"; // la fin des fonctions
       entreePrinc->Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
          
          
// *** à changer en fonction de l'utilisation
           // deuxième passage on met à jour les conteneurs
//           niveauF_grandeurND->type_grandeur_GGlob.Change_taille(nb_GGlob);
//           niveauF_grandeurND->c_proport.Change_taille(nb_GGlob);
          
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
       passer_une_ligne = false;
      
       // on regarde s'il faut lire le type de mélange
       if (strstr(entreePrinc->tablcar,"type_melange=")!=NULL)
        { *(entreePrinc->entree)  >> nom;
          if (nom != "type_melange=")
            { cout << "\n erreur en lecture de la loi des melanges en sigma, on attendait le mot cle type_melange="
                   << " alors que l'on a lue " << nom;
              entreePrinc->MessageBuffer("**erreur11 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
          *(entreePrinc->entree)  >> type_melange;
          if ((type_melange!= 1) && (type_melange != 2))
            { cout << "\n erreur en lecture du type de melange , il doit etre egale a 1 ou 2 alors que l'on a lu "
                   << type_melange;
              entreePrinc->MessageBuffer("**erreur12 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
          entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
          // on ajoute 2 au type de mélange car ce sera l'indicateur qui permettra de savoir si on est
          // dans la mise en donnée historique ou la nouvelle mise en donnée
          type_melange += 2;
        }
       else
        { type_melange = 3;};
     };
   
    // maintenant lecture des 2 lois
    if (passer_une_ligne)
      entreePrinc->NouvelleDonnee();
    calcule_si_prop_non_nulle.Change_taille(0); // init au cas où 
    int dim_lois=0; int nb_loi = 0;Enum_categorie_loi_comp categ=RIEN_CATEGORIE_LOI_COMP;
    while (strstr(entreePrinc->tablcar,"fin_liste_lois_elementaires")==NULL)
      { // lecture du nom de la loi
        string st2,nom3;
        *(entreePrinc->entree)  >> st2;
        // on regarde si on est dans le cas d'une proportion exclusive (cf. info_commande_LoisDeComp)
        if (   (strstr(entreePrinc->tablcar,"calcule_si_prop_non_nulle_")!=NULL)
            || (strstr(entreePrinc->tablcar,"demarre_a_prop_non_nulle_puis_strictement_decroissante_")!=NULL)
            || (strstr(entreePrinc->tablcar,"demarre_a_prop_non_nulle_puis_strictement_decroissante_sur_chaque_incre_")!=NULL))
          { *(entreePrinc->entree)  >> nom3;
            if (calcule_si_prop_non_nulle.Taille() == 0)
               calcule_si_prop_non_nulle.Change_taille(2,0);
            if(nom3 == "calcule_si_prop_non_nulle_")
               {calcule_si_prop_non_nulle(nb_loi+1)=1;}
            else if(nom3 == "demarre_a_prop_non_nulle_puis_strictement_decroissante_") // sinon cas demarre_a_prop_non_nulle_puis_strictement_decroissante_
               {calcule_si_prop_non_nulle(nb_loi+1)=2;}
            else if(nom3 == "demarre_a_prop_non_nulle_puis_strictement_decroissante_sur_chaque_incre_") // sinon cas idem prec mais
               // sur chaque incrément
               {calcule_si_prop_non_nulle(nb_loi+1)=3;}
            else
               { cout << "\n erreur en lecture des lois constitutives elementaire d'une loi LoiDesMelangesEnSigma"
                     << "\n le mot cle lue: " << nom3
                     << " devrait etre soit calcule_si_prop_non_nulle_ ou soit demarre_a_prop_non_nulle_puis_strictement_decroissante_ ";
                entreePrinc->MessageBuffer("**erreur LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
                throw (UtilLecture::ErrNouvelleDonnee(-1));
                Sortie(1);     
              };
          };

        // definition de la loi
        LoiAbstraiteGeneral * pt = LesLoisDeComp::Def_loi(st2);
        if (nb_loi==0) // la première fois que l'on passe ici le nombre de loi = 0
          {lois_internes1 = (Loi_comp_abstraite*) LesLoisDeComp::Def_loi(st2);
           pt = lois_internes1;}
        else   
          {lois_internes2 = (Loi_comp_abstraite*) LesLoisDeComp::Def_loi(st2);
           pt = lois_internes2;}

        // --- 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
            dim = dim_lois;categorie_loi_comp = categ;
            if (!GroupeMecanique(categorie_loi_comp))
              { cout << "\n erreur1 en lecture des lois constitutives elementaire d'une loi LoiDesMelangesEnSigma"
                     << "\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 LoiDesMelangesEnSigma::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  LoiDesMelangesEnSigma"
                   << "\n la loi lue: " << pt->Nom_comport() << " n'a pas la meme dimension que la premier loi lue";
              entreePrinc->MessageBuffer("**erreur2 lecture  LoiDesMelangesEnSigma"); 
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1); 
            }
           if (!GroupeMecanique(pt->Id_categorie()))
              { cout << "\n erreur en lecture des lois constitutives elementaire d'une loi LoiDesMelangesEnSigma"
                     << "\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 LoiDesMelangesEnSigma::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;
        nb_loi++;
        if (nb_loi > 2 )
          { cout << "\n erreur en lecture de la loi des melanges en sigma,"
                 << " vous avez defini plus de deux lois internes !";
            entreePrinc->MessageBuffer("**erreur3 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
            throw (UtilLecture::ErrNouvelleDonnee(-1));
            Sortie(1);
          };
      };
    // vérification que l'on a bien lu deux lois
    if (nb_loi != 2 )
      { cout << "\n erreur en lecture de la loi des melanges en sigma,"
             << " vous n'avez pas defini deux lois internes !";
        entreePrinc->MessageBuffer("**erreur4 LoiDesMelangesEnSigma::LectureDonneesParticulieres (...**");
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie(1);
      };
       
    // 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);
  };

// affichage de la loi
void LoiDesMelangesEnSigma::Affiche() const 
  {  cout << "\n .......  loi de comportement LoiDesMelangesEnSigma ........";
     cout << "\n type de melange: "<<type_melange << " ";
     cout << "\n grandeur utiliser pour controler le melange: " ;
     if (type_melange < 3) // mise en donnée historique
      { if (type_grandeur.Nom_vide()) {cout << Nom_ddl(type_grandeur.Enum()) << " ";}
	       else                          {cout << type_grandeur.Nom() << " ";};
        if (valeur_aux_noeuds)
     	    { cout << " , venant des noeuds par interpolation ";}
        else
     	    { cout << " , venant directement du point d'integration ";};
	       // extension éventuelle
        if (aA != 1.)
          cout << " cas d'une somme ponderee etendue A= " << aA ;	
        // courbe d'interface	 
          if ( c_proport != NULL) { cout << " courbe d'interface  " 
                                             << " courbe c_proport=f(): " << c_proport->NomCourbe() <<" ";};
          cout << " \n ";
      }
     else // deuxième mise en donnée
      { cout << "niveauF_grandeurND" << "  ";
        if (niveauF_grandeurND->NomFonction() != "_")
            { cout << niveauF_grandeurND->NomFonction();}
        else
            { niveauF_grandeurND->Affiche();};
        if (niveauF_ddlEtendu!= NULL)
          niveauF_ddlEtendu->Affiche();
        if (niveauF_temps!= NULL)
          niveauF_temps->Affiche();
      };
     if (calcule_si_prop_non_nulle.Taille() == 2)
      { cout << " calcule_si_prop_non_nulle1= " << calcule_si_prop_non_nulle(1) 
             << " calcule_si_prop_non_nulle2= " << calcule_si_prop_non_nulle(2) << " \n";
      };
     cout << "\n -- partie relative aux lois internes: ";

     lois_internes1->Affiche();
     lois_internes2->Affiche();
     cout << "\n .......  fin de la loi de comportement LoiDesMelangesEnSigma ........";     
  };
            
// affichage et definition interactive des commandes particulières à chaques lois
void LoiDesMelangesEnSigma::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 LoiDesMelangesEnSigma ........"
         << "\n# deux types de mises en donnees sont proposees "
         << "\n#  ";
    if (rep == "o")
     {//--------- cas de la première mise en donnée (historique) -------
      {
       sort << "\n#  "
            << "\n#  $$$ === premier type possible de mise en donnees ===$$$ "
            << "\n#  "
            << "\n#  sur la premiere ligne on indique successivement : "
            << "\n#  a) obligatoirement: le type de grandeur (mot cle: grandeur_proportion= ) qui regle la proportion entre "
            << "\n#     les deux lois, on peut utiliser n'importe quelle grandeur definie (mais qui doit exister par ailleurs) "
            << "\n#     aux noeuds par exemple, cf. documentation "
            << "\n#  b) optionnellement:  le type de melange (mot cle: type_melange= ) (1 ou 2) cf. expli qui suit "
            << "\n#  c) optionnellement: si la proportion provient des noeuds ou du pt d'integ directement "
            << "\n#      (mot cle: valeur_aux_noeuds= ) (1 ou 0)  la valeur par defaut est 1 (en fait tout nb diff de 0), "
            << "\n#      dans le cas de 0, pour l'instant les  cas implantes sont relatif a PROP_CRISTA, def_duale_mises, "
            << "\n#      Spherique_eps, def_duale_mises_maxi, Spherique_sig"
            << "\n# --> ex:    grandeur_proportion=   PROP_CRISTA  type_melange= 2 valeur_aux_noeuds= 0 "
            << "\n#  d) optionnellement: l'extension a une somme ponderee etendue mot cle: somme_pondere_etendue_ "
            << "\n#     si oui, on passe une ligne et sur la ligne suivante on a le mot cle A= "
            << "\n#     suivit du coeff multiplicatif de la somme ponderee (cf explication qui suit) "
            << "\n#  "
            << "\n#  e) optionnellement: une fonction permettant le calcul de la proportion en fonction de la grandeur"
            << "\n#                      qui regle la proportion mot cle: avec_fonction_proportion_ "
            << "\n#     dans ce cas, on passe une ligne et la fonction est decrite avec le mot cle: fonction_prop=  "
            << "\n#     suivit du nom de la fonction (si elle existe deja) ou de la definition de la fonction "
            << "\n#  "
            << "\n#  f) puis on passe une ligne pour decrire les 2 lois individuelles"
            << "\n#  "
            << "\n#  ---- explications complementaires ------ "
            << "\n#  en fait il y a deux type de loi des melanges possible:  "
            << "\n#  soit : sigma = grandeur * sigma(loi1) + (1.-grandeur) * sigma(loi2) , ce qui est le type 1 (par defaut) "
            << "\n#  soit : delta sigma = grandeur * delta sigma(loi1) + (1.-grandeur) * delta sigma(loi2) , ce qui est le type 2"
            << "\n#         en tenant compte que les contraintes sont cumulees dans le type 2. "
            << "\n#  le type 1 est par defaut, mais on peut indiquer le type 2  apres le mot cle type_melange= "
            << "\n#  puis il faut donner le nom de chaque loi (2 maxi) suivi des parametres sur les lignes suivantes"
            << "\n#  "
            << "\n#  Dans le cas d'une somme ponderee etendue, la contrainte est calculee suivant la formule suivante: "
            << "\n#  sigma = A*(grandeur * sigma(loi1) + (1-grandeur) * sigma(loi2)) "
            << "\n#  ou : delta sigma = A*(grandeur * delta sigma(loi1) + (1-grandeur) * delta sigma(loi2)) "
            << "\n#   ainsi A peut etre different de 1, par exemple si A=2, on peut tendre vers la somme non ponderee des deux lois "
            << "\n#   "
            << "\n#  ------------ cas d'une proportion exclusive --------------- "
            << "\n#   g) optionnellement: apres chaque loi, on peut indiquer le mot cle: calcule_si_prop_non_nulle_ "
            << "\n#      cela indique que la loi n'est calculee que si son coefficient est non nul, "
            << "\n#      bien noter que dans ce cas il n'y a pas accumulation de l'historique du comportement  "
            << "\n#      donc c'est une option qui est raisonnable que pour une loi non incrementale"
            << "\n#      dans le cas contraire, il faut avoir conscience de ce que l'on impose"
            << "\n#  "
            << "\n# ----- exemple de deux lois elastiques -----"
            << "\n#  "
            << "\n      grandeur_proportion= PROP_CRISTA  type_melange= 2 valeur_aux_noeuds= 1  ";
     
       // 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 LoiDesMelangesEnSigma" << endl;
      
       sort  << "\n#  "
             << "\n#  ------ exemple d'une somme etendue avec fonction d'interface (partie avant les lois) ------"
             << "\n#  "
             << "\n#      grandeur_proportion=   def_equivalente  type_melange= 1 valeur_aux_noeuds= 0 somme_pondere_etendue_ "
             << "\n#      A= 2. avec_fonction_proportion_  "
             << "\n#      fonction_prop=  courbe1  "
             << "\n#      ..... "
             << "\n#  ";
      };
  
       //--------- cas de la deuxième mise en donnée  -------
      
      {
       sort  << "\n#  "
             << "\n#  $$$ === second type possible de mise en donnees ===$$$ "
             << "\n#  "
             << "\n#  ce second type permet d'utiliser un plus large choix de fonctions de ponderation, par contre"
             << "\n#  son utilisation est peut-etre un peu plus complexe (?) "
             << "\n#  Plus precisemment, la ponderation peut-etre un assemblage multiplicatif de:  "
             << "\n#   - une fonction nD de grandeurs globales (ex: precision d'equilibre globale, num d'iteration, etc.)"
             << "\n#   - avec le produit d'un ensemble de courbes 1D , chacune fonction d'un ddl etendu. Ici c'est le cas  "
             << "\n#     identique au premier type de mise en donnees"
             << "\n#   - avec le produit d'une courbe 1D fonction du temps"
             << "\n#  "
             << "\n#  sur la premiere ligne on indique successivement : "
             << "\n#  a) le mot cle: les_grandeurs_de_controle_= "
             << "\n#  b) ensuite on donne la liste des grandeurs que l'on va utiliser, ces grandeurs peuvent etre"
             << "\n#   - le temps (mot cle: TEMPS ) "
             << "\n#   - un ddl primaire (ex: U1 ou X1 au noeud) ou secondaire (SIG11 ou EPS11 au pti)"
             << "\n#   - un ddl etendue "
             << "\n#   - une grandeur globale"
             << "\n#   l'ensemble des grandeurs doit se terminer par le mot cle : fin_grandeurs_"
             << "\n#  c) ensuite sur la ligne suivante: on donne la liste des fonctions que l'on va utiliser "
             << "\n#    - mot cle deb_fonct_= "
             << "\n#     la liste doit suivre le meme ordre que celui des grandeurs, cependant "
             << "\n#    1) dans le cas des grandeurs globales (sauf le temps), il y a une seule fonction pour toutes les grandeurs"
             << "\n#     c'est donc la place de la premiere grandeur globale qui est consideree "
             << "\n#     IMPORTANT:  les grandeurs globales qui vont etre utilisees sont celles indiquees dans la definition"
             << "\n#     de la fonction nD, aussi dans la def de la proportion, il suffit d'indiquer une seule grandeur  "
             << "\n#     globale pour ensuite definir une fonction nD. Par contre dans la definition de la fonction nD  "
             << "\n#     on peut introduire d'autres grandeurs, en particulier des grandeurs non locales. "
             << "\n#     La fonction nD permet donc d'introduire tout type de grandeur, elle fait donc"
             << "\n#     double emploi avec les autres courbes. Cependant on laisse les autres courbes "
             << "\n#     pour des raisons historiques et pour des cas simples, on l'utilisation d'une courbe "
             << "\n#     peut-etre plus explicite qu'une fonction nD.  "
             << "\n#    2) pour les ddl et ddl etendue il faut indiquer apres chaque fonction d'un ddl s'il s'agit "
             << "\n#      a) d'une grandeur au pti avec le mot cle  AuPti_ "
             << "\n#      b) d'une grandeur au noeud avec le mot cle AuxNoeuds_ "
             << "\n#     l'ensemble de la liste des fonctions doit se terminer par le mot cle: fin_fonct_ "
             << "\n#   e) puis sur la ligne suivante, optionnellement:  "
             << "\n#      le type de melange (mot cle: type_melange= ) (1 ou 2)  "
             << "\n#      l'explication est identique au cas de la premiere mise en donnees "
             << "\n#  "
             << "\n#   f) puis on passe une ligne pour decrire les 2 lois individuelles"
             << "\n#      On peut comme dans le cas de la premiere mise en donnee, utiliser"
             << "\n#      une proportion exclusive, la syntaxe est identique au cas de la premiere "
             << "\n#      mise en donnee "
             << "\n#  "
             << "\n# ----- exemple de deux lois elastiques -----"
             << "\n#  "
             << "\n#      les_grandeurs_de_controle_= TEMPS \\ "
             << "\n#                      compteur_increment_charge_algo_global\\ "
             << "\n#                      compteur_iteration_algo_global\\ "
             << "\n#                      def_equivalente  X1 \\ "
             << "\n#      fin_grandeurs_ "
                    
             << "\n#      deb_fonct_= f_temps fonction1  \\ "
             << "\n#                      f_const AuPti_  \\ "
             << "\n#                      f_const AuxNoeuds_  \\ "
             << "\n#                      fin_fonct_ ";
      
         // 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 LoiDesMelangesEnSigma" << endl;

       sort  << "\n#  ";
       sort  << "\n#a la suite du mot cle qui definit une loi interne on peut choisir entre 4 "
             << "types de fonctionnement. Pour simplifier et expliciter la presentation,"
             << " on suppose que la premiere loi est une simple loi de Hooke. Les 4 types"
             << " de fonctionnement sont alors les suivants:"
             << "\n#  ISOELAS -> aucune particularite ,"
	            << "\n#  ISOELAS calcule_si_prop_non_nulle_ -> le mot cle  est utilise"
             << " pour indiquer que la loi ne doit-être calculee que si la proportion"
             << " la concernant (c-a-c alpha pour la première loi, et (1.-alpha) pour "
             << " la seconde loi) est non nulle. Si elle est nulle, la loi n'est pas calculee."
             << "\n#  ISOELAS demarre_a_prop_non_nulle_puis_strictement_decroissante_} "
             << " -> le fonctionnement est  semblable au cas precedent avec en plus la "
             << " particularite supplementaire suivante: on interdit a la proportion d'augmenter."
             << " Ainsi, si entre deux appels consecutifs de la loi de comportement, la valeur d'alpha"
             << " tente d'augmente au travers d'un calcul via une fonction de ponderation,"
             << " c'est la valeur la plus faible qui est retenue, et ceci tout au long du calcul. "
             << " Ce comportement tres particulier, est construit en particulier pour être utilise"
             << " via une fonction de ponderation qui depend de la precision de l'equilibre globale."
             << " On force ainsi l'evolution d'alpha a etre strictement decroissante a mesure "
             << " que la precision augmente."
	            << "\n#  ISOELAS demarre_a_prop_non_nulle_puis_strictement_decroissante_sur_chaque_incre_"
             << " -> le fonctionnement est  un peu semblable au cas precedent mais avec la particularite"
             << " supplementaire suivante: l'evolution est strictement decroissante sur un increment."
             << " Par contre au debut de chaque increment, on initialise la valeur d'alpha"
             << " via les fonctions de proportion."
             << endl;

      };
    }
   else // cas simplifié, on ne donne que les exemples
     {//--------- cas de la première mise en donnée (historique) -------
      {
       sort << "\n#  "
            << "\n#  $$$ === premier type possible de mise en donnees ===$$$ "
            << "\n#  "
            << "\n# ----- exemple de deux lois elastiques -----"
            << "\n#  "
            << "\n      grandeur_proportion= PROP_CRISTA  type_melange= 2 valeur_aux_noeuds= 1  ";
     
       // 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 LoiDesMelangesEnSigma" << endl;
      
      };
  
       //--------- cas de la deuxième mise en donnée  -------
      
      {
       sort  << "\n#  "
             << "\n#  $$$ === second type possible de mise en donnees ===$$$ "
             << "\n#  "
             << "\n# ----- exemple de deux lois elastiques -----"
             << "\n#  "
             << "\n#      les_grandeurs_de_controle_= TEMPS \\ "
             << "\n#                      compteur_increment_charge_algo_global\\ "
             << "\n#                      compteur_iteration_algo_global\\ "
             << "\n#                      def_equivalente  X1 \\ "
             << "\n#      fin_grandeurs_ "
                    
             << "\n#      deb_fonct_= f_temps fonction1  \\ "
             << "\n#                      f_const AuPti_  \\ "
             << "\n#                      f_const AuxNoeuds_  \\ "
             << "\n#                      fin_fonct_ ";
      
         // 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 LoiDesMelangesEnSigma" << endl;
      };
    }
  
  };  		  	  

// test si la loi est complete
int LoiDesMelangesEnSigma::TestComplet()
    { int ret = LoiAbstraiteGeneral::TestComplet();
      ret *=lois_internes1->TestComplet();
      ret *=lois_internes2->TestComplet();
      // puis les proportions
      if (type_melange < 3) // mise en donnée historique
        {  // courbe d'interface
           if ( c_proport != NULL)
              c_proport->Complet_courbe();
        }
      else // deuxième mise en donnée
        { //if (niveauF_grandeurND != NULL)
          //  niveauF_grandeurND->Verif_complet();
          if (niveauF_ddlEtendu!= NULL)
            niveauF_ddlEtendu->Verif_complet();
          if (niveauF_temps!= NULL)
            niveauF_temps->Verif_complet();
        };

     return ret; 
    }; 
		          
// calcul d'un module d'young équivalent à la loi, ceci pour un
// chargement nul
double LoiDesMelangesEnSigma::Module_young_equivalent(Enum_dure temps,const Deformation & def ,SaveResul * saveResul_ex)
  { double E=0.; 
    // on récupère les infos de chaque loi
    SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveResul_ex);
    list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
    // on utilise les proportions sauvegardées qui peuvent éventuellement ne pas avoir été déjà calculées
    // dans ce cas la proportion = 1
    E +=save_resul.proportion * lois_internes1->Module_young_equivalent(temps,def,*isave);
    isave++;
    E +=(1.-save_resul.proportion) * lois_internes2->Module_young_equivalent(temps,def,*isave);
    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 LoiDesMelangesEnSigma::Module_compressibilite_equivalent(Enum_dure temps,const Deformation & def ,SaveResul * saveResul_ex)
  { double module_compressibilite=0.; 
    // on récupère les infos de chaque loi
    SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveResul_ex);
    list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
    // on utilise les proportions sauvegardées qui peuvent éventuellement ne pas avoir été déjà calculées
    // dans ce cas la proportion = 1
    module_compressibilite +=save_resul.proportion * lois_internes1->Module_compressibilite_equivalent(temps,def,*isave);
    isave++;
    module_compressibilite +=(1.-save_resul.proportion) * lois_internes2->Module_compressibilite_equivalent(temps,def,*isave);
    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 LoiDesMelangesEnSigma::Activation_donnees(Tableau<Noeud *>& tabnoeud,bool dilatation,LesPtIntegMecaInterne& lesPtMecaInt)
 { if (type_melange < 3) // cas de la loi historique
     { // dans le cas d'une proportion venant des noeuds par interpolation
       // on active les ddl correspondant à la grandeur qui règle la proportion
       if (valeur_aux_noeuds)
        { 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(type_grandeur.Enum()))
                 {tabnoeud(i)->Met_en_service(type_grandeur.Enum());}
             else
   //              { cout << "\n erreur: la grandeur " << Nom_ddl(type_grandeur) << " n'existe pas "
                 { cout << "\n erreur: la grandeur " << type_grandeur << " n'existe pas "
                        << " il n'est pas possible d'utiliser une loi des melanges avec cette grandeur "
                        << " il manque sans doute des donnees !!! "
                        << "\n LoiDesMelangesEnSigma::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 des melanges ne peut pas s'utiliser ici telle quelle ***"
                 << " demander une modification ! ";
            cout << "\n 	LoiDesMelangesEnSigma::Activation_donnees(.. " << endl;
            Sortie(1);
          };
         // cas normal
         switch (type_grandeur.Position()-NbEnum_ddl())
          {case 77: case 78: case 87: case 88: // cas de "def_duale_mises", cas de "Spherique_eps", cas de "def_duale_mises_maxi"
             {// il faut que l'on active le calcul des invariants de déformations
              int nbpti = lesPtMecaInt.NbPti();
              for (int i= 1;i<= nbpti;i++)
                lesPtMecaInt(i).Change_statut_Invariants_deformation (true);
              break;
             }
           case 81: // cas de "Spherique_sig"
             {// il faut que l'on active le calcul des invariants des contraintes
              int nbpti = lesPtMecaInt.NbPti();
              for (int i= 1;i<= nbpti;i++)
                lesPtMecaInt(i).Change_statut_Invariants_contrainte (true);
              break;
             }
           default:
              cout << "\n erreur, le type de proportion " << type_grandeur << " n'est pas disponible "
                   << " pour l'instant au point d'integration ! "
                   << "\n LoiDesMelangesEnSigma::Activation_donnees(.... ";
              Sortie(1);
              break;
          };
        };
     }
   else // cas type_melange = 3 ou 4: -> fonctions complexes
     {if (niveauF_ddlEtendu != NULL)
        niveauF_ddlEtendu->Activation_donnees(tabnoeud, dilatation, lesPtMecaInt);
     };
   
   // appel des lois élémentaires
   lois_internes1->Activation_donnees(tabnoeud,dilatation,lesPtMecaInt);    
   lois_internes2->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 LoiDesMelangesEnSigma::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_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveDon);
   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();

       SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveDon);
       // 1) -----cas des contraintes individuelles à chaque loi à t et courantes
       if ((enuTQ) == CONTRAINTE_INDIVIDUELLE_A_CHAQUE_LOI_A_T_SANS_PROPORTION)
        { Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
          // on boucle sur les lois 
          list <TenseurHH* >::iterator isig_t;
          // première loi
          isig_t = save_resul.l_sigoHH_t.begin();
          // 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
          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)++;
          // seconde loi
          isig_t++;
          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)++;
        };
       // 2) -----cas des contraintes individuelles à chaque loi à t uniquement
       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 <TenseurHH* >::iterator jsig_t;
          // première loi
          jsig_t = save_resul.J_sigoHH_t.begin();
         
          // 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
          TenseurHH* sigHH = (*(jsig_t)); // pour simplifier
          if (Dabs(sigHH->Dimension()) != dim)
            {tyTQ(1+(*idecal)).Affectation_trans_dimension((*sigHH) * aA*save_resul.proportion_t,true);
            }
          else // cas même dimension
            {tyTQ(1+(*idecal)) = (*(*(jsig_t))) * aA*save_resul.proportion_t;
            };
          (*idecal)++;
//debug
//cout << "\n (*(*(jsig_t))) * save_resul.proportion_t= ";
//((*(*(jsig_t))) * save_resul.proportion_t).Ecriture(cout);
//cout << "\n debug LoiDesMelangesEnSigma::Grandeur_particuliere" << endl;
//findebug
          // seconde loi
          jsig_t++;
         
          sigHH = (*(jsig_t)); // pour simplifier
          if (Dabs(sigHH->Dimension()) != dim)
            {tyTQ(1+(*idecal)).Affectation_trans_dimension((*sigHH) * aA*(1.-save_resul.proportion_t),true);
            }
          else // cas même dimension
            {tyTQ(1+(*idecal)) = (*(*(jsig_t))) * aA*(1.-save_resul.proportion_t);
            };
          (*idecal)++;
//debug
//cout << "\n (*(*(jsig_t))) * save_resul.proportion_t= ";
//((*(*(jsig_t))) * save_resul.proportion_t).Ecriture(cout);
//cout << "\n debug LoiDesMelangesEnSigma::Grandeur_particuliere" << endl;
//findebug
         };
       // 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 <EnergieMeca >::iterator ienerg_t; 
          ienerg_t = save_resul.l_energ_t.begin();      
          tyTQ(1+(*idecal)) = (*ienerg_t).EnergieElastique();  (*idecal)++;
          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 <EnergieMeca >::iterator ienerg_t; 
          ienerg_t = save_resul.l_energ_t.begin();      
          tyTQ(1+(*idecal)) = (*ienerg_t).DissipationPlastique();  (*idecal)++;
          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 <EnergieMeca >::iterator ienerg_t; 
          ienerg_t = save_resul.l_energ_t.begin();      
          tyTQ(1+(*idecal)) = (*ienerg_t).DissipationVisqueuse();  (*idecal)++;
          ienerg_t++;      
          tyTQ(1+(*idecal)) = (*ienerg_t).DissipationVisqueuse();  (*idecal)++;
         };
       // 6) -----cas de la proportion relative entre les deux lois  
       if (enuTQ == PROPORTION_LOI_MELANGE)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
		        tyTQ(1+(*idecal)) = save_resul.proportion_t;  (*idecal)++;
//          *(tyTQ.ConteneurDouble()) = save_resul.proportion_t;
         };
       };
      };
   // puis appel des lois élémentaires
	list <SaveResul*>::iterator ill = save_resul.liste_des_SaveResul.begin();
   lois_internes1->Grandeur_particuliere(absolue,liTQ,*ill,decal); ill++;
   lois_internes2->Grandeur_particuliere(absolue,liTQ,*ill,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 LoiDesMelangesEnSigma::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
	  int nb_loi = 2; // pour être identique pour la loi additive !!
   lois_internes1->ListeGrandeurs_particulieres(absolue,liTQ);
   lois_internes2->ListeGrandeurs_particulieres(absolue,liTQ);
	
   // ... maintenant on s'occupe des grandeurs de la loi additive elle même,   
   // 1) -----cas des contraintes individuelles à chaque loi à t et courantes
   // 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_SANS_PROPORTION)
       { 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_SANS_PROPORTION,SIG11,gtHH);
        liTQ.push_back(typQ);
        delete tens; // car on n'en a plus besoin
       };
   };
   // 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 la proportion relative entre les deux lois
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {//on commence par définir une grandeur_scalaire_double
    Tableau <double> tab_1(1);
    Tab_Grandeur_scalaire_double gtab(tab_1);
	   List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
	   for (itq=liTQ.begin();itq!=itqfin;itq++)
     if ((*itq).EnuTypeQuelconque() == PROPORTION_LOI_MELANGE)
        { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
		        int taille = tyTQ.Taille()+1;
			       tyTQ.Change_taille(taille); nexistePas = false;
		      };
	   if (nexistePas)
	    { TypeQuelconque typQ1(PROPORTION_LOI_MELANGE,SIG11,gtab);
       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  LoiDesMelangesEnSigma::Comportement_3D_CP_DP_1D()
 { // si la première lois internes n'est pas nulle, on ramène le cas de la première loi
   if (lois_internes1 != NULL)
     {return lois_internes1->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 LoiDesMelangesEnSigma::Lecture_base_info_loi(istream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { if (cas == 1) 
     { string st1; string nom;
       ent >> st1 >>  nom >> type_melange  ;
       if (st1 != "LOI_DES_MELANGES_EN_SIGMA")
        { cout << "\n erreur en lecture de la loi : LOI_DES_MELANGES_EN_SIGMA,"
               << " on attendait le mot cle : LOI_DES_MELANGES_EN_SIGMA "
               << "\n LoiDesMelangesEnSigma::Lecture_base_info_loi(...";
          Sortie(1);
         };
     
       if (type_melange < 3) // cas de la mise en données historique
        {ent >> nom >> type_grandeur
             >> nom >> valeur_aux_noeuds >> nom;
         // extension éventuelle
         ent >> st1 >> aA;
         // courbe d'interface éventuelle	 
         bool test = false;
         ent  >> test;
         if (!test)
            { if (c_proport != NULL) {if (c_proport->NomCourbe() == "_")
              delete c_proport; c_proport = NULL;};
            }
         else
            { ent >> nom; c_proport = lesCourbes1D.Lecture_pour_base_info(ent,cas,c_proport); };
        }
       else // cas de la deuxième mise en données
        { // les grandeurs globales
          ent >> nom;
          if (nom == "avec_Ponderation_nD")
           { niveauF_grandeurND = lesFonctionsnD.Lecture_pour_base_info(ent,cas,niveauF_grandeurND);};
          // les pondérations avec les ddl
          ent >> nom;
          if (nom == "avec_Ponderation_ddl")
           {if (niveauF_ddlEtendu==NULL)
              niveauF_ddlEtendu = new Ponderation;
            niveauF_ddlEtendu->Lecture_base_info(ent,cas, lesCourbes1D);
           }
          else
           { if (niveauF_ddlEtendu!=NULL)
               delete niveauF_ddlEtendu;
           };
          // la pondération temps
          ent >> nom;
          if (nom == "avec_Ponderation_temps")
           {if (niveauF_temps==NULL)
              niveauF_temps = new Ponderation_temps;
            niveauF_temps->Lecture_base_info(ent,cas, lesCourbes1D);
           }
          else
           { if (niveauF_temps!=NULL)
               delete niveauF_temps;
           };
        };

       // ensuite normalement il n'y a pas de pb de lecture puisque c'est écrit automatiquement
       // on supprime les lois actuellement présentent par sécurité
       if (lois_internes1 != NULL) delete lois_internes1;
       if (lois_internes2 != NULL) delete lois_internes2;
       // lecture de la gestion conditionnel si prop non nulle
       ent >> nom;
       if (nom == "sans_test_proportion_non_nulle")
          { calcule_si_prop_non_nulle.Change_taille(0);}
       else
          { calcule_si_prop_non_nulle.Change_taille(2);
            ent >> nom >> calcule_si_prop_non_nulle(1) >> nom >> calcule_si_prop_non_nulle(2);
          };
       // --partie_relative_aux_lois_internes:
       ent >> nom;
       // on lit les deux lois
       ent >> nom >> st1; lois_internes1 = (Loi_comp_abstraite *) LesLoisDeComp::Def_loi(st1);
       lois_internes1->Lecture_base_info_loi(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
       ent >> nom >> st1; lois_internes2 = (Loi_comp_abstraite *) LesLoisDeComp::Def_loi(st1);
       lois_internes2->Lecture_base_info_loi(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
      }
    else
     { // on boucle directement sur les lois déjà définis
       string nom;
       ent >> nom; // lois_1-->
       lois_internes1->Lecture_base_info_loi(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
       ent >> nom; // lois_2-->
       lois_internes2->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 LoiDesMelangesEnSigma::Ecriture_base_info_loi(ostream& sort,const int cas)
 { if (cas == 1)
    { sort << "\n  LOI_DES_MELANGES_EN_SIGMA "
           << "\n type_de_melange: "<<type_melange << " ";
      if (type_melange < 3) // cas de la mise en données historique
        {sort << " grandeur_proportion= " << type_grandeur
              << " aux_noeuds " << valeur_aux_noeuds <<" lois ";
         // extension éventuelle
         sort << " A= " << aA ;	
         // courbe d'interface	 
         if (c_proport == NULL)
           { sort << false << " " ;}
         else 
           { sort << true << " fonction_c_proport ";
             LesCourbes1D::Ecriture_pour_base_info(sort,cas,c_proport);
            };
        }
      else // cas de la deuxième mise en données
       { bool sans_courbe = true;
         if (niveauF_grandeurND != NULL)
           {sort << " avec_Ponderation_nD ";
            LesFonctions_nD::Ecriture_pour_base_info(sort, cas,niveauF_grandeurND);
           }
         else {sort << " sans_Ponderation_nD ";};
         if (niveauF_ddlEtendu!= NULL)
           {sort << " avec_Ponderation_ddl ";
            niveauF_ddlEtendu->Ecriture_base_info(sort,cas);
           }
         else {sort << " sans_Ponderation_ddl ";};
         if (niveauF_temps!= NULL)
           {sort << " avec_Ponderation_temps ";
            niveauF_temps->Ecriture_base_info(sort,cas);
           }
         else {sort << " sans_Ponderation_temps ";};
       };
		    // gestion conditionnel si prop non nulle
		    if (calcule_si_prop_non_nulle.Taille() != 2)
        { sort << "\n sans_test_proportion_non_nulle \n ";}
		    else 
		      { sort << "\n AVEC_test_proportion_non_nulle ";
	         sort << "\n calcule_si_prop_non_nulle1= " << calcule_si_prop_non_nulle(1) 
	              << " calcule_si_prop_non_nulle2= " << calcule_si_prop_non_nulle(2) << " ";
			     };
      sort << "\n --partie_relative_aux_lois_internes: ";
      sort << "\n lois_1--->  " << lois_internes1->Nom_comport() << "  "; lois_internes1->Ecriture_base_info_loi(sort,cas);
      sort << "\n lois_2--->  " << lois_internes2->Nom_comport() << "  "; lois_internes2->Ecriture_base_info_loi(sort,cas);
    }
   else
    { sort << "\n lois_1--> ";
      lois_internes1->Ecriture_base_info_loi(sort,cas);
      sort << "\n lois_2--> ";
      lois_internes2->Ecriture_base_info_loi(sort,cas);
    };
 }; 
            

 // ========== codage des METHODES VIRTUELLES  protegees:================
        // calcul des contraintes a t+dt
void LoiDesMelangesEnSigma::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();
   // on utilise des pointeurs pour utiliser delete à la fin
   TenseurHH * sigtotalHH = (NevezTenseurHH(dim_tens,0.));
   TenseurHH * zeroHH = (NevezTenseurHH(dim_tens,0.));
   TenseurHH * deltaSigHH = (NevezTenseurHH(dim_tens,0.)); // pour la variation de contraintes
   
   SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveResul);
   module_compressibilite=module_cisaillement=0.; // init
   energ.Inita(0.); // initialisation des énergies mises en jeux
   // on balaie l'ensemble des lois
   list <TenseurHH* >::iterator isig,isig_t,jsig,jsig_t; int ili;
   list <EnergieMeca >::iterator ienerg,ienerg_t;
   list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
   Loi_comp_abstraite * pt=NULL;
   // on récupère la valeur de la proportion enregistrée, qui a donc été calculée dans les grandeurs de
   // travail
   proportion = save_resul.proportion;
  
   bool premier_passage = true;
  
   for (ili=1,isig_t = save_resul.l_sigoHH_t.begin(),isig = save_resul.l_sigoHH.begin()
             ,jsig_t = save_resul.J_sigoHH_t.begin(),jsig = save_resul.J_sigoHH.begin()
        ,ienerg = save_resul.l_energ.begin(),ienerg_t = save_resul.l_energ_t.begin();
        ili<=2;ili++,isig_t++,isig++,jsig_t++,jsig++,isave++,ienerg++,ienerg_t++)
      { // 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.);};
        
        if ((*jsig)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*jsig); (*jsig)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        if ((*jsig_t)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*jsig_t); (*jsig_t)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        
		      // initialisation du tenseurs contrainte 
		      sigHH = (*zeroHH);
        // calcul de la contrainte résultante, 
        if (ili==1) {pt=lois_internes1;} else {pt=lois_internes2;};
              
        double compress_inter=0.; double cisaill_inter=0;  // init
        // passage des informations spécifique à la loi liste_des_SaveResul
        pt->IndiqueSaveResult(*isave); 
        pt->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
        pt->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours

		      // prise en compte éventuel d'un calcul conditionel au cas d'une proportion non nulle
		      bool traitement = true; // par défaut
		      if (calcule_si_prop_non_nulle.Taille() == 2)
		        {if (calcule_si_prop_non_nulle(ili) == 1)
			         {if (premier_passage &&  ( proportion == 0.)) {traitement = false;}
			          else if ((!premier_passage) &&  ( proportion == 1.)) {traitement = false;};
				        }
           else if ((calcule_si_prop_non_nulle(ili) == 2)||(calcule_si_prop_non_nulle(ili) == 3))
			         { if ((premier_passage)&& (!save_resul.deja_actif_sur_iter1))
                // première loi et pas encore actif
               { if ( proportion == 0. ) // on désactive et on signale pour la suite
                   {traitement = false;save_resul.deja_actif_sur_iter1=true;};
               };
			           if ((!premier_passage)&& (!save_resul.deja_actif_sur_iter2))
                // seconde loi et pas encore actif
               { if ( proportion == 1. ) // on ne traite pas
                   {traitement = false;}
                 else // sinon le traitement commence
                   {save_resul.deja_actif_sur_iter2=true;};
               };
				        }
          };
			   
//--- debug
// cout << "\n debug LoiDesMelangesEnSigma::Calcul_SigmaHH traitement= "
//      << traitement ;
// if (premier_passage) {cout << " P1 " << endl;} else {cout << " P2 " << endl;}
// if (!premier_passage && traitement)
//   {cout << "\n debug LoiDesMelangesEnSigma::Calcul_SigmaHH traitement=  enclanche "
//         << calcule_si_prop_non_nulle(1) << " " << calcule_si_prop_non_nulle(2)
//         << endl;
//   };
//--- fin debug
		      if (traitement)
         { pt->Calcul_SigmaHH((*(*isig_t)),DepsBB,tab_ddl,gijBB_t,gijHH_t,giB,gi_H,epsBB_,delta_epsBB,
                               gijBB_,gijHH_,d_gijBB_,jacobien_0,jacobien,sigHH
                               ,(*ienerg),(*ienerg_t),compress_inter,cisaill_inter,ex);
           // on commence par sauvegarder la contrainte partielle avant application de la proportion
           (*(*isig))=sigHH; // on sauvegarde la contrainte partielle totale
         
           // def du facteur multiplicatif du à  la proportion
           double facteur_multiplicatif = aA * proportion;
////--- debug
// cout << "\n debug LoiDesMelangesEnSigma::Calcul_SigmaHH facteur_multiplicatif= "
//      << facteur_multiplicatif << endl;
////--- fin debug
          
           #ifdef MISE_AU_POINT
           if (Permet_affichage() > 3)
              cout << "\n LoiDesMelangesEnSigma::Calcul_SigmaHH ";
           #endif
           if (premier_passage) { premier_passage = false;}
           else                 {facteur_multiplicatif = aA*(1.-proportion);};

           // traitement
           if ((type_melange == 1)||(type_melange == 3))
             { sigHH *= facteur_multiplicatif;
               (*(*jsig))=sigHH; // on sauvegarde la contrainte partielle proportionalisée
               (*sigtotalHH) += sigHH; // on ajoute la contrainte au total
               #ifdef MISE_AU_POINT
               if (Permet_affichage() > 3)
                {if (premier_passage) {cout << "\n 1ere loi:";}
                 else {cout << "\n 2ieme loi: ";};
                 cout << " facteur_multiplicatif= "
                        << facteur_multiplicatif
                        << ", sigHH_tdt avec ponderation ";
                 sigHH.Ecriture(cout);
                };
               #endif
             }
           else  // cas == 2
             { (*deltaSigHH) = sigHH - (*(*isig_t)); (*deltaSigHH) *= facteur_multiplicatif;
               (*(*jsig))=(*(*jsig_t)) + (*deltaSigHH); // on sauvegarde la contrainte partielle proportionalisée
               (*sigtotalHH) += (*(*jsig)); // cumule
             };
           energ += (*ienerg) * facteur_multiplicatif; // update des énergies
           module_compressibilite += compress_inter * facteur_multiplicatif;
           module_cisaillement +=  cisaill_inter * facteur_multiplicatif; 
			      }
		      else 
		       { if (premier_passage) { premier_passage = false;};
			        (*(*isig))=(*zeroHH); 
			        (*(*jsig))=(*zeroHH);
			        (*ienerg).Inita(0.); 
			      }; // fin du traitement conditionnel
      }; // fin de la boucle sur les deux lois
   // recopie du résultat
   sigHH = (*sigtotalHH);
   delete sigtotalHH; delete zeroHH;delete deltaSigHH;
   LibereTenseur();   
 };
        
        // calcul des contraintes a t+dt et de ses variations  
void LoiDesMelangesEnSigma::Calcul_DsigmaHH_tdt (TenseurHH& sigHH_t,TenseurBB& DepsBB,DdlElement & tab_ddl
            ,BaseB& giB_t,TenseurBB & gijBB_t,TenseurHH & gijHH_t,
            BaseB& giB_tdt,Tableau <BaseB> & d_giB_tdt,BaseH& giH_tdt,Tableau <BaseH> & d_giH_tdt,
            TenseurBB & epsBB_tdt,Tableau <TenseurBB *>& d_epsBB,
            TenseurBB & delta_epsBB,TenseurBB & gijBB_tdt,TenseurHH & gijHH_tdt,
		    Tableau <TenseurBB *>& d_gijBB_tdt,
		  	Tableau <TenseurHH *>& d_gijHH_tdt,double& jacobien_0,double& jacobien,
		  	Vecteur& d_jacobien_tdt,TenseurHH& sigHH_tdt,Tableau <TenseurHH *>& d_sigHH
		  	,EnergieMeca & energ,const EnergieMeca & 
		  	,double& module_compressibilite,double&  module_cisaillement
		  	,const Met_abstraite::Impli& ex)
 { // on commence par créer un tenseur contrainte qui totalisera toutes les contraintes
   // le tenseurs est initialisé à 0.
   // on utilise des pointeurs pour utiliser delete à la fin
   int dim_tens = sigHH_tdt.Dimension();
   TenseurHH * sigtotalHH = (NevezTenseurHH(dim_tens,0.));
   TenseurHH * zeroHH = (NevezTenseurHH(dim_tens,0.));
   TenseurHH * deltaSigHH = (NevezTenseurHH(dim_tens,0.)); // pour la variation de contraintes
   SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveResul);
   module_compressibilite=module_cisaillement=0.; // init

//---debug
//ofstream fichier("toto", ios::app);
//save_resul.Ecriture_base_info(fichier,1);        // calcul de la contrainte résultante
//list <SaveResul *>::iterator ili=save_resul.liste_des_SaveResul.begin();
//(*ili)->Ecriture_base_info(fichier,1);
//ili++;
//(*ili)->Ecriture_base_info(fichier,1);
//save_resul.Ecriture_base_info(fichier,1);        // calcul de la contrainte résultante
////fichier.close();
////---fin debug

   energ.Inita(0.); // initialisation des énergies mises en jeux
   // on vérifie que le tableau de travail intermédiaire statique est correctement 
   // dimensionné sinon on le modifie   
   int taille = d_sigHH.Taille();
   if (d_sigtotalHH.Taille() == 0) 
     { d_sigtotalHH.Change_taille(taille,NULL);}
//       for (int i=1;i<=taille;i++) d_sigtotalHH)(i)=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
   bool premier_passage = true;
   list <TenseurHH* >::iterator isig_t = save_resul.l_sigoHH_t.begin();
   list <TenseurHH* >::iterator isig = save_resul.l_sigoHH.begin();
   list <TenseurHH* >::iterator jsig_t = save_resul.J_sigoHH_t.begin();
   list <TenseurHH* >::iterator jsig = save_resul.J_sigoHH.begin();
   list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
   list <EnergieMeca >::iterator ienerg = save_resul.l_energ.begin();
   list <EnergieMeca >::iterator ienerg_t = save_resul.l_energ_t.begin();
   Loi_comp_abstraite * pt=NULL;
   // on récupère la valeur de la proportion enregistrée, qui a donc été calculée dans les grandeurs de
   // travail
   proportion = save_resul.proportion;

//try {
   for (int ili=1;ili<=2;ili++,isig_t++,isig++,jsig_t++,jsig++,isave++,ienerg++,ienerg_t++)
      { // 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.);};
        if ((*jsig)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*jsig); (*jsig)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        if ((*jsig_t)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*jsig_t); (*jsig_t)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        // calcul de la contrainte résultante, 
        if (ili==1) {pt=lois_internes1;} else {pt=lois_internes2;};
        double compress_inter=0.; double cisaill_inter=0;  // init
        // passage des informations spécifique à la loi liste_des_SaveResul
        pt->IndiqueSaveResult(*isave);          
        pt->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
        pt->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours

////---debug
//cout << "\n  isave melange = " << ( (*isave) == NULL ) << endl;
////ofstream fichier("toto");
//(*isave)->Ecriture_base_info(fichier,1);        // calcul de la contrainte résultante
//fichier.close();
//---fin debug

		      // prise en compte éventuel d'un calcul conditionel au cas d'une proportion non nulle
		      bool traitement = true; // par défaut
		      if (calcule_si_prop_non_nulle.Taille() == 2)
		        {if (calcule_si_prop_non_nulle(ili) == 1)
			         {if (premier_passage &&  ( proportion == 0.)) {traitement = false;}
			          else if ((!premier_passage) &&  ( proportion == 1.)) {traitement = false;};
				        }
           else if ((calcule_si_prop_non_nulle(ili) == 2)||(calcule_si_prop_non_nulle(ili) == 3))
			         { if ((premier_passage)&& (!save_resul.deja_actif_sur_iter1))
                // première loi et pas encore actif
               { if ( proportion == 0. ) // on désactive et on signale pour la suite
                   {traitement = false;save_resul.deja_actif_sur_iter1=true;};
               };
			           if ((!premier_passage)&& (!save_resul.deja_actif_sur_iter2))
                // seconde loi et pas encore actif
               { if ( proportion == 1. ) // on ne traite pas
                   {traitement = false;}
                 else // sinon le traitement commence
                   {save_resul.deja_actif_sur_iter2=true;};
               };
				        }
          };
//--- debug
//	if (proportion == 0.) 
//	 cout << "\n premier_passage= " << premier_passage << ", traitement= " << traitement << endl;
//--- fin debug				
	

		      if (traitement)	  
         { pt->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);
         
          // on sauvegarde la contrainte partielle totale
          (*(*isig))=sigHH_tdt; 
         
          #ifdef MISE_AU_POINT
          if (Permet_affichage() > 3)
             cout << "\n LoiDesMelangesEnSigma::Calcul_DsigmaHH_tdt ";
          #endif
          // def du facteur multiplicatif du à  la proportion
          double facteur_multiplicatif = aA * proportion;
          if (premier_passage) { premier_passage = false;}
          else                 {facteur_multiplicatif = aA*(1.-proportion);};

          // traitement 
           if ((type_melange == 1)||(type_melange == 3))
            { sigHH_tdt *= facteur_multiplicatif;
              (*(*jsig))=sigHH_tdt; // on sauvegarde la contrainte partielle proportionalisée
              (*sigtotalHH) += sigHH_tdt; // on ajoute la contrainte au total
              #ifdef MISE_AU_POINT
              if (Permet_affichage() > 3)
               {if (premier_passage) {cout << "\n 1ere loi:";}
                else {cout << "\n 2ieme loi: ";};
                cout << " facteur_multiplicatif= "
                       << facteur_multiplicatif
                       << ", sigHH_tdt avec ponderation ";
                sigHH_tdt.Ecriture(cout);
               };
              #endif
            }
          else  // cas == 2
            { (*deltaSigHH) = sigHH_tdt - (*(*isig_t)); (*deltaSigHH) *= facteur_multiplicatif;
              (*(*jsig))=(*(*jsig_t)) + (*deltaSigHH); // on sauvegarde la contrainte partielle proportionalisée
              (*sigtotalHH) += (*(*jsig)); // cumule
            };
          energ += (*ienerg) * facteur_multiplicatif; // update des énergies
          module_compressibilite += compress_inter * facteur_multiplicatif;
          module_cisaillement +=  cisaill_inter * facteur_multiplicatif; 
        
          // récup de l'opérateur tangent
          for (int j=1;j<=taille;j++) (*d_sigHH(j))*= facteur_multiplicatif;
          #ifdef MISE_AU_POINT
          if (Permet_affichage() > 4)
           for (int j = 1; j<= taille; j++)
            {  cout << "\n d_sigHH("<<j<<") ";
               d_sigHH(j)->Ecriture(cout);
            };
          #endif
          for (int j=1;j<=taille;j++)
           { (*d_SigtotalHH(j)) += (*d_sigHH(j)); // cumul
             *d_sigHH(j) = (*zeroHH);             // et on initialise pour le prochain coup
            } 
			      }
		      else 
		       { if (premier_passage) { premier_passage = false;};
           (*(*isig))=(*zeroHH); 
			        (*(*jsig))=(*zeroHH);
			        (*ienerg).Inita(0.); 
			      }; // fin du traitement conditionnel
		    }; // fin de la boucle sur les deux lois
//	}
//catch ( ... )
//	 { this->Affiche();
//		Sortie(1);
//	 };

   // recopie du résultat
   sigHH_tdt = (*sigtotalHH);
   for (int k=1;k<=taille;k++)
      (*d_sigHH(k)) = (*d_SigtotalHH(k));
   delete sigtotalHH; delete zeroHH;delete deltaSigHH;
   LibereTenseur();   
//---debug
//fichier.close();
//---fin debug
 };
		  	
        // 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 LoiDesMelangesEnSigma::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.));
   TenseurHH * deltaSigHH = (NevezTenseurHH(dim_tens,0.)); // pour la variation de contraintes
   SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) 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);};
       
   // maintenant on balaie l'ensemble des lois
   bool premier_passage = true;
   list <TenseurHH* >::iterator isig,isig_t,jsig,jsig_t;int ili;
   list <EnergieMeca >::iterator ienerg,ienerg_t;
   list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
   Loi_comp_abstraite * pt=NULL;
   // on récupère la valeur de la proportion enregistrée, qui a donc été calculée dans les grandeurs de
   // travail
   proportion = save_resul.proportion;

   for (ili=1,isig_t = save_resul.l_sigoHH_t.begin(),isig = save_resul.l_sigoHH.begin()
             ,jsig_t = save_resul.l_sigoHH_t.begin(),jsig = save_resul.l_sigoHH.begin()
        ,ienerg = save_resul.l_energ.begin(),ienerg_t = save_resul.l_energ_t.begin();
        ili<=2;ili++,isig_t++,isig++,jsig_t++,jsig++,isave++,ienerg++,ienerg_t++)
      { // 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.);};
        
        if ((*jsig)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*jsig); (*jsig)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        if ((*jsig_t)->Dimension()!=sigHH_t.Dimension()) 
          { delete (*jsig_t); (*jsig_t)=NevezTenseurHH(sigHH_t.Dimension(),0.);};
        // calcul de la contrainte résultante, 
        if (ili==1) {pt=lois_internes1;} else {pt=lois_internes2;};
        double compress_inter=0.; double cisaill_inter=0;  // init
        // passage des informations spécifique à la loi liste_des_SaveResul
        pt->IndiqueSaveResult(*isave);          
        pt->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
        pt->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours
        // initialisation du comportement tangent
        d_sigma_deps_inter->Inita(0.);
		  

		      // prise en compte éventuel d'un calcul conditionel au cas d'une proportion non nulle
		      bool traitement = true; // par défaut
		      if (calcule_si_prop_non_nulle.Taille() == 2)
		        {if (calcule_si_prop_non_nulle(ili) == 1)
			         {if (premier_passage &&  ( proportion == 0.)) {traitement = false;}
			          else if ((!premier_passage) &&  ( proportion == 1.)) {traitement = false;};
				        }
           else if ((calcule_si_prop_non_nulle(ili) == 2)||(calcule_si_prop_non_nulle(ili) == 3))
			         { if ((premier_passage)&& (!save_resul.deja_actif_sur_iter1))
                // première loi et pas encore actif
               { if ( proportion == 0. ) // on désactive et on signale pour la suite
                   {traitement = false;save_resul.deja_actif_sur_iter1=true;};
               };
			           if ((!premier_passage)&& (!save_resul.deja_actif_sur_iter2))
                // seconde loi et pas encore actif
               { if ( proportion == 1. ) // on ne traite pas
                   {traitement = false;}
                 else // sinon le traitement commence
                   {save_resul.deja_actif_sur_iter2=true;};
               };
				        }
          };

		      if (traitement)	  
         { // calcul de la contrainte résultante
           pt->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);
           // on sauvegarde la contrainte partielle totale
           (*(*isig))=sigHH_tdt; 
         
           #ifdef MISE_AU_POINT
           if (Permet_affichage() > 3)
              cout << "\n LoiDesMelangesEnSigma::Calcul_dsigma_deps ";
           #endif
           // def du facteur multiplicatif du à  la proportion
           double facteur_multiplicatif = aA * proportion;
           if (premier_passage) { premier_passage = false;}
           else                 {facteur_multiplicatif = aA*(1.-proportion);};

           // traitement 
           if ((type_melange == 1)||(type_melange == 3))
             { sigHH_tdt *= facteur_multiplicatif;
               (*(*jsig))=sigHH_tdt; // on sauvegarde la contrainte partielle proportionalisée
               (*sigtotalHH) += sigHH_tdt; // on ajoute la contrainte au total
               #ifdef MISE_AU_POINT
               if (Permet_affichage() > 3)
                {if (premier_passage) {cout << "\n 1ere loi:";}
                 else {cout << "\n 2ieme loi: ";};
                 cout << " facteur_multiplicatif= "
                        << facteur_multiplicatif
                        << ", sigHH_tdt avec ponderation ";
                 sigHH_tdt.Ecriture(cout);
                };
               #endif
             }
           else  // cas == 2
             { (*deltaSigHH) = sigHH_tdt - (*(*isig_t)); (*deltaSigHH) *= facteur_multiplicatif;
               (*(*jsig))=(*(*jsig_t)) + (*deltaSigHH); // on sauvegarde la contrainte partielle proportionalisée
               (*sigtotalHH) += (*(*jsig)); // cumule
             };
           energ += (*ienerg) * facteur_multiplicatif; // update des énergies
           module_compressibilite += compress_inter * facteur_multiplicatif;
           module_cisaillement +=  cisaill_inter * facteur_multiplicatif; 
           (*d_sigma_deps_inter) *= facteur_multiplicatif; // module tangent
           #ifdef MISE_AU_POINT
           if (Permet_affichage() > 4)
             {  cout << "\n d_sigma_deps_inter: ";
                d_sigma_deps_inter->Ecriture(cout);
             };
           #endif

           // récup de l'opérateur tangent
           d_sigma_deps += *d_sigma_deps_inter;
			      }
		      else 
		       { if (premier_passage) { premier_passage = false;};
			        (*(*isig))=(*zeroHH); 
			        (*(*jsig))=(*zeroHH);
			        (*ienerg).Inita(0.); 
			      }; // fin du traitement conditionnel
		    }; // fin de la boucle sur les deux lois
   // recopie du résultat
   sigHH_tdt = (*sigtotalHH);
   delete sigtotalHH; delete zeroHH;delete deltaSigHH;
   LibereTenseur();LibereTenseurQ();   
 };


// fonction surchargée dans les classes dérivée si besoin est
void LoiDesMelangesEnSigma::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
     )
{ // calcul de la proportion
  double proportion_locale; // variable locale de travail pour être indépendant de la variable de la classe
  if (type_melange < 3) // cas de la loi historique
   { if (valeur_aux_noeuds) // pour l'instant que des ddl patentés !
       // cas d'une proportion provenant d'une interpolation aux noeuds
       { double grand = def.DonneeInterpoleeScalaire(type_grandeur.Enum(),temps); 
         if (c_proport != NULL)
          { proportion_locale = c_proport->Valeur(grand);}
         else
          { proportion_locale = grand;};
       }
     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 (type_grandeur.Nom_vide())
          {switch (type_grandeur.Enum())
            { case PROP_CRISTA:
               { const double* taux_crita = dTP.TauxCrista();
                 if (taux_crita != NULL)
                  { if (c_proport != NULL)
                      { proportion_locale = c_proport->Valeur(*taux_crita);}
                    else
                      { proportion_locale = *taux_crita;};
                  }
                 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 LoiDesMelangesEnSigma::CalculGrandeurTravail(.... ";
                  }; 	
                 break;
               }
              default:
   //     	   	   cout << "\n erreur, le type de proportion " << Nom_ddl(type_grandeur) << " n'est pas disponible "
                cout << "\n erreur, le type de proportion " << type_grandeur << " n'est pas disponible "
                     << " pour l'instant au point d'integration ! " 
                     << "\n LoiDesMelangesEnSigma::CalculGrandeurTravail(.... ";
                Sortie(1);
            };
          }
         else
          {// cas d'un vrai ddl étendue
           switch (type_grandeur.Position()-NbEnum_ddl())
            {case 87: // cas de "def_equivalente"
              {const double def_equivalente  =  ptintmeca.Deformation_equi_const()(1); // recup de la def equi
               if (c_proport != NULL)
                 { proportion_locale = c_proport->Valeur(def_equivalente);}
               else
                 { proportion_locale = def_equivalente;}; // là mécanquement c'est débile mais techniquement c'est correcte
               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
               if (c_proport != NULL)
                { proportion_locale = c_proport->Valeur(def_duale_mises_maxi);}
               else
                { proportion_locale = def_duale_mises_maxi;}; // là mécanquement c'est débile mais techniquement c'est correcte
               break;
              }
             case 77: // cas de "def_duale_mises"
              {const double def_duale_mises  =  ptintmeca.Deformation_equi_const()(2); // recup de la def equi
               if (c_proport != NULL)
                { proportion_locale = c_proport->Valeur(def_duale_mises);}
               else
                { proportion_locale = def_duale_mises;}; // là mécanquement c'est débile mais techniquement c'est correcte
               break;
              }
   //			     {const Vecteur &  epsInvar   = ptintmeca.EpsInvar_const(); // recup des invariants
   //				   double def_duale_mises = sqrt(2./3. * epsInvar(2)); 
   //				  
   //				   if (c_proport != NULL)
   //				    { proportion = c_proport->Valeur(def_duale_mises);}
   //				   else
   //				    { proportion = def_duale_mises;}; // là mécanquement c'est débile mais techniquement c'est correcte	
   //				   break;
   //				   }
             case 78: // cas de "Spherique_eps"
              {const Vecteur &  epsInvar   = ptintmeca.EpsInvar_const(); // recup des invariants
               double spherique_eps = epsInvar(1); 
   //					cout << " Ieps=" << spherique_eps;
         
               if (c_proport != NULL)
                 { proportion_locale = c_proport->Valeur(spherique_eps);}
               else
                 { proportion_locale = spherique_eps;}; // là mécaniquement c'est débile mais techniquement c'est correcte
               break;
              }
             case 81: // cas de "Spherique_sig"
              {const Vecteur &  sigInvar   = ptintmeca.SigInvar_const(); // recup des invariants
               double spherique_sig = sigInvar(1); 
         
               if (c_proport != NULL)
                { proportion_locale = c_proport->Valeur(spherique_sig);}
               else
                { proportion_locale = spherique_sig;}; // là mécaniquement c'est débile mais techniquement c'est correcte
               break;
              }
             default:
               cout << "\n erreur, le type de proportion " << type_grandeur << " n'est pas disponible "
                    << " pour l'instant au point d'integration ! " 
                    << "\n LoiDesMelangesEnSigma::CalculGrandeurTravail(.... ";
               Sortie(1);
             break;
            }
          }			  	
       };
   }
  else // cas type_melange = 3 ou 4: -> fonctions complexes
   {
     // le résultat de la proportion est le produit de toutes les proportions
     // on initialise donc à 1
     proportion_locale = 1.;
     if (niveauF_grandeurND != NULL)
       {
        // il faut calculer la fonction nD
        SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveResul);
        // on utilise la méthode générique de loi abstraite
        Tableau <double> & tab_val = Loi_comp_abstraite::Loi_comp_Valeur_FnD_Evoluee
            (niveauF_grandeurND,1 // une seule valeur attendue en retour
             ,ex_impli,ex_expli_tdt,ex_umat
             ,exclure_dd_etend
             ,exclure_Q
             ,&save_resul.liste_des_SaveResul
            );

/*
        
        // ici on utilise les variables connues aux pti, ou calculées à partir de
        // on commence par récupérer les conteneurs des grandeurs à fournir
        List_io <Ddl_enum_etendu>& li_enu_scal = niveauF_grandeurND->Li_enu_etendu_scalaire();
        List_io <TypeQuelconque >& li_quelc = niveauF_grandeurND->Li_equi_Quel_evolue();
        bool absolue = true; // on se place systématiquement en absolu
        SaveResul_LoiDesMelangesEnSigma & save_resul = *((SaveResul_LoiDesMelangesEnSigma*) saveResul);

        // on va exclure certaines grandeurs de l'appel de Valeur_multi_interpoler_ou_calculer(..)
        // on va utiliser la méhode Valeur_multi_interpoler_ou_calculer
        // pour les grandeurs strictement scalaire
        List_io<EnumTypeQuelconque> exclure_Q; // init de la liste à exclure
        {List_io <TypeQuelconque>::iterator it,itfin = li_quelc.end();
         map <  EnumTypeQuelconque , TypeQuelconque, std::less < EnumTypeQuelconque> >::const_iterator imap;
         for (it = li_quelc.begin(); it != itfin; it++)
           {bool valeur_recuperer = false; // pour savoir s'il y a eu récupération
            EnumTypeQuelconque enu=(*it).EnuTypeQuelconque().EnumTQ();
            // on boucle sur les lois pour récupérer les types quelconques
            Loi_comp_abstraite * pt=NULL;
            // pour  couvrir l'ensemble des lois
            list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
            for (int iloi = 1;iloi<3;iloi++,isave++)
             { if (iloi==1) {pt=lois_internes1;} else {pt=lois_internes2;};
               // récupération des type quelconque sous forme d'un arbre pour faciliter la recherche
               const map <  EnumTypeQuelconque , TypeQuelconque, std::less < EnumTypeQuelconque> >*
                    map_quelcon = (*isave)->Map_type_quelconque();
                if (map_quelcon != NULL) // sinon il n'y a pas de map
                 {imap = map_quelcon->find(enu);
                  if (imap != map_quelcon->end())
                   { // on a trouvé la grandeur
                     switch (Type_de_grandeur_associee(enu))
                       {  case SCALAIRE_DOUBLE:
                           { const Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
                                         (*imap).second.Const_Grandeur_pointee());
                            // on renseigne l'argument
                            (*(*it).Grandeur_pointee()) = tyTQ;
                            valeur_recuperer = true;
                            break;
                           }
                          case SCALAIRE_ENTIER:
                           { const Grandeur_scalaire_entier& tyTQ= *((Grandeur_scalaire_entier*)
                                         (*imap).second.Const_Grandeur_pointee());
                             // on renseigne l'argument
                             (*(*it).Grandeur_pointee()) = tyTQ;
                             valeur_recuperer = true;
                            break;
                           }
                          default:
                           {cout << "\n erreur fatale dans l'utilisation de la grandeur locale,"
                                 << NomTypeQuelconque(enu)
                                 << " necessaire pour le calcul de la ponderation "
                                 << " cette grandeur n'est pas un scalaire, pour l'instant "
                                 << " on ne sait pas comment l'utiliser !! "
                                 << "\n LoiDesMelangesEnSigma::CalculGrandeurTravail(... ";
                            Sortie(1);
                           };
                         break;
                      };
                     // on sort de la boucle
                     break;
                   };
                 };
              };
            // si la grandeur a été récupérée, on l'exclue de la liste à transmettre
            // à la méthode Valeurs_Tensorielles_interpoler_ou_calculer
            if (valeur_recuperer)
              exclure_Q.push_back(enu);
           };
        };
        
        // maintenant on appel les méthodes génériques
        Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
               (absolue,TEMPS_tdt,li_enu_scal,ex_impli,ex_expli_tdt,ex_umat,exclure_dd_etend)
                                      );
        // on fait de même pour les grandeurs tensorielles
        // on utilise la méthode Valeurs_Tensorielles_interpoler_ou_calculer
        // pour les Coordonnees et Tenseur
        Valeurs_Tensorielles_interpoler_ou_calculer
               (absolue,TEMPS_tdt,li_quelc,ex_impli,ex_expli_tdt,ex_umat,&exclure_Q);
        // calcul de la valeur et retour dans tab_val
        Tableau <double> & tab_val = niveauF_grandeurND->Valeur_FnD_Evoluee(&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
        #ifdef MISE_AU_POINT
        if (tab_val.Taille() != 1)
           { cout << "\nErreur : la fonction nD relative a la ponderation nD "
                  << " doit calculer un scalaire or le tableau de retour est de taille "
                  << tab_val.Taille() << " ce n'est pas normal !\n";
             cout << " LoiDesMelangesEnSigma::CalculGrandeurTravail(..\n";
             Sortie(1);
           };
        #endif
*/
        proportion_locale *= tab_val(1); // mise à jour de la proportion
       };
     if (niveauF_temps != NULL) // cas d'une dépendance au temps
        proportion_locale *= niveauF_temps->CalculPonder();
     // avec une dépendance via éventuellement des ddl étendu
     if (niveauF_ddlEtendu != NULL)
        proportion_locale *= niveauF_ddlEtendu->CalculPonderMultiplicatif(ptintmeca, def, temps, dTP);

   };
 
  // --- arrivée ici on a une proposition de proportion = proportion_locale
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
    {
     cout << "\n loi melange: proportion avant limitation "<< proportion_locale;
    }
  #endif

  // on traite les extrémums !!: a conserver absolument, car sert dans les tests avec le tableau: calcule_si_prop_non_nulle 
  if (proportion_locale < 0.) proportion_locale = 0;
  if (proportion_locale > 1.) proportion_locale = 1.;
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 4)
    {
     cout << "\n proportion apres limitation "<< proportion_locale;
    }
  #endif



//     if ( (proportion < -0.02) || (proportion > 1.02))
//       { cout << "\n attention, la proportion entre les deux lois est hors de [-0.02,1.02], proportion = " 
//              << proportion << " ";
//         cout << "\n LoiDesMelangesEnSigma::CalculGrandeurTravail(..";    
//        };

  // calcul de l'enregistrement dans les variables spécifiques au point calculé
  SaveResul_LoiDesMelangesEnSigma & save_res = *((SaveResul_LoiDesMelangesEnSigma*) saveResul);
 
  // auparavant: traitement particulier d'une proportion toujours progressive
//  if (calcule_si_prop_non_nulle.Taille() == 2)
//    {if ((calcule_si_prop_non_nulle(1) == 2) || (calcule_si_prop_non_nulle(2) == 2)
//         || ((calcule_si_prop_non_nulle(1) == 3) || (calcule_si_prop_non_nulle(2) == 3))
//        )
  if ((save_res.type_evolution_proportion == 1) || (save_res.type_evolution_proportion == 2))
        // ici il s'agit d'une évolution absolue sur tout le calcul = tous les incréments
			         { if (proportion_locale > save_res.proportion )
                 proportion_locale = save_res.proportion; // la proportion a augmenté, on garde la plus petite
				        }
//    };

  // suite normale
  save_res.proportion = proportion_locale;
  // répercution sur les classes dérivées si besoin est
  list <SaveResul*>::iterator isave=save_res.liste_des_SaveResul.begin(); // pour les saveResul des lois
  Loi_comp_abstraite * pt=NULL;
  for (int ili=1;ili<=2;ili++,isave++)
    { if (ili==1) {pt=lois_internes1;} else {pt=lois_internes2;};
      // passage des informations spécifique à la loi liste_des_SaveResul
      pt->IndiqueSaveResult(*isave);          
      pt->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
      pt->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours
	     pt->CalculGrandeurTravail(ptintmeca,def,temps,dTP,ex_impli
                                ,ex_expli_tdt,ex_umat,exclure_dd_etend,exclure_Q);
    };
};
   
       // 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 LoiDesMelangesEnSigma::RepercuteChangeTemperature(Enum_dure temps)
  { lois_internes1->temperature_0 = this->temperature_0;
    lois_internes1->temperature_t = this->temperature_t;
    lois_internes1->temperature_tdt = this->temperature_tdt;
    lois_internes1->dilatation=dilatation;
    lois_internes2->temperature_0 = this->temperature_0;
    lois_internes2->temperature_t = this->temperature_t;
    lois_internes2->temperature_tdt = this->temperature_tdt;
    lois_internes2->dilatation=dilatation;
    if (dilatation)
     {//  a- dimensionnement des tenseurs intermédiaires 
      int dim_tens = epsBB_therm->Dimension();
          // -- cas de la déformation
      if (lois_internes1->epsBB_therm == NULL) { lois_internes1->epsBB_therm = NevezTenseurBB(dim_tens);}
      else if (lois_internes1->epsBB_therm->Dimension() != dim_tens)
         { delete lois_internes1->epsBB_therm;lois_internes1->epsBB_therm = NevezTenseurBB(dim_tens);};
      if (lois_internes2->epsBB_therm == NULL) { lois_internes2->epsBB_therm = NevezTenseurBB(dim_tens);}
      else if (lois_internes2->epsBB_therm->Dimension() != dim_tens)
         { delete lois_internes2->epsBB_therm;lois_internes2->epsBB_therm = NevezTenseurBB(dim_tens);};
          // -- cas de la vitesse de déformation
      if (lois_internes1->DepsBB_therm == NULL) { lois_internes1->DepsBB_therm = NevezTenseurBB(dim_tens);}
      else if (lois_internes1->DepsBB_therm->Dimension() != dim_tens)
       { delete lois_internes1->DepsBB_therm;lois_internes1->DepsBB_totale = NevezTenseurBB(dim_tens);};
      if (lois_internes2->DepsBB_therm == NULL) { lois_internes2->DepsBB_therm = NevezTenseurBB(dim_tens);}
      else if (lois_internes2->DepsBB_therm->Dimension() != dim_tens)
       { delete lois_internes2->DepsBB_therm;lois_internes2->DepsBB_totale = NevezTenseurBB(dim_tens);};
      // b- affectation des tenseurs
      (*lois_internes1->epsBB_therm)=(*epsBB_therm);
      (*lois_internes1->DepsBB_therm)=(*DepsBB_therm);
      (*lois_internes2->epsBB_therm)=(*epsBB_therm);
      (*lois_internes2->DepsBB_therm)=(*DepsBB_therm);
     };
    lois_internes1->RepercuteChangeTemperature(temps);
    lois_internes2->RepercuteChangeTemperature(temps);

    switch (temps)
      { case TEMPS_0: 
         {lois_internes1->temperature = &lois_internes1->temperature_0;
          lois_internes2->temperature = &lois_internes2->temperature_0; 
          break;
          }
        case TEMPS_t: 
         {lois_internes1->temperature = &lois_internes1->temperature_t;
          lois_internes2->temperature = &lois_internes2->temperature_t; 
          break;
          }
        case TEMPS_tdt: 
         {lois_internes1->temperature = &lois_internes1->temperature_tdt;
          lois_internes2->temperature = &lois_internes2->temperature_tdt; 
          break;
          }
        default:
          { cout << "\n erreur, cas de temps non prevu !! "
                 << "\n LoiDesMelangesEnSigma::RepercuteChangeTemperature(...";
            Sortie(1);      
          };
      }; 
    #ifdef MISE_AU_POINT
     if (Permet_affichage() > 7)
         { cout << "\n init temperatures:\n "
                << " lois_internes1->temperature_0= " << lois_internes1->temperature_0
                << " lois_internes1->temperature_t= " << lois_internes1->temperature_t
                << " lois_internes1->temperature_tdt= " << lois_internes1->temperature_tdt
                << " lois_internes1->temperature= " << *(lois_internes1->temperature)
                << " lois_internes2->temperature_0= " << lois_internes2->temperature_0
                << " lois_internes2->temperature_t= " << lois_internes2->temperature_t
                << " lois_internes2->temperature_tdt= " << lois_internes2->temperature_tdt
                << " lois_internes2->temperature= " << *(lois_internes2->temperature)
                << " \n LoiDesMelangesEnSigma::RepercuteChangeTemperature(.."
                << endl;
         };
    #endif

  }; 
   
   
   
