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


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


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

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

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




// fonction critère de plissement de membrane
// en entrée:
// implicit : si oui on est en implicite, sinon en explicite
// retour:
// ** ancienne mouture
//    = -2  : erreur en calcul des valeurs propres de déformation, on ne tiens pas compte des plis
//    = -1  : erreur en calcul des valeurs propres de contrainte, on ne tiens pas compte des plis
//          : ou erreur en calcul des  vecteurs propres de contrainte 
//    = 1   : tout est ok, il n'y a pas d'apparition de plis, rien n'est en compression
//    = 2   : il y a des plis dans les deux sens, aucune raideur ni contrainte
//    = 3   : on a des plis dans une direction

// ** nouvelle mouture
//   = -1 : pas de calcul de valeur propre possible en contrainte
//   =  1 : pas de plis (pas de calcul de nouvelle direction )
//   = -2 : pas de calcul de valeur propre de déformation
//   = -3 : plis dans les deux sens, mais pas de calcul de direction propre valide
//   =  2 : plis dans les deux sens, calcul des directions de plis
//   = -4 : pas de calcul de vecteurs propres possible pour les contraintes
//   =  3 : plis dans une seule directions, calcul ok

int LoiCritere::Critere_plis_membrane(bool en_base_orthonormee,TenseurHH & sigHH_t,TenseurBB& DepsBB
            ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB,double& jacobien_0,double& jacobien
		  	       ,TenseurHH& sigHH,TenseurHHHH& d_sigma_deps_inter
		  	       ,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite
            ,double&  module_cisaillement
		  	       ,bool implicit,const Met_abstraite::Umat_cont& ex)
  {// on sauvegarde les modules de compressibilité et de cisaillement
   // car l'appel à la loi de contrainte plane annulle les valeurs stockées
   // et dans le cas ou il y a un pb, le mieux est de garder les anciennes valeurs
//   double module_compressibilite_save = module_compressibilite;
//   double module_cisaillement_save = module_cisaillement;
  
   // dim et vérification
   int dim_tens = abs(sigHH.Dimension());
   // normalement le critère ne s'applique que pour des tenseurs 2D
   #ifdef MISE_AU_POINT
   if (dim_tens != 2)
     { cout << "\n erreur le critere de plissement de membrane ne peut s'appliquer que pour des lois 2D"
            << " \n LoiCritere::Critere_plis_membrane_expli(..";
       Sortie(1);
     };
   #endif
        
   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   int retour = 0; // init par défaut

   // pilotage éventuelle du recalcul des directions de plis
   int calcul_dir_plis = 1; // initialisation
   // si  rien n'a été auparavant calculé, on est obligé de faire un premier calcul
   // de direction sinon on appelle éventuellement l'indicateur

   // on récupère l'indicateur: qui est déterminé par une fonction nD
   //    si cas_cal_plis == 0 cela veut dire soit qu'il n'y a pas eu déjà un calcul
   //    soit que ce précédant calcul ne s'est pas bien passé, dans ces deux il faut
   //    imposer de faire le calcul
   if ((recalcul_dir_plis != NULL) && (save_resul.cas_cal_plis != 0))
     {// opération de transmission de la métrique
      const Met_abstraite::Impli* ex_impli = NULL;
      const Met_abstraite::Expli_t_tdt* ex_expli_tdt = NULL;
      const Met_abstraite::Umat_cont* ex_expli = &ex ;

      // 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
                 = recalcul_dir_plis->Li_enu_etendu_scalaire();
      List_io <TypeQuelconque >& li_quelc = recalcul_dir_plis->Li_equi_Quel_evolue();
      bool absolue = true; // on se place systématiquement en absolu
      // on va utiliser la méhode Valeur_multi_interpoler_ou_calculer
      // pour les grandeurs strictement scalaire
      Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
                 (absolue,TEMPS_tdt,li_enu_scal,ex_impli,ex_expli_tdt,ex_expli,NULL)
                                    );
      // 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_expli,NULL);
      // calcul de la valeur et retour dans tab_ret
      Tableau <double> & tab_val
             = recalcul_dir_plis->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 au recalcul de la direction des plis "
                << " doit calculer un scalaire or le tableau de retour est de taille "
                << tab_val.Taille() << " ce n'est pas normal !\n";
           cout << " LoiCritere::Critere_plis_membrane(... \n";
           Sortie(1);
         };
      #endif
      // on récupère le premier élément du tableau uniquement
      calcul_dir_plis = (int) tab_val(1);
     };
   
   // en fonction de l'indicateur calcul conditionnel des plis
   // ou utilisation des grandeurs sauvegardées
   Tableau <Coordonnee2H> V_Pr_H(2);
   Coordonnee2 valPropreSig;
   Coordonnee2 valPropreEps;

   switch (calcul_dir_plis) // test en fonction d'un pilotage éventuel fct de la fonction nD
                            // recalcul_dir_plis->Valeur_FnD_Evoluee
   // rappel de la gestion des différents cas via la valeur de: calcul_dir_plis
   //      si == 0 on utilise la valeur stockee actuelle, c-a-d ici à l'itération précédente
   //               si aucun calcul de direction n'a ete effectue, il y a un premier calcul qui est fait
   //      si == 1 on recalcule les directions des plis,
   //      si == 2 on recalcule les directions des plis uniquement pour la zone non complètement
   //              relâchée à l'incrément précédent, pour cette dernière on maintient le relâchement
   //      si == -1 on utilise la valeur stockee a t (celle de l'incrément precedent qui a convergé),
   //               si aucun calcul de direction n'a ete effectue, il y a un premier calcul qui est fait
   //      si == -2 idem -1 , sauf que s'il n'y a pas de direction existante, on ne recalcule pas une
   //               nouvelle direction, on continue avec un calcul sans plis
   //        --> cela signifie que la zone de plis est totalement figée / au précédent incrément
   //      si == -3 idem 0 , sauf que s'il n'y a pas de direction existante, on ne recalcule pas une
   //               nouvelle direction, on continue avec un calcul sans plis
   //        --> cela signifie que la zone de plis est totalement figée / à la précédente itération

    { case 2: // cas ou on doit recalculer la direction des plis uniquement pour la zone non relâché
       { if (save_resul.cas_cal_plis_t != 2)
          { int retour = Calcul_directions_plis(epsBB_tdt,sigHH,valPropreEps,V_Pr_H,ex,valPropreSig);
            #ifdef MISE_AU_POINT
            // vérif normalement inutile car le retour doit toujours être non nul
            if (!retour)
              {cout << "\n **** erreur  a priori: normalement on ne devrait jamais avoir de retour nul  "
                    << " or on veut l'utiliser: ce n'est pas possible !! arret !! "
                    << "\n LoiCritere::Critere_plis_membrane(...";
               Sortie(1);
             };
            #endif
          }
        else // sinon on maintien l'indicateur de relâchement
          {save_resul.cas_cal_plis = save_resul.cas_cal_plis_t;
          };

// retour dans le save_resul.cas_cal_plis
//   = -1 : pas de calcul de valeur propre possible en contrainte
//   =  1 : pas de plis (pas de calcul de nouvelle direction )
//   = -2 : pas de calcul de valeur propre de déformation 
//   = -3 : plis dans les deux sens, mais pas de calcul de direction propre valide
//   =  2 : plis dans les deux sens, calcul des directions de plis 
//   = -4 : pas de calcul de vecteurs propres possible pour les contraintes
//   =  3 : plis dans une seule directions, calcul ok
         // si cela s'est bien passé, les résultats sont dans V_Pr_H
         // sinon on utilisera pas de directions: calculées ou stockées
         break; // fin du cas où on recalcule la direction des plis
							}
      case 1: // cas ou on doit recalculer la direction des plis
       { int retour = Calcul_directions_plis(epsBB_tdt,sigHH,valPropreEps,V_Pr_H,ex,valPropreSig);
         #ifdef MISE_AU_POINT
         // vérif normalement inutile car le retour doit toujours être non nul
         if (!retour)
           {cout << "\n **** erreur  a priori: normalement on ne devrait jamais avoir de retour nul  "
                 << " or on veut l'utiliser: ce n'est pas possible !! arret !! "
                 << "\n LoiCritere::Critere_plis_membrane(...";
            Sortie(1);
          };
         #endif

// retour dans le save_resul.cas_cal_plis
//   = -1 : pas de calcul de valeur propre possible en contrainte
//   =  1 : pas de plis (pas de calcul de nouvelle direction )
//   = -2 : pas de calcul de valeur propre de déformation
//   = -3 : plis dans les deux sens, mais pas de calcul de direction propre valide
//   =  2 : plis dans les deux sens, calcul des directions de plis
//   = -4 : pas de calcul de vecteurs propres possible pour les contraintes
//   =  3 : plis dans une seule directions, calcul ok
         // si cela s'est bien passé, les résultats sont dans V_Pr_H
         // sinon on utilisera pas de directions: calculées ou stockées
         break; // fin du cas où on recalcule la direction des plis
       }
      case 0: // cas où on se sert de ce qui a été sauvegardé à l'itération précédente
       // si aucun calcul de direction n'a ete effectue, il y a un premier calcul qui est fait
       { // en fait seul les cas 3 et 2 sont exploitables et seront exploités
         if ((save_resul.cas_cal_plis == 3)||(save_resul.cas_cal_plis == 2))
           { // V_Pr_H(be)(j) correspond à la coordonnée locale ^j du vecteur be
             // donc V_Pr_H(be)(j) = V_Pr(be) * giH(j)
             //  les vecteurs V_Pr_H(be) sont supposés être dans le plan des g_alpha
             for (int be=1;be<3;be++) // < 3 donc de 1 à 2
              {for (int al=1;al<3;al++) // < 3 donc de 1 à 2
                  V_Pr_H(be)(al) = (*save_resul.V_P_sig)(be) * ex.giH_tdt->Coordo(al);
              };
           }
         else // sinon cela veut dire que le calcul précédent n'est pas exploitable
              // on refait un calcul
          {int retour = Calcul_directions_plis(epsBB_tdt,sigHH,valPropreEps,V_Pr_H,ex,valPropreSig);
           #ifdef MISE_AU_POINT
           // vérif normalement inutile car le retour doit toujours être non nul
           if (!retour)
             {cout << "\n **** erreur  a priori: normalement on ne devrait jamais avoir de retour nul  "
                   << " or on veut l'utiliser: ce n'est pas possible !! arret !! "
                   << "\n LoiCritere::Critere_plis_membrane(...";
              Sortie(1);
             };
           #endif
          };
         break; // fin du cas où on utilise la direction des plis sauvegardée à l'itération prec
       }
			   case -1:  // cas où on se sert de ce qui a été sauvegardé à l'incrément précédent
       // si aucun calcul de direction n'a ete effectue, il y a un premier calcul qui est fait
       { // en fait seul les cas 3 et 2 sont exploitables et seront exploités
         if ((save_resul.cas_cal_plis_t == 3)||(save_resul.cas_cal_plis_t == 2))
           { // V_Pr_H(be)(j) correspond à la coordonnée locale ^j du vecteur be
             // donc V_Pr_H(be)(j) = V_Pr(be) * giH(j)
             //  les vecteurs V_Pr_H(be) sont supposés être dans le plan des g_alpha
             // on utilise aussi les   vecteurs de la base à t, ce qui permet de convecter
             // les vecteurs des directions de plis
             #ifdef MISE_AU_POINT
             // on vérifie que les données à t existent
             if (save_resul.V_P_sig_t == NULL)
               {cout << "\n **** erreur la direction des plis a t n'est pas encore sauvegardee  "
                     << " or on veut l'utiliser: ce n'est pas possible !! arret !! "
                     << "\n LoiCritere::Critere_plis_membrane(...";
                Sortie(1);
               };
             #endif
            
             for (int be=1;be<3;be++) // < 3 donc de 1 à 2
              {for (int al=1;al<3;al++) // < 3 donc de 1 à 2
                  V_Pr_H(be)(al) = (*save_resul.V_P_sig_t)(be) * ex.giH_t->Coordo(al);
              };
             // on met à jour save_resul.cas_cal_plis en fonction
             save_resul.cas_cal_plis = save_resul.cas_cal_plis_t;
           }
         else // sinon cela veut dire que le calcul précédent n'est pas exploitable
               // on refait un calcul
           {int retour = Calcul_directions_plis(epsBB_tdt,sigHH,valPropreEps,V_Pr_H,ex,valPropreSig);
            #ifdef MISE_AU_POINT
            // vérif normalement inutile car le retour doit toujours être non nul
            if (!retour)
              {cout << "\n **** erreur  a priori: normalement on ne devrait jamais avoir de retour nul  "
                    << " or on veut l'utiliser: ce n'est pas possible !! arret !! "
                    << "\n LoiCritere::Critere_plis_membrane(...";
               Sortie(1);
              };
            #endif
           };
        
          break; // fin du cas où on utilise la direction des plis sauvegardée à l'increment prec
        }
      case -2: // cas où la zone de plis de l'incrément précédent
               // est totalement figée
       { // en fait seul les cas 3 et 2 sont exploitables et seront exploités
         if ((save_resul.cas_cal_plis_t == 3)||(save_resul.cas_cal_plis_t == 2))
           { // V_Pr_H(be)(j) correspond à la coordonnée locale ^j du vecteur be
             // donc V_Pr_H(be)(j) = V_Pr(be) * giH(j)
             //  les vecteurs V_Pr_H(be) sont supposés être dans le plan des g_alpha
             // on utilise aussi les   vecteurs de la base à t, ce qui permet de convecter
             // les vecteurs des directions de plis
             #ifdef MISE_AU_POINT
             // on vérifie que les données à t existent
             if (save_resul.V_P_sig_t == NULL)
               {cout << "\n **** erreur la direction des plis a t n'est pas encore sauvegardee  "
                     << " or on veut l'utiliser: ce n'est pas possible !! arret !! "
                     << "\n LoiCritere::Critere_plis_membrane(...";
                Sortie(1);
               };
             #endif
            
             for (int be=1;be<3;be++) // < 3 donc de 1 à 2
              {for (int al=1;al<3;al++) // < 3 donc de 1 à 2
                  V_Pr_H(be)(al) = (*save_resul.V_P_sig_t)(be) * ex.giH_t->Coordo(al);
              };
             // on met à jour save_resul.cas_cal_plis en fonction
             save_resul.cas_cal_plis = save_resul.cas_cal_plis_t;
           }
         else // sinon on continue avec un cas sans plis
           { int retour = Calcul_directions_plis(epsBB_tdt,sigHH,valPropreEps,V_Pr_H,ex,valPropreSig,false);
             // on met à jour save_resul.cas_cal_plis en fonction
             save_resul.cas_cal_plis = retour;
           };
          break; // fin du cas où on utilise la direction des plis sauvegardée à l'increment prec
        }
      case -3: // cas où on se sert de ce qui a été sauvegardé à l'itération précédente
       //      idem 0 , sauf que s'il n'y a pas de direction existante, on ne recalcule pas une
       //               nouvelle direction, on continue avec un calcul sans plis
       //        --> cela signifie que la zone de plis est totalement figée / à la précédente itération
       { // en fait seul les cas 3 et 2 sont exploitables et seront exploités
         if ((save_resul.cas_cal_plis == 3)||(save_resul.cas_cal_plis == 2))
           { // V_Pr_H(be)(j) correspond à la coordonnée locale ^j du vecteur be
             // donc V_Pr_H(be)(j) = V_Pr(be) * giH(j)
             //  les vecteurs V_Pr_H(be) sont supposés être dans le plan des g_alpha
             for (int be=1;be<3;be++) // < 3 donc de 1 à 2
              {for (int al=1;al<3;al++) // < 3 donc de 1 à 2
                  V_Pr_H(be)(al) = (*save_resul.V_P_sig)(be) * ex.giH_tdt->Coordo(al);
              };
           }
         else // sinon on continue avec un cas sans plis
           { int retour = Calcul_directions_plis(epsBB_tdt,sigHH,valPropreEps,V_Pr_H,ex,valPropreSig,false);
             // on met à jour save_resul.cas_cal_plis en fonction
             save_resul.cas_cal_plis = retour;
           };
         break; // fin du cas où on utilise la direction des plis sauvegardée à l'itération prec
       }
      default:
       cout << "\n erreur non prevu : calcul_dir_plis= "<< save_resul.cas_cal_plis
            << "\n LoiCritere::Critere_plis_membrane(...";
       Sortie(1);
   };
										 
//   if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//    cout << "\n test3: LoiCritere::Critere_plis_membrane(... " << flush;

   // maintenant on fait un traitement en fonction de save_resul.cas_cal_plis
//   = -1 : pas de calcul de valeur propre possible en contrainte
//   =  1 : pas de plis (pas de calcul de nouvelle direction )
//   = -2 : pas de calcul de valeur propre de déformation 
//   = -3 : plis dans les deux sens, mais pas de calcul de direction propre valide
//   =  2 : plis dans les deux sens, calcul des directions de plis 
//   = -4 : pas de calcul de vecteurs propres possible pour les contraintes
//   =  3 : plis dans une seule directions, calcul ok
   retour = save_resul.cas_cal_plis; // init
			switch (save_resul.cas_cal_plis) 
				{ case -1: // pas de calcul de valeur propre possible en contrainte
				    {save_resul.eps_pli.Zero(); // pas de pli répertorié
				     break;
				    }
				  case 1: // pas de plis
				    {break;
				    }
				  case -2: // pas de calcul de valeur propre de déformation
				    {save_resul.eps_pli.Zero(); // pas de pli répertorié
				     break;
				    }
				  // on traite -3 et 2 en même temps, car la fin est commune  
				  case -3: // plis dans les deux sens, mais pas de calcul de direction propre valide
				  case  2: // plis dans les deux sens, calcul des directions de plis 
				    {if (save_resul.cas_cal_plis == -3)
				       {save_resul.eps_pli.Zero(); // pas de pli répertorié
				       }
				     else // -> cas:  save_resul.cas_cal_plis == 2 
           {if (calcul_dir_plis != 2)
             { // calcul normal relatif à la zone relâchée
               // les coordonnées des vecteurs propres sont exprimées dans l'ancienne base
               // on a donc
               //    Vi_B(i) = gpB(i) = beta(i,j) * gB(j), i indice de ligne, j indice de colonne
               Mat_pleine beta(2,2);
               for (int i=1;i<3;i++) // < 3 donc de 1 à 2
                for (int j=1;j<3;j++)
                  beta(i,j) = V_Pr_H(i)(j);
               Mat_pleine gamma(beta.Inverse().Transpose()); // on calcule la matrice inverse
               // la matrice gamma correspond à la matrice de changement de base des g^i au gpH
               // gamma est  l'inverse transposée
               // gpH(i) = gamma(i,j) * gH(j), i indice de ligne, j indice de colonne
               //   c-a-d= gp^i = gamma^i_j * g^j
               bool deux_plis = true;
               // on calcul les def de plis : save_resul.eps_pli
               Passage_3ou2_vers_1(gamma,sigHH_t,beta,DepsBB,epsBB_tdt
                                  ,delta_epsBB,deux_plis,save_resul.eps_pli);
             }
            else // sinon calcul_dir_plis == 2, cela veut dire que l'on n'a pas recalculé
              // dans la zône relâchée donc on utilise les déformations déjà calculées à t
             { save_resul.eps_pli = save_resul.eps_pli_t;
               // on retient les directions des plis précendentes
               (*save_resul.V_P_sig) = (*save_resul.V_P_sig_t);
             };
           };
         // traitement des épaisseurs et des largeurs
//         LoiContraintesPlanes::SaveResul_LoiContraintesPlanes * save_result_plan_inter // pour simplifier
//                             =  (LoiContraintesPlanes::SaveResul_LoiContraintesPlanes *)
//                                 (*(save_resul.liste_des_SaveResul.begin()));
         LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_plan_inter // pour simplifier
                             =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
                                 (*(save_resul.liste_des_SaveResul.begin()));
         switch (choix_calcul_epaisseur_si_relachement_complet)
           { case 1: // cas où on impose un retour à l'épaisseur et à la largeur initiales
              save_result_plan_inter->hsurh0 = 1.;
              save_result_plan_inter->bsurb0 = 1.;
              break;
             case 2: // cas où on impose l'épaisseur et la largeur du pas précédent
              {if (save_result_plan_inter->h_tsurh0 != 0.)
                {save_result_plan_inter->hsurh0 = save_result_plan_inter->h_tsurh0;}
               else // sinon on remet à 1.
                {save_result_plan_inter->hsurh0 = 1.;};
               if (save_result_plan_inter->b_tsurb0 != 0.)
                {save_result_plan_inter->bsurb0 = save_result_plan_inter->b_tsurb0;}
               else // sinon on remet à 1.
                {save_result_plan_inter->bsurb0 = 1.;};
               break;
              }
             default:
               cout << "\n erreur *** la variable choix_calcul_epaisseur_si_relachement_complet= "
                    << choix_calcul_epaisseur_si_relachement_complet
                    << " est differente de 1= le seul choix actuellement implante " << endl;
               Sortie(1);
               break;
           };
         // on annule la contrainte et sa contribution éventuelle à la raideur
         sigHH.Inita(0.);
         //d_sigma_deps_inter.Inita(0.);
         // on annule également les énergies
         energ.Inita(0.);
         break;
        }				    
				  case -4: // pas de calcul de vecteurs propres possible pour les contraintes
				    {save_resul.eps_pli.Zero(); // pas de pli répertorié
				     break;
				    }
				  case 3: // plis dans une seule directions
				    {// va être traité en dehors du switch car c'est le gros morceau 
				     break;
				    }
				    
				  default: // normalement n'arrive jamais car Calcul_directions_plis a toujours une solution diff de 0
								{ cout << "\n *** cas d'erreur inconnue dans le calcul de la direction des plis "
								       << " save_resul.cas_cal_plis= "<< save_resul.cas_cal_plis ;
										Sortie(1);
										break;
								}
				};
				
//   if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//    cout << "\n test4: LoiCritere::Critere_plis_membrane(... " << flush;
			// le gros morceau: cas où on a une seule direction
			if (save_resul.cas_cal_plis == 3)	
			  {// choix entre la méthode historique et la nouvelle méthode
      switch (choix_methode_cal_plis_memb)
       {case 1:
          {Premie_type_calcul_en_un_pli(epsBB_tdt,delta_epsBB
                            ,sigHH_t,jacobien_0,jacobien,energ,energ_t
                            ,DepsBB,module_compressibilite,module_cisaillement
                            ,V_Pr_H,sigHH,d_sigma_deps_inter
                            ,valPropreSig,ex);
           break;
          }
        case 2:
          {Deuxieme_type_calcul_en_un_pli(epsBB_tdt,delta_epsBB
                            ,sigHH_t,jacobien_0,jacobien,energ,energ_t
                            ,DepsBB,module_compressibilite,module_cisaillement
                            ,V_Pr_H,sigHH,d_sigma_deps_inter
                            ,valPropreSig,ex);
           break;
          }
        default:
          cout << "\n cas non prevu: choix_methode_cal_plis_memb= "
               << choix_methode_cal_plis_memb ;
          Sortie(1);
          break;
      };


			  };
   
   return retour;
  };

// calcul d'une nouvelle direction de plis
// en entrée: force: = true par défaut
//            si == false -> pas de calcul de direction demandée, et mise en place
//                des indicateurs en cohérence avec le fait de ne pas faire de calcul
// en retour:
//   = -1 : pas de calcul de valeur propre possible en contrainte
//   =  1 : pas de plis (pas de calcul de nouvelle direction )
//   = -2 : pas de calcul de valeur propre de déformation 
//   = -3 : plis dans les deux sens, mais pas de calcul de direction propre valide
//   =  2 : plis dans les deux sens, calcul des directions de plis 
//   = -4 : pas de calcul de vecteurs propres possible pour les contraintes
//   =  3 : plis dans une seule directions, calcul ok
//   =  0 : erreur inconnue ??
 
int LoiCritere::Calcul_directions_plis(const TenseurBB & epsBB_tdt,const TenseurHH& sigHH
                                       ,Coordonnee2& valPropreEps
                                       ,Tableau <Coordonnee2H>& V_Pr_H
                                       ,const Met_abstraite::Umat_cont& ex
                                       ,Coordonnee2& valPropreSig
                                       , bool force
                                       )
  {// dim et vérification
   int dim_tens = abs(sigHH.Dimension());
   V_Pr_H.Change_taille(2);
   // normalement le critère ne s'applique que pour des tenseurs 2D
   #ifdef MISE_AU_POINT
   if (dim_tens != 2)
     { cout << "\n erreur le critere de plissement de membrane ne peut s'appliquer que pour des lois 2D"
            << " \n LoiCritere::Calcul_directions_plis(..";
       Sortie(1);
     };
   #endif
   
   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   int retour = 0; // init par défaut
   
   if (!force)
    // cas particulier ou on ne veut pas de calcul, mais par contre on veut mettre les indicateurs
    // cohérence avec le fait de ne pas faire de calcul
    { retour = 1; //on signale
      save_resul.eps_pli.Zero(); // pas de pli répertorié
      // comme il n'y a pas de plis, donc par de variation de largeur
      LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_1DCP2_inter // pour simplifier
                             =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
                                 (*(save_resul.liste_des_SaveResul.begin()));
      save_result_1DCP2_inter->Zero_var_largeur(); // mise à 0 de b_surb0
    }
   else
    {// on va calculer les valeurs propres relatives au tenseur des contraintes
     
     TenseurHB* sigHB = (NevezTenseurHB(dim_tens,0.));
     (*sigHB) =  sigHH * (* ex.gijBB_tdt);
     int casSig = 0; // init par défaut
     // calcul des valeurs propres correspondantes à des vecteurs propres CoordonneeH
     valPropreSig = sigHB->ValPropre(casSig);
     // si le calcul n'est pas possible on ne fait rien mais on poste un message
     if (casSig == -1)
      // ==== cas d'une erreur de valeur propre sur la contrainte ====
      { if (Permet_affichage() > 4)
          cout << "\n warning : le calcul des valeurs propres de contrainte n'a pas ete possible,"
               << " l'application du critere de plissement n'est pas possible, et donc non effectuee " << endl;
        retour = -1;
        save_resul.eps_pli.Zero(); // pas de pli répertorié
      }
     else if (valPropreSig(dim_tens) >= save_resul.niveau_declenchement_critere) // 0.)
      { // on se trouve dans le cas où rien n'est en compression, donc cas normal sans plissement
        retour = 1; //on signale
        save_resul.eps_pli.Zero(); // pas de pli répertorié
        // comme il n'y a pas de plis, donc par de variation de largeur
        LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_1DCP2_inter // pour simplifier
                               =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
                                   (*(save_resul.liste_des_SaveResul.begin()));
        save_result_1DCP2_inter->Zero_var_largeur(); // mise à 0 de b_surb0
      }
     else
      { // ==== on se trouve dans le cas où potentiellement on peut avoir des plis ====
        // on regarde les valeurs propres en déformation
       
        TenseurHB* epsHB = (NevezTenseurHB(dim_tens,0.));
        (*epsHB) = (* ex.gijHH_tdt) * epsBB_tdt;
        int casEps = 0; // init par défaut
        // calcul des valeurs propres correspondantes à des vecteurs propres CoordonneeH
        valPropreEps = epsHB->ValPropre(casEps);
        if (casEps == -1)
          { if (Permet_affichage() > 4)
              cout << "\n warning : le calcul des valeurs propres de deformation n'a pas ete possible,"
                   << " l'application du critere de plissement n'est pas possible, et donc non effectuee " << endl;
            retour = -2;
            save_resul.eps_pli.Zero(); // pas de pli répertorié
          }
        else if (valPropreEps(1) < 0.)
          // ==== cas de plis dans les deux sens ====
          {// si la plus grande des valeurs propres de déformation est négative,
           // dans ce cas il y a des plis dans les deux sens il faut que l'on récupère
           // les def des plis
         //*** il faudra grouper ce if avec le cas d'un pli de manière à éviter les erreurs de duplication ***
           // -- on doit définir un repère ortho dont le premier vecteur est celui selon lequel on fait du 1D
           // calcul des vecteurs propres
           int cas = 0; // init
             
           Tableau <Coordonnee> V_inter;
           sigHB->VecteursPropres(valPropreSig,cas, V_inter);
           // si cas = -1, la construction des vecteurs propres est impossible, on arrête le traitement
           if (cas == -1)
            {save_resul.eps_pli.Zero(); // on ne peut pas donner une intensité au def de pli !
             // les vecteurs propres sauvegardées sont nulles
             Coordonnee3 zero3; // un vecteur nul
             save_resul.V_P_sig->Change_taille(3,zero3); // en 3D qui est obligatoire ici
             retour = -3;
            }
           else
            {
             #ifdef MISE_AU_POINT
             if (Permet_affichage() > 5)
              if (Dabs(V_inter(1) * V_inter(2)) > ConstMath::petit)
               {cout << "\n== LoiCritere::Critere_plis_membrane: plis dans les deux sens ";
                //cout << "\n sigma: vecteurs propres: \n  "<< V_inter;
                cout << "\n sigma: valeurs propres: "; valPropreSig.Affiche_1(cout);
                // on va vérifier les vecteurs propres
                Coordonnee2H VpH1; VpH1.Change_val(V_inter(1));
                cout << "\n vecteur propre 1 VpH1= " << VpH1;
                Coordonnee2H VpropreH1 = (*sigHB) * VpH1;
                //cout << "\n sigHH * VH1 "<< VpropreH1;
                // comme les valeurs peuvent être très petites on régularise
                VpropreH1 /= (valPropreSig(1)+ConstMath::petit);
                cout << "\n verif: (sigHB * VH1)/(lambda1+epsilon) = "<< VpropreH1;
                CoordonneeB aB; aB.Change_val(V_inter(2));
                Coordonnee2H VpH2 = aB * (* ex.gijHH_tdt);
                cout << "\n vecteur propre 2 VpH2 "<< VpH2;
                Coordonnee2H VpropreH2 = (*sigHB) * VpH2;
                //cout << "\n sigHH * VH2 "<< VpropreH2;
                VpropreH2 /= (valPropreSig(2)+ConstMath::petit);
                cout << "\n verif: (sigHB * VH2)/(lambda2+epsilon) = "<< VpropreH2;
                cout << endl;
               };
             #endif
            
             // Le premier vecteur propre s'exprime dans la base naturelle, par contre le second s'exprime
             // dans la base duale donc : V1^H, et V2_B
             // donc si on veut un changement de base de naturelle en naturelle il faut calculer V2^H
             V_Pr_H(1).Change_val(V_inter(1)); // le premier vecteur ok
             CoordonneeB aB; aB.Change_val(V_inter(2));
             V_Pr_H(2)= aB * (* ex.gijHH_tdt);
             // pour l'instant ces vecteurs propres ne sont pas normés car les vecteurs
             // de base ne sont pas normés, on va donc les normer
             #ifdef MISE_AU_POINT
             if (Permet_affichage() > 5)
               {cout << "\n normalisation des vecteurs propres:";
               };
             #endif
             // on calcul les vecteurs propres en orthonormee
             // on définit l'espace de stockage des vecteurs propres si nécessaire
             #ifdef MISE_AU_POINT
             if (Permet_affichage() > 5)
               {cout << "\n vecteurs propres en orthonormee:";
               };
             #endif
             if (save_resul.V_P_sig == NULL)
                save_resul.V_P_sig = new Tableau <Coordonnee>;
             Coordonnee3 zero3; // un vecteur nul
             save_resul.V_P_sig->Change_taille(3,zero3); // on va calculer en 3D qui est obligatoire ici

             for (int be=1;be<3;be++) // be < 3 donc de 1 à 2
               for (int al=1;al<3;al++)
                 (*save_resul.V_P_sig)(be) += V_Pr_H(be)(al) * ex.giB_tdt->Coordo(al);
             // on norme les vecteurs après le passage en absolue (modif prise en compte)
             for (int al=1;al<3;al++) // al < 3 erreur
                {
                 #ifdef MISE_AU_POINT
                 if (Permet_affichage() > 5)
                   {cout << "\n vecteur propre ("<<al<<") local avant normalisation " << V_Pr_H(al);
                    cout << "\n vecteur propre ("<<al<<") global avant normalisation " << (*save_resul.V_P_sig)(al);
                    double norme2 = sqrt(V_Pr_H(al) * ((* ex.gijBB_tdt) *  V_Pr_H(al)));
                    cout << "\n norme locale pour verif (doit etre =  norme globale): "<< norme2;
                   };
                 #endif
                 double norme2 = (*save_resul.V_P_sig)(al).Norme();
                 (*save_resul.V_P_sig)(al) /= (norme2+ConstMath::petit);
                 // on norme également les vecteurs V_Pr_H qui vont être utilisés par le programme appelant
                 V_Pr_H(al) /= (norme2+ConstMath::petit);
                 #ifdef MISE_AU_POINT
                 if (Permet_affichage() > 5)
                 {cout << "\n vecteur propre local apres normalisation " << V_Pr_H(al);
                  cout << "\n norme VPH("<<al<<") en globale avant normalisation "<< norme2;
                  cout << "\n vecteur propre ("<<al<<") global apres normalisation " << (*save_resul.V_P_sig)(al);
                 };
                 #endif
                };
             (*save_resul.V_P_sig)(3) = Util::ProdVec_coor((*save_resul.V_P_sig)(1),(*save_resul.V_P_sig)(2));
             (*save_resul.V_P_sig)(3).Normer();// on norme le troisième vecteur *** normalement ne devrait pas être nécessaire
             retour = 2;
            };
          }
        else
          {// cas où on passe d'un comportement 2D à 1D
           Loi_comp_abstraite* loi = *(lois_internes.begin()); // pour simplifier
           // -- donc maintenant la suite concerne le cas où seule une direction est en traction
           // on va se mettre en 1D dans le repère principal de contrainte
           
           // -- on doit définir un repère ortho dont le premier vecteur est celui selon lequel on fait du 1D
           // calcul des vecteurs propres
           int cas = 0; // init
           Tableau <Coordonnee> V_inter;
           sigHB->VecteursPropres(valPropreSig,cas, V_inter);
           // si cas = -1, la construction des vecteurs propres est impossible, on arrête le traitement
           if (cas == -1)
            { if (Permet_affichage() > 4)
               cout << "\n warning : le calcul des valeurs propres de contrainte n'a pas ete possible,"
                    << " l'application du critere de plissement n'est pas possible, et donc non effectuee " << endl;
             retour = -4;
             save_resul.eps_pli.Zero(); // pas de pli répertorié
             // les vecteurs propres sauvegardées sont nulles
             Coordonnee3 zero3; // un vecteur nul
             save_resul.V_P_sig->Change_taille(3,zero3); // en 3D qui est obligatoire ici
            }
           else
            {
             #ifdef MISE_AU_POINT
             if (Permet_affichage() > 5)
               {cout << "\n== LoiCritere::Critere_plis_membrane plis dans un seul sens ";
                //cout << "\n sigma: vecteurs propres: \n  "<< V_inter;
                cout << "\n sigma: valeurs propres: "; valPropreSig.Affiche_1(cout);
                // on va vérifier les vecteurs propres
                Coordonnee2H VpH1; VpH1.Change_val(V_inter(1));
                cout << "\n vecteur propre 1 VpH1= " << VpH1;
                Coordonnee2H VpropreH1 = (*sigHB) * VpH1;
                //cout << "\n sigHH * VH1 "<< VpropreH1;
                // comme les valeurs peuvent être très petites on régularise
                VpropreH1 /= (valPropreSig(1)+ConstMath::petit);
                cout << "\n verif: (sigHB * VH1)/(lambda1+epsilon) = "<< VpropreH1;
                CoordonneeB aB; aB.Change_val(V_inter(2));
                Coordonnee2H VpH2 = aB * (* ex.gijHH_tdt);
                cout << "\n vecteur propre 2 VpH2 "<< VpH2;
                Coordonnee2H VpropreH2 = (*sigHB) * VpH2;
                //cout << "\n sigHH * VH2 "<< VpropreH2;
                VpropreH2 /= (valPropreSig(2)+ConstMath::petit);
                cout << "\n verif: (sigHB * VH2)/(lambda2+epsilon) = "<< VpropreH2;
                cout << endl;
               };
             #endif

             // Le premier vecteur propre s'exprime dans la base naturelle, par contre le second s'exprime
             // dans la base duale donc : V1^H, et V2_B
             // donc si on veut un changement de base de naturelle en naturelle il faut calculer V2^H
             V_Pr_H(1).Change_val(V_inter(1)); // le premier vecteur ok
             CoordonneeB aB; aB.Change_val(V_inter(2));
             V_Pr_H(2)= aB * (* ex.gijHH_tdt);
             // pour l'instant ces vecteurs propres ne sont pas normés car les vecteurs
             // de base ne sont pas normés, on va donc les normer
             #ifdef MISE_AU_POINT
             if (Permet_affichage() > 5)
               {cout << "\n normalisation des vecteurs propres:";
               };
             #endif
             // on calcul les vecteurs propres en orthonormee
             // on définit l'espace de stockage des vecteurs propres si nécessaire
             #ifdef MISE_AU_POINT
             if (Permet_affichage() >5)
               {cout << "\n vecteurs propres en orthonormee:";
               };
             #endif
             if (save_resul.V_P_sig == NULL) save_resul.V_P_sig = new Tableau <Coordonnee>;
             Coordonnee3 zero3; // un vecteur nul
             save_resul.V_P_sig->Change_taille(3,zero3); // on va calculer en 3D

             for (int be=1;be<3;be++) // be < 3 donc de 1 à 2
               for (int al=1;al<3;al++)
                 (*save_resul.V_P_sig)(be) += V_Pr_H(be)(al) * ex.giB_tdt->Coordo(al);
             // on norme les vecteurs après le passage en absolue
             for (int al=1;al<3;al++) // al < 3 erreur
                {
                 #ifdef MISE_AU_POINT
                 if (Permet_affichage() > 5)
                   {cout << "\n vecteur propre local avant normalisation " << V_Pr_H(al);
                    cout << "\n vecteur propre ("<<al<<") global avant normalisation " << (*save_resul.V_P_sig)(al);
                    double norme2 = sqrt(V_Pr_H(al) * ((* ex.gijBB_tdt) *  V_Pr_H(al)));
                    cout << "\n norme locale pour verif (doit etre =  norme globale): "<< norme2;
                   };
                 #endif
                 double norme2 = (*save_resul.V_P_sig)(al).Norme();
                 (*save_resul.V_P_sig)(al) /= ((norme2)+ConstMath::petit);
                 // on norme également les vecteurs V_Pr_H qui vont être utilisés par le programme appelant
                 V_Pr_H(al) /= (norme2+ConstMath::petit);
                 #ifdef MISE_AU_POINT
                 if (Permet_affichage() > 5)
                   {cout << "\n vecteur propre local apres normalisation " << V_Pr_H(al);
                    cout << "\n norme VPH("<<al<<") en globale avant normalisation "<< norme2;
                    cout << "\n vecteur propre ("<<al<<") global apres normalisation " << (*save_resul.V_P_sig)(al);
                   };
                 #endif
                };
             (*save_resul.V_P_sig)(3) = Util::ProdVec_coor((*save_resul.V_P_sig)(1),(*save_resul.V_P_sig)(2));
             (*save_resul.V_P_sig)(3).Normer();// on norme le troisième vecteur *** normalement ne devrait pas être nécessaire
             retour = 3;
            };
          };
        // on supprime les tenseurs provisoires
        delete epsHB;
      };
     // on supprime les tenseurs provisoires
     delete sigHB;
    };
   
   // mise à jour de l'indicateur dans save_resul
   save_resul.cas_cal_plis=retour;
   // affichage conditionnelle
   #ifdef MISE_AU_POINT
   if (Permet_affichage() > 4)
    {bool erreur = false;
     switch (retour)
      { case -1 : cout << "\n pas de calcul de valeur propre possible en contrainte ";erreur=true;break;
        case -2 : cout << "\n pas de calcul de valeur propre possible de deformation "; erreur=true;break;
        case -3 : cout << "\n plis dans les deux sens, mais pas de calcul de direction propre valide "; erreur=true;break;
        case -4 : cout << "\n pas de calcul de vecteurs propres possible pour les contraintes "; erreur=true;break;
        case   0 : cout << "\n erreur inconnue dans le calcul directions plis ?? "; erreur=true;break;
        default: break; // cas normal, aucun affichage
      };
    if (erreur)
      if (ptintmeca_en_cours != NULL)
         cout << " mail: "<< ptintmeca_en_cours->Nb_mail() << " ele: "<< ptintmeca_en_cours->Nb_ele()
              << " npti: "<< ptintmeca_en_cours->Nb_pti() ;
    };
   #endif
   
   // retour
   return retour;
  };


// création du conteneur UMAT a partir des vecteurs propres 
void LoiCritere::Creation_metrique_a_partir_vecteurs_propres_pour_Umat1D
   (const Met_abstraite::Umat_cont& ex,const Mat_pleine& beta )
 {
    // on va se mettre en 1D dans le repère principal de contrainte
    SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);

   // la partie dépendant des vitesses: entre accolades pour pouvoir fermer
   // ici il est nécessaire de recalculer les gradients dans la nouvelle base
   // dans le cas où ils existent
   {if (ex.gradVmoyBB_t != NULL)
      {umat_cont_1D->gradVmoyBB_t= gradVmoyBB_t_1D_P = &gradVmoyBB_t_1D;
       // on change de base
       TenseurBB* t_interBB = NevezTenseurBB(*ex.gradVmoyBB_t);
       t_interBB->ChBase(beta);
       // puis on transfert en 1D
       umat_cont_1D->gradVmoyBB_t->Affectation_trans_dimension(*t_interBB,true);
       delete t_interBB;
      };
    if (ex.gradVmoyBB_tdt != NULL)
      {umat_cont_1D->gradVmoyBB_tdt=gradVmoyBB_tdt_1D_P = &gradVmoyBB_tdt_1D;
       // on change de base
       TenseurBB* t_interBB = NevezTenseurBB(*ex.gradVmoyBB_tdt);
       t_interBB->ChBase(beta);
       // puis on transfert en 1D
       umat_cont_1D->gradVmoyBB_tdt->Affectation_trans_dimension(*t_interBB,true);
       delete t_interBB;
      };
    if (ex.gradVBB_tdt != NULL)
      {umat_cont_1D->gradVBB_tdt=gradVBB_tdt_1D_P = &gradVBB_tdt_1D;
       // on change de base
       TenseurBB* t_interBB = NevezTenseurBB(*ex.gradVBB_tdt);
       t_interBB->ChBase(beta);
       // puis on transfert en 1D
       umat_cont_1D->gradVBB_tdt->Affectation_trans_dimension(*t_interBB,true);
       delete t_interBB;
      };
   }; // fin de la partie dédiée à la vitesse

   //  -- maintenant on construit les éléments de l'Umat pour le repère ortho avec 1 seul
   //  vecteur de base, et en orthonormé
   // en fait on va construire un repère orthonormé à partir des vecteurs propres
// **** comme on considère que la base locale est orthonormé, normalement elle ne change pas
// pour l'instant on laisse sa construction, mais en fait une seule est suffisante
// ***** 2 oct 2018: je commente la ligne qui suit car en fait j'ai l'impression
// que la base change puisqu'elle vaut les directions propres et que ceux-ci dépendent
// du calcul .... là je ne comprends pas pourquoi j'ai mis le test ....
//   if ((*(umat_cont_1D->gijBB_0))(1,1) == 0.) // pour savoir si la construction a été faite on non
    { // les vecteurs propres sont considérés normés: cf. voir leurs calculs
      BaseB&  giB_tdt = *(umat_cont_1D->giB_tdt); // pour simplifier
      const Coordonnee& V_sig = (*save_resul.V_P_sig)(1); // pour simplifier
      giB_tdt.CoordoB(1).Change_val(V_sig); // on utilise un vecteur 3D, ici dans la base orthonormee
//      giB_tdt(1) = V_Pr_B(1); //.Change_val(V_sig);
//      giB_tdt(1)(1) = 1.;
      // idem pour les temps 0 et t
      *(umat_cont_1D->giB_0)=giB_tdt;
      *(umat_cont_1D->giB_t)=giB_tdt;
      // idem pour le contravariant
      BaseH&  giH_tdt = *(umat_cont_1D->giH_tdt); // pour simplifier
      // comme la base est orthonormée, H et B sont identiques
      giH_tdt.CoordoH(1).Change_val(V_sig);
//      giH_tdt(1).Change_val(V_Pr_B(1).Coor());
//      giH_tdt(1)(1) = 1.;
      *(umat_cont_1D->giH_0)=giH_tdt;
      *(umat_cont_1D->giH_t)=giH_tdt;
      // maintenant les métriques : ici identité
      (*(umat_cont_1D->gijBB_0)).Coor(1,1)=(*(umat_cont_1D->gijHH_0)).Coor(1,1)=1.;
      (*(umat_cont_1D->gijBB_t)).Coor(1,1)=(*(umat_cont_1D->gijHH_t)).Coor(1,1)=1.;
      (*(umat_cont_1D->gijBB_tdt)).Coor(1,1)=(*(umat_cont_1D->gijHH_tdt)).Coor(1,1)=1.;
      #ifdef MISE_AU_POINT
      if (Permet_affichage() > 5)
        {cout << "\n LoiCritere::Creation_metrique_a_partir_vecteurs_propres_pour_Umat1D( ";
         cout << "\n base gipB(1) "<< giB_tdt(1)
              << "\n base gipH(1) "<< giH_tdt(1);
        };
      #endif
    };
 };

  // passage des grandeurs métriques de l'ordre 3 ou 2 à 1: cas implicite
  void LoiCritere::Passage_metrique_ordre_3_2_vers_1(const Met_abstraite::Umat_cont& ex,const Mat_pleine& gamma)
{};


// chgt de repère et de dimension pour les variables de passage pour le calcul final de la loi en 1D
void LoiCritere::Passage_3ou2_vers_1(const Mat_pleine& gamma,const TenseurHH & sigHH_t
                         ,const Mat_pleine& beta
                         ,const TenseurBB& DepsBB
                         ,const TenseurBB & epsBB_tdt,const TenseurBB & delta_epsBB
                         ,const bool& deux_plis,Coordonnee2& eps_pli)
   { // on s'occupe du changement de base
     int dim_tens = abs(sigHH_t.Dimension());
     // on crée des nouveaux tenseurs au lieu d'utiliser les tenseurs initiaux, car on fait un changement de base
     // qui a pour effet de modifier le tenseur. Donc si ensuite on veut utiliser les tenseurs initiaux, ce ne sera
     // plus possible comme initialement
     if (dim_tens == 2)
      { Tenseur2HH sigHH_2_inter(sigHH_t); sigHH_2_inter.ChBase(gamma);
        sig_HH_t_1D.Affectation_trans_dimension(sigHH_2_inter,false);// passage des tenseurs résultats à l'ordre 1
        Tenseur2BB DepsBB_2_inter(DepsBB); DepsBB_2_inter.ChBase(beta);
        Deps_BB_1D.Affectation_trans_dimension(DepsBB_2_inter,false);
        Tenseur2BB epsBB_tdt_2_inter(epsBB_tdt);epsBB_tdt_2_inter.ChBase(beta);
/*

Lorsqu'il y a un pli dans une seule direction, le premier vecteur indique la direction selon laquelle la membrane est en traction. Son intensité est égale à la déformation mécanique dans cette même direction. Le second vecteur est normal à la première direction, son intensité est égale à la déformation cinématique selon cette direction, c'est-à-dire calculée à l'aide des déplacements des noeuds du maillage. Cette déformation est différente de la déformation mécanique calculée par la loi 3D, c'est-à-dire issue de la contraction de la zone, due à la traction suivant la première direction. Cette déformation mécanique peut-être récupéré via la deformation "DEF\_LARGEUR" associée à la loi de comportement.

Lorsqu'il y a des plis dans deux directions, les deux vecteurs indiquent les directions principales d'apparition de plis. L'intensité des vecteurs est égale à la déformation cinématique dans la direction associée.

Lorsqu'il n'y a pas  de plis,  l'intensité des vecteurs est nulle.

*/
       
        eps_pli(1) = epsBB_tdt_2_inter(2,2);  // on sauvegarde les def de plis
        if (deux_plis) // cas où il y aurait des plis dans les deux sens
           eps_pli(2) = epsBB_tdt_2_inter(1,1);
        else eps_pli(2) = 0.; // cas d'un seul plis
        eps_BB_1D.Affectation_trans_dimension(epsBB_tdt_2_inter,false);
        Tenseur2BB delta_epsBB_2_inter(delta_epsBB); delta_epsBB_2_inter.ChBase(beta);
        delta_eps_BB_1D.Affectation_trans_dimension(delta_epsBB_2_inter,false);
        #ifdef MISE_AU_POINT
        if (Permet_affichage() > 5)
          {cout << "\n debug LoiCritere::Passage_3ou2_vers_1( ";
           cout << "\n sigHH_t= en g_i "; sigHH_t.Ecriture(cout);
           cout << "\n sigHH_t= en vecteurs propres "<< sigHH_2_inter;
           cout << "\n epsBB_tdt en gi ";epsBB_tdt.Ecriture(cout);
           cout << "\n epsBB_tdt en vecteurs propres "<< epsBB_tdt_2_inter;
           cout << "\n epsBB 1D en local vecteurs propres " << eps_BB_1D;
           // en orthonormee
           Tenseur3BB epsBB_3_inter;
           eps_BB_1D.BaseAbsolue(epsBB_3_inter,(giH_tdt_1D));
           cout << "\n base giH_tdt_1D: "<<giH_tdt_1D;
           cout << "\n epsBB 1D =en orthonormee (contient que l'action de la composante de traction) \n "
                <<epsBB_3_inter;
           cout << "\n delta_epsBB en vecteurs propres= "<< delta_epsBB_2_inter;
           cout << endl;
          };
        #endif
      }
    else // cas 3D
      { Tenseur3HH sigHH_3_inter(sigHH_t); sigHH_3_inter.ChBase(gamma);
        sig_HH_t_1D.Affectation_trans_dimension(sigHH_3_inter,false);// passage des tenseurs résultats à l'ordre 1
        Tenseur3BB DepsBB_3_inter(DepsBB); DepsBB_3_inter.ChBase(beta);
        Deps_BB_1D.Affectation_trans_dimension(DepsBB_3_inter,false);
        Tenseur3BB epsBB_tdt_3_inter(epsBB_tdt);epsBB_tdt_3_inter.ChBase(beta);
        eps_BB_1D.Affectation_trans_dimension(epsBB_tdt_3_inter,false);
        Tenseur3BB delta_epsBB_3_inter(delta_epsBB); delta_epsBB_3_inter.ChBase(beta);
        delta_eps_BB_1D.Affectation_trans_dimension(delta_epsBB_3_inter,false);
      };
    // cas des jacobiens: il nous faut définir des jacobiens cohérents en 1D au niveau de leur
    // variation entre 0 et tdt
    // on se sert de la déformation et d'un jacobien final mis à 1. arbitrairement
    jacobien_tdt_1D = 1.; // initialisation arbitraire
    // -- maintenant on tient compte du type de déformation, et de sa valeur 11
    // sachant que le repère actuel est normé, donc le repère initial ne peut pas être normé
    // le vecteur de base est le vecteur propre
    //  en 1D la longueur est le jacobien
    switch (type_de_deformation)
    {case  DEFORMATION_STANDART :  case DEFORMATION_POUTRE_PLAQUE_STANDART :
          // cas d'une déformation d'Almansi
          {  // epsBB11 = 1/2 * (1. - (l0/l)^2), dans un repère normé, ce qui est le cas ici
             // -> l0 = l * sqrt(1. - 2.* eps11)
             jacobien_0_1D = sqrt(1.-eps_BB_1D(1,1));
          };
          break;
     case DEFORMATION_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEFORMATION_CUMU_LOGARITHMIQUE :
         // cas d'une def logarithmique ou une approximation
         // epsBB11 = log (l/l0) --> l0 = l / exp(epsBB11)
          { jacobien_0_1D = jacobien_tdt_1D / exp(eps_BB_1D(1,1));
          };
          break;
     default :
       cout << "\nErreur : type de deformation qui n'est pas actuellement pris en compte, type= "
            << Nom_type_deformation(type_de_deformation);
       cout << "\n LoiCritere::Passage_3ou2_vers_1(.. \n";
       Sortie(1);
    };
    
   };

// passage inverse: chgt de repère et de dimension pour les variables de passage
// et stockage des infos de doublement plane pour le post-traitement pour le prochain appel
// en entrée: d_sigma_deps_1D : l'opérateur qui a été calculé
// en sortie: d_sigma_deps_inter
void LoiCritere::Passage_1_vers_3ou2(const Mat_pleine& gamma,TenseurHH & sigHH
                           ,const TenseurHHHH& d_sigma_deps_1D
                           ,const Mat_pleine& beta
                           ,TenseurHHHH& d_sigma_deps_inter,const Met_abstraite::Umat_cont& ex
                           ,const Tableau <Coordonnee2H>& V_Pr_H
                           ,const Tableau <Coordonnee>& V_P_sig)
 { // on s'occupe du changement de base
   int dim_tens = abs(sigHH.Dimension());
//     if (dim_tens == 2)
//      { // normalement les contraintes sont nulles dans les directions autres que 11
//        sigHH.Affectation_trans_dimension(sig_HH_t_1D,true);
//        sigHH.ChBase(beta); // on revient dans le repère naturel
//      }
//    else // cas 3D
//      { Tenseur3HH sigHH_3_inter(sigHH_t); sigHH_3_inter.ChBase(gamma);
//        sig_HH_t_1D.Affectation_trans_dimension(sigHH_3_inter,false);// passage des tenseurs résultats à l'ordre 1
//        Tenseur3BB DepsBB_3_inter(DepsBB); DepsBB_3_inter.ChBase(gamma);
//        Deps_BB_1D.Affectation_trans_dimension(DepsBB_3_inter,false);
//        Tenseur3BB epsBB_tdt_3_inter(epsBB_tdt);epsBB_tdt_3_inter.ChBase(gamma);
//        eps_BB_1D.Affectation_trans_dimension(epsBB_tdt_3_inter,false);
//        Tenseur3BB delta_epsBB_3_inter(delta_epsBB); delta_epsBB_3_inter.ChBase(gamma);
//        delta_eps_BB_1D.Affectation_trans_dimension(delta_epsBB_3_inter,false);
//      };

   // normalement les contraintes sont nulles dans les directions autres que 11
   sigHH.Affectation_trans_dimension(sig_HH_1D,true);
   
   #ifdef MISE_AU_POINT
   if (Permet_affichage() > 5)
     {Tenseur2HH sigHH_2_inter(sigHH);
      cout << "\n LoiCritere::Passage_1_vers_3ou2(";
      cout << "\n sigHH (en VP) affecté du resultat 1D = "; sigHH.Ecriture(cout);
      // en base orthonormee
      Tenseur3HH sigHH_3_inter;
      sig_HH_1D.BaseAbsolue(sigHH_3_inter,(giB_tdt_1D));
      cout << "\n sigHH 1D =en orthonormee "<<sigHH_3_inter;
//      cout << endl;
     };
   #endif
    
//   if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//     cout << "\n test2: LoiCritere::Passage_1_vers_3ou2(... " << flush;
   // changement de base pour la contrainte
   // ici il s'agit de revenir à la base initiale il faut donc utiliser
   // l'inverse gamma c-a-d finalement beta transposée
   sigHH.ChBase(beta.Transpose()); // on revient dans le repère naturel
   
   #ifdef MISE_AU_POINT
   if (Permet_affichage() > 5)
     {Tenseur2HH sigHH_2_inter(sigHH);
//      cout << "\n debug LoiCritere::Passage_1_vers_3ou2(";
      cout << "\n sigHH en g_i après changement de base "; sigHH.Ecriture(cout);
      // en base orthonormee
      Tenseur3HH sigHH_3_inter;
      sigHH.BaseAbsolue(sigHH_3_inter,(* ex.giB_tdt));
      cout << "\n sigHH = en orthonormee "<<sigHH_3_inter;
//      cout << endl;
     };
   #endif
   
   // concernant l'opérateur tangent: pour l'instant on a un opérateur en 33, mais une seule
   // valeur est utilisée ! peut-être à changer par la suite, en tenseur 11
//   Tenseur3HHHH& d_sig_deps_3HHHH = *((Tenseur3HHHH *) &d_sigma_deps);
//   d_sig_deps_1HHHH.ChangeBase(<#TenseurHHHH &A#>, const BaseB &gi)
   if (dim_tens == 2)
      { // un tenseur de travail qui contient l'opérateur tangent, mais transporté en 2D
//   if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//     cout << "\n test3: LoiCritere::Passage_1_vers_3ou2(... " << flush;
        Tenseur2HHHH tens_travail2HHHH;
        bool plusZero=true;
        tens_travail2HHHH.Affectation_trans_dimension(*d_sigma_deps_1D_P,plusZero);
        // construction de la base qui permet de passer des vecteurs propres au gi
        // donc on veut: V_al = beta_al^be g_be
        // il se trouve que c'est égal à la matrice passée en paramètre : beta(al,be)
//   if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//     cout << "\n test4: LoiCritere::Passage_1_vers_3ou2(... " << flush;
        BaseB V_al_B(2,2,0.);
        V_al_B.CoordoB(1)(1) = beta(1,1);V_al_B.CoordoB(1)(2) = beta(1,2);
        V_al_B.CoordoB(2)(1) = beta(2,1);V_al_B.CoordoB(2)(2) = beta(2,2);

        #ifdef MISE_AU_POINT
        if (Permet_affichage() > 5)
          {//cout << "\n debug LoiCritere::Passage_1_vers_3ou2(";
           // vérif du calcul de la base
          // cout << "\n BaseB des gi \n "<< (* ex.giB_tdt);
           cout << "\n construction d'une BaseB V_al_B pour cgt base tenseurHHHH \n "<< V_al_B;
           // calcul long
           BaseB V_inter_B(2,2,0.);
           for (int al = 1;al < 3; al++)
             for (int be = 1; be < 3; be++)
               V_inter_B.CoordoB(al)(be) = (* ex.giH_tdt).Coordo(be) * V_P_sig(al);
           cout << "\n BaseB V_inter_B "<< V_inter_B;

           // pour voir si la base est correcte on la teste sur le tenseur des contraintes
           Tenseur2HH sigHH_2_inter;
           // on exprime sigHH dans la base des V_P qui ici est considéré comme absolue pour la vérif
           sig_HH_1D.BaseAbsolue(sigHH_2_inter,V_al_B);
           cout << "\n verif via sig_HH_1D = dans la base des gi de nouveau \n "<<sigHH_2_inter;
//           cout << endl;
          };
        #endif

        // on fait le changement de base
        Tenseur2HHHH* d_sig_deps_2HHHH = ((Tenseur2HHHH *) &d_sigma_deps_inter);
//        d_sig_deps_2HHHH->ChangeBase(tens_travail2HHHH,gi_al_B);
        tens_travail2HHHH.ChangeBase(*d_sig_deps_2HHHH,V_al_B);
      }
    else // cas 3D
      { //if (d_sigma_deps_inter == NULL)
         // d_sigma_deps_inter = NevezTenseurHHHH(3);
        // la suite dépendra de l'application donc du critère, donc on met un message
        // pour l'instant
        cout << "\n pour l'instant la suite n'est pas codee !! se plaindre !! "
             << "\n LoiCritere::Passage_1_vers_3ou2(..." << endl;
        Sortie(2);
      };
//   if  ((ParaGlob::NiveauImpression() > 8) || (Permet_affichage() > 5))
//     cout << "\n test7: LoiCritere::Passage_1_vers_3ou2(... " << flush;


   };

       // 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 LoiCritere::RepercuteChangeTemperature(Enum_dure temps)
  { list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
    for (ili=lois_internes.begin();ili!=ilifin;ili++) 
      {(*ili)->temperature_0 = this->temperature_0;
       (*ili)->temperature_t = this->temperature_t;
       (*ili)->temperature_tdt = this->temperature_tdt;
       (*ili)->dilatation=dilatation;
       
       // on répercute également les déformations thermiques, qui ne sont utilisées
       // telles quelles que pour certaines lois: ex: loi hyper-élastique
       if (dilatation)
          {//  a- dimensionnement des tenseurs intermédiaires 
           int dim_tens = epsBB_therm->Dimension();
               // -- cas de la déformation
           if ((*ili)->epsBB_therm == NULL) { (*ili)->epsBB_therm = NevezTenseurBB(dim_tens);}
           else if ((*ili)->epsBB_therm->Dimension() != dim_tens)
              { delete (*ili)->epsBB_therm;(*ili)->epsBB_therm = NevezTenseurBB(dim_tens);};
               // -- cas de la vitesse de déformation
           if ((*ili)->DepsBB_therm == NULL) { (*ili)->DepsBB_therm = NevezTenseurBB(dim_tens);}
           else if ((*ili)->DepsBB_therm->Dimension() != dim_tens)
            { delete (*ili)->DepsBB_therm;(*ili)->DepsBB_totale = NevezTenseurBB(dim_tens);};
           // b- affectation des tenseurs
           (*(*ili)->epsBB_therm)=(*epsBB_therm);
           (*(*ili)->DepsBB_therm)=(*DepsBB_therm);
          };

       (*ili)->RepercuteChangeTemperature(temps);
       
       switch (temps)
         { case TEMPS_0: {(*ili)->temperature = &(*ili)->temperature_0; break;}
           case TEMPS_t: {(*ili)->temperature = &(*ili)->temperature_t; break;}
           case TEMPS_tdt: {(*ili)->temperature = &(*ili)->temperature_tdt; break;}
           default:
             { cout << "\n erreur, cas de temps non prevu !! "
                    << "\n LoiCritere::RepercuteChangeTemperature(...";
               Sortie(1);      
              };
         };
      };
   }; 
   
// fonction surchargée dans les classes dérivée si besoin est
void LoiCritere::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
          )
  { if (avec_ponderation)
      { // on passe en revue les grandeurs servant au calcul des fonctions de proportion
        list <Ponderation >::iterator il,ilfin=list_ponderation.end();
        list <double>::iterator ipfonc = fonc_ponder.begin();
        for (il=list_ponderation.begin();il != ilfin;il++,ipfonc++)
         { Ponderation& ponder = (*il); // pour simplifier
           (*ipfonc)=1.; // init
           int taille = ponder.Type_grandeur().Taille();
           for (int i=1;i<= taille; i++)
            { // calcul des pondérations
              if (ponder.Valeur_aux_noeuds()(i)) // pour l'instant que des ddl patentés !
               // cas d'une proportion provenant d'une interpolation aux noeuds
               { double grand = def.DonneeInterpoleeScalaire(ponder.Type_grandeur()(i).Enum(),temps);
                 double fonc = ponder.C_proport()(i)->Valeur(grand);
                 (*ipfonc) *= fonc; // on accumule multiplicativement
               }
              else
               // sinon il s'agit d'une grandeur directement accessible au point d'intégration
               // pour l'instant il n'y a pas de procédure générale de récupération, seulement des cas particuliers
               { 
                // deux cas suivant que l'on a affaire à un ddl de base ou à un vrai ddl étendu
                if (ponder.Type_grandeur()(i).Nom_vide())
                 {switch (ponder.Type_grandeur()(i).Enum())
                  { case PROP_CRISTA:
                      { const double* taux_crita = dTP.TauxCrista();
                        if (taux_crita != NULL)
                          {	double fonc = ponder.C_proport()(i)->Valeur(*taux_crita);
                           (*ipfonc) *= fonc; // on accumule multiplicativement
                          }
                        else
                          {cout << "\n erreur, le taux de cristalinite n'est pas disponible au point d'integration "
                                << " il n'est pas possible de calculer la proportion pour la loi des melanges "
                                << "\n LoiCritere::CalculGrandeurTravail(.... ";
                          }; 	
                        break;
                      }
                    default:
                       cout << "\n erreur, le type de proportion " << ponder.Type_grandeur()(i) << " n'est pas disponible "
                            << " pour l'instant au point d'integration ! "
                            << "\n LoiCritere::CalculGrandeurTravail(.... ";
                  };
                 }
                else
                 {// cas d'un vrai ddl étendue
                  switch (ponder.Type_grandeur()(i).Position()-NbEnum_ddl())
                  {case 87: // cas de "def_equivalente"
                     {const double def_equivalente  =  ptintmeca.Deformation_equi_const()(1); // recup de la def equi
                      double fonc = ponder.C_proport()(i)->Valeur(def_equivalente);
                      (*ipfonc) *= fonc; // on accumule multiplicativement
            //cout << "\n defEqui= " << def_equivalente << " fonct= " << fonc << " ";									 
                      break;
                     }
                   case 88: // cas de "def_duale_mises_maxi"
                      {const double def_duale_mises_maxi  =  ptintmeca.Deformation_equi_const()(3); // recup de la def equi
                       double fonc = ponder.C_proport()(i)->Valeur(def_duale_mises_maxi);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       break;
                      }
                   case 89: // cas de "vitesse_def_equivalente"
                      {const double delta_def_equivalente  =  ptintmeca.Deformation_equi_const()(4); // recup du delta def equi
                       // recup de l'incrément de temps
                       double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
                       double unSurDeltat=0;    
                       if (Abs(deltat) >= ConstMath::trespetit)
                       {unSurDeltat = 1./deltat;}
                       else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
                       { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
                         if (unSurDeltat < 0)
                         { cout << "\n le pas de temps est négatif !! "; };
                         unSurDeltat = ConstMath::tresgrand;
                       };
                       double vitesse_def_equi = 	delta_def_equivalente * unSurDeltat;
                       double fonc = ponder.C_proport()(i)->Valeur(vitesse_def_equi);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
             //cout << "\n vit= " << vitesse_def_equi << " f= " << fonc << endl;									 
                       break;
                      }
                   case 77: // cas de "def_duale_mises"
                      {const double def_duale_mises  =  ptintmeca.Deformation_equi_const()(2); // recup de la def equi
                       double fonc = ponder.C_proport()(i)->Valeur(def_duale_mises);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       break;
                      }
                   case 78: // cas de "Spherique_eps"
                      {const Vecteur &  epsInvar   = ptintmeca.EpsInvar_const(); // recup des invariants
                       double spherique_eps = epsInvar(1); 
                       double fonc = ponder.C_proport()(i)->Valeur(spherique_eps);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       break;
                      }
                   case 81: // cas de "Spherique_sig"
                      {const Vecteur &  sigInvar   = ptintmeca.SigInvar_const(); // recup des invariants
                       double spherique_sig = sigInvar(1); 
                       double fonc = ponder.C_proport()(i)->Valeur(spherique_sig);
                       (*ipfonc) *= fonc; // on accumule multiplicativement
                       break;
                      }
                   default:
                       cout << "\n erreur, le type de proportion " << ponder.Type_grandeur()(i)
                            << " n'est pas disponible "
                            << " pour l'instant au point d'integration ! "
                            << "\n LoiCritere::CalculGrandeurTravail(.... ";
                   break;
                   };
                 };			  	
               };
            };
         };
      };
    // enregistrement dans les variables spécifiques au point calculé
    SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
    save_resul.f_ponder = fonc_ponder;
    // on initialise le niveau de déclanchement avec les grandeurs de la lois
    // si la valeur est différente de 0, sinon ce sera 1.
//    if (niveau_declenchement_critere != 0.)
//      {save_resul.niveau_declenchement_critere = niveau_declenchement_critere;}
//    else
//      {save_resul.niveau_declenchement_critere = 1.;};
    // init par défaut
    save_resul.niveau_declenchement_critere = niveau_declenchement_critere;

    if (avecNiveauSigmaI_mini_pour_plis)
      {// on initialise le niveau de déclanchement avec les grandeurs de la lois
       // si la valeur est différente de 0, sinon ce sera 1.
       // car en multiplication, si on par de 0 cela donnera toujours 0
//       if (niveau_declenchement_critere == 0.)
//         {save_resul.niveau_declenchement_critere = 1.;};
       // non on ne fait pas cela sinon c'est compliqué à comprendre
       // donc si on est dans un niveau réglable, systématiquement on met 1.
       // ce qui fait que l'on a directement la valeur de la fonction
       save_resul.niveau_declenchement_critere = 1.;
      
       if (niveauF_fct_nD != NULL)
         { // on appel la fonction générique
           list <SaveResul*> list_save; // inter pour l'appel de la fonction
           list_save.push_back(saveResul);
         
          Tableau <double> &  tab = Loi_comp_Valeur_FnD_Evoluee
                                      (niveauF_fct_nD->C_proport(),1
                                       ,ex_impli,ex_expli_tdt,ex_umat
                                       ,exclure_dd_etend,exclure_Q
                                       ,&list_save
                                      );
         
//           // comme il s'agit d'une grandeur globale, on n'a pas besoin de la récupérer
//           double fonc = niveauF_fct_nD->C_proport()->Valeur_pour_variables_globales()(1);
//           save_resul.niveau_declenchement_critere *= fonc;

           save_resul.niveau_declenchement_critere *= tab(1);

         };
       if (niveauF_temps != NULL) // cas d'une dépendance au temps
         { const VariablesTemps& var_temps = ParaGlob::Variables_de_temps();
           double fonc = niveauF_temps->Valeur(var_temps.TempsCourant());
           save_resul.niveau_declenchement_critere *= fonc;
         };
       // avec une dépendance via éventuellement un ddl étendu
       if (niveauF_ddlEtendu != NULL)
         { Ponderation& ponder = *niveauF_ddlEtendu; // pour simplifier
           double fonc_finale = 1.; // init
           int taille = ponder.Type_grandeur().Taille();
           for (int i=1;i<= taille; i++)
             { // calcul des pondérations
               if (ponder.Valeur_aux_noeuds()(i)) // pour l'instant que des ddl patentés !
                 // cas d'une proportion provenant d'une interpolation aux noeuds
                 { double grand = def.DonneeInterpoleeScalaire(ponder.Type_grandeur()(i).Enum(),temps);
                   double fonc = ponder.C_proport()(i)->Valeur(grand);
                   fonc_finale *= fonc; // on accumule multiplicativement
                 }
               else
                 // sinon il s'agit d'une grandeur directement accessible au point d'intégration
                 // pour l'instant il n'y a pas de procédure générale de récupération, seulement des cas particuliers
                 { 
                  // deux cas suivant que l'on a affaire à un ddl de base ou à un vrai ddl étendu
                  if (ponder.Type_grandeur()(i).Nom_vide())
                   {switch (ponder.Type_grandeur()(i).Enum())
                    { case PROP_CRISTA:
                        { const double* taux_crita = dTP.TauxCrista();
                          if (taux_crita != NULL)
                            {	double fonc = ponder.C_proport()(i)->Valeur(*taux_crita);
                              fonc_finale *= fonc; // on accumule multiplicativement
                            }
                          else
                            {cout << "\n erreur, le taux de cristalinite n'est pas disponible au point d'integration "
                                  << " il n'est pas possible de calculer le niveau_declenchement_critere "
                                  << "\n LoiCritere::CalculGrandeurTravail(.... ";
                            }; 	
                          break;
                        }
                      default:
                         cout << "\n erreur, le type  " << ponder.Type_grandeur()(i) << " n'est pas disponible "
                              << " pour l'instant au point d'integration ! "
                              << "\n LoiCritere::CalculGrandeurTravail(.... ";
                    };
                   }
                  else
                   {// cas d'un vrai ddl étendue
                    switch (ponder.Type_grandeur()(i).Position()-NbEnum_ddl())
                    {case 87: // cas de "def_equivalente"
                       {const double def_equivalente  =  ptintmeca.Deformation_equi_const()(1); // recup de la def equi
                        double fonc = ponder.C_proport()(i)->Valeur(def_equivalente);
                        fonc_finale *= fonc; // on accumule multiplicativement
                        break;
                       }
                     case 88: // cas de "def_duale_mises_maxi"
                       {const double def_duale_mises_maxi  =  ptintmeca.Deformation_equi_const()(3); // recup de la def equi
                        double fonc = ponder.C_proport()(i)->Valeur(def_duale_mises_maxi);
                        fonc_finale *= fonc; // on accumule multiplicativement
                        break;
                       }
                     case 89: // cas de "vitesse_def_equivalente"
                       {const double delta_def_equivalente  =  ptintmeca.Deformation_equi_const()(4); // recup du delta def equi
                        // recup de l'incrément de temps
                        double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
                        double unSurDeltat=0;    
                        if (Abs(deltat) >= ConstMath::trespetit)
                        {unSurDeltat = 1./deltat;}
                        else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
                        { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
                          if (unSurDeltat < 0)
                          { cout << "\n le pas de temps est négatif !! "; };
                          unSurDeltat = ConstMath::tresgrand;
                        };
                        double vitesse_def_equi = 	delta_def_equivalente * unSurDeltat;
                        double fonc = ponder.C_proport()(i)->Valeur(vitesse_def_equi);
                        fonc_finale *= fonc; // on accumule multiplicativement
                        break;
                       }
                     case 77: // cas de "def_duale_mises"
                       {const double def_duale_mises  =  ptintmeca.Deformation_equi_const()(2); // recup de la def equi
                        double fonc = ponder.C_proport()(i)->Valeur(def_duale_mises);
                        fonc_finale *= fonc; // on accumule multiplicativement
                        break;
                       }
                     case 78: // cas de "Spherique_eps"
                       {const Vecteur &  epsInvar   = ptintmeca.EpsInvar_const(); // recup des invariants
                        double spherique_eps = epsInvar(1); 
                        double fonc = ponder.C_proport()(i)->Valeur(spherique_eps);
                        fonc_finale *= fonc; // on accumule multiplicativement
                        break;
                       }
                     case 81: // cas de "Spherique_sig"
                       {const Vecteur &  sigInvar   = ptintmeca.SigInvar_const(); // recup des invariants
                        double spherique_sig = sigInvar(1); 
                        double fonc = ponder.C_proport()(i)->Valeur(spherique_sig);
                        fonc_finale *= fonc; // on accumule multiplicativement
                        break;
                       }
                     default:
                        cout << "\n erreur, le type  " << ponder.Type_grandeur()(i)
                             << " n'est pas disponible "
                             << " pour l'instant au point d'integration ! "
                             << "\n LoiCritere::CalculGrandeurTravail(.... ";
                     break;
                    };
                   };			  	
                 };
               };
           // on met à jour le niveau
           save_resul.niveau_declenchement_critere *= fonc_finale;
         };
      };
	  
    // répercution sur les classes dérivées si besoin est
    list <SaveResul*>::iterator isave=save_resul.liste_des_SaveResul.begin(); // pour les saveResul des lois
    list <Loi_comp_abstraite *>::const_iterator ili,ilifin=lois_internes.end();
	   for (ili=lois_internes.begin();ili!=ilifin;ili++,isave++)
       {// passage des informations spécifique à la loi liste_des_SaveResul
         (*ili)->IndiqueSaveResult(*isave);  		  
         (*ili)->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
         (*ili)->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours
		       (*ili)->CalculGrandeurTravail(ptintmeca,def,temps,dTP
                                      ,ex_impli,ex_expli_tdt,ex_umat,exclure_dd_etend,exclure_Q);
       };
  };

// fonction critère de plissement de biel
// en entrée:
// implicit : si oui on est en implicite, sinon en explicite
// retour:
//  0  : il y a eu un pb que l'on n'a pas peu résoudre, rien n'a été modifié
//  1  : le critère n'a rien modifié
//  2  : l'application du critère conduit à une contrainte et un opérateur tangent nul
int LoiCritere::Critere_plis_biel(bool en_base_orthonormee,TenseurHH & sigHH_t,TenseurBB& DepsBB
            ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB,double& jacobien_0,double& jacobien
		  	       ,TenseurHH& sigHH,TenseurHHHH& d_sigma_deps_inter
		  	       ,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite
            ,double&  module_cisaillement
		  	       ,bool implicit,const Met_abstraite::Umat_cont& ex)
  {// dim et vérification
   int dim_tens = abs(sigHH.Dimension());
   // normalement le critère ne s'applique que pour des tenseurs 1D
   #ifdef MISE_AU_POINT
   if (dim_tens != 1)
     { cout << "\n erreur le critere de plissement de biel ne peut s'appliquer que pour des lois 1D"
            << " \n LoiCritere::Critere_plis_biel(..";
       Sortie(1);
     };
   #endif
        
   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   
   // on va utiliser la valeur de la contrainte, par contre on la ramène dans un repère normé
   // pour son intensité ce qui revient à calculer la trace du tenseur
   double sig_I = sigHH && (* ex.gijBB_tdt);
   int retour = 0; // init par défaut
   if (sig_I >= niveau_declenchement_critere) // pas de plis
    { // on se trouve dans le cas où rien n'est en compression, donc cas normal sans plissement
      retour = 1; //on signale
      save_resul.eps_pli.Zero(); // pas de pli répertorié
    }
   else
    { // on se trouve dans le cas où on a  des plis
    
      // l'idée est de ce positionner au niveau du seuil de déclenchement, pour cela on va utiliser
      // un facteur multiplicatif de manière à pouvoir conserver un opérateur tangent cohérent avec le seuil
      // (si on impose dans une boucle de Newton, la contrainte on va récupérer une def méca et un opérateur
      //  tangent par rapport à cette def méca. Du coup on ne pourra pas en déduire un opérateur tangent par
      //  rapport à la def cinématique ...)
//      double rapport = niveau_declenchement_critere / (Dabs(sig_I)+ConstMath::pasmalpetit);
    
    
    
    
      // on annule la contrainte et sa contribution éventuelle à la raideur
      sigHH.Inita(0.);
      d_sigma_deps_inter.Inita(0.); // dans le cas explicite, ne sert à rien mais c'est rapide
      // comme marqueur de l'intensité des plis on utilise la def de compression
      save_resul.eps_pli(1) = epsBB_tdt && (* ex.gijHH_tdt);
      // d'autre part on définit le vecteur propre normé qui n'est autre que gi_1 normé
      int dim = ParaGlob::Dimension();
      if (save_resul.V_P_sig == NULL)
         save_resul.V_P_sig = new Tableau <Coordonnee>;
      Coordonnee zero(dim); // un vecteur nul
      save_resul.V_P_sig->Change_taille(2); // on n'a besoin que d'un vecteur
          // **** mais  pour l'instant j'en mets 2 de manière à être cohérent avec les membranes
          // sinon pb en sortie des grandeurs
      Coordonnee inter = ex.giB_tdt->Coordo(1);
      (*save_resul.V_P_sig)(1)= inter.Normer();
      retour = 2;
    };

   return retour;
  };


  // récupération de la variation relative d'épaisseur calculée: h/h0
  //  cette variation n'est utile que pour des lois en contraintes planes
  // - pour les lois 3D : retour d'un nombre très grand, indiquant que cette fonction est invalide
  // - pour les lois 2D def planes: retour de 0
  // les infos nécessaires à la récupération , sont stockées dans saveResul
  // qui est le conteneur spécifique au point où a été calculé la loi
double LoiCritere::HsurH0(SaveResul * saveResul) const
{  SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   switch (type_critere)
    {  case PLISSEMENT_MEMBRANE:
        { // traitement des épaisseurs
          LoiContraintesPlanes::SaveResul_LoiContraintesPlanes * save_result_plan_inter // pour simplifier
                             =  (LoiContraintesPlanes::SaveResul_LoiContraintesPlanes *)
                                 (*(save_resul.liste_des_SaveResul.begin()));
          return save_result_plan_inter->hsurh0;
         break;
        }
       case PLISSEMENT_BIEL:
        { LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_1DCP2_inter // pour simplifier
                             =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
                                 (*(save_resul.liste_des_SaveResul.begin()));
          return save_result_1DCP2_inter->hsurh0;
         break;
        }
       default :
         cout << "\nErreur : LoiCritere::HsurH0(.. non implante pour le critere " << Nom_Critere_Loi(type_critere)
              << "  !\n";
         Sortie(1);
    };



};


 // premier type de calcul dans le cas d'un pli dans une seule direction
void LoiCritere::Premie_type_calcul_en_un_pli(const TenseurBB & epsBB_tdt,const TenseurBB & delta_epsBB
                          ,const TenseurHH & sigHH_t
                          ,const double& jacobien_0,const double& jacobien
                          ,EnergieMeca & energ,const EnergieMeca & energ_t
                          ,const TenseurBB& DepsBB
                          ,double& module_compressibilite,double&  module_cisaillement
                          ,const Tableau <Coordonnee2H>& V_Pr_H
                          ,TenseurHH& sigHH,TenseurHHHH& d_sigma_deps_inter
                          ,const Coordonnee2& valPropreSig
                          ,const Met_abstraite::Umat_cont& ex)
{
  SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
  // les coordonnées des vecteurs propres sont exprimées dans l'ancienne base
  // on a donc
  //    Vi_B(i) = gpB(i) = beta(i,j) * gB(j), i indice de ligne, j indice de colonne
 
  Mat_pleine beta(2,2);
  for (int i=1;i<3;i++) // < 3 donc de 1 à 2
   for (int j=1;j<3;j++)
     beta(i,j) = V_Pr_H(i)(j);
  Mat_pleine gamma(beta.Inverse().Transpose()); // on calcule la matrice inverse
  // la matrice gamma correspond à la matrice de changement de base des g^i au gpH
  // gamma est  l'inverse transposée
  // gpH(i) = gamma(i,j) * gH(j), i indice de ligne, j indice de colonne
  //   c-a-d= gp^i = gamma^i_j * g^j
 
  // on va également définir une matrice de changement pour les tenseurs 3D
  Tableau <Coordonnee3H> V_Pr3D_H(3);
  // comme V_Pr est de dim 2, il faut transférer les coordonnées
  V_Pr3D_H(1)(1) = V_Pr_H(1)(1);V_Pr3D_H(1)(2) = V_Pr_H(1)(2);
  V_Pr3D_H(2)(1) = V_Pr_H(2)(1);V_Pr3D_H(2)(2) = V_Pr_H(2)(2);
  // le troisième est en local 0,0,1
  V_Pr3D_H(3)(3) = 1.;
  Mat_pleine beta3D(3,3);// initialisée à 0
  // d'abord les 2 vecteurs propres
  for (int i=1;i<3;i++)
   for (int j=1;j<4;j++)
     beta3D(i,j) = V_Pr3D_H(i)(j);
  // puis la normale
  beta3D(3,3) = 1.;
  Mat_pleine gamma3D(beta3D.Inverse().Transpose());
 

  #ifdef MISE_AU_POINT
  // pour tester, on passe les contraintes dans le repère principal
  if (Permet_affichage() > 5)
    {Tenseur2HH sigHH_2_inter(sigHH);
     cout << "\n utilisation du repere ortho des vecteurs propres: V_P ";
     cout << "\n sigHH= en giB : "; sigHH.Ecriture(cout);
     cout << "\n base giB(1) "<< (* ex.giB_tdt)(1)
          << "\n base giB(2) "<< (* ex.giB_tdt)(2);
     // en base orthonormee
     Tenseur3HH sigHH_3_inter;
     sigHH.BaseAbsolue(sigHH_3_inter,(* ex.giB_tdt));
//             TenseurHH* ptHH = NevezTenseurHH((*(*isig)));
//             (*(*isig)).BaseAbsolue(*ptHH,giB);
     cout << "\n sigHH= en absolue 3D : "<<sigHH_3_inter;
     cout << "\n chgt de base: Vi_B(i) = gpB(i) = beta(i,j) * gB(j) --> beta= ";beta.Affiche();
     cout << "\n sigHH_2_inter avant chgt= "<< sigHH_2_inter;
     sigHH_2_inter.ChBase(gamma,false);
     cout << "\n sigHH= en V_P : "<< sigHH_2_inter;
     // on revient à la base de départ pour vérifier que l'opération inverse ne pose
     // pas de pb
     sigHH_2_inter.ChBase(beta.Transpose(),false);
     cout << "\n verif: sigHH après retour au repère initial giB: ";
     sigHH_2_inter.Ecriture(cout);
     //cout << "\n gamma * beta = "; (gamma * beta).Affiche();
     cout << "\n vecteurs propres en 3D ortho: "; //<< (*save_resul.V_P_sig);
     cout << "\n VP1  "<< (*save_resul.V_P_sig)(1);
     cout << "\n VP2 "<< (*save_resul.V_P_sig)(2);
     cout << "\n VP3 "<< (*save_resul.V_P_sig)(3);
     // vérif des vecteurs propres
     Coordonnee3B VpB1; VpB1.Change_val((*save_resul.V_P_sig)(1));
     Coordonnee3H VpropreH1 = sigHH_3_inter * VpB1;
     //cout << "\n sigHH_3_inter * VP1 "<< VpropreH1;
     VpropreH1 /= (valPropreSig(1)+ConstMath::petit);
     cout << "\n (sigHH_3_ortho * VP1) / (lambda1+epsilon)= "<< VpropreH1;
     Coordonnee3B VpB2; VpB2.Change_val((*save_resul.V_P_sig)(2));
     Coordonnee3H VpropreH2 = sigHH_3_inter * VpB2;
     //cout << "\n sigHH_3_inter * VP2 "<< VpropreH2;
     VpropreH2 /= (valPropreSig(2)+ConstMath::petit);
     cout << "\n (sigHH_3_ortho * VP2) / (lambda2+epsilon)= "<< VpropreH2;
    };
  #endif
         
{      // --il faut créer un save_result pour l'appel des contraintes doublement planes
      // on récupère le conteneur qui bien qu'associé à une loi CP, est également
      // en réalité un conteneur CP2 car c'est comme cela qu'il a été créé via
      //  LoiCritere::LoiCritere::New_et_Initialise()
//*** là il va falloir revoir cette partie, car en fait ce n'est pas sûr qui faut utiliser un conteneur intermédiaire
//*** cela pose pas mal de pb, car il faut de nouveau mettre à jour les infos du conteneur initial, dans le cas des lois
//*** incrémentales, or pour l'instant ce n'est pas fait, ça c'est une erreur
/* *** l'idée initiale était que l'utilisation du 1D était transitoire en particulier d'une itération à l'autre.
donc supposons qu'à une itération on ait un plis dans une direction, on change toutes les grandeurs tensorielles en fonction
de cette direction (par exemple les tenseurs de ref) et donc à l'itération suivante on n'aura plus le même état de démarrage.
Mais ... en fait on remet les choses dans le repère initial à la fin du traitement:
save_resul.save_result_1DCP2->ChBase_des_grandeurs(gamma3D);
donc dans ce cas là, je ne comprends pas pourquoi on utilise pas directement le conteneur initial
Pour l'instant, je laisse en l'état (25 nov 2015) et après la réunion avec le CNES, je vais faire les tests en incrémental et modifier
car c'est possible qu'il y a quelque chose qui m'échappe.
Par contre à minima je remets les def de largeur, dans le conteneur initial
*/
}

     
  LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_1DCP2_inter // pour simplifier
                         =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
                             (*(save_resul.liste_des_SaveResul.begin()));
  // on affecte les grandeurs à un conteneur de travail
  if (save_resul.save_result_1DCP2 == NULL)
      { SaveResul * inter = save_result_1DCP2_inter->Nevez_SaveResul();
        save_resul.save_result_1DCP2 = ((LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble*) inter);
      }
  else // sinon on peut affecter directement
      *(save_resul.save_result_1DCP2) = *((Loi_comp_abstraite::SaveResul *) save_result_1DCP2_inter);

  // . -- changement de repère pour venir dans le nouveau repère ortho
  // on change toutes les infos tensorielles contenues pour qu'elles soient exprimées dans le nouveau repère
  // ceci ne concerne pas les grandeurs scalaires et les grandeurs exprimées dans le repère global
 
  // là il faut utiliser une matrice 3x3 car on a systématiquement des grandeurs 3D, car la loi interne est 3D
  save_resul.save_result_1DCP2->ChBase_des_grandeurs(beta3D,gamma3D);
 
  // il faut initialiser les métriques en 1D à null, pour qu'elles soient recalculer systématiquement car par exemple
  // la métrique à 0 change d'une itération à l'autre et d'un incrément à l'autre
  {Deformation::Stmet met_ref_00,met_ref_t,met_ref_tdt; // def de métrique vide, qui vont être construite pendant le calcul
   save_resul.save_result_1DCP2->Affectation_metriques_locale(met_ref_00,met_ref_t,met_ref_tdt);
  };
 
  loi_1DCP2_de_3D->IndiquePtIntegMecaInterne(ptintmeca_en_cours); // on transmet le ptintmeca global
  loi_1DCP2_de_3D->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours
  loi_1DCP2_de_3D->IndiqueSaveResult(save_resul.save_result_1DCP2); // on indique à la loi le conteneur qu'il faut utiliser
////-- debug --
{//#ifdef MISE_AU_POINT
//if ( save_resul.save_result_1DCP2->meti_ref_00.giB_ != NULL)
//  cout << "\n debug Critere_plis_membrane ";
//#endif
////-- fin debug --
      // -- appel du programme de contraintes doublement planes -> récup des résultats dans le nouveau repère
// 7 nov 2018: ?? normalement on est en base orthonormée !      bool base_orthonormee = false;
}
  bool base_orthonormee = true;
  // conditionnnement de la nouvelle métrique
  Creation_metrique_a_partir_vecteurs_propres_pour_Umat1D(ex,beta);
  // chgt de variable pour les autres variables de passage: contrainte, def, D, delta eps ...
 
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
   {
     //cout << "\n debug LoiCritere::Critere_plis_membrane(";
//     for (int a=1; a<4;a++)
//      {cout << "\n giH_0("<<a<<"): "; (*(umat_cont_1D->giB_0))(a).Affiche();
//       cout << "\n giH_0("<<a<<"): "; (*(umat_cont_1D->giB_0))(a).Affiche();
//      };
     cout << "\n epsBB initial en local 2D "; epsBB_tdt.Ecriture(cout);
     // en orthonormee
     Tenseur3BB epsBB_3_inter;
     epsBB_tdt.BaseAbsolue(epsBB_3_inter,*(ex.giH_tdt));
     cout << "\n epsBB d'entrée =en orthonormee "<<epsBB_3_inter;
     cout << endl;
    }
  #endif
 
  bool deux_plis = false;
  Passage_3ou2_vers_1(gamma,sigHH_t,beta,DepsBB,epsBB_tdt
                     ,delta_epsBB,deux_plis,save_resul.eps_pli);
 
  // avant le calcul on initialise l'énergie
  energ.Inita(0.); // car sinon on cumule l'énergie sans plis et avec plis !!
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
     cout << "\n LoiCritere::Critere_plis_membrane ==> calcul en 1D CP2";
  #endif
  loi_1DCP2_de_3D->Calcul_dsigma_deps(base_orthonormee,sig_HH_t_1D,Deps_BB_1D
                            ,eps_BB_1D,delta_eps_BB_1D,jacobien_0_1D,jacobien_tdt_1D
                            ,sig_HH_1D,d_sigma_deps_1D,energ,energ_t,module_compressibilite, module_cisaillement
                            ,*umat_cont_1D);

  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 4)
   {  if (Permet_affichage() > 5)
        {cout << "\n\n ... LoiCritere::Critere_plis_membrane apres CP2: ";
         cout << "\n sig_HH_1D "<< sig_HH_1D;
         cout << "\n d_sigma_deps_1D "<< d_sigma_deps_1D;
        };
      if ((!isfinite(d_sigma_deps_1D(1,1,1,1))) || (isnan(d_sigma_deps_1D(1,1,1,1))) )
           {cout << "\n *** attention d_sigma_deps_3D(1,1,1,1)= "<< d_sigma_deps_1D(1,1,1,1);
            if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
            cout << "\n LoiCritere::Critere_plis_membrane ==> calcul en 1D CP2";
            cout << flush;
//// --- pour le débug
//  loi_1DCP2_de_3D->Calcul_dsigma_deps(base_orthonormee,sig_HH_t_1D,Deps_BB_1D
//                            ,eps_BB_1D,delta_eps_BB_1D,jacobien_0_1D,jacobien_tdt_1D
//                            ,sig_HH_1D,d_sigma_deps_1D,energ,energ_t,module_compressibilite, module_cisaillement
//                            ,*umat_cont_1D);
//// ---fin debug
           };
      Tenseur1HH deltasigHH = (d_sigma_deps_1D && delta_eps_BB_1D);
      cout << "\n deltasigHH "<< deltasigHH;
      cout << endl;
   };
  #endif
  if (Permet_affichage() > 4)
    if (//(sig_HH_1D(1,1) <= -1.)||
        (std::isinf(sig_HH_1D(1,1)))||( std::isnan(sig_HH_1D(1,1))))
     {cout << "\n *** attention sig_HH_1D(1,1) negatif ou infinie (debug LoiCritere::Critere_plis_membrane(.. \n";
      cout << sig_HH_1D(1,1)
           << endl;
      cout << "\n ***** erreur detectee : on continue quand meme ... ";
//      Sortie(2);
     };
 
  // -- passage des résultats: sig, dsig, module, énergies dans l'ancien repère
  // passage inverse: chgt de repère et de dimension pour les variables de passage
  // et stockage des infos de doublement plane pour le post-traitement pour le prochain appel
  Passage_1_vers_3ou2(gamma,sigHH,d_sigma_deps_1D
                      ,beta,d_sigma_deps_inter,ex,V_Pr_H
                      ,*(save_resul.V_P_sig));
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
   {  cout << "\n apres Passage_1_vers_3ou2, suite LoiCritere::Critere_plis_membrane";
      cout << "\n sigHH en giB: "; sigHH.Ecriture(cout);
      cout << "\n d_sigma_deps_inter en giB: ";d_sigma_deps_inter.Ecriture(cout);
      Tenseur2HH deltasigHH = (d_sigma_deps_inter && delta_epsBB);
      cout << "\n deltasig2HH en giB: "<< deltasigHH;
      cout << endl;
   };
  #endif
         
  if (Permet_affichage() > 4)
    for (int al = 1; al<3;al++)
     for (int be=1;be<3;be++)
       if (//(sigHH(al,be) < 0.)||
           (std::isinf(sigHH(al,be))||( std::isnan(sigHH(al,be)))))
         {cout << "\n *** attention (sigHH("<<al<<","<<be
               << ")="<< sigHH(al,be) << " nan debug LoiCritere::Critere_plis_membrane( \n";
          cout << "\n ***** erreur detectee : on continue quand meme ... ";
         };
  // -- mise à jour du save_result de contraintes planes avec celui des doublements planes en tenant
  //    compte du chgt de repère
//*** ça ce sera à revoir: cf. la remarque plus haut ***
  save_resul.save_result_1DCP2->ChBase_des_grandeurs(beta3D,gamma3D);
  // on met à jour les  def de largeur et d'épaisseur sur le conteneur initial
  save_result_1DCP2_inter->Transfert_var_hetb(*save_resul.save_result_1DCP2);

};

 // deuxième type de calcul dans le cas d'un pli dans une seule direction
void LoiCritere::Deuxieme_type_calcul_en_un_pli
                         (const TenseurBB & epsBB_tdt,const TenseurBB & delta_epsBB
                          ,const TenseurHH & sigHH_t
                          ,double& jacobien_0,double& jacobien
                          ,EnergieMeca & energ,const EnergieMeca & energ_t
                          ,const TenseurBB& DepsBB
                          ,double& module_compressibilite,double&  module_cisaillement
                          ,const Tableau <Coordonnee2H>& V_Pr_H
                          ,TenseurHH& sigHH,TenseurHHHH& d_sigma_deps_inter
                          ,const Coordonnee2& valPropreSig
                          ,const Met_abstraite::Umat_cont& ex
                         )
{
  SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
  // le conteneur Met_abstraite::Umat_cont& ex correspond à une métrique 2D
  // il nous faut l'équivalent en 3D, on se sert de la loi cp et de la méthode ad hoc
  const Met_abstraite::Umat_cont* ex3D = loi_2DCP_de_3D->Passage_metrique_ordre2_vers_3(ex);
  // en fait le repère 2D a été complété par la normale aux 2 premiers vecteurs
 
  // -- en entrée on connait la direction des vecteurs propres de contrainte
  //    correspondant au calcul sans prise en compte de pli
  // on va calculer les bases associées: ViB et ViH: ici 3 vecteurs en 3D
  // a) ViH = les vecteurs en contravariant: c'est en fait = V_Pr_H pour
  //    les 2 premiers vecteurs
  // mais on doit passer de 2D en 3D, manuellement
  ViH.CoordoH(1)(1) = V_Pr_H(1)(1);ViH.CoordoH(1)(2) = V_Pr_H(1)(2);
  ViH.CoordoH(1)(3) = 0.; // normalement pas de composante suivant la normale
  ViH.CoordoH(2)(1) = V_Pr_H(2)(1);ViH.CoordoH(2)(2) = V_Pr_H(2)(2);
  ViH.CoordoH(2)(3) = 0.; // normalement pas de composante suivant la normale
  // pour le 3 ième vecteur on se sert des grandeurs sauvegardées
  for (int i=1;i<4;i++) // < 4 donc de 1 à 3
      ViH.CoordoH(3)(i) = (*save_resul.V_P_sig)(3) * ex3D->giH_tdt->Coordo(i);
  // b) ViB -> là il faut les calculer
  //    on choisit d'utiliser les grandeurs stockées qui représentent les
  //    les vecteurs orthonormées
  for (int j=1;j<4;j++)
    for (int i=1;i<4;i++) // < 4 donc de 1 à 3
      ViB.CoordoB(j)(i) = (*save_resul.V_P_sig)(j) * ex3D->giB_tdt->Coordo(i);
 
  // on calcul les def de plis : save_resul.eps_pli
  Mat_pleine beta(2,2);
  for (int i=1;i<3;i++) // < 3 donc de 1 à 2
   for (int j=1;j<3;j++)
     beta(i,j) = V_Pr_H(i)(j);
  Mat_pleine gamma(beta.Inverse().Transpose()); // on calcule la matrice inverse
  Tenseur2BB epsBB_tdt_2_inter(epsBB_tdt);epsBB_tdt_2_inter.ChBase(beta);
  save_resul.eps_pli(1) = epsBB_tdt_2_inter(2,2);  // on sauvegarde les def de plis
  save_resul.eps_pli(2) = 0.; // cas d'un seul plis

 
  #ifdef MISE_AU_POINT
  // pour tester et afficher: calcul des matrices de changement de base
  if (Permet_affichage() > 5)
    {// les coordonnées des vecteurs propres sont exprimées dans l'ancienne base
     // on a donc
     //    Vi_B(i) = gpB(i) = beta(i,j) * gB(j), i indice de ligne, j indice de colonne
     
//     Mat_pleine beta(2,2);
//     for (int i=1;i<3;i++) // < 3 donc de 1 à 2
//      for (int j=1;j<3;j++)
//        beta(i,j) = V_Pr_H(i)(j);
     Mat_pleine gamma(beta.Inverse().Transpose()); // on calcule la matrice inverse
     // la matrice gamma correspond à la matrice de changement de base des g^i au gpH
     // gamma est  l'inverse transposée
     // gpH(i) = gamma(i,j) * gH(j), i indice de ligne, j indice de colonne
     //   c-a-d= gp^i = gamma^i_j * g^j
     
     // on va également définir une matrice de changement pour les tenseurs 3D
     Tableau <Coordonnee3H> V_Pr3D_H(3);
     // comme V_Pr est de dim 2, il faut transférer les coordonnées
     V_Pr3D_H(1)(1) = V_Pr_H(1)(1);V_Pr3D_H(1)(2) = V_Pr_H(1)(2);
     V_Pr3D_H(2)(1) = V_Pr_H(2)(1);V_Pr3D_H(2)(2) = V_Pr_H(2)(2);
     // le troisième est en local 0,0,1
     V_Pr3D_H(3)(3) = 1.;
     Mat_pleine beta3D(3,3);// initialisée à 0
     // d'abord les 2 vecteurs propres
     for (int i=1;i<3;i++)
      for (int j=1;j<4;j++)
        beta3D(i,j) = V_Pr3D_H(i)(j);
     // puis la normale
     beta3D(3,3) = 1.;
     Mat_pleine gamma3D(beta3D.Inverse().Transpose());
     Tenseur2HH sigHH_2_inter(sigHH);
     cout << "\n utilisation du repere ortho des vecteurs propres: V_P ";
     cout << "\n sigHH= en giB : "; sigHH.Ecriture(cout);
     cout << "\n base giB(1) "<< (* ex3D->giB_tdt)(1)
          << "\n base giB(2) "<< (* ex3D->giB_tdt)(2);
     // en base orthonormee
     Tenseur3HH sigHH_3_inter;
     sigHH.BaseAbsolue(sigHH_3_inter,(* ex3D->giB_tdt));
     cout << "\n sigHH= en absolue 3D : "<<sigHH_3_inter;
     cout << "\n chgt de base: Vi_B(i) = gpB(i) = beta(i,j) * gB(j) --> beta= ";beta.Affiche();
     cout << "\n sigHH_2_inter avant chgt= "<< sigHH_2_inter;
     sigHH_2_inter.ChBase(gamma,false);
     cout << "\n sigHH= en V_P : "<< sigHH_2_inter;
     // on revient à la base de départ pour vérifier que l'opération inverse ne pose
     // pas de pb
     sigHH_2_inter.ChBase(beta.Transpose(),false);
     cout << "\n verif: sigHH après retour au repère initial giB: ";
     sigHH_2_inter.Ecriture(cout);
     //cout << "\n gamma * beta = "; (gamma * beta).Affiche();
     cout << "\n vecteurs propres en 3D ortho: "; //<< (*save_resul.V_P_sig);
     cout << "\n VP1  "<< (*save_resul.V_P_sig)(1);
     cout << "\n VP2 "<< (*save_resul.V_P_sig)(2);
     cout << "\n VP3 "<< (*save_resul.V_P_sig)(3);
     // vérif des vecteurs propres
     Coordonnee3B VpB1; VpB1.Change_val((*save_resul.V_P_sig)(1));
     Coordonnee3H VpropreH1 = sigHH_3_inter * VpB1;
     //cout << "\n sigHH_3_inter * VP1 "<< VpropreH1;
     VpropreH1 /= (valPropreSig(1)+ConstMath::petit);
     cout << "\n (sigHH_3_ortho * VP1) / (lambda1+epsilon)= "<< VpropreH1;
     Coordonnee3B VpB2; VpB2.Change_val((*save_resul.V_P_sig)(2));
     Coordonnee3H VpropreH2 = sigHH_3_inter * VpB2;
     //cout << "\n sigHH_3_inter * VP2 "<< VpropreH2;
     VpropreH2 /= (valPropreSig(2)+ConstMath::petit);
     cout << "\n (sigHH_3_ortho * VP2) / (lambda2+epsilon)= "<< VpropreH2;
    };
  #endif
 
  LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_1DCP2_inter // pour simplifier
                         =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
                             (*(save_resul.liste_des_SaveResul.begin()));
 
  loi_1DCP2_de_3D->IndiqueSaveResult(save_result_1DCP2_inter); // on indique à la loi le conteneur qu'il faut utiliser
  loi_1DCP2_de_3D->IndiquePtIntegMecaInterne(ptintmeca_en_cours); // on transmet le ptintmeca global
  loi_1DCP2_de_3D->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours
  bool base_orthonormee = false; // ici on va travailler avec les gi
  // on utilise donc la métrique passée en paramètre
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
    {
     //cout << "\n debug LoiCritere::Critere_plis_membrane(";
//     for (int a=1; a<4;a++)
//      {cout << "\n giH_0("<<a<<"): "; (*(umat_cont_1D->giB_0))(a).Affiche();
//       cout << "\n giH_0("<<a<<"): "; (*(umat_cont_1D->giB_0))(a).Affiche();
//      };
     cout << "\n epsBB initial en local 2D "; epsBB_tdt.Ecriture(cout);
     // en orthonormee
     Tenseur3BB epsBB_3_inter;
     epsBB_tdt.BaseAbsolue(epsBB_3_inter,*(ex.giH_tdt));
     cout << "\n epsBB d'entrée =en orthonormee "<<epsBB_3_inter;
     cout << endl;
    }
  #endif
  
  // passage des informations liées à la déformation  de 2 vers 3
 Passage_deformation_contrainte_ordre2_vers_3(DepsBB,epsBB_tdt,delta_epsBB,sigHH_t);
  // avant le calcul on initialise l'énergie
  energ.Inita(0.); // car sinon on cumule l'énergie sans plis et avec plis !!
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
    {
     cout << "\n LoiCritere::Critere_plis_membrane ==> calcul en 3D CP2";
    }
  #endif
  loi_1DCP2_de_3D->Calcul_dsigma_deps
                                   (base_orthonormee,&ViB,&ViH,sig_HH_t_3D,Deps_BB_3D
                                    ,eps_BB_3D,delta_eps_BB_3D,jacobien_0,jacobien
                                    ,sig_HH_3D,d_sig_deps_3D_HHHH
                                    ,energ,energ_t
                                    ,module_compressibilite,module_cisaillement
                                    ,*ex3D);

  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
   {  cout << "\n\n ... LoiCritere::Deuxieme_type_calcul_en_un_pli apres CP2: ";
      cout << "\n sigHH_3D en giB: "; sig_HH_3D.Ecriture(cout);
      if (Permet_affichage() > 6)
        {cout << "\n d_sig_deps_3D_HHHH en giB: ";d_sig_deps_3D_HHHH.Ecriture(cout);};
      Tenseur3HH deltasigHH = (d_sig_deps_3D_HHHH && delta_eps_BB_3D);
      cout << "\n deltasig3HH en giB: "<< deltasigHH;
      cout << endl;
   };
  #endif
 
  if (Permet_affichage() > 4)
   {bool erreur = false;
    for (int al = 1; al<4;al++)
     for (int be=1;be<4;be++)
       if (//(sigHH(al,be) < 0.)||
           (std::isinf(sig_HH_3D(al,be))||( std::isnan(sig_HH_3D(al,be)))))
         {cout << "\n *** attention (sigHH_3D("<<al<<","<<be
               << ")="<< sig_HH_3D(al,be) << " valeur nan  LoiCritere::Critere_plis_membrane( \n"
               << "\n LoiCritere::Deuxieme_type_calcul_en_un_pli apres CP2:.. \n";
          erreur = true;
         };
    if (erreur)
      {cout << "\n sigHH= ";sig_HH_3D.Ecriture(cout);
       cout << "\n **** erreur nan sur loi critere !! **** on continue quand meme ... ";
//       Sortie(2);
      };
   };
 
  // passage des informations liées à la nouvelle contrainte de 2 vers 3
  // et à l'opérateur tangent : méthode 2
// non !! pas de mise à jour --> // mise à jour de save_resul.eps_pli
// *** a supprimer le passage de save_resul.eps_pli
// car c'est une erreur

 
  bool deux_plis = false;
  Passage_contrainte_et_operateur_tangent_ordre2_vers_3
              (sigHH,d_sigma_deps_inter,deux_plis,save_resul.eps_pli);
  #ifdef MISE_AU_POINT
  if (Permet_affichage() > 5)
   {  cout << "\n retour en dim 2 :  ";
      cout << "\n sigHH en giB: "; sigHH.Ecriture(cout);
      cout << "\n d_sig_deps_HHHH en giB: ";d_sigma_deps_inter.Ecriture(cout);
      Tenseur2HH deltasigHH = (d_sigma_deps_inter && delta_epsBB);
      cout << "\n deltasig2HH en giB: "<< deltasigHH;
      cout << endl;
   };
  #endif
 
};


// fonction pre_critère de plissement de membrane
// dans le cas d'un critère pli (plutôt seconde méthode), l'incrément de déformation
// dépend de la situation précédente: avec pli ou pas
// du coup on utilise un delta_eps intermédiaire au lieu du delta cinématique
// ce deltat_eps doit être précalculé
// en entrée:
// implicit : si oui on est en implicite, sinon en explicite
// retour:
void LoiCritere::Pre_Critere_plis_membrane
           (TenseurBB & epsBB_tdt_,TenseurBB & delta_epsBB
            ,const Met_abstraite::Expli_t_tdt* ex_expli
            ,const Met_abstraite::Impli* ex_impli
            ,const Met_abstraite::Umat_cont* ex_umat
           )
 { // on commence par récupérer les métriques en fonctions du conteneur ex valide
   const Tenseur2HH * gijHH_;   //   pour simplifier
   const Tenseur2BB * gijBB_;   //   "      "  "  "
   const Tenseur2HH * gijHH_t_;  //   "      "  "  "
   const Tenseur2BB * gijBB_t_;  //   "      "  "  "
   if (ex_expli != NULL)
    { gijHH_ = ((Tenseur2HH*) ex_expli->gijHH_tdt); //   pour simplifier
      gijBB_ = ((Tenseur2BB*) ex_expli->gijBB_tdt); //   "      "  "  "
      gijHH_t_ = ((Tenseur2HH*) ex_expli->gijHH_t); //   "      "  "  "
      gijBB_t_ = ((Tenseur2BB*) ex_expli->gijBB_t); //   "      "  "  "
    }
   else if (ex_impli != NULL)
    { gijHH_ = ((Tenseur2HH*) ex_impli->gijHH_tdt); //   pour simplifier
      gijBB_ = ((Tenseur2BB*) ex_impli->gijBB_tdt); //   "      "  "  "
      gijHH_t_ = ((Tenseur2HH*) ex_impli->gijHH_t); //   "      "  "  "
      gijBB_t_ = ((Tenseur2BB*) ex_impli->gijBB_t); //   "      "  "  "
    }
   else if (ex_umat != NULL)
    { gijHH_ = ((Tenseur2HH*) ex_umat->gijHH_tdt); //   pour simplifier
      gijBB_ = ((Tenseur2BB*) ex_umat->gijBB_tdt); //   "      "  "  "
      gijHH_t_ = ((Tenseur2HH*) ex_umat->gijHH_t); //   "      "  "  "
      gijBB_t_ = ((Tenseur2BB*) ex_umat->gijBB_t); //   "      "  "  "
    }
   else
    {cout << "\n **** erreur: pas de conteneur de metrique disponible ..."
          << "\n LoiCritere::Pre_Critere_plis_membrane(...";
     Sortie(1);
    };

   const Tenseur2HH & gijHH = *gijHH_; //   pour simplifier
   const Tenseur2BB & gijBB = *gijBB_; //   "      "  "  "
   const Tenseur2HH & gijHH_t = *gijHH_t_; //   "      "  "  "
   const Tenseur2BB & gijBB_t = *gijBB_t_; //   "      "  "  "
  
   // et la déformation
   const Tenseur2BB & epsBB_tdt = *((Tenseur2BB*) &epsBB_tdt_); //   "      "  "  "
 
   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
   int retour = 0; // init par défaut
   LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_1DCP2_inter // pour simplifier
                         =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
                             (*(save_resul.liste_des_SaveResul.begin()));

   // l'objectif est de mettre à jour : delta_eps_BB_2D
   delta_eps_BB_2D = delta_epsBB; // initialisation par défaut
  
   // on regarde l'état précédent: sans plis, avec un pli, avec 2 plis ?
   int cas_cal_plis_t = save_resul.cas_cal_plis_t;
   // en fait seule les cas avec un deux plis, sans erreur, sont exploitables
   // ou le cas sans pli, pour tous les autres cas, on considèrera qu'il n'y avait pas de plis
   // car les infos sauvegardées (def méca) ne sont pas correctes
   switch (save_resul.cas_cal_plis_t)
    { case -1: case 1: case -2: case -3: case -4:// pas de plis
        {// a priori rien à faire, delta_eps_BB_2D a déjà été initialisée
         break;
        }
      case 2: case 3: // plis dans une seule directions ou dans deux directions
        { // L'incrément de déformation, entre t et t+dt est obtenu par la différence entre les
          // déformations t+dt et les déformations mécaniques à t, transportée de manière cohérente
          // avec la dérivée de Jauman à  t+dt:  1/2 deux fois covariant + deux fois contra
          // a) on commence par récupérer les def méca à l'instant t
          Tenseur3BB& eps_mecaBB_t = *((Tenseur3BB*) (save_result_1DCP2_inter->eps_mecaBB_t));
          // la déformation 33 est directement gérée par la loi 2D CP via les variations d'épaisseurs
          // sachant que l'axe 3 est indépendant des deux autres axes donc on ne s'en occupe pas
          eps_BB_2D_t.Affectation_3D_a_2D(eps_mecaBB_t);
          // b) on fait le transport cohérent avec Jauman
          eps_HH_2D_t = gijHH_t * eps_BB_2D_t * gijHH_t;
          delta_epsBB = epsBB_tdt - 0.5 * (gijBB * eps_HH_2D_t * gijBB + eps_BB_2D_t);
         break;
        }
      case 0:
        // cas où aucun calcul n'a encore été effectué on n'a rien n'a faire
        break;
      default: // normalement n'arrive jamais car Calcul_directions_plis a toujours une solution diff de 0
        { cout << "\n *** cas d'erreur inconnue dans le calcul de la direction des plis "
               << " save_resul.cas_cal_plis= "<< save_resul.cas_cal_plis
               << "\n LoiCritere::Pre_Critere_plis_membrane(... ";
          Sortie(1);
          break;
        }
    };
 };

// passage des informations liées à la déformation  de 2 vers 3
void LoiCritere::Passage_deformation_contrainte_ordre2_vers_3
                  (const TenseurBB& DepsBB,const TenseurBB & epsBB_tdt
                   ,const TenseurBB & delta_epsBB,const TenseurHH&  sig_HH_t)

 { // on complète avec des 0
   bool plusZero = true;
   Deps_BB_3D.Affectation_2D_a_3D(*((Tenseur2BB*) &DepsBB),plusZero);
   eps_BB_3D.Affectation_2D_a_3D(*((Tenseur2BB*) &epsBB_tdt),plusZero);
   delta_eps_BB_3D.Affectation_2D_a_3D(*((Tenseur2BB*) &delta_epsBB),plusZero);
   sig_HH_t_3D.Affectation_2D_a_3D(*((Tenseur2HH*) &sig_HH_t),plusZero);
};

// passage des informations liées à la nouvelle contrainte de 2 vers 3
// et à l'opérateur tangent : méthode 2
void LoiCritere::Passage_contrainte_et_operateur_tangent_ordre2_vers_3
                     (TenseurHH&  sig_HH_tdt_,TenseurHHHH& d_sig_deps_HHHH_
                     ,const bool& deux_plis,Coordonnee2& eps_pli)
{ // normalement les directions 1 et 2 sont identiques en 2D et 3D
  // on recopie donc simplement les grandeurs
  Tenseur2HH & sigHH = *((Tenseur2HH*) &sig_HH_tdt_);  //   "      "  "  "
  sigHH.Affectation_3D_a_2D(sig_HH_3D);
  // idem pour l'opérateur tangent
  Tenseur2HHHH & d_sig_deps_HHHH =  *((Tenseur2HHHH*) &d_sig_deps_HHHH_); // pour simplifier
  d_sig_deps_HHHH.TransfertDunTenseurGeneral(d_sig_deps_3D_HHHH);
 
/* Lorsqu'il y a un pli dans une seule direction, le premier vecteur indique la direction selon laquelle la membrane est en traction. Son intensité est égale à la déformation mécanique dans cette même direction. Le second vecteur est normal à la première direction, son intensité est égale à la déformation cinématique selon cette direction, c'est-à-dire calculée à l'aide des déplacements des noeuds du maillage. Cette déformation est différente de la déformation mécanique calculée par la loi 3D, c'est-à-dire issue de la contraction de la zone, due à la traction suivant la première direction. Cette déformation mécanique peut-être récupéré via la deformation "DEF\_LARGEUR" associée à la loi de comportement.

Lorsqu'il y a des plis dans deux directions, les deux vecteurs indiquent les directions principales d'apparition de plis. L'intensité des vecteurs est égale à la déformation cinématique dans la direction associée.

Lorsqu'il n'y a pas  de plis,  l'intensité des vecteurs est nulle.

*/

//--- modif 24 sept 2020:
// les def pour les plis ont déjà été calculées dans LoiCritere::Passage_3ou2_vers_1(..
// et il s'agit uniquement de def cinématique donc la suite n'est pas nécessaire et même incorrecte

//   SaveResul_LoiCritere & save_resul = *((SaveResul_LoiCritere*) saveResul);
//   LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble * save_result_1DCP2_inter // pour simplifier
//                         =  (LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble *)
//                             (*(save_resul.liste_des_SaveResul.begin()));
//   Tenseur3BB& eps_mecaBB = *((Tenseur3BB*) (save_result_1DCP2_inter->eps_mecaBB));
//
//   eps_pli(1) = eps_mecaBB(2,2);  // on sauvegarde les def de plis
//   if (deux_plis) // cas où il y aurait des plis dans les deux sens
//        eps_pli(2) = eps_mecaBB(1,1);
//   else eps_pli(2) = 0.; // cas d'un seul plis
//   Tenseur3BB& eps_P_mecaBB = *((Tenseur3BB*) (save_result_1DCP2_inter->eps_P_mecaBB));
//
//   eps_pli(1) = eps_P_mecaBB(2,2);  // on sauvegarde les def de plis
//   if (deux_plis) // cas où il y aurait des plis dans les deux sens
//        eps_pli(2) = eps_P_mecaBB(1,1);
//   else eps_pli(2) = 0.; // cas d'un seul plis

};







