// FICHIER : LoiContraintesPlanesDouble.cp
// CLASSE : LoiContraintesPlanesDouble


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


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

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

#include "LoiContraintesPlanesDouble.h"


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

// constructeur  par défaut à ne pas utiliser
LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble() :
    LoiContraintesPlanes::SaveResul_LoiContraintesPlanes()
    ,def_P(),def_P_t()
    ,bsurb0(0.),b_tsurb0(0.),d_bsurb0()
    ,meti_ref_00(0,0),meti_ref_t(0,0),meti_ref_tdt(0,0)

  { cout << "\n erreur, le constructeur par defaut ne doit pas etre utilise !"
	        << "\n LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble()";
    Sortie(1);
  }; 

// le constructeur courant
LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble
                        (SaveResul* l_des_SaveResul):
    LoiContraintesPlanes::SaveResul_LoiContraintesPlanes(l_des_SaveResul)
    ,def_P(),def_P_t()
    ,bsurb0(0.),b_tsurb0(0.),d_bsurb0()
    ,meti_ref_00(),meti_ref_t(),meti_ref_tdt() // les références sont en 3D, mais on init à null
	 { if (l_des_SaveResul != NULL) le_SaveResul = l_des_SaveResul->Nevez_SaveResul();
    // par défaut les contraintes sont en dim 3
    l_sigoHH=NevezTenseurHH(3,0);
    // idem interHH,  par défaut les contraintes sont en dim 3
    l_sigoHH_t =NevezTenseurHH(3,0.);
  }; 

// constructeur de copie 
LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble
                                         (const LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble& sav ):
 LoiContraintesPlanes::SaveResul_LoiContraintesPlanes(sav)
 ,def_P(sav.def_P),def_P_t(sav.def_P_t)
 ,bsurb0(sav.bsurb0),b_tsurb0(sav.b_tsurb0),d_bsurb0()
 ,meti_ref_00(),meti_ref_t(),meti_ref_tdt()
	 { // les métriques peuvent être non affectées au début, c'est seulement lors de leurs utilisations
    // qu'elles seront affectées aux bonnes dimmensions
    if ( sav.meti_ref_00.giB_ != NULL)
       meti_ref_00 = sav.meti_ref_00;
    if ( sav.meti_ref_t.giB_ != NULL)
       meti_ref_t = sav.meti_ref_t;
    if ( sav.meti_ref_tdt.giB_ != NULL)
       meti_ref_tdt = sav.meti_ref_tdt;
  };
	        // destructeur
LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::~SaveResul_LoiContraintesPlanesDouble()
  {
  };
  
// affectation
Loi_comp_abstraite::SaveResul &
     LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::operator = ( const Loi_comp_abstraite::SaveResul & a)
  { LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble& sav
                      = *((LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble*) &a);

    // tout d'abord on s'occupe des infos de contraintes planes
    this->LoiContraintesPlanes::SaveResul_LoiContraintesPlanes::operator=(a);
    meti_ref_00 = sav.meti_ref_00;
    meti_ref_t = sav.meti_ref_t;
    meti_ref_tdt = sav.meti_ref_tdt;
    def_P = sav.def_P;def_P_t=sav.def_P_t;
    bsurb0 = sav.bsurb0;
    b_tsurb0 = sav.b_tsurb0;
//    d_hsurh0 = sav.d_hsurh0;
    d_bsurb0 = sav.d_bsurb0;
    return *this;
  };

     //============= lecture écriture dans base info ==========
     
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::Lecture_base_info
                                                 (ifstream& ent,const int cas)
  {  // ici toutes les données sont toujours a priori variables
     // ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
     string toto; ent >> toto;
     #ifdef MISE_AU_POINT	 	 
      if (toto != "S_C_Plane_D")
          { cout << "\n erreur en lecture du conteneur pour la loi de contrainte plane generique "
                 << " \n LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::Lecture_base_info(..";
            Sortie(1);     
          }
     #endif
     // on lit d'abord la loi contrainte plane
     SaveResul_LoiContraintesPlanes::Lecture_base_info(ent,cas);
     // ensuite les éléments spécifiques à la contrainte plane double
     ent >> toto >> b_tsurb0;
     bsurb0 = b_tsurb0; // puis init au cas où de la valeur à tdt
     ent >> toto >> def_P_t;  def_P=def_P_t;
     switch (cas)
      { case 1 :
          ent >> toto ;
          if (toto == "meti_ref_00") // là c'est affecté
             ent >>  meti_ref_00 ;
          ent >> toto;
          if (toto == "meti_ref_t") // là c'est affecté
             ent >> meti_ref_t ;
          break;
        case 2 :
 // -- on test --       
 //         ent >> nom >>  meti_t ;
          break;
          
        default:
           cout << "\n cas non considere !!: cas= " << cas 
                << "\n   LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::Lecture_base_info (...";
           Sortie(1);
      };
  };

// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::Ecriture_base_info
                                                 (ofstream& sort,const int cas)
   {  // ici toutes les données sont toujours a priori variables
      // ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
      sort << "\n S_C_Plane_D  ";
      // on écrit d'abord la loi contrainte plane
      SaveResul_LoiContraintesPlanes::Ecriture_base_info(sort,cas);
      // ensuite les éléments spécifiques à la contrainte plane double
      sort << " b_tsurb0 " << b_tsurb0; // la variation de largeur
      sort << " def_P " << def_P_t;
      // on ne sauvegarde que ce qui est à 0 et à t, ce qui est à tdt est considéré une zone de travail
      switch (cas)
       { case 1 :
           // les métriques peuvent être non affectées au début, c'est seulement lors de leurs utilisations
           // qu'elles seront affectées aux bonnes dimmensions
           if ( meti_ref_00.giB_ != NULL)
             { sort << "meti_ref_00 "<< meti_ref_00 << " ";}
           else
             { sort << "meti_ref_00_pas_affectee  ";}
           if ( meti_ref_t.giB_ != NULL)
              { sort << "meti_ref_t "<< meti_ref_t << " ";}
           else
             { sort << "meti_ref_t_pas_affectee  ";}
           break;
         case 2 :
  // -- on test --       
  //         sort << " SaveDefResul: ";
  //         sort << " meti_t: " << meti_t << " ";
           break;
         default:
            cout << "\n cas non considere !!: cas= " << cas 
                 << "\n   LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::Ecriture_base_info(...";
            Sortie(1);
       };

	 };
	        
	  // mise à jour des informations transitoires en définitif s'il y a convergence 
	  // par exemple (pour la plasticité par exemple)
void LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::TdtversT()
  { // appel de la méthode de CP
    SaveResul_LoiContraintesPlanes::TdtversT();
    // les données particulières à CPD2
    meti_ref_t = meti_ref_tdt;
    b_tsurb0 = bsurb0;
    def_P_t = def_P;
//    d_hsurh0.Zero(); // on initialise le vecteur tangent
//    h_tsurh0 = hsurh0; // -- idem pour la largeur
    d_bsurb0.Zero(); //          "
	};

void LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::TversTdt()
  { // appel de la méthode de CP
    SaveResul_LoiContraintesPlanes::TversTdt();
    // les données particulières à CPD2
    meti_ref_tdt = meti_ref_t;
    bsurb0 = b_tsurb0;
    def_P = def_P_t;
    d_bsurb0.Zero(); // on initialise le vecteur tangent
//    h_tsurh0 = hsurh0; // -- idem pour la largeur
//    d_hsurh0.Zero(); //          "
	};
			  
// affichage à l'écran des infos
void LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::Affiche() const
{ cout << "\n SaveResul_LoiContraintesPlanesDouble: " ;
  // d'abord la classe sup
  SaveResul_LoiContraintesPlanes::Affiche();
  // puis les données particulières à CPD2
  cout << "\n b_tsurb0 "<< b_tsurb0 << " def_P_t " << def_P_t <<" ";
  cout << "\n meti_ref_00: " << meti_ref_00 << " meti_ref_t " << meti_ref_t
        << " meti_ref_tdt " << meti_ref_tdt <<" ";
  cout << "\n -- partie relative a la loi interne: ";
  le_SaveResul->Affiche();

  cout << "\n .. fin SaveResul_LoiContraintesPlanesDouble:.. \n" ;
};

//changement de base de toutes les grandeurs internes tensorielles stockées
// beta(i,j) represente les coordonnees de la nouvelle base naturelle gpB dans l'ancienne gB
// gpB(i) = beta(i,j) * gB(j), i indice de ligne, j indice de colonne
// gpH(i) = gamma(i,j) * gH(j)
void LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::ChBase_des_grandeurs(const Mat_pleine& beta,const Mat_pleine& gamma)
{ // on appelle la classe mere
  LoiContraintesPlanes::SaveResul_LoiContraintesPlanes::ChBase_des_grandeurs(beta,gamma);
  // les vecteurs sont un moyen de stockage mais pas dépendant de la base, donc pas de chgt de coordonnées
};

// procedure permettant de completer éventuellement les données particulières
// de la loi stockées
// au niveau du point d'intégration par exemple: exemple: un repère d'anisotropie
// completer est appelé apres sa creation avec les donnees du bloc transmis
// peut etre appeler plusieurs fois
Loi_comp_abstraite::SaveResul* LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble
         ::Complete_SaveResul(const BlocGen & bloc, const Tableau <Coordonnee>& tab_coor
                             ,const Loi_comp_abstraite* loi)
  {// on transmet au conteneur 3D interne
   const LoiContraintesPlanesDouble * loi_CP = (const LoiContraintesPlanesDouble*) loi;
   le_SaveResul->Complete_SaveResul(bloc,tab_coor,loi_CP->lois_interne);
   return this;
  };

	        // ---- récupération d'information: spécifique à certaine classe dérivée
double LoiContraintesPlanesDouble::SaveResul_LoiContraintesPlanesDouble::Deformation_plastique()
   { cout << "\n pour l'instant cette option n'est pas implante dans le cas d'une loi"
          << "\n contrainte plane quelconque "
          << "\n double Loi_comp_abstraite::SaveResul_LoiContraintesPlanesDouble::Deformation_plastique()";
     Sortie(1);
     return 0.; // pour taire le warning, mais on ne passe jamais là
   };

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

LoiContraintesPlanesDouble::LoiContraintesPlanesDouble ()  : // Constructeur par defaut
  Loi_comp_abstraite(LOI_CONTRAINTES_PLANES_DOUBLE,RIEN_CATEGORIE_LOI_COMP,1)
  ,type_de_contrainte(RIEN_CONTRAINTE_MATHEMATIQUE),fac_penal(30.),prec(0.005)
  ,lois_interne(NULL)
  ,alg_zero(),maxi_delta_var_eps_sur_iter_pour_Newton(0.1)
  ,sortie_post(0),calcul_en_3D_via_direction_quelconque(false)
  ,d_sig_ef_gh(2,2),d_eps_ef_11(2)
  ,fct_tolerance_residu(NULL),fct_tolerance_residu_rel(NULL)
  // ---- réglage par défaut de la résolution avec linéarisation de sig22_33(bsurb0,hsurh0)=(0,0)
  ,val_initiale(2),racine(2)//,der_at_racine(2,2)
  ,der_at_racine(2,2,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  ,residu(2)//,derResidu(2,2),
  ,derResidu(2,2,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  //--------  spécifiques à Calcul_dsigma_deps hors axes ------------------------
  ,ViB_3D(NULL),ViH_3D(NULL)
  ,val_initiale_3D(3),residu_3D(3),derResidu_3D(3,3,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  ,eps_P_BB(),Deps_P_BB(),delta_eps_P_BB(),racine_3D(3)
  ,gamma3D(3,3),beta3D(3,3),gammaP_3D(3,3),betaP_3D(3,3)
  ,epsBB_tdt_cin(NULL),DepsBB_cin(NULL),delta_epsBB_cin(NULL)
  ,mat_inter(3,3),gij_meca_BB(),gij_meca_BB_t()
  ,V1V1_BB(),ind(3),jnd(3),VhVg_BB(3)
  //--------  fin spécifiques à Calcul_dsigma_deps hors axes ------------------------
  ,mini_hsurh0(0.001),mini_bsurb0(0.001),maxi_hsurh0(1000.),maxi_bsurb0(1000.)
  ,giB_normer_3_tdt_3D_sauve(3),giB_normer_2_tdt_3D_sauve(3)
  // -- conteneur des métriques
  ,expli_3D(NULL),impli_3D(NULL),umat_cont_3D(NULL) 
  // -- les variables pointées dans les conteneurs, et leur pointeur associé éventuellement
  ,giB_0_3D(),giH_0_3D(),giB_t_3D(),giH_t_3D(),giB_tdt_3D(),giH_tdt_3D()   
  ,gijBB_0_3D(),gijHH_0_3D(),gijBB_t_3D(),gijHH_t_3D()
  ,gijBB_tdt_3D(),gijHH_tdt_3D()  
  ,gradVmoyBB_t_3D(),gradVmoyBB_tdt_3D(),gradVBB_tdt_3D()
  ,gradVmoyBB_t_3D_P(NULL),gradVmoyBB_tdt_3D_P(NULL),gradVBB_tdt_3D_P(NULL)  
  ,jacobien_tdt_3D(0.),jacobien_0_3D(0.)
  
  
       // les vrais tableaux associés aux tableaux de pointeurs
  ,d_giB_tdt_3D(),d_giH_tdt_3D()   
  ,d_gijBB_tdt_3D(),d2_gijBB_tdt_3D(),d_gijHH_tdt_3D()
  ,d_gijBB_tdt_3D_P(NULL),d2_gijBB_tdt_3D_P(NULL),d_gijHH_tdt_3D_P(NULL)  
  ,d_jacobien_tdt_3D(NULL)  
  ,d_gradVmoyBB_t_3D(),d_gradVmoyBB_tdt_3D(),d_gradVBB_t_3D(),d_gradVBB_tdt_3D()
  ,d_gradVmoyBB_t_3D_P(NULL),d_gradVmoyBB_tdt_3D_P(NULL),d_gradVBB_t_3D_P(NULL),d_gradVBB_tdt_3D_P(NULL)
		 
  // puis les grandeurs hors métriques
  ,sig_HH_t_3D(),sig_HH_3D(),Deps_BB_3D(),eps_BB_3D(),delta_eps_BB_3D()
  ,d_eps_BB_3D_P(),d_sig_HH_3D_P()
  ,d_eps_BB_3D(),d_sig_HH_3D(),d_sigma_deps_3D(),d_sigma_deps_1D()

     // un conteneur d'un point d'intégration courant
  ,ptintmeca(3)

    { // conteneurs des métriques
	     // a priori seules les grandeurs principales sont affecté
	     expli_3D = new Met_abstraite::Expli_t_tdt  // constructeur normal
                          (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
                          ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
                          ,&gijBB_tdt_3D,&gijHH_tdt_3D
                          ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
                          ,&d_gijBB_tdt_3D_P,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
      impli_3D = new  Met_abstraite::Impli  // constructeur normal 
                       (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&d_giB_tdt_3D,&giH_tdt_3D,&d_giH_tdt_3D
                        ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D,&gijBB_tdt_3D,&gijHH_tdt_3D
                        ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
                        ,&d_gijBB_tdt_3D_P
								                ,d2_gijBB_tdt_3D_P // pas affecté par défaut
								                ,&d_gijHH_tdt_3D_P
                        ,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D,&d_jacobien_tdt_3D
                        ,d_gradVmoyBB_t_3D_P,d_gradVmoyBB_tdt_3D_P     // pas affecté par défaut
		  	               ,d_gradVBB_t_3D_P,d_gradVBB_tdt_3D_P);	        // pas affecté par défaut
	     umat_cont_3D = new Met_abstraite::Umat_cont  // constructeur normal
                          (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
                          ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
                          ,&gijBB_tdt_3D,&gijHH_tdt_3D
                          ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P      // pas affecté par défaut
                          ,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
		    // on ajoute les invariants au pt integ courant
		    ptintmeca.Change_statut_Invariants_contrainte (true);						  
      // initialisation par défaut des paramètres de la résolution de newton
      double  tolerance_residu = 5.e-3;
      double  tolerance_residu_rel = 1.e-4;
      int nb_boucle_maxi = 6; // le maximum d'itération permis
      int nb_dichotomie = 4; // le maxi de dichotomie prévu pour l'équation de Newton
      alg_zero.Modif_prec_res_abs(tolerance_residu);
      alg_zero.Modif_prec_res_rel(tolerance_residu_rel);
      alg_zero.Modif_iter_max(nb_boucle_maxi);
      alg_zero.Modif_nbMaxiIncre(nb_dichotomie);
      // def des indices
      ind(1)=2;ind(2)=3;ind(3)=2;
      jnd(1)=2;jnd(2)=3;jnd(3)=1;
     
      // résolution de d_sig_ef_gh
//      d_sig_ef_gh.Change_Choix_resolution(CRAMER,RIEN_PRECONDITIONNEMENT);
//      der_at_racine.Change_Choix_resolution(CRAMER,RIEN_PRECONDITIONNEMENT);
//      derResidu.Change_Choix_resolution(CRAMER,RIEN_PRECONDITIONNEMENT);
	   };

 
// constructeur à partir d'une instance de contraintes planes
// à condition que cette loi s'appuie sur un comportement 3D
// les deux lois étant proche, les paramètres semblables sont mis en commun
LoiContraintesPlanesDouble::LoiContraintesPlanesDouble
            (LoiContraintesPlanes& loi,bool calcul_en_3D_via_direction_quelconque_):
  Loi_comp_abstraite(LOI_CONTRAINTES_PLANES_DOUBLE,loi.Id_categorie(),1)
  ,calcul_en_3D_via_direction_quelconque(calcul_en_3D_via_direction_quelconque_)

	 ,type_de_contrainte(loi.type_de_contrainte)
	 ,fac_penal(loi.fac_penal),prec(loi.prec)
  ,lois_interne(NULL)
	 ,alg_zero(loi.alg_zero),maxi_delta_var_eps_sur_iter_pour_Newton(loi.maxi_delta_var_eps_sur_iter_pour_Newton)
  ,sortie_post(loi.sortie_post)
  ,d_sig_ef_gh(2,2),d_eps_ef_11(2)
  ,fct_tolerance_residu(NULL),fct_tolerance_residu_rel(NULL)
  // ---- réglage résolution avec linéarisation
  ,val_initiale(2),racine(2)//,der_at_racine(2,2)
  ,residu(2)//,derResidu(2,2)
  ,der_at_racine(2,2,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  ,derResidu(2,2,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  //--------  spécifiques à Calcul_dsigma_deps hors axes ------------------------
  ,ViB_3D(NULL),ViH_3D(NULL)
  ,val_initiale_3D(3),residu_3D(3),derResidu_3D(3,3,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  ,eps_P_BB(),Deps_P_BB(),delta_eps_P_BB(),racine_3D(3)
  ,gamma3D(3,3),beta3D(3,3),gammaP_3D(3,3),betaP_3D(3,3)
  ,epsBB_tdt_cin(NULL),DepsBB_cin(NULL),delta_epsBB_cin(NULL)
  ,mat_inter(3,3),gij_meca_BB(),gij_meca_BB_t()
  ,V1V1_BB(),ind(3),jnd(3),VhVg_BB(3)
  //--------  fin spécifiques à Calcul_dsigma_deps hors axes ------------------------
  // pour les mini et maxi on utilise ceux de h
  ,mini_hsurh0(loi.mini_hsurh0),mini_bsurb0(loi.mini_hsurh0)
  ,maxi_hsurh0(loi.maxi_hsurh0),maxi_bsurb0(loi.maxi_hsurh0)

  ,giB_normer_3_tdt_3D_sauve(3),giB_normer_2_tdt_3D_sauve(3)
  // -- conteneur des métriques: ce sont des pointeurs, pour l'instant on ne les affecte pas
  ,expli_3D(NULL),impli_3D(NULL),umat_cont_3D(NULL) 
  // -- les variables pointées dans les conteneurs
  ,giB_0_3D(loi.giB_0_3D),giH_0_3D(loi.giH_0_3D),giB_t_3D(loi.giB_t_3D),giH_t_3D(loi.giH_t_3D) 
  ,giB_tdt_3D(loi.giB_tdt_3D),d_giB_tdt_3D(loi.d_giB_tdt_3D),giH_tdt_3D(loi.giH_tdt_3D)
  ,d_giH_tdt_3D(loi.d_giH_tdt_3D),gijBB_0_3D(loi.gijBB_0_3D),gijHH_0_3D(loi.gijHH_0_3D) 
  ,gijBB_t_3D(loi.gijBB_t_3D),gijHH_t_3D(loi.gijHH_t_3D),gijBB_tdt_3D(loi.gijBB_tdt_3D)
  ,gijHH_tdt_3D(loi.gijHH_tdt_3D),gradVmoyBB_t_3D(loi.gradVmoyBB_t_3D)
  ,gradVmoyBB_tdt_3D(loi.gradVmoyBB_tdt_3D),gradVBB_tdt_3D(loi.gradVBB_tdt_3D)
  ,jacobien_0_3D(loi.jacobien_0_3D),d_jacobien_tdt_3D(loi.d_jacobien_tdt_3D)
  ,d_gradVBB_t_3D_P(loi.d_gradVBB_t_3D_P),d_gradVBB_tdt_3D_P(loi.d_gradVBB_tdt_3D_P)
       // avec les vrais tableaux associés aux tableaux de pointeurs: ici uniquement le dimensionnement
  ,d_gijBB_tdt_3D(loi.d_gijBB_tdt_3D),d2_gijBB_tdt_3D(loi.d2_gijBB_tdt_3D)
  ,d_gijHH_tdt_3D(loi.d_gijHH_tdt_3D)
  ,d_gradVmoyBB_t_3D(loi.d_gradVmoyBB_t_3D),d_gradVmoyBB_tdt_3D(loi.d_gradVmoyBB_tdt_3D)
  ,d_gradVBB_t_3D(loi.d_gradVBB_t_3D),d_gradVBB_tdt_3D(loi.d_gradVBB_tdt_3D)
		 
  // puis les grandeurs hors métriques, pour les tableaux de pointeurs, c'est uniquement du dimensionnement
  ,sig_HH_t_3D(loi.sig_HH_t_3D),sig_HH_3D(loi.sig_HH_3D),Deps_BB_3D(loi.Deps_BB_3D)
  ,eps_BB_3D(loi.eps_BB_3D),delta_eps_BB_3D(loi.delta_eps_BB_3D)
  ,d_eps_BB_3D_P(loi.d_eps_BB_3D_P),d_sig_HH_3D_P(loi.d_sig_HH_3D_P)
  ,d_eps_BB_3D(loi.d_eps_BB_3D),d_sig_HH_3D(loi.d_sig_HH_3D),d_sigma_deps_3D(loi.d_sigma_deps_3D)
  ,d_sigma_deps_1D()
     // un conteneur d'un point d'intégration courant
  ,ptintmeca(loi.ptintmeca)
	
     { lois_interne = loi.lois_interne->Nouvelle_loi_identique();
	      // association des pointeurs de grandeurs si nécessaire		 
	      if (loi.gradVmoyBB_t_3D_P != NULL) {gradVmoyBB_t_3D_P = &gradVmoyBB_t_3D;};
	      if (loi.gradVmoyBB_tdt_3D_P != NULL) {gradVmoyBB_tdt_3D_P = &gradVmoyBB_tdt_3D;};
	      if (loi.gradVBB_tdt_3D_P != NULL) {gradVBB_tdt_3D_P = &gradVBB_tdt_3D;}; 
		 
	      // def des tableaux de pointeurs pour les conteneurs de métriques
		
       // -- cas des tableaux de pointeurs, ils ont déjà la bonne dimension
	      int ta_d_gijBB_tdt_3D = loi.d_gijBB_tdt_3D.Taille();
	      for (int i=1;i<= ta_d_gijBB_tdt_3D;i++)
	      		d_gijBB_tdt_3D_P(i) = &(d_gijBB_tdt_3D(i));

	      if (loi.d2_gijBB_tdt_3D_P!= NULL)
	       { int tai_d2_gijBB_tdt_3D = d2_gijBB_tdt_3D.Taille1();
	         d2_gijBB_tdt_3D_P = new Tableau2<TenseurBB *> (tai_d2_gijBB_tdt_3D);
	         int taj_d2_gijBB_tdt_3D = d2_gijBB_tdt_3D.Taille2();
	         for (int i=1;i<= tai_d2_gijBB_tdt_3D;i++)
	           for (int j=1;j<= taj_d2_gijBB_tdt_3D;j++)
	             (*d2_gijBB_tdt_3D_P)(i,j) = &(d2_gijBB_tdt_3D(i,j));
	       };
			 
	      int ta_d_gijHH_tdt_3D = d_gijHH_tdt_3D.Taille();
	      for (int i=1;i<= ta_d_gijHH_tdt_3D;i++)
	      		d_gijHH_tdt_3D_P(i) = &(d_gijHH_tdt_3D(i));
	     
	      if (loi.d_gradVmoyBB_t_3D_P != NULL)
	       { int ta_d_gradVmoyBB_t_3D = d_gradVmoyBB_t_3D.Taille();
	         d_gradVmoyBB_t_3D_P = new Tableau<TenseurBB *> (ta_d_gradVmoyBB_t_3D);
	      	for (int i=1;i<= ta_d_gradVmoyBB_t_3D;i++)
	      		(*d_gradVmoyBB_t_3D_P)(i) = &(d_gradVmoyBB_t_3D(i));
	       };
			 
	      if (loi.d_gradVmoyBB_tdt_3D_P != NULL)
	       { int ta_d_gradVmoyBB_tdt_3D = d_gradVmoyBB_tdt_3D.Taille();
	         d_gradVmoyBB_tdt_3D_P = new Tableau<TenseurBB *> (ta_d_gradVmoyBB_tdt_3D);
	      	  for (int i=1;i<= ta_d_gradVmoyBB_tdt_3D;i++)
	      		   (*d_gradVmoyBB_tdt_3D_P)(i) = &(d_gradVmoyBB_tdt_3D(i));
	       };		 
		    
	      if (loi.d_gradVBB_t_3D_P != NULL)
	       { int ta_d_gradVBB_t_3D = d_gradVBB_t_3D.Taille();
	         d_gradVBB_t_3D_P = new Tableau<TenseurBB *> (ta_d_gradVBB_t_3D);
	      	  for (int i=1;i<= ta_d_gradVBB_t_3D;i++)
	      		  (*d_gradVBB_t_3D_P)(i) = &(d_gradVBB_t_3D(i));
	       };
			 
	      if (loi.d_gradVBB_tdt_3D_P != NULL)
	       { int ta_d_gradVBB_tdt_3D = d_gradVBB_tdt_3D.Taille();
	         d_gradVBB_tdt_3D_P = new Tableau<TenseurBB *> (ta_d_gradVBB_tdt_3D);
	      	  for (int i=1;i<= ta_d_gradVBB_tdt_3D;i++)
	      		   (*d_gradVBB_tdt_3D_P)(i) = &(d_gradVBB_tdt_3D(i));
	       };		 
		
	      // conteneurs des métriques
	      // a priori seules les grandeurs principales sont affecté
	      expli_3D = new Met_abstraite::Expli_t_tdt  // constructeur normal
                          (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
                          ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
                          ,&gijBB_tdt_3D,&gijHH_tdt_3D
                          ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
                          ,&d_gijBB_tdt_3D_P,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
       impli_3D = new  Met_abstraite::Impli  // constructeur normal 
                       (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&d_giB_tdt_3D,&giH_tdt_3D,&d_giH_tdt_3D
                        ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D,&gijBB_tdt_3D,&gijHH_tdt_3D
                        ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
                        ,&d_gijBB_tdt_3D_P
								                ,d2_gijBB_tdt_3D_P // pas affecté par défaut
								                ,&d_gijHH_tdt_3D_P
                        ,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D,&d_jacobien_tdt_3D
                        ,d_gradVmoyBB_t_3D_P,d_gradVmoyBB_tdt_3D_P     // pas affecté par défaut
		  	               ,d_gradVBB_t_3D_P,d_gradVBB_tdt_3D_P);	        // pas affecté par défaut
	      umat_cont_3D = new Met_abstraite::Umat_cont  // constructeur normal
                          (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
                          ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
                          ,&gijBB_tdt_3D,&gijHH_tdt_3D
                          ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P      // pas affecté par défaut
                          ,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
			 
	      // puis les tableaux de pointeurs de grandeurs hors métriques
	      int ta_d_eps_BB_3D = d_eps_BB_3D.Taille();
	      for (int i=1;i<= ta_d_eps_BB_3D;i++)
	          d_eps_BB_3D_P(i) = &(d_eps_BB_3D(i));
			 
	      int ta_d_sig_HH_3D = d_sig_HH_3D.Taille();
	      for (int i=1;i<= ta_d_sig_HH_3D;i++)
	          d_sig_HH_3D_P(i) = &(d_sig_HH_3D(i));
      // def des indices
      ind(1)=2;ind(2)=3;ind(3)=1;
      jnd(1)=2;jnd(2)=3;jnd(3)=2;
     
   		};

// Constructeur de copie
LoiContraintesPlanesDouble::LoiContraintesPlanesDouble (const LoiContraintesPlanesDouble& loi) :
   Loi_comp_abstraite(loi)
	 ,type_de_contrainte(loi.type_de_contrainte)
	 ,fac_penal(loi.fac_penal),prec(loi.prec)
  ,lois_interne(NULL)
	 ,alg_zero(loi.alg_zero),maxi_delta_var_eps_sur_iter_pour_Newton(loi.maxi_delta_var_eps_sur_iter_pour_Newton)
  ,sortie_post(loi.sortie_post)
  ,fct_tolerance_residu(loi.fct_tolerance_residu),fct_tolerance_residu_rel(loi.fct_tolerance_residu_rel)
  ,calcul_en_3D_via_direction_quelconque(loi.calcul_en_3D_via_direction_quelconque)
  ,d_sig_ef_gh(2,2),d_eps_ef_11(2)
  // ---- réglage résolution avec linéarisation
  ,val_initiale(2),racine(2)//,der_at_racine(2,2)
  ,residu(2)//,derResidu(2,2)
  ,der_at_racine(2,2,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  ,derResidu(2,2,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  //--------  spécifiques à Calcul_dsigma_deps hors axes ------------------------
  ,ViB_3D(NULL),ViH_3D(NULL)
  ,val_initiale_3D(3),residu_3D(3),derResidu_3D(3,3,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT)
  ,eps_P_BB(loi.eps_P_BB),Deps_P_BB(loi.Deps_P_BB),delta_eps_P_BB(loi.delta_eps_P_BB)
  ,racine_3D(3)
  ,gamma3D(3,3),beta3D(3,3),gammaP_3D(3,3),betaP_3D(3,3)
  ,epsBB_tdt_cin(NULL),DepsBB_cin(NULL),delta_epsBB_cin(NULL)
  ,mat_inter(3,3),gij_meca_BB(),gij_meca_BB_t()
  ,V1V1_BB(),ind(3),jnd(3),VhVg_BB(3)
  //--------  fin spécifiques à Calcul_dsigma_deps hors axes ------------------------
  ,mini_hsurh0(loi.mini_hsurh0),mini_bsurb0(loi.mini_bsurb0)
  ,maxi_hsurh0(loi.maxi_hsurh0),maxi_bsurb0(loi.maxi_bsurb0)
  ,giB_normer_3_tdt_3D_sauve(3),giB_normer_2_tdt_3D_sauve(3)
  // -- conteneur des métriques: ce sont des pointeurs, pour l'instant on ne les affecte pas
  ,expli_3D(NULL),impli_3D(NULL),umat_cont_3D(NULL) 
  // -- les variables pointées dans les conteneurs
  ,giB_0_3D(loi.giB_0_3D),giH_0_3D(loi.giH_0_3D),giB_t_3D(loi.giB_t_3D),giH_t_3D(loi.giH_t_3D) 
  ,giB_tdt_3D(loi.giB_tdt_3D),d_giB_tdt_3D(loi.d_giB_tdt_3D),giH_tdt_3D(loi.giH_tdt_3D)
  ,d_giH_tdt_3D(loi.d_giH_tdt_3D),gijBB_0_3D(loi.gijBB_0_3D),gijHH_0_3D(loi.gijHH_0_3D) 
  ,gijBB_t_3D(loi.gijBB_t_3D),gijHH_t_3D(loi.gijHH_t_3D),gijBB_tdt_3D(loi.gijBB_tdt_3D)
  ,gijHH_tdt_3D(loi.gijHH_tdt_3D),gradVmoyBB_t_3D(loi.gradVmoyBB_t_3D)
  ,gradVmoyBB_tdt_3D(loi.gradVmoyBB_tdt_3D),gradVBB_tdt_3D(loi.gradVBB_tdt_3D)
  ,jacobien_0_3D(loi.jacobien_0_3D),d_jacobien_tdt_3D(loi.d_jacobien_tdt_3D)
  ,d_gradVBB_t_3D_P(loi.d_gradVBB_t_3D_P),d_gradVBB_tdt_3D_P(loi.d_gradVBB_tdt_3D_P)
       // avec les vrais tableaux associés aux tableaux de pointeurs: ici uniquement le dimensionnement
  ,d_gijBB_tdt_3D(loi.d_gijBB_tdt_3D),d2_gijBB_tdt_3D(loi.d2_gijBB_tdt_3D)
  ,d_gijHH_tdt_3D(loi.d_gijHH_tdt_3D)
  ,d_gradVmoyBB_t_3D(loi.d_gradVmoyBB_t_3D),d_gradVmoyBB_tdt_3D(loi.d_gradVmoyBB_tdt_3D)
  ,d_gradVBB_t_3D(loi.d_gradVBB_t_3D),d_gradVBB_tdt_3D(loi.d_gradVBB_tdt_3D)
		 
  // puis les grandeurs hors métriques, pour les tableaux de pointeurs, c'est uniquement du dimensionnement
  ,sig_HH_t_3D(loi.sig_HH_t_3D),sig_HH_3D(loi.sig_HH_3D),Deps_BB_3D(loi.Deps_BB_3D)
  ,eps_BB_3D(loi.eps_BB_3D),delta_eps_BB_3D(loi.delta_eps_BB_3D)
  ,d_eps_BB_3D_P(loi.d_eps_BB_3D_P),d_sig_HH_3D_P(loi.d_sig_HH_3D_P)
  ,d_eps_BB_3D(loi.d_eps_BB_3D),d_sig_HH_3D(loi.d_sig_HH_3D),d_sigma_deps_3D(loi.d_sigma_deps_3D)
  ,d_sigma_deps_1D(loi.d_sigma_deps_1D)
     // un conteneur d'un point d'intégration courant
  ,ptintmeca(loi.ptintmeca)
	
     { lois_interne = loi.lois_interne->Nouvelle_loi_identique();
	      // association des pointeurs de grandeurs si nécessaire		 
	      if (loi.gradVmoyBB_t_3D_P != NULL) {gradVmoyBB_t_3D_P = &gradVmoyBB_t_3D;};
	      if (loi.gradVmoyBB_tdt_3D_P != NULL) {gradVmoyBB_tdt_3D_P = &gradVmoyBB_tdt_3D;};
	      if (loi.gradVBB_tdt_3D_P != NULL) {gradVBB_tdt_3D_P = &gradVBB_tdt_3D;}; 
		 
	      // def des tableaux de pointeurs pour les conteneurs de métriques
		
       // -- cas des tableaux de pointeurs, ils ont déjà la bonne dimension
	      int ta_d_gijBB_tdt_3D = loi.d_gijBB_tdt_3D.Taille();
	      for (int i=1;i<= ta_d_gijBB_tdt_3D;i++)
	      		d_gijBB_tdt_3D_P(i) = &(d_gijBB_tdt_3D(i));

	      if (loi.d2_gijBB_tdt_3D_P!= NULL)
	       { int tai_d2_gijBB_tdt_3D = d2_gijBB_tdt_3D.Taille1();
	         d2_gijBB_tdt_3D_P = new Tableau2<TenseurBB *> (tai_d2_gijBB_tdt_3D);
	         int taj_d2_gijBB_tdt_3D = d2_gijBB_tdt_3D.Taille2();
	         for (int i=1;i<= tai_d2_gijBB_tdt_3D;i++)
	           for (int j=1;j<= taj_d2_gijBB_tdt_3D;j++)
	             (*d2_gijBB_tdt_3D_P)(i,j) = &(d2_gijBB_tdt_3D(i,j));
	       };
			 
	      int ta_d_gijHH_tdt_3D = d_gijHH_tdt_3D.Taille();
	      for (int i=1;i<= ta_d_gijHH_tdt_3D;i++)
	      		d_gijHH_tdt_3D_P(i) = &(d_gijHH_tdt_3D(i));
	     
	      if (loi.d_gradVmoyBB_t_3D_P != NULL)
	       { int ta_d_gradVmoyBB_t_3D = d_gradVmoyBB_t_3D.Taille();
	         d_gradVmoyBB_t_3D_P = new Tableau<TenseurBB *> (ta_d_gradVmoyBB_t_3D);
	      	for (int i=1;i<= ta_d_gradVmoyBB_t_3D;i++)
	      		(*d_gradVmoyBB_t_3D_P)(i) = &(d_gradVmoyBB_t_3D(i));
	       };
			 
	      if (loi.d_gradVmoyBB_tdt_3D_P != NULL)
	       { int ta_d_gradVmoyBB_tdt_3D = d_gradVmoyBB_tdt_3D.Taille();
	         d_gradVmoyBB_tdt_3D_P = new Tableau<TenseurBB *> (ta_d_gradVmoyBB_tdt_3D);
	      	  for (int i=1;i<= ta_d_gradVmoyBB_tdt_3D;i++)
	      		   (*d_gradVmoyBB_tdt_3D_P)(i) = &(d_gradVmoyBB_tdt_3D(i));
	       };		 
		    
	      if (loi.d_gradVBB_t_3D_P != NULL)
	       { int ta_d_gradVBB_t_3D = d_gradVBB_t_3D.Taille();
	         d_gradVBB_t_3D_P = new Tableau<TenseurBB *> (ta_d_gradVBB_t_3D);
	      	  for (int i=1;i<= ta_d_gradVBB_t_3D;i++)
	      		  (*d_gradVBB_t_3D_P)(i) = &(d_gradVBB_t_3D(i));
	       };
			 
	      if (loi.d_gradVBB_tdt_3D_P != NULL)
	       { int ta_d_gradVBB_tdt_3D = d_gradVBB_tdt_3D.Taille();
	         d_gradVBB_tdt_3D_P = new Tableau<TenseurBB *> (ta_d_gradVBB_tdt_3D);
	      	  for (int i=1;i<= ta_d_gradVBB_tdt_3D;i++)
	      		   (*d_gradVBB_tdt_3D_P)(i) = &(d_gradVBB_tdt_3D(i));
	       };		 
		
	      // conteneurs des métriques
	      // a priori seules les grandeurs principales sont affecté
	      expli_3D = new Met_abstraite::Expli_t_tdt  // constructeur normal
                          (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
                          ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
                          ,&gijBB_tdt_3D,&gijHH_tdt_3D
                          ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
                          ,&d_gijBB_tdt_3D_P,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
       impli_3D = new  Met_abstraite::Impli  // constructeur normal 
                       (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&d_giB_tdt_3D,&giH_tdt_3D,&d_giH_tdt_3D
                        ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D,&gijBB_tdt_3D,&gijHH_tdt_3D
                        ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
                        ,&d_gijBB_tdt_3D_P
								                ,d2_gijBB_tdt_3D_P // pas affecté par défaut
								                ,&d_gijHH_tdt_3D_P
                        ,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D,&d_jacobien_tdt_3D
                        ,d_gradVmoyBB_t_3D_P,d_gradVmoyBB_tdt_3D_P     // pas affecté par défaut
		  	               ,d_gradVBB_t_3D_P,d_gradVBB_tdt_3D_P);	        // pas affecté par défaut
	      umat_cont_3D = new Met_abstraite::Umat_cont  // constructeur normal
                          (&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
                          ,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
                          ,&gijBB_tdt_3D,&gijHH_tdt_3D
                          ,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P      // pas affecté par défaut
                          ,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
			 
	      // puis les tableaux de pointeurs de grandeurs hors métriques
	      int ta_d_eps_BB_3D = d_eps_BB_3D.Taille();
	      for (int i=1;i<= ta_d_eps_BB_3D;i++)
	          d_eps_BB_3D_P(i) = &(d_eps_BB_3D(i));
			 
	      int ta_d_sig_HH_3D = d_sig_HH_3D.Taille();
	      for (int i=1;i<= ta_d_sig_HH_3D;i++)
	          d_sig_HH_3D_P(i) = &(d_sig_HH_3D(i));
       // initialisation des paramètres de la résolution de newton
       // résolution de d_sig_ef_gh
//       d_sig_ef_gh.Change_Choix_resolution(CRAMER,RIEN_PRECONDITIONNEMENT);
//       der_at_racine.Change_Choix_resolution(CRAMER,RIEN_PRECONDITIONNEMENT);
//       derResidu.Change_Choix_resolution(CRAMER,RIEN_PRECONDITIONNEMENT);
       // def des indices
       ind(1)=2;ind(2)=3;ind(3)=1;
       jnd(1)=2;jnd(2)=3;jnd(3)=2;
       // on regarde s'il y a un pilotage via des fct nD de la précision
       if (fct_tolerance_residu != NULL)
         { if (fct_tolerance_residu->NomFonction() == "_")
          {// comme il s'agit d'une fonction locale on la redéfinie (sinon pb lors du destructeur de loi)
           string non_fonction("_");
           fct_tolerance_residu = Fonction_nD::New_Fonction_nD(*fct_tolerance_residu);
          };
         };
       if (fct_tolerance_residu_rel != NULL)
         { if (fct_tolerance_residu_rel->NomFonction() == "_")
          {// comme il s'agit d'une fonction locale on la redéfinie (sinon pb lors du destructeur de loi)
           string non_fonction("_");
           fct_tolerance_residu_rel = Fonction_nD::New_Fonction_nD(*fct_tolerance_residu_rel);
          };
         };
   		};

LoiContraintesPlanesDouble::~LoiContraintesPlanesDouble ()
// Destructeur 
     { if (lois_interne != NULL) delete lois_interne;
       // les conteneurs de pointeurs:
       delete expli_3D;delete  impli_3D; delete umat_cont_3D;
		 
       // pour les grandeurs de base, pas de new, donc pas de delete
		 
       // pour les tableaux de pointeurs, idem s'ils ne sont pas addressé par un pointeur
       // sinon il faut détruire le tableau

       if (d2_gijBB_tdt_3D_P!= NULL) delete d2_gijBB_tdt_3D_P;
       if (d_gradVmoyBB_t_3D_P!= NULL) delete d_gradVmoyBB_t_3D_P;
       if (d_gradVmoyBB_tdt_3D_P!= NULL) delete d_gradVmoyBB_tdt_3D_P;
       if (d_gradVBB_t_3D_P!= NULL) delete d_gradVBB_t_3D_P;
       if (d_gradVBB_tdt_3D_P!= NULL) delete d_gradVBB_tdt_3D_P;
       // cas du pilotage de la précision
       if (fct_tolerance_residu != NULL)
         if (fct_tolerance_residu->NomFonction() == "_") delete fct_tolerance_residu;
       if (fct_tolerance_residu_rel != NULL)
         if (fct_tolerance_residu_rel->NomFonction() == "_") delete fct_tolerance_residu_rel;
	    };

   // def d'une instance de données spécifiques, et initialisation
// valable une fois que les différentes lois internes sont définit
LoiContraintesPlanesDouble::SaveResul * LoiContraintesPlanesDouble::New_et_Initialise()
   { // on crée éventuellement le conteneur pour la loi
     SaveResul* le_SaveResul = NULL; 
     if (lois_interne != NULL) le_SaveResul = lois_interne->New_et_Initialise(); 
     // on ramène la bonne instance
     LoiContraintesPlanesDouble::SaveResul * retour =  new SaveResul_LoiContraintesPlanesDouble(le_SaveResul);
     SaveResul_LoiContraintesPlanesDouble * inter = (SaveResul_LoiContraintesPlanesDouble *) retour;
     if (calcul_en_3D_via_direction_quelconque)
       {inter->Creation_def_mecanique();
        inter->def_P.Change_taille(3);inter->def_P_t.Change_taille(3);
       };
     // retour
     return retour;	  
	};

// Lecture des donnees de la classe sur fichier
void LoiContraintesPlanesDouble::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { // vérification que la dimension de l'espace est 3D
    if (ParaGlob::Dimension() != 3)
	     { cout << "\n *** erreur 1 : la dimension de l'espace doit etre 3, pour pouvoir utiliser une loi de contrainte plane ";
        throw (UtilLecture::ErrNouvelleDonnee(-1));
	       if (ParaGlob::NiveauImpression() > 5)
		        cout << "\n LoiContraintesPlanesDouble::LectureDonneesParticulieres (... ";
	       Sortie(1);
		    };
   
    string nom_class_methode("LoiContraintesPlanesDouble::LectureDonneesParticulieres" );
    // on lit tout d'abord la méthode pour prendre en compte la contrainte
	   *(entreePrinc->entree)  >> type_de_contrainte;
	   // on met tout d'abord les valeurs par défaut
	   prec = 0.005; fac_penal = 30.;
    string nom;
    // on traite en fonction du type de contrainte
    switch (type_de_contrainte)
	     {
		      case PERTURBATION :
         { if (strstr(entreePrinc->tablcar,"deformation_transversale")!=NULL)
            { *(entreePrinc->entree)  >> nom;
              if (nom != "deformation_transversale")
                { cout << "\n erreur en lecture de la loi Contraintes planes, on attendait le mot cle deformation_transversale"
                        << " alors que l'on a lue " << nom;
                  entreePrinc->MessageBuffer("**erreur 2 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie(1);
                };
            }
           else // sinon les autres cas de perturbation ne sont actuellement pas pris en compte 
            { cout << "\n erreur en lecture du type de perturbation : pour l'instant seule "
                << " le type: deformation_transversale , est pris en compte " ;
              entreePrinc->MessageBuffer("**erreur 3 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
           break;
         }
		      case PENALISATION : case MULTIPLICATEUR_DE_LAGRANGE :
         { // ---- on regarde s'il faut lire une précision
           if (strstr(entreePrinc->tablcar,"prec=")!=NULL)
            { *(entreePrinc->entree)  >> nom;
              if (nom != "prec=")
                { cout << "\n erreur en lecture de la loi Contraintes planes, on attendait le mot cle prec="
                       << " alors que l'on a lue " << nom;
                  entreePrinc->MessageBuffer("**erreur 4 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie(1);
                };
              *(entreePrinc->entree)  >> prec;
            };

           // --- on regarde s'il faut lire la pénalisation
           if (strstr(entreePrinc->tablcar,"fac=")!=NULL)
            { *(entreePrinc->entree)  >> nom;
              if (nom != "fac=")
                { cout << "\n erreur en lecture de la loi Contraintes planes, on attendait le mot cle fac="
                       << " alors que l'on a lue " << nom;
                  entreePrinc->MessageBuffer("**erreur 5 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie(1);
                };
               *(entreePrinc->entree)  >> fac_penal;
            };
           break;
         }
        
		      case NEWTON_LOCAL :
         { // ---- on regarde s'il faut lire des paramètres de réglage
        
            // --- lecture éventuelle des paramètres de réglage ----
            //     de l'algo de résolution de l'équation d'avancement temporel
            if(strstr(entreePrinc->tablcar,"avec_parametres_de_reglage_")!=0)
             {entreePrinc->NouvelleDonnee(); // on se positionne sur un nouvel enreg
              // on lit tant que l'on ne rencontre pas la ligne contenant "fin_parametres_reglage_Algo_Newton_"
              // ou un nouveau mot clé global auquel cas il y a pb !!
              MotCle motCle; // ref aux mots cle
              while (strstr(entreePrinc->tablcar,"fin_parametres_reglage_Algo_Newton_")==0)
               {
                // si on a  un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur
                if ( motCle.SimotCle(entreePrinc->tablcar))
                 { cout << "\n erreur de lecture des parametre de reglage de l'algorithme de Newton: on n'a pas trouve le mot cle "
                        << " fin_parametres_reglage_Algo_Newton_ et par contre la ligne courante contient un mot cle global  ";
                   entreePrinc->MessageBuffer("** erreur5 des parametres de reglage de la loi de comportement de contraintes planes**");
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);     
                 };
                 
                // lecture d'un mot clé
                *(entreePrinc->entree) >> nom;
                
                if ((entreePrinc->entree)->rdstate() == 0) 
                  {} // lecture normale
                #ifdef ENLINUX 
                else  if ((entreePrinc->entree)->fail())
                   // on a atteind la fin de la ligne et on appelle un nouvel enregistrement 
                  {   entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
                      *(entreePrinc->entree) >>nom;
                   }
                #else
                else  if ((entreePrinc->entree)->eof())
                  // la lecture est bonne mais on a atteind la fin de la ligne
                  { if(nom != "fin_parametres_reglage_Algo_Newton_")
                      {entreePrinc->NouvelleDonnee(); *(entreePrinc->entree) >> nom;};
                  } 
                #endif  
                else // cas d'une erreur de lecture
                 { cout << "\n erreur de lecture inconnue  ";
                   entreePrinc->MessageBuffer("** erreur4 des parametres de reglage de l'algoritheme de Newton de la loi de comportement de contraintes planes**");
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);     
                 };
                
                // nombre d'itération maxi
                if (nom == "nb_iteration_maxi_")
                 {int nb_boucle_maxi; // le maximum d'itération permis
                  *(entreePrinc->entree) >> nb_boucle_maxi;
                  alg_zero.Modif_iter_max(nb_boucle_maxi);
                 }
                // nombre de dichotomie maxi 
                else if (nom == "nb_dichotomie_maxi_")
                 {int nb_dichotomie; // le maxi de dichotomie prévu pour l'équation de Newton
                  *(entreePrinc->entree) >> nb_dichotomie;
                  alg_zero.Modif_nbMaxiIncre(nb_dichotomie);
                 }
                // tolérance absolue sur le résidu
                else if (nom == "tolerance_residu_")
                 { string mot_cle("=fonction_nD:");
                   if(strstr(entreePrinc->tablcar,mot_cle.c_str())==0)
                     {// lecture du paramètre
                      double  tolerance_residu; // tolérance absolue sur la résolution de l'équation
                      *(entreePrinc->entree) >> tolerance_residu;
                      alg_zero.Modif_prec_res_abs(tolerance_residu);
                     }
                   else // on lit une fonction
                     {// on lit le nom de la fonction
                      string nom_fonct;
                      bool lec = entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle,nom_fonct);
                      if (!lec )
                         { entreePrinc->MessageBuffer("**erreur en lecture**  tolerance_residu_ via une fonction nD");
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                      // maintenant on définit la fonction
                      if (lesFonctionsnD.Existe(nom_fonct))
                       {fct_tolerance_residu = lesFonctionsnD.Trouve(nom_fonct);
                       }
                      else
                       {// sinon il faut la lire maintenant
                        string non("_");
                        fct_tolerance_residu = Fonction_nD::New_Fonction_nD(non, Id_Nom_Fonction_nD(nom_fonct));
                        // lecture de la courbe
                        fct_tolerance_residu->LectDonnParticulieres_Fonction_nD (non,entreePrinc);
                        // maintenant on vérifie que la fonction est utilisable
                        if (fct_tolerance_residu->NbComposante() != 1 )
                         { cout << "\n erreur en lecture, la fonction " << nom_fonct
                                << " est une fonction vectorielle a   " << fct_tolerance_residu->NbComposante()
                                << " composantes alors qu'elle devrait etre scalaire ! "
                                << " elle n'est donc pas utilisable !! ";
                           string message("\n**erreur** \n"+nom_class_methode+"(...");
                           entreePrinc->MessageBuffer(message);
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                       };
                      // on mettra à jour pendant le calcul, la valeur de la précision
                     };
                 }
                // tolérance relative sur le résidu
                else if (nom == "tolerance_residu_rel_")
                 { string mot_cle("=fonction_nD:");
                   if(strstr(entreePrinc->tablcar,mot_cle.c_str())==0)
                     {// lecture du paramètre
                      double  tolerance_residu_rel; // tolérance absolue sur la résolution de l'équation
                      *(entreePrinc->entree) >> tolerance_residu_rel;
                      alg_zero.Modif_prec_res_rel(tolerance_residu_rel);
                     }
                   else // on lit une fonction
                     {// on lit le nom de la fonction
                      string nom_fonct;
                      bool lec = entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle,nom_fonct);
                      if (!lec )
                         { entreePrinc->MessageBuffer("**erreur en lecture**  tolerance_residu_ via une fonction nD");
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                      // maintenant on définit la fonction
                      if (lesFonctionsnD.Existe(nom_fonct))
                       {fct_tolerance_residu_rel = lesFonctionsnD.Trouve(nom_fonct);
                       }
                      else
                       {// sinon il faut la lire maintenant
                        string non("_");
                        fct_tolerance_residu_rel = Fonction_nD::New_Fonction_nD(non, Id_Nom_Fonction_nD(nom_fonct));
                        // lecture de la courbe
                        fct_tolerance_residu_rel->LectDonnParticulieres_Fonction_nD (non,entreePrinc);
                        // maintenant on vérifie que la fonction est utilisable
                        if (fct_tolerance_residu_rel->NbComposante() != 1 )
                         { cout << "\n erreur en lecture, la fonction " << nom_fonct
                                << " est une fonction vectorielle a   " << fct_tolerance_residu_rel->NbComposante()
                                << " composantes alors qu'elle devrait etre scalaire ! "
                                << " elle n'est donc pas utilisable !! ";
                           string message("\n**erreur** \n"+nom_class_methode+"(...");
                           entreePrinc->MessageBuffer(message);
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                       };
                      // on mettra à jour pendant le calcul, la valeur de la précision relative
                     };
                 }
                // maxi_delta_var_eps_sur_iter_pour_Newton
                else if (nom == "maxi_delta_var_eps_sur_iter_pour_Newton_")
                 { *(entreePrinc->entree) >> maxi_delta_var_eps_sur_iter_pour_Newton;
                 }
                // le minimum de hsurh0
                else if (nom == "mini_hsurh0_")
                 {*(entreePrinc->entree) >> mini_hsurh0;
                 }
                // le maximum de hsurh0
                else if (nom == "maxi_hsurh0_")
                 {*(entreePrinc->entree) >> maxi_hsurh0;
                 }
                // le minimum de bsurb0
                else if (nom == "mini_bsurb0_")
                 {*(entreePrinc->entree) >> mini_bsurb0;
                 }
                // le maximum de bsurb0
                else if (nom == "maxi_bsurb0_")
                 {*(entreePrinc->entree) >> maxi_bsurb0;
                 }
                // forcer un stockage des indicateurs de la résolution
                else if (nom == "sortie_post_")
                 {*(entreePrinc->entree) >> sortie_post;
                 }
                else if (nom == "calcul_en_3D_via_direction_quelconque_")
                 {calcul_en_3D_via_direction_quelconque = true;
                 }
                // forcer un affichage particulier pour les méthodes
                else if (nom == "permet_affichage_")
                 {int niveau=0;
                  *(entreePrinc->entree) >> niveau;
                  alg_zero.Modif_affichage(niveau); // on met à jour l'algo de newton
                 }
                // sinon ce n'est pas un mot clé connu, on le signale
                else if (nom != "fin_parametres_reglage_Algo_Newton_")
                 { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu "
                        << " on a lu : " << nom << endl;
                   if (ParaGlob::NiveauImpression()>3)
                        cout << "\n LoiContraintesPlanesDouble::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);          
                 }
               }; //-- fin du while
             }; //-- fin de la lecture des paramètres de réglage

           break;
         }
        
        
		      default :
			           cout << "\nErreur : valeur incorrecte du type de contrainte lue !: " << type_de_contrainte << " \n";
              entreePrinc->MessageBuffer("**erreur 6 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
	     };
	// -- on lit maintenant au choix soit rien, soit un facteur de pénalisation et/ou une précision
											 
	 // maintenant lecture de la loi  
    entreePrinc->NouvelleDonnee();
    // lecture du nom de la loi
    string st2,nom3;
    *(entreePrinc->entree)  >> st2;
    // definition de la loi
    LoiAbstraiteGeneral * pt = LesLoisDeComp::Def_loi(st2);
    lois_interne = (Loi_comp_abstraite*) LesLoisDeComp::Def_loi(st2);
    pt = lois_interne;

    // --- lecture des informations particulières propres à la  loi   
    entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
    pt->LectureDonneesParticulieres (entreePrinc,lesCourbes1D,lesFonctionsnD);
    // on s'occupe de la catégorie après la lecture des informations particulières (variable def dans LoiAbstraiteGeneral)
	   LoiAbstraiteGeneral::categorie_loi_comp = pt->Id_categorie();
    if (!GroupeMecanique(categorie_loi_comp))
      { cout << "\n erreur1 en lecture des lois constitutives elementaire d'une loi LoiContraintesPlanesDouble"
             << "\n la loi lue: " << pt->Nom_comport() << " n'est pas une loi mecanique, elle fait partie "
             << " de la categorie: "<< Nom_categorie_loi_comp(categorie_loi_comp);
        entreePrinc->MessageBuffer("**erreur 7 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie(1);     
       };
    
    // si la loi est thermo dépendante on indique que la loi de contrainte plane l'est aussi
    if (((Loi_comp_abstraite*)pt)->ThermoDependante()) this->thermo_dependant = true;
       
//    entreePrinc->NouvelleDonnee(); // prepa du flot de lecture pour d'autre loi éventuellement
    // appel au niveau de la classe mère
    Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire
                 (*entreePrinc,lesFonctionsnD,true);
  };


// Lecture des paramètres particuliers de l'objet sur fichier
// cette lecture est utilisée lorsque l'objet a été déjà défini
// il s'agit donc d'une lecture à l'intérieur d'une autre loi par exemple
void LoiContraintesPlanesDouble::LectureParametres_controles (UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { // vérification que la dimension de l'espace est 3D
    if (ParaGlob::Dimension() != 3)
      { cout << "\n *** erreur 1 : la dimension de l'espace doit etre 3, pour pouvoir utiliser une loi de contrainte plane ";
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        if (ParaGlob::NiveauImpression() > 5)
          cout << "\n LoiContraintesPlanesDouble::LectureDonneesParticulieres (... ";
        Sortie(1);
      };
   
    string nom_class_methode("LoiContraintesPlanesDouble::LectureParametres_controles" );
    // on lit tout d'abord la méthode pour prendre en compte la contrainte
    *(entreePrinc->entree)  >> type_de_contrainte;
    string nom;
    // on traite en fonction du type de contrainte
    switch (type_de_contrainte)
      {
        case PERTURBATION :
         { if (strstr(entreePrinc->tablcar,"deformation_transversale")!=NULL)
            { *(entreePrinc->entree)  >> nom;
              if (nom != "deformation_transversale")
                { cout << "\n erreur en lecture de la loi Contraintes planes, on attendait le mot cle deformation_transversale"
                        << " alors que l'on a lue " << nom;
                  entreePrinc->MessageBuffer("**erreur 2 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie(1);
                };
            }
           else // sinon les autres cas de perturbation ne sont actuellement pas pris en compte
            { cout << "\n erreur en lecture du type de perturbation : pour l'instant seule "
                << " le type: deformation_transversale , est pris en compte " ;
              entreePrinc->MessageBuffer("**erreur 3 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
            };
           break;
         }
        case PENALISATION : case MULTIPLICATEUR_DE_LAGRANGE :
         { // ---- on regarde s'il faut lire une précision
           if (strstr(entreePrinc->tablcar,"prec=")!=NULL)
            { *(entreePrinc->entree)  >> nom;
              if (nom != "prec=")
                { cout << "\n erreur en lecture de la loi Contraintes planes, on attendait le mot cle prec="
                       << " alors que l'on a lue " << nom;
                  entreePrinc->MessageBuffer("**erreur 4 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie(1);
                };
              *(entreePrinc->entree)  >> prec;
            };

           // --- on regarde s'il faut lire la pénalisation
           if (strstr(entreePrinc->tablcar,"fac=")!=NULL)
            { *(entreePrinc->entree)  >> nom;
              if (nom != "fac=")
                { cout << "\n erreur en lecture de la loi Contraintes planes, on attendait le mot cle fac="
                       << " alors que l'on a lue " << nom;
                  entreePrinc->MessageBuffer("**erreur 5 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
                  throw (UtilLecture::ErrNouvelleDonnee(-1));
                  Sortie(1);
                };
               *(entreePrinc->entree)  >> fac_penal;
            };
           break;
         }
        
        case NEWTON_LOCAL :
         { // ---- on regarde s'il faut lire des paramètres de réglage
        
            // --- lecture éventuelle des paramètres de réglage ----
            //     de l'algo de résolution de l'équation d'avancement temporel
            if(strstr(entreePrinc->tablcar,"avec_parametres_de_reglage_")!=0)
             {entreePrinc->NouvelleDonnee(); // on se positionne sur un nouvel enreg
              // on lit tant que l'on ne rencontre pas la ligne contenant "fin_parametres_reglage_Algo_Newton_"
              // ou un nouveau mot clé global auquel cas il y a pb !!
              MotCle motCle; // ref aux mots cle
              while (strstr(entreePrinc->tablcar,"fin_parametres_reglage_Algo_Newton_")==0)
               {
                // si on a  un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur
                if ( motCle.SimotCle(entreePrinc->tablcar))
                 { cout << "\n erreur de lecture des parametre de reglage de l'algorithme de Newton: on n'a pas trouve le mot cle "
                        << " fin_parametres_reglage_Algo_Newton_ et par contre la ligne courante contient un mot cle global  ";
                   entreePrinc->MessageBuffer("** erreur5 des parametres de reglage de la loi de comportement de contraintes planes**");
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);
                 };
                
                // lecture d'un mot clé
                *(entreePrinc->entree) >> nom;
                
                if ((entreePrinc->entree)->rdstate() == 0)
                  {} // lecture normale
                #ifdef ENLINUX
                else  if ((entreePrinc->entree)->fail())
                   // on a atteind la fin de la ligne et on appelle un nouvel enregistrement
                  {   entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
                      *(entreePrinc->entree) >>nom;
                   }
                #else
                else  if ((entreePrinc->entree)->eof())
                  // la lecture est bonne mais on a atteind la fin de la ligne
                  { if(nom != "fin_parametres_reglage_Algo_Newton_")
                      {entreePrinc->NouvelleDonnee(); *(entreePrinc->entree) >> nom;};
                  }
                #endif
                else // cas d'une erreur de lecture
                 { cout << "\n erreur de lecture inconnue  ";
                   entreePrinc->MessageBuffer("** erreur4 des parametres de reglage de l'algoritheme de Newton de la loi de comportement de contraintes planes**");
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);
                 };
                
                // nombre d'itération maxi
                if (nom == "nb_iteration_maxi_")
                 {int nb_boucle_maxi; // le maximum d'itération permis
                  *(entreePrinc->entree) >> nb_boucle_maxi;
                  alg_zero.Modif_iter_max(nb_boucle_maxi);
                 }
                // nombre de dichotomie maxi
                else if (nom == "nb_dichotomie_maxi_")
                 {int nb_dichotomie; // le maxi de dichotomie prévu pour l'équation de Newton
                  *(entreePrinc->entree) >> nb_dichotomie;
                  alg_zero.Modif_nbMaxiIncre(nb_dichotomie);
                 }
                // tolérance absolue sur le résidu
                else if (nom == "tolerance_residu_")
                 { string mot_cle("=fonction_nD:");
                   if(strstr(entreePrinc->tablcar,mot_cle.c_str())==0)
                     {// lecture du paramètre
                      double  tolerance_residu; // tolérance absolue sur la résolution de l'équation
                      *(entreePrinc->entree) >> tolerance_residu;
                      alg_zero.Modif_prec_res_abs(tolerance_residu);
                     }
                   else // on lit une fonction
                     {// on lit le nom de la fonction
                      string nom_fonct;
                      bool lec = entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle,nom_fonct);
                      if (!lec )
                         { entreePrinc->MessageBuffer("**erreur en lecture**  tolerance_residu_ via une fonction nD");
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                      // maintenant on définit la fonction
                      if (lesFonctionsnD.Existe(nom_fonct))
                       {fct_tolerance_residu = lesFonctionsnD.Trouve(nom_fonct);
                       }
                      else
                       {// sinon il faut la lire maintenant
                        string non("_");
                        fct_tolerance_residu = Fonction_nD::New_Fonction_nD(non, Id_Nom_Fonction_nD(nom_fonct));
                        // lecture de la courbe
                        fct_tolerance_residu->LectDonnParticulieres_Fonction_nD (non,entreePrinc);
                        // maintenant on vérifie que la fonction est utilisable
                        if (fct_tolerance_residu->NbComposante() != 1 )
                         { cout << "\n erreur en lecture, la fonction " << nom_fonct
                                << " est une fonction vectorielle a   " << fct_tolerance_residu->NbComposante()
                                << " composantes alors qu'elle devrait etre scalaire ! "
                                << " elle n'est donc pas utilisable !! ";
                           string message("\n**erreur** \n"+nom_class_methode+"(...");
                           entreePrinc->MessageBuffer(message);
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                       };
                      // on mettra à jour pendant le calcul, la valeur de la précision
                     };
                 }
                // tolérance relative sur le résidu
                else if (nom == "tolerance_residu_rel_")
                 { string mot_cle("=fonction_nD:");
                   if(strstr(entreePrinc->tablcar,mot_cle.c_str())==0)
                     {// lecture du paramètre
                      double  tolerance_residu_rel; // tolérance absolue sur la résolution de l'équation
                      *(entreePrinc->entree) >> tolerance_residu_rel;
                      alg_zero.Modif_prec_res_rel(tolerance_residu_rel);
                     }
                   else // on lit une fonction
                     {// on lit le nom de la fonction
                      string nom_fonct;
                      bool lec = entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle,nom_fonct);
                      if (!lec )
                         { entreePrinc->MessageBuffer("**erreur en lecture**  tolerance_residu_ via une fonction nD");
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                      // maintenant on définit la fonction
                      if (lesFonctionsnD.Existe(nom_fonct))
                       {fct_tolerance_residu_rel = lesFonctionsnD.Trouve(nom_fonct);
                       }
                      else
                       {// sinon il faut la lire maintenant
                        string non("_");
                        fct_tolerance_residu_rel = Fonction_nD::New_Fonction_nD(non, Id_Nom_Fonction_nD(nom_fonct));
                        // lecture de la courbe
                        fct_tolerance_residu_rel->LectDonnParticulieres_Fonction_nD (non,entreePrinc);
                        // maintenant on vérifie que la fonction est utilisable
                        if (fct_tolerance_residu_rel->NbComposante() != 1 )
                         { cout << "\n erreur en lecture, la fonction " << nom_fonct
                                << " est une fonction vectorielle a   " << fct_tolerance_residu_rel->NbComposante()
                                << " composantes alors qu'elle devrait etre scalaire ! "
                                << " elle n'est donc pas utilisable !! ";
                           string message("\n**erreur** \n"+nom_class_methode+"(...");
                           entreePrinc->MessageBuffer(message);
                           throw (UtilLecture::ErrNouvelleDonnee(-1));
                           Sortie(1);
                         };
                       };
                      // on mettra à jour pendant le calcul, la valeur de la précision relative
                     };
                 }
                // maxi_delta_var_eps_sur_iter_pour_Newton
                else if (nom == "maxi_delta_var_eps_sur_iter_pour_Newton_")
                 { *(entreePrinc->entree) >> maxi_delta_var_eps_sur_iter_pour_Newton;
                 }
                // le minimum de hsurh0
                else if (nom == "mini_hsurh0_")
                 {*(entreePrinc->entree) >> mini_hsurh0;
                 }
                // le maximum de hsurh0
                else if (nom == "maxi_hsurh0_")
                 {*(entreePrinc->entree) >> maxi_hsurh0;
                 }
                // le minimum de bsurb0
                else if (nom == "mini_bsurb0_")
                 {*(entreePrinc->entree) >> mini_bsurb0;
                 }
                // le maximum de bsurb0
                else if (nom == "maxi_bsurb0_")
                 {*(entreePrinc->entree) >> maxi_bsurb0;
                 }
                // forcer un stockage des indicateurs de la résolution
                else if (nom == "sortie_post_")
                 {*(entreePrinc->entree) >> sortie_post;
                 }
                // forcer un affichage particulier pour les méthodes
                else if (nom == "permet_affichage_")
                 {int niveau=0;
                  *(entreePrinc->entree) >> niveau;
                  alg_zero.Modif_affichage(niveau); // on met à jour l'algo de newton
                 }
                else if (nom == "calcul_en_3D_via_direction_quelconque_")
                 {calcul_en_3D_via_direction_quelconque = true;
                 }
                // sinon ce n'est pas un mot clé connu, on le signale
                else if (nom != "fin_parametres_reglage_Algo_Newton_")
                 { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu "
                        << " on a lu : " << nom << endl;
                   if (ParaGlob::NiveauImpression()>3)
                        cout << "\n LoiContraintesPlanesDouble::LectureDonneesParticulieres(UtilLecture * entreePrinc) " << endl ;
                   throw (UtilLecture::ErrNouvelleDonnee(-1));
                   Sortie(1);
                 }
               }; //-- fin du while
             }; //-- fin de la lecture des paramètres de réglage

           break;
         }
        
        
        default :
              cout << "\nErreur : valeur incorrecte du type de contrainte lue !: " << type_de_contrainte << " \n";
              entreePrinc->MessageBuffer("**erreur 6 LoiContraintesPlanesDouble::LectureDonneesParticulieres (...**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
      };
   
//    entreePrinc->NouvelleDonnee(); // prepa du flot de lecture pour d'autre loi éventuellement
    // appel au niveau de la classe mère
    Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire
                 (*entreePrinc,lesFonctionsnD,true);
  };

// affichage de la loi
void LoiContraintesPlanesDouble::Affiche() const
  {  cout << "\n .......  loi de comportement LoiContraintesPlanesDouble ........";
     cout << "\n type_de_contrainte: " << Nom_contrainte_mathematique(type_de_contrainte)
	         << " prec= " << prec << " ";
	    if (type_de_contrainte == PENALISATION) 
	      { cout << " fac_penal= " << fac_penal << " ";}
     else if (type_de_contrainte == NEWTON_LOCAL)
       { // --- paramètre de réglage
         cout << "\n reglage_algo_newton_equadiff: " ;
         alg_zero.Affiche();
         cout << " maxi_delta_var_eps_sur_iter_pour_Newton_ "<<maxi_delta_var_eps_sur_iter_pour_Newton << " ";
         if (fct_tolerance_residu != NULL)
           {cout << "\n pilotage tol_residu: ";
            if (fct_tolerance_residu->NomFonction() != "_")
              cout << fct_tolerance_residu->NomFonction();
            else
              fct_tolerance_residu->Affiche();
            cout << "\n";
           };
         if (fct_tolerance_residu_rel != NULL)
           {cout << "\n pilotage tol_residu_rel: ";
            if (fct_tolerance_residu_rel->NomFonction() != "_")
              cout << fct_tolerance_residu_rel->NomFonction();
            else
              fct_tolerance_residu_rel->Affiche();
            cout << "\n";
           };

         // niveau d'affichage
         Affiche_niveau_affichage();
         cout << " sortie_post "<< sortie_post
              << " ";
         cout << " calcul_en_3D_via_direction_quelconque "<< calcul_en_3D_via_direction_quelconque
              << " ";
        };
   
     lois_interne->Affiche();
     cout << "\n .......  fin de la loi de comportement LoiContraintesPlanesDouble ........";
  };
            
// affichage et definition interactive des commandes particulières à chaques lois
void LoiContraintesPlanesDouble::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
 {ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
	 cout << "\n definition standart pour CP2  (rep o) ou exemples exhaustifs (rep n'importe quoi) ? ";
	 string rep = "_";     // procédure de lecture avec prise en charge d'un retour chariot
  rep = lect_return_defaut(true,"o");

	 if ((rep == "o") || (rep != "O" ))
    sort  << "\n#   --- exemple de declaration pour une loi elastique --- "
          << "\n#   "
          << "\n#   toto LOI_CONTRAINTES_PLANES_DOUBLE    "
          << "\n#          NEWTON_LOCAL 	avec_parametres_de_reglage_   "
          << "\n#                    nb_iteration_maxi_  20   "
          << "\n#                    nb_dichotomie_maxi_  20   "
          << "\n#                    tolerance_residu_ 1.e-3   "
          << "\n#                 fin_parametres_reglage_Algo_Newton_   "
          << "\n#   "
          << "\n#     ISOELAS   "
          << "\n#       200000  0.3   "
          << "\n#   fin_loi_contrainte_plane  # --- fin de la loi de contrainte plane double "
          << "\n\n \n ";
  
	 if ((rep != "o") && (rep != "O" ) && (rep != "0") )
   {sort << "\n# .......  loi de comportement LoiContraintesPlanesDouble ........"
         << "\n#  a)sur la premiere ligne on indique  : "
         << "\n#     Obligatoirement : la methode utilisee pour imposer les contraintes plane: par defaut par multiplicateur de Lagrange "
         << "\n#     les differents choix sont:  "
         << "\n#										   "
         << "\n#	PERTURBATION deformation_transversale :  a chaque iteration (en implicite) ou increment (en explicite) la deformation d'epaisseur	et de largeur   "
         << "\n#                                          est mise a jour, c'est a dire la deformation eps33 et eps22 "
         << "\n#                                          pour cela on se sert du module de compressibilite et de la condition de "
         << "\n#                                          de contrainte plane "
         << "\n#										   "
         << "\n#										   "
/*
         << "\n#     MULTIPLICATEUR_LAGRANGE : utilisation d'un multiplicateur de Lagrange, l'equilibre n'est cependant pas exact "
         << "\n#										  il depend de la valeur des ddl calcules globalement. La precision de la condition "
         << "\n#										  sig33=0 est consultee lors de la resolution globale, on peut ainsi indiquer une precision  "
         << "\n#										  en dessous de laquelle on considerera que la condition est ok. Par defaut cette precision "
         << "\n#										  est relative et vaut 0.005 * Max|sig_ij|. On peut indiquer a la suite du mot cle prec= valeur"
         << "\n#										  ou prec= est un mot cle facultatif, valeur indique la precision que l'on desire "
         << "\n#										   "
         << "\n#     PENALISATION            : utilisation d'un facteur de penalisation dont la valeur est par defaut "
         << "\n#                               30 fois le maximum de |d_sig_ij/d_ddl| , a la suite du  "
         << "\n#                               mot cle on peut indiquer fac= facteur , ou fac= est un mot cle et facteur "
         << "\n#                               est un nombre qui multiplie par le maxi de |d_sig_ij/d_ddl| sera la penalisation  "
         << "\n#										  comme pour la methode avec multiplicateur de Lagrange, la condition est approchee aussi  "
         << "\n#										  la precision de la contrainte sig33=0 est consultee lors de la resolution globale. On "
         << "\n#										  peut donc aussi indiquer une precision differente de celle par defaut de la meme maniere "
         << "\n#										  que pour le multiplicateu de Lagrange "
         << "\n#										   "
*/
         << "\n#     NEWTON                  : utilisation d'une methode interne de Newton pour imposer precisemment la condition "
         << "\n#										  La methode itere localement en chaque point d'integration pour imposer la condition "
         << "\n#										  Par defaut, on considere que la convergence est ok lorsque la condition est satisfaite  "
         << "\n#										  pour une precision relative de 0.005 * Max|sig_ij|. "
         << "\n#			---	exemple de declaration:					---	   "
         << "\n#				NEWTON 				"
         << "\n#										   "
         << "\n# ** il est egalement possible (mais pas obligatoire) de definir des parametres de reglage "
         << "\n# de la resolution. Dans ce cas, a la suite du mot cle NEWTON on indique le mot cle: avec_parametres_de_reglage_ "
         << "\n# ensuite on defini (dans un ordre quelconque) les parametres que l'on souhaites "
         << "\n# chaque parametre est precede d'un mot cle, on a donc une succession de mot cle suivi d'une grandeur "
         << "\n# on peut avoir un ou plusieur couple parametre-grandeur sur chaque ligne "
         << "\n# par contre la derniere ligne doit comporter uniquement le mot cle: "
         << "\n#  fin_parametres_reglage_Algo_Newton_ "
         << "\n# les differents parametres sont: "
         << "\n# le nombre d'iteration  ex: nb_iteration_maxi_  20 "
         << "\n# le nombre de dichotomie ex: nb_dichotomie_maxi_  20 "
         << "\n# la tolerance absolue sur le residu ex: tolerance_residu_ 5.e-3 "
         << "\n# la tolerance relative sur le residu ex: tolerance_residu_rel_ 1.e-4 "
         << "\n# le minimum de variation de h sur h0 (par defaut 0.001) ex: mini_hsurh0_ 1.e-4 "
         << "\n# le minimum de variation de b sur b0 (par defaut 0.001) ex: mini_bsurb0_ 1.e-4 "
         << "\n# le maximum de variation de h sur h0 (par defaut 1000) ex: maxi_hsurh0_ 1000. "
         << "\n# le maximum de variation de b sur b0 (par defaut 1000) ex: mini_bsurb0_ 1000. "
         << "\n# la valeur absolue maximale du delta deformation qui est permise a chaque iteration de Newton  "
         << "\n#   par defaut = 0.1 , si on veut une autre valeur: exe: "
         << "\n# maxi_delta_var_eps_sur_iter_pour_Newton_ 0.2           "
         << "\n#		 si on donne une valeur negative, il n'y a plus de limite								   "
         << "\n#      "
         << "\n# Le mot cle: calcul_en_3D_via_direction_quelconque_           "
         << "\n#    cela correspond a un comportement particulier pour lequel on utilise la loi 3D "
         << "\n#    dans des directions quelconques (cf. partie theorique). Ce fonctionnement "
         << "\n#    est en particulier mis en place pour verifier et valider la loi plis dans sa "
         << "\n#    deuxieme version, donc a ne  pas utiliser d'une maniere generale"
         << "\n#             "
         << "\n#  le mot cle  sortie_post_ , par defaut il vaut 0, dans ce cas aucun indicateur n'est stoke"
         << "\n#  s'il est different de 0, on peut acceder aux indicateurs en post-traitement (nombre d'iteration, dichotomie ... "
         << "\n#  seules les indicateurs en cours sont disponibles, il n'y a pas de stockage sur plusieurs increment "
         << "\n# "
         << "\n# ex: sortie_post_ 1 "
         << "\n# "
         << "\n# -------------- affichage des erreurs et des warning ---------- "
         << "\n# - l'affichage normale est fonction du parametre global d'affichage gerer par le niveau d'affichage"
         << "\n# cependant pour des raisons par exemple de mise au point, il est possible de permettre l'affichage "
         << "\n# a un niveau particulier (mot cle : permet_affichage_ suivi d'un nombre entier) en plus de l'affichage normal. "
         << "\n# l'affichage s'effectuera donc en fonction de l'affichage normale et de l'affichage particulier."
         << "\n# Le fonctionnement de l'affichage particulier suit les mêmes règles que l'affichage globale"
         << "\n# soit permet_affichage_ est nulle (cas par defaut), dans ce cas l'affichage est fonction du niveau global"
         << "\n# soit permet_affichage_ vaut n par exemple, dans ce cas l'affichage est fonction uniquement de n "
         << "\n# "
         << "\n# ex: permet_affichage_ 5  "
         << "\n#										   "
         << "\n#				-- exemple de declaration:				--		   "
         << "\n#				NEWTON_LOCAL 				avec_parametres_de_reglage_"
         << "\n#                  nb_iteration_maxi_  20 "
         << "\n#                  nb_dichotomie_maxi_  20 "
         << "\n#                  tolerance_residu_ 5.e-3 "
         << "\n#                  tolerance_residu_rel_ 1.e-4 "
         << "\n#                  mini_hsurh0_ 1.e-4 "
         << "\n#                  mini_bsurb0_ 1.e-4 "
         << "\n#                  maxi_hsurh0_ 1000. "
         << "\n#                  mini_bsurb0_ 1000. "
         << "\n#                  sortie_post_ 1 "
         << "\n#                  permet_affichage_ 3 "
         << "\n#               fin_parametres_reglage_Algo_Newton_ "
         << "\n#										   "
         << "\n#  NB: il est possible de piloter les tolerances de l'algo de Newton avec une fonction nD  "
         << "\n#     ce qui permet par exemple d'avoir des tolerances qui varient en fct de la precision globlae "
         << "\n#             "
         << "\n#    exemples:  avec fc1 et fc2, 2 fct nD  "
         << "\n#      tolerance_residu_  =fonction_nD: fc1 "
         << "\n#      tolerance_residu_rel_  =fonction_nD: fc2 "
         << "\n#             "
         << "\n#             "
         << "\n#-----------------------------------"
         << "\n#	b)puis sur la ligne suivante: 									   "
         << "\n#     Obligatoirement:  le nom de la loi de comportement 3D sur laquelle on veut imposer une condition de contrainte plane "
         << "\n#								La suite des informations est relative a la loi 3D, voir donc la syntaxe associee"
         << "\n#										   "
         << "\n#										   "
         << "\n#	exemple 0: 		   "
         << "\n		PERTURBATION deformation_transversale  "
         << "\n		  HYSTERESIS_3D	"
         << "\n#		.... # partie relative aux parametres specifiques a la loi d'Hysteresis								   "
         << "\n#										   "
/*
         << "\n#	exemple 1: 		   "
         << "\n#		MULTIPLICATEUR_LAGRANGE prec= 1.e-3 "
         << "\n#		  HYSTERESIS_3D	"
         << "\n#		.... # partie relative aux parametres specifiques a la loi d'Hysteresis								   "
         << "\n#										   "
         << "\n#	exemple 2: 	prec et fac sont facultatifs, mais prec doit etre avant fac	   "
         << "\n#		PENALISATION prec= 1.e-3 fac= 40. 	"
         << "\n#		  HYSTERESIS_3D	"
         << "\n#		.... # partie relative aux parametres specifiques a la loi d'Hysteresis								   "
         << "\n#										   "
         << "\n#	exemple 3: 		   "
         << "\n#		NEWTON_LOCAL prec= 1.e-3  	"
         << "\n#		  HYSTERESIS_3D	"
         << "\n#		.... # partie relative aux parametres specifiques a la loi d'Hysteresis								   "
*/
         << "\n#										   "
         << "\n#	a la fin de fin de la loi, on indique un mot cle de fin		";
    sort << "\n          fin_loi_contrainte_plane_double   # ----- fin de Loi de contrainte plane double " << endl;
			};
  };  		  	  

// test si la loi est complete
int LoiContraintesPlanesDouble::TestComplet()
    { int ret = LoiAbstraiteGeneral::TestComplet();
      ret *=lois_interne->TestComplet();
      return ret; 
    }; 
		          
// calcul d'un module d'young équivalent à la loi, ceci pour un
// chargement nul
double LoiContraintesPlanesDouble::Module_young_equivalent(Enum_dure temps,const Deformation & def ,SaveResul * saveResul_ex)
  {
    SaveResul_LoiContraintesPlanesDouble & save_resul = *((SaveResul_LoiContraintesPlanesDouble*) saveResul_ex);
    double E =lois_interne->Module_young_equivalent(temps,def,save_resul.le_SaveResul);
    return E;
   }; 
		          
// récupération d'un module de compressibilité équivalent à la loi, ceci pour un chargement nul
// il s'agit ici de la relation -pression = sigma_trace/3. = module de compressibilité * I_eps
double LoiContraintesPlanesDouble::Module_compressibilite_equivalent(Enum_dure temps,const Deformation & def ,SaveResul * saveResul_ex)
  {
    SaveResul_LoiContraintesPlanesDouble & save_resul = *((SaveResul_LoiContraintesPlanesDouble*) saveResul_ex);
    double module_compressibilite =lois_interne->Module_compressibilite_equivalent(temps,def,save_resul.le_SaveResul);
    return module_compressibilite;
   }; 

// activation des données des noeuds et/ou elements nécessaires au fonctionnement de la loi
// exemple: mise en service des ddl de température aux noeuds
// ici la grandeur qui sert de proportion entre la première loi et la seconde
void LoiContraintesPlanesDouble::Activation_donnees(Tableau<Noeud *>& tabnoeud,bool dilatation,LesPtIntegMecaInterne& lesPtMecaInt)
  { // appel relatif à la lois associée
    lois_interne->Activation_donnees(tabnoeud,dilatation,lesPtMecaInt);    
    // appel de la méthode de la classe mère
    Loi_comp_abstraite::Activ_donnees(tabnoeud,dilatation,lesPtMecaInt);     
   };
   
// récupération des grandeurs particulière (hors ddl )
// correspondant à liTQ
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void LoiContraintesPlanesDouble::Grandeur_particuliere
              (bool absolue,List_io<TypeQuelconque>& liTQ,Loi_comp_abstraite::SaveResul * saveDon,list<int>& decal) const
 { // tout d'abord on récupère le conteneur
   SaveResul_LoiContraintesPlanesDouble & save_resul = *((SaveResul_LoiContraintesPlanesDouble*) saveDon);
   // maintenant on s'occupe des grandeurs de la loi  elle même,
   List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
   list<int>::iterator idecal=decal.begin();
   for (itq=liTQ.begin();itq!=itqfin;itq++,idecal++)
     { 
      SaveResul_LoiContraintesPlanesDouble & save_resul = *((SaveResul_LoiContraintesPlanesDouble*) saveDon);
      TypeQuelconque& tipParticu = (*itq); // pour simplifier
      if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
       switch (tipParticu.EnuTypeQuelconque().EnumTQ())
       {  case CONTRAINTE_INDIVIDUELLE_A_CHAQUE_LOI_A_T:
           // 2) -----cas des contraintes individuelles à chaque loi à t uniquement
            { Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
              // en fait on utilise systématiquement un tenseur d'ordre le + élevé, car c'est le conteneur le plus générique
              // et Tab_Grandeur_TenseurHH ne supporte que des tenseurs du même ordre donc s'il y a un tenseur élevé
              // interne il faut que tous les tenseurs soient du même ordre
              TenseurHH* sigHH = (save_resul.l_sigoHH_t); // pour simplifier
              if (Dabs(sigHH->Dimension()) != dim)
                {tyTQ(1+(*idecal)).Affectation_trans_dimension(*sigHH,true);
                }
              else // cas même dimension
                {tyTQ(1+(*idecal)) = (*(save_resul.l_sigoHH_t));
                };
              (*idecal)++;
              break;
            }
          case ENERGIE_ELASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T:
           // 3) -----cas de l'énergie élastique individuelles à chaque loi à t
            { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
              tyTQ(1+(*idecal)) = save_resul.l_energ_t.EnergieElastique();  (*idecal)++;
              break;
            }
          case ENERGIE_PLASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T:
          // 4) -----cas de l'énergie plastique individuelles à chaque loi à t
          if ((*itq).EnuTypeQuelconque() == ENERGIE_PLASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
           { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             tyTQ(1+(*idecal)) = save_resul.l_energ_t.DissipationPlastique();  (*idecal)++;
              break;
            }
          case ENERGIE_VISQUEUSE_INDIVIDUELLE_A_CHAQUE_LOI_A_T:
          // 5) -----cas de l'énergie visqueuse individuelles à chaque loi à t
          if ((*itq).EnuTypeQuelconque() == ENERGIE_VISQUEUSE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
           { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             tyTQ(1+(*idecal)) = save_resul.l_energ_t.DissipationVisqueuse();  (*idecal)++;
              break;
            }
          case DEF_EPAISSEUR:
          // 6) -----cas de la déformation d'épaisseur à t
          if ((*itq).EnuTypeQuelconque() == DEF_EPAISSEUR)
           { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             // -- on calcul en fonction de l'élongation d'épaisseur
             double hsurh0=1. ; // init par défaut: on utilise une variable inter, car s'il n'y a pas eu
                 // de calcul préalable,save_resul.hsurh0 == 0 ce qui conduit à une def infinie
             if (save_resul.hsurh0 != 0.) // cas où il y a  eu un calcul
                hsurh0=save_resul.hsurh0;
             switch (type_de_deformation)
                {case  DEFORMATION_STANDART :  case DEFORMATION_POUTRE_PLAQUE_STANDART :
                      // cas d'une déformation d'Almansi
                      {  // dans le repère local: epsBB33 = 1/2 * (h^2 - 1.), or h0=1.
                         // donc dans le repère global : epsBB33 = 1/2 * (1. - 1./(h/h0)^2)
                         tyTQ(1+(*idecal)) = 0.5 * (1. - 1./(hsurh0 * hsurh0));(*idecal)++;
                      };
                      break;
                 case DEFORMATION_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEFORMATION_CUMU_LOGARITHMIQUE :
                     // cas d'une def logarithmique ou une approximation
                      {  tyTQ(1+(*idecal)) = log(hsurh0);(*idecal)++;
                      };
                      break;
                 default :
                   cout << "\nErreur : type de deformation qui n'est pas actuellement pris en compte, type= "
                        << Nom_type_deformation(type_de_deformation);
                   cout << "\n LoiContraintesPlanes::Grandeur_particuliere \n";
                   Sortie(1);
                };
              break;
            }
          case DEF_LARGEUR:
          // 6) -----cas de la déformation de largeur à t
          if ((*itq).EnuTypeQuelconque() == DEF_LARGEUR)
           { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             // -- on calcul en fonction de l'élongation d'épaisseur
             double bsurb0=1. ; // init par défaut: on utilise une variable inter, car s'il n'y a pas eu
                 // de calcul préalable,save_resul.bsurb0 == 0 ce qui conduit à une def infinie
             if (save_resul.bsurb0 != 0.) // cas où il y a  eu un calcul
                bsurb0=save_resul.bsurb0;
             switch (type_de_deformation)
                {case  DEFORMATION_STANDART :  case DEFORMATION_POUTRE_PLAQUE_STANDART :
                      // cas d'une déformation d'Almansi
                      {  // dans le repère local: epsBB22 = 1/2 * (b^2 - 1.), or b0=1.
                         // donc dans le repère global : epsBB22 = 1/2 * (1.-1./(b/b0)^2)
                         tyTQ(1+(*idecal)) = 0.5 * (1.-1./(bsurb0 * bsurb0));(*idecal)++;
                      };
                      break;
                 case DEFORMATION_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEFORMATION_CUMU_LOGARITHMIQUE :
                     // cas d'une def logarithmique ou une approximation
                      {  tyTQ(1+(*idecal)) = log(bsurb0);(*idecal)++;
                      };
                      break;
                 default :
                   cout << "\nErreur : type de deformation qui n'est pas actuellement pris en compte, type= "
                        << Nom_type_deformation(type_de_deformation);
                   cout << "\n LoiContraintesPlanes::Grandeur_particuliere \n";
                   Sortie(1);
                };
              break;
            }
          //  -----cas des deformations dans le repère de traction def_P
          // calculées dans le cadre de l'option: calcul_en_3D_via_direction_quelconque == true
          //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
          case DEF_P_DANS_V_A:
           { Tab_Grandeur_Vecteur& tyTQ= *((Tab_Grandeur_Vecteur*) (*itq).Grandeur_pointee()); // pour simplifier
             if (save_resul.def_P_t.Taille())
               tyTQ(1+(*idecal)) =  save_resul.def_P_t;
             else tyTQ(1+(*idecal)).Zero();
               (*idecal)++; break;
           }
          case NB_INCRE_TOTAL_RESIDU:
           { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if ((save_resul.indicateurs_resolution_t.Taille()))
                  tyTQ(1+(*idecal)) =  save_resul.indicateurs_resolution_t(1);
             else tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
          case NB_ITER_TOTAL_RESIDU:
           { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
             if ((save_resul.indicateurs_resolution_t.Taille()))
                  tyTQ(1+(*idecal)) =  save_resul.indicateurs_resolution_t(2);
             else tyTQ(1+(*idecal)) = 0.;
             (*idecal)++; break;
           }
         
          default: ;// on ne fait rien
       };
     };
   // puis appel pour la lois associée
   lois_interne->Grandeur_particuliere(absolue,liTQ,save_resul.le_SaveResul,decal);
  };

// récupération de la liste de tous les grandeurs particulières
// ces grandeurs sont ajoutées à la liste passées en paramètres
void LoiContraintesPlanesDouble::ListeGrandeurs_particulieres(bool absolue,List_io<TypeQuelconque>& liTQ) const
 { // tout d'abord on passe en revue les grandeurs des lois associées
   // ** au niveau de l'exécution ce sera l'inverse de cette ordre: on s'occupera d'abord de this puis les lois internes
	  // ** mais a priori cela n'a pas d'importance 
   // appel de la loi 3D
	  int nb_loi = 1; // pour être identique pour la loi additive !!
   lois_interne->ListeGrandeurs_particulieres(absolue,liTQ);
	
   // ... maintenant on s'occupe des grandeurs de la loi  elle même,   
   // 1) -----cas des contraintes individuelles à la loi à t uniquement
   {// ici il s'agit du tenseur des contraintes du pas précédent ou du pas actuel
    //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
     {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
       for (itq=liTQ.begin();itq!=itqfin;itq++)
        if ((*itq).EnuTypeQuelconque() == CONTRAINTE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
         { Tab_Grandeur_TenseurHH& tyTQ= *((Tab_Grandeur_TenseurHH*) (*itq).Grandeur_pointee()); // pour simplifier
           int taille = tyTQ.Taille()+nb_loi;
           tyTQ.Change_taille(taille); nexistePas = false;
         };
       if (nexistePas)
        {TenseurHH* tens = NevezTenseurHH(ParaGlob::Dimension()); // un tenseur typique
                                                // qui fonctionnera en absolue ou non
         Tab_Grandeur_TenseurHH gtHH(*tens,nb_loi); 
         // def d'un type quelconque représentatif 
         TypeQuelconque typQ(CONTRAINTE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,gtHH);
         liTQ.push_back(typQ);
         delete tens; // car on n'en a plus besoin
        };
     };
   };
   // pour toutes les énergies
   Tableau <double> tab_double(nb_loi);   
   Tab_Grandeur_scalaire_double grand_courant(tab_double);
  
   // 3) -----cas de l'énergie élastique individuelles à chaque loi à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
         if ((*itq).EnuTypeQuelconque() == ENERGIE_ELASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
          { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
        int taille = tyTQ.Taille()+nb_loi;
      tyTQ.Change_taille(taille); nexistePas = false;
       };
    if (nexistePas)
      {TypeQuelconque typQ1(ENERGIE_ELASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,grand_courant);
         liTQ.push_back(typQ1);
     };
   };
   // 4) -----cas de l'énergie plastique individuelles à chaque loi à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
         if ((*itq).EnuTypeQuelconque() == ENERGIE_PLASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
          { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
        int taille = tyTQ.Taille()+nb_loi;
      tyTQ.Change_taille(taille); nexistePas = false;
       };
    if (nexistePas)
      {TypeQuelconque typQ1(ENERGIE_PLASTIQUE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,grand_courant);
         liTQ.push_back(typQ1);
     };
   };
   // 5) -----cas de l'énergie visqueuse individuelles à chaque loi à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
         if ((*itq).EnuTypeQuelconque() == ENERGIE_VISQUEUSE_INDIVIDUELLE_A_CHAQUE_LOI_A_T)
          { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
        int taille = tyTQ.Taille()+nb_loi;
      tyTQ.Change_taille(taille); nexistePas = false;
       };
    if (nexistePas)
      {TypeQuelconque typQ1(ENERGIE_VISQUEUSE_INDIVIDUELLE_A_CHAQUE_LOI_A_T,SIG11,grand_courant);
         liTQ.push_back(typQ1);
     };
   };
   //  -----cas de la déformation d'épaisseur à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
         if ((*itq).EnuTypeQuelconque() == DEF_EPAISSEUR)
          { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
        int taille = tyTQ.Taille()+nb_loi;
      tyTQ.Change_taille(taille); nexistePas = false;
       };
    if (nexistePas)
      {TypeQuelconque typQ1(DEF_EPAISSEUR,EPS11,grand_courant);
         liTQ.push_back(typQ1);
     };
   };
   //  -----cas de la déformation de largeur à t uniquement
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
         if ((*itq).EnuTypeQuelconque() == DEF_LARGEUR)
          { Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
            int taille = tyTQ.Taille()+nb_loi;
            tyTQ.Change_taille(taille); nexistePas = false;
          };
    if (nexistePas)
      {TypeQuelconque typQ1(DEF_LARGEUR,EPS11,grand_courant);
         liTQ.push_back(typQ1);
     };
   };
  
   //  -----cas des deformations dans le repère de traction def_P
   // calculées dans le cadre de l'option: calcul_en_3D_via_direction_quelconque == true
   //on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
   {Vecteur  VV(3);
    Tab_Grandeur_Vecteur grand_vecteur_3(VV,1);
    List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
    for (itq=liTQ.begin();itq!=itqfin;itq++)
       if ((*itq).EnuTypeQuelconque() == DEF_P_DANS_V_A)
          { Tab_Grandeur_Vecteur& tyTQ= *((Tab_Grandeur_Vecteur*) (*itq).Grandeur_pointee()); // pour simplifier
            int taille = tyTQ.Taille()+nb_loi;
            tyTQ.Change_taille(taille); nexistePas = false;
       };
    if (nexistePas)
      {TypeQuelconque typQ1(DEF_P_DANS_V_A,EPS11,grand_vecteur_3);
         liTQ.push_back(typQ1);
     };
   };

   // ---- la suite dépend de l'indicateur : sortie_post
   if (sortie_post)
    { // j) ----- NB_INCRE_TOTAL_RESIDU
     {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
      for (itq=liTQ.begin();itq!=itqfin;itq++)
        if ((*itq).EnuTypeQuelconque() == NB_INCRE_TOTAL_RESIDU)
         {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          int taille = tyTQ.Taille()+1;
          tyTQ.Change_taille(taille); nexistePas = false;
         };
      if (nexistePas)
        {TypeQuelconque typQ1(NB_INCRE_TOTAL_RESIDU,SIG11,grand_courant);
         liTQ.push_back(typQ1);
        };
     };
     // k) ----- NB_ITER_TOTAL_RESIDU
     {List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end(); bool nexistePas = true;
      for (itq=liTQ.begin();itq!=itqfin;itq++)
        if ((*itq).EnuTypeQuelconque() == NB_ITER_TOTAL_RESIDU)
         {Tab_Grandeur_scalaire_double& tyTQ= *((Tab_Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          int taille = tyTQ.Taille()+1;
          tyTQ.Change_taille(taille); nexistePas = false;
         };
      if (nexistePas)
        {TypeQuelconque typQ1(NB_ITER_TOTAL_RESIDU,SIG11,grand_courant);
         liTQ.push_back(typQ1);
        };
     };
    }; // fin du cas ou sortie_post est actif, c-a-d que l'on veut des infos sur les indicateurs  de résolution

  };
  
	   //----- lecture écriture de restart -----
	   // cas donne le niveau de la récupération
       // = 1 : on récupère tout
       // = 2 : on récupère uniquement les données variables (supposées comme telles)
 void LoiContraintesPlanesDouble::Lecture_base_info_loi(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { if (cas == 1) 
     { string st1; string nom;
       ent >> st1 >> nom >> type_de_contrainte >> nom >> fac_penal >> nom >> prec;
       // --- paramètre de réglage
       ent >> nom ; // lecture de "parametre_algo_newton_equadiff:"
       alg_zero.Lecture_base_info(ent,cas);
       // le paramètre maxi_delta_var_eps_sur_iter_pour_Newton
       ent >> nom >> maxi_delta_var_eps_sur_iter_pour_Newton ;
       // pilotage éventuel de la précision
       ent >> nom;
       if (nom != "non_pilot_tol_residu")
        { ent >> nom; // lecture fct locale ou globale
          if (nom == "fct_globale")
            {ent >> nom; // lecture du nom de la fonction
             if (fct_tolerance_residu != NULL)
               delete fct_tolerance_residu;
             // maintenant on définit la fonction
             if (lesFonctionsnD.Existe(nom))
                  {fct_tolerance_residu = lesFonctionsnD.Trouve(nom);}
             else { cout << "\n *** erreur en lecture de la fonction nD " << nom
                         << " on ne la trouve pas !! ";
                    Sortie(1);
                  };
            }
          else // sinon c'est une fonction locale
           { if (nom != "fct_locale")
               { cout << "\n *** erreur en lecture de la fonction nD "
                      << " on attendait le mot cle fct_locale !! ";
                 Sortie(1);
               }
             else
              {// on lit le type de fonction
               ent >> nom; EnumFonction_nD enu = Id_Nom_Fonction_nD(nom);
               nom = "_";
               fct_tolerance_residu = Fonction_nD::New_Fonction_nD(nom, enu);
               fct_tolerance_residu->Lecture_base_info(ent,cas);
              };
           };
        };
         
       if (nom != "non_pilot_tol_residu")
        { ent >> nom; // lecture fct locale ou globale
          if (nom == "fct_globale")
            {ent >> nom; // lecture du nom de la fonction
             if (fct_tolerance_residu_rel != NULL)
               delete fct_tolerance_residu_rel;
             // maintenant on définit la fonction
             if (lesFonctionsnD.Existe(nom))
                  {fct_tolerance_residu_rel = lesFonctionsnD.Trouve(nom);}
             else { cout << "\n *** erreur en lecture de la fonction nD " << nom
                         << " on ne la trouve pas !! ";
                    Sortie(1);
                  };
            }
          else // sinon c'est une fonction locale
           { if (nom != "fct_locale")
               { cout << "\n *** erreur en lecture de la fonction nD "
                      << " on attendait le mot cle fct_locale !! ";
                 Sortie(1);
               }
             else
              {// on lit le type de fonction
               ent >> nom; EnumFonction_nD enu = Id_Nom_Fonction_nD(nom);
               nom = "_";
               fct_tolerance_residu_rel = Fonction_nD::New_Fonction_nD(nom, enu);
               fct_tolerance_residu_rel->Lecture_base_info(ent,cas);
              };
           };
        };
      
       // les autres paramètres
       ent >>  nom; // entête
       ent >>  nom >>  mini_hsurh0;
       ent >>  nom >>  mini_bsurb0;
       // le niveau d'affichage
       Lecture_permet_affichage(ent,cas,lesFonctionsnD);
       ent >>  nom >> sortie_post >> nom >> calcul_en_3D_via_direction_quelconque;
// non cas l'affichage dans l'algo est propre à l'algo       alg_zero.Modif_affichage(permet_affichage); // on met à jour l'algo de newton
       // --- la loi associée
       ent >> nom ;

 	     if (st1 != "LOI_CONTRAINTES_PLANES_DOUBLE")
	       { cout << "\n erreur en lecture de la loi : LOI_CONTRAINTES_PLANES_DOUBLE, on attendait le mot cle : LOI_CONTRAINTES_PLANES_DOUBLE "
	              << " et on a lue: " << st1
					          << "\n LoiContraintesPlanesDouble::Lecture_base_info_loi(...";
	         Sortie(1);
        };

       // on lit la loi 3D
       ent >> st1; lois_interne = (Loi_comp_abstraite *) LesLoisDeComp::Def_loi(st1);
       lois_interne->Lecture_base_info_loi(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
     }
    else
     { // on utilise directement la  loi déjà défini
       lois_interne->Lecture_base_info_loi(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
     };
  }; 

       // cas donne le niveau de sauvegarde
       // = 1 : on sauvegarde tout
       // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LoiContraintesPlanesDouble::Ecriture_base_info_loi(ofstream& sort,const int cas)
  { if (cas == 1) 
     { sort << "\n  LOI_CONTRAINTES_PLANES_DOUBLE " << " type_de_contrainte= " << type_de_contrainte
            << " fac_penal= " << fac_penal << " prec= " << prec ;
       // --- paramètre de réglage
       sort << "\n parametre_algo_newton_equadiff:--> ";
       alg_zero.Ecriture_base_info(sort,cas);
       // le paramètre maxi_delta_var_eps_sur_iter_pour_Newton
       sort << " maxi_delta_var_eps_sur_iter_pour_Newton_ "<<maxi_delta_var_eps_sur_iter_pour_Newton << " ";
       // pilotage éventuel de la précision
       if (fct_tolerance_residu == NULL)
          sort << " non_pilot_tol_residu ";
       else
          {sort << " pilot_tol_residu ";
           if (fct_tolerance_residu->NomFonction() != "_")
             sort << " fct_globale " << fct_tolerance_residu->NomFonction();
           else
             {sort << " fct_locale " << Nom_Fonction_nD(fct_tolerance_residu->Type_Fonction());
              fct_tolerance_residu->Ecriture_base_info(sort,cas);
             }
           sort << "\n";
          };
       if (fct_tolerance_residu_rel == NULL)
          sort << " non_pilot_tol_resi_rel ";
       else
          {sort << " pilot_tol_resi_rel ";
           if (fct_tolerance_residu_rel->NomFonction() != "_")
             sort << " fct_globale " << fct_tolerance_residu_rel->NomFonction();
           else
             {sort << " fct_locale "<< Nom_Fonction_nD(fct_tolerance_residu->Type_Fonction());
              fct_tolerance_residu_rel->Ecriture_base_info(sort,cas);
             }
           sort << "\n";
          };
      
       // les autres paramètres
       sort << "\n autres-parametres_loiCP2:--> ";
       sort << "\n mini_hsurh0: "<<mini_hsurh0;
       sort << "\n mini_bsurb0: "<<mini_bsurb0;
       // niveau d'affichage
       Affiche_niveau_affichage(sort,cas);
       sort << " sortie_post " << sortie_post
            << " calcul_en_3D_via_direction_quelconque " << calcul_en_3D_via_direction_quelconque;
       // --- la loi associée
       sort <<"\n -->loi_associee_CP2: ";

       sort << lois_interne->Nom_comport() << "  "; lois_interne->Ecriture_base_info_loi(sort,cas);
     }
    else
     { lois_interne->Ecriture_base_info_loi(sort,cas);
     }       
  }; 
            

 // ========== codage des METHODES VIRTUELLES  protegees:================
        // calcul des contraintes a t+dt
void LoiContraintesPlanesDouble::Calcul_SigmaHH
            (TenseurHH& sigHH_t,TenseurBB& DepsBB,DdlElement & tab_ddl
             ,TenseurBB & gijBB_t,TenseurHH & gijHH_t,BaseB& giB,BaseH& gi_H
             ,TenseurBB & epsBB_,TenseurBB & delta_epsBB
             ,TenseurBB & gijBB_,TenseurHH & gijHH_,Tableau <TenseurBB *>& d_gijBB_
             ,double& jacobien_0,double& jacobien,TenseurHH & sigHH
             ,EnergieMeca & energ,const EnergieMeca &
             ,double& module_compressibilite,double&  module_cisaillement
             ,const Met_abstraite::Expli_t_tdt& ex
            )
{// récup du conteneur spécifique
 SaveResul_LoiContraintesPlanesDouble & save_resul = *((SaveResul_LoiContraintesPlanesDouble*) saveResul);
 module_compressibilite=module_cisaillement=0.; // init
 energ.Inita(0.); // initialisation des énergies mises en jeux
 
	// initialisation du tenseurs contrainte 
//	sig_HH_3D.Inita(0.);
 // pour les contraintes
 bool plusZero = true;
 sig_HH_t_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_t),plusZero);
// sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH),plusZero);
 
 // passage des informations spécifique à la loi le_SaveResul
 lois_interne->IndiqueSaveResult(save_resul.le_SaveResul);
 lois_interne->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
 lois_interne->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours

 // on sauvegarde les dimensions transverse, car elles vont être modifiées et si on doit
 // repartir au départ, ce ne sera plus possible sans cette sauvegarde
 double sauve_hsurh0=save_resul.hsurh0;
 double sauve_bsurb0=save_resul.bsurb0;
	// passage des métriques de l'ordre 1 vers 3
	Passage_metrique_ordre1_vers_3(ex);
	// passage des informations liées à la déformation  de 1 vers 3, et variation de volume éventuelle
	Vecteur* d_jacobien_tdt = NULL;      // ne sert pas ici
	Tableau <TenseurBB *>* d_epsBB=NULL; //   "    "
	Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_,d_epsBB,delta_epsBB
                                   ,jacobien_0,jacobien,d_jacobien_tdt,*(ex.jacobien_t));
	
	
  // choix entre calcul avec une boucle locale de Newton on non. Dans le premier cas il nous faut la version d_sig/d_eps
  // au lieu de d_sig/d_ddl
  bool mauvaise_convergence = false; // init
  switch (type_de_contrainte)
   {case NEWTON_LOCAL: // cas de la version d_sig/d_eps
     {
       // initialisation du tenseurs contrainte
       sig_HH_3D.Inita(0.);
       sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH),plusZero);
       // passage des métriques de l'ordre 1 vers 3
       Passage_metrique_ordre1_vers_3(ex);
       // passage des informations liées à la déformation  de 1 vers 3, et variation de volume éventuelle
       Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_,d_epsBB,delta_epsBB
                                          ,jacobien_0,jacobien,d_jacobien_tdt,*(ex.jacobien_t));

       // on appel la procédure de résolution de sig22_33(bsurb0,hsurh0)=(0,0)
       if ((sortie_post)&&(save_resul.indicateurs_resolution.Taille()!= 2)) // dimensionnement éventuelle de la sortie d'indicateurs
          save_resul.indicateurs_resolution.Change_taille(2);
       // ----- pour ce faire on appelle une méthode de recherche de zero
       val_initiale(1)=save_resul.b_tsurb0; // on démarre la recherche à la valeur à t
       val_initiale(2)=save_resul.h_tsurh0; // on démarre la recherche à la valeur à t
       // on impose que les grandeurs soient dans les limites admises
       if (Limitation_h_b(val_initiale(2),val_initiale(1)))
         {if (Permet_affichage() > 3)
            cout << "\n val initiales:  LoiContraintesPlanesDouble::Calcul_SigmaHH(... " << endl;
         };
       racine.Zero();            // init du résultat à 0., mais c'est une grandeur de sortie donc cela ne sert à rien
       der_at_racine.Initialise(0.); // init de la matrice dérivée à 0.
       try // on met le bloc sous surveillance
        {
         int nb_incr_total,nb_iter_total; // variables intermédiaires d'indicateurs, pas utilisées ici
         
         // dans le cas où on utilise une précision qui est pilotée
         {// opération de transmission de la métrique: encapsulé ici
          const Met_abstraite::Impli* ex_impli = NULL;
          const Met_abstraite::Expli_t_tdt* ex_expli_tdt = &ex;
          const Met_abstraite::Umat_cont* ex_expli = NULL;

          if (fct_tolerance_residu != NULL)
           {// 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 = fct_tolerance_residu->Li_enu_etendu_scalaire();
            List_io <TypeQuelconque >& li_quelc = fct_tolerance_residu->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 = fct_tolerance_residu->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 de pilotage de la precision "
                      << " doit calculer un scalaire or le tableau de retour est de taille "
                      << tab_val.Taille() << " ce n'est pas normal !\n";
                 cout << " LoiContraintesPlanesDouble::Calcul_SigmaHH\n";
                 Sortie(1);
               };
            #endif
            // on récupère le premier élément du tableau uniquement
            double tol = tab_val(1);
            #ifdef MISE_AU_POINT
            if (Permet_affichage() > 5)
               cout << "\n Newton_prec: tol_= "<< tol;
            #endif
            alg_zero.Modif_prec_res_abs(tol);
          };

          if (fct_tolerance_residu_rel != NULL)
           {// 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 = fct_tolerance_residu_rel->Li_enu_etendu_scalaire();
            List_io <TypeQuelconque >& li_quelc = fct_tolerance_residu_rel->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 = fct_tolerance_residu_rel->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 de pilotage de la precision relative "
                      << " doit calculer un scalaire or le tableau de retour est de taille "
                      << tab_val.Taille() << " ce n'est pas normal !\n";
                 cout << " LoiContraintesPlanesDouble::Calcul_SigmaHH\n";
                 Sortie(1);
               };
            #endif
            // on récupère le premier élément du tableau uniquement
            double tol_rel = tab_val(1);
            #ifdef MISE_AU_POINT
            if (Permet_affichage() > 5)
               cout << ", tol_relative= "<< tol_rel;
            #endif
            alg_zero.Modif_prec_res_rel(tol_rel);
          };
         };
         
         //  résolution de l'équation constitutive d'avancement discrétisée en euler implicite
         bool conver=alg_zero.Newton_raphson
                  (*this,&LoiContraintesPlanesDouble::Residu_constitutif,&LoiContraintesPlanesDouble::Mat_tangente_constitutif
                   ,val_initiale,racine,der_at_racine,nb_incr_total,nb_iter_total
                   ,maxi_delta_var_eps_sur_iter_pour_Newton);
         if(sortie_post) // sauvegarde éventuelle des indicateurs
              {save_resul.indicateurs_resolution(1)+=nb_incr_total;
               save_resul.indicateurs_resolution(2)+=nb_iter_total;
////---- debug
//               cout << "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt: indicateurs_resolution(1)= "<< save_resul.indicateurs_resolution(1)
//                    << "  indicateurs_resolution(2)=" << save_resul.indicateurs_resolution(2)
//                    << " nb_incr_total "<< nb_incr_total << " nb_iter_total "<< nb_iter_total<< endl;
////---- fin debug
              };
         // on vérifie qu'il n'y a pas de pb de convergence
         double absracinemax=racine.Max_val_abs();
         if ((!conver) || (!isfinite(absracinemax)) || (isnan(absracinemax)) )
           { if (Permet_affichage() > 0)
               { cout << "\n non convergence sur l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                      << "\n b/b_0(t+dt)= " << racine(1) << " a t = " << save_resul.b_tsurb0
                      << " h/h_0(t+dt)= " << racine(2) << " a t = " << save_resul.h_tsurh0
                      << "\n nb_incr_total=" << nb_incr_total
                      << " nb_iter_total=" << nb_iter_total
                      << "\n LoiContraintesPlanesDouble::Calcul_SigmaHH (...";
               };
             // on garde en mémoire
             mauvaise_convergence=true;
           };
         // on vérifie que les nouvelles dimensions transversales ne sont pas négatives
         if ((racine(1) < 0.) || (racine(2) < 0.) )
             { if (Permet_affichage() > 0)
                 { cout << "\n **** erreur dans la resolution : on obtient une "
                        << " dimension transversale negative "
                        << "\n b/b_0(t+dt)= " << racine(1) << " a t = " << save_resul.b_tsurb0
                        << ", h/h_0(t+dt)= " << racine(2) << " a t = " << save_resul.h_tsurh0
                        << "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt (...";
                 };
               // on garde en mémoire
               mauvaise_convergence=true;
             };
        }
       catch (ErrNonConvergence_Newton erreur)
         {
          if (Permet_affichage() > 0)
               { cout << "\n erreur de non convergence avec l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                      << " on obtient une valeur infinie  ou NaN "
                      << "\n LoiContraintesPlanesDouble::Calcul_SigmaHH_tdt (...";
               };
          // on garde en mémoire
          mauvaise_convergence=true;
         }
       catch (ErrSortieFinale)
            // cas d'une direction voulue vers la sortie
            // on relance l'interuption pour le niveau supérieur
          { ErrSortieFinale toto;
            throw (toto);
          }
       catch ( ... )
        { // dans le cas d'une erreur inconnue, on génère également une exception
          if (Permet_affichage() > 0)
               { cout << "\n erreur non identifiee sur l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                      << "\n LoiContraintesPlanesDouble::Calcul_SigmaHH (...";
               };
          // on garde en mémoire
          mauvaise_convergence=true;
        };
       if (!mauvaise_convergence)
         { // arrivée ici, cela veut dire que tout à bien fonctionné
           save_resul.bsurb0 = racine(1); // récup de la solution
           save_resul.hsurh0 = racine(2); // récup de la solution
           // on met à jour les modules
           module_compressibilite= module_compressibilite_3D;
           module_cisaillement= module_cisaillement_3D;
          
           // passage des tenseurs résultats à l'ordre 1
           ((Tenseur1HH*) &sigHH)->Affectation_trans_dimension(sig_HH_3D,false);
           break;
         };
       // sinon on ne fait pas de break, donc on continue avec la méthode de perturbation
     };

    default: // cas de la version d_sig/d_ddl
     {
       // initialisation du tenseurs contrainte
       sig_HH_3D.Inita(0.);
       sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH),plusZero);
       // récup de l'épaisseur et la largeur de départ
       // on impose que les grandeurs sauvegardées soient dans les limites admises
       if (Limitation_h_b(sauve_hsurh0,sauve_bsurb0))
        {if (Permet_affichage() > 3)
           cout << "calcul direct sans Newton "
                <<  "\n LoiContraintesPlanesDouble::Calcul_SigmaHH(... " << endl;
        };
       save_resul.hsurh0 = sauve_hsurh0;
       save_resul.bsurb0 = sauve_bsurb0;
       // passage des métriques de l'ordre 1 vers 3
       Passage_metrique_ordre1_vers_3(ex);
       // passage des informations liées à la déformation  de 1 vers 3, et variation de volume éventuelle
       Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_,d_epsBB,delta_epsBB
                                              ,jacobien_0,jacobien,d_jacobien_tdt,*(ex.jacobien_t));
     
       lois_interne->Calcul_SigmaHH(sig_HH_t_3D,Deps_BB_3D,tab_ddl,gijBB_t_3D,gijHH_t_3D,giB_tdt_3D,giH_tdt_3D
                 ,eps_BB_3D,delta_eps_BB_3D
                 ,gijBB_tdt_3D,gijHH_tdt_3D,d_gijBB_tdt_3D_P,jacobien_0_3D,jacobien_tdt_3D,sig_HH_3D
                 ,save_resul.l_energ,save_resul.l_energ_t,module_compressibilite,module_cisaillement,*expli_3D
                 );

      // passage des tenseurs résultats à l'ordre 1
      ((Tenseur1HH*) &sigHH)->Affectation_trans_dimension(sig_HH_3D,false);
      if ((Permet_affichage() > 0) && mauvaise_convergence)
          { cout << "\n valeur final de  h/h_0(t+dt)= " << save_resul.hsurh0
                 << " et de  b/b_0(t+dt)= " << save_resul.bsurb0;
          };
      //	sigHH_tdt.Ecriture(cout);
  //debug
  //cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt sig33_3D= "<<sig_HH_3D(3,3)<<endl;
  // fin debug
     }
    break;
   };
 
 
	(*save_resul.l_sigoHH) = sig_HH_3D; // sauvegarde en locale
	// ---calcul des invariants de déformation et de vitesse de déformation
 Calcul_invariants_et_def_cumul();
  
 // --- on remet à jour éventuellement l'épaisseur
 // dans le cas d'une contrainte par perturbation
  if (type_de_contrainte == PERTURBATION )
    // calcul de la déformation d'épaisseur correspondant à la condition de contraintes planes
    {Tenseur3BH sigBH = gijBB_tdt_3D * sig_HH_3D;
     Tenseur3BH sigBH_t = gijBB_t_3D * sig_HH_t_3D;
     Calcul_eps_trans_parVarVolume1(sigBH_t,jacobien_0,module_compressibilite,jacobien,sigBH,*(ex.jacobien_t));
     if  ((Permet_affichage() > 0) && mauvaise_convergence)
          { cout << "\n valeur final de  h/h_0(t+dt)= " << save_resul.hsurh0
                 << " et de  b/b_0(t+dt)= " << save_resul.bsurb0;
          };
    };
	
	energ = save_resul.l_energ; // récup des énergies
	// passage des tenseurs résultats à l'ordre 1
	((Tenseur1HH*) &sigHH)->Affectation_trans_dimension(sig_HH_3D,false);
 //	sigHH_tdt.Ecriture(cout);
	LibereTenseur();   
 LibereTenseurQ();
 };
        
        // calcul des contraintes a t+dt et de ses variations  
void LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt (TenseurHH& sigHH_t,TenseurBB& DepsBB,DdlElement & tab_ddl
            ,BaseB& giB_t,TenseurBB & gijBB_t,TenseurHH & gijHH_t
            ,BaseB& giB_tdt,Tableau <BaseB> & d_giB_tdt,BaseH& giH_tdt,Tableau <BaseH> & d_giH_tdt
            ,TenseurBB & epsBB_tdt,Tableau <TenseurBB *>& d_epsBB
            ,TenseurBB & delta_epsBB,TenseurBB & gijBB_tdt,TenseurHH & gijHH_tdt
		          ,Tableau <TenseurBB *>& d_gijBB_tdt
		          ,Tableau <TenseurHH *>& d_gijHH_tdt,double& jacobien_0,double& jacobien
		          ,Vecteur& d_jacobien_tdt,TenseurHH& sigHH_tdt,Tableau <TenseurHH *>& d_sigHH
		          ,EnergieMeca & energ,const EnergieMeca & toto
		          ,double& module_compressibilite,double&  module_cisaillement
		          ,const Met_abstraite::Impli& ex)
{
 if (calcul_en_3D_via_direction_quelconque)
    {Passage_Calcul_1D_3D_dsigma_DsigmaHH_tdt(sigHH_t,DepsBB,tab_ddl,giB_t,gijBB_t,gijHH_t
            ,giB_tdt,d_giB_tdt,giH_tdt,d_giH_tdt,epsBB_tdt,d_epsBB,delta_epsBB,gijBB_tdt,gijHH_tdt
            ,d_gijBB_tdt,d_gijHH_tdt,jacobien_0,jacobien,d_jacobien_tdt,sigHH_tdt,d_sigHH
            ,energ,toto,module_compressibilite,module_cisaillement,ex);
     return;
    };
 // récup du conteneur spécifique
 SaveResul_LoiContraintesPlanesDouble & save_resul = *((SaveResul_LoiContraintesPlanesDouble*) saveResul);
 module_compressibilite=module_cisaillement=0.; // init
 energ.Inita(0.); // initialisation des énergies mises en jeux
	
 // on vérifie que les tableaux sont correctement
 // dimensionnés sinon on les modifie   
 int taille = d_sigHH.Taille();

	// on affecte et/ou on redimensionne éventuellement les tableaux contraintes-déformation fonctions du nombre de ddl
	// pour le passage 3D: on considère que tous les tableaux doivent avoir la même dimension: la même que dans le cas 1D
	int ta_d_sig_HH_3D = d_sig_HH_3D.Taille();
	if (ta_d_sig_HH_3D != taille)
	  { // cela veut dire que tous les tableaux sont mal dimensionnés
		   ta_d_sig_HH_3D = d_sigHH.Taille();
	    d_sig_HH_3D.Change_taille(ta_d_sig_HH_3D); d_sig_HH_3D_P.Change_taille(ta_d_sig_HH_3D);
	    for (int i=1;i<=ta_d_sig_HH_3D;i++) {d_sig_HH_3D_P(i) = &(d_sig_HH_3D(i));}
	  };
	for (int i=1;i<=ta_d_sig_HH_3D;i++) {d_sig_HH_3D_P(i)->Inita(0.);};
       
	// initialisation du tenseurs contrainte 
//	sig_HH_3D.Inita(0.);
 // --- pour les contraintes passage en 3D
 bool plusZero = true;
 sig_HH_t_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_t),plusZero);
// sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_tdt),plusZero);
 // --- pour la cinématique
 // passage des informations spécifique à la loi le_SaveResul
 lois_interne->IndiqueSaveResult(save_resul.le_SaveResul);
 lois_interne->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
 lois_interne->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours
 // on sauvegarde les dimensions transverse, car elles vont être modifiées et si on doit
 // repartir au départ, ce ne sera plus possible sans cette sauvegarde
 double sauve_hsurh0=save_resul.hsurh0;
 double sauve_bsurb0=save_resul.bsurb0;
	// passage des métriques de l'ordre 1 vers 3
//	Passage_metrique_ordre1_vers_3(ex);
	// passage des informations liées à la déformation  de 1 vers 3, et variation de volume
//	Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_tdt,&d_epsBB,delta_epsBB
//                                            ,jacobien_0,jacobien,&d_jacobien_tdt);

////debug
//cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt sig33= ";
//{Tenseur3BH epsBH = eps_BB_3D * gijHH_tdt_3D;
//cout << "\n epsBH=";epsBH.Ecriture(cout);
//int taille = d_eps_BB_3D.Taille();
//for (int i=1;i<=taille;i++)
//  { Tenseur3BH depsBH = d_eps_BB_3D(i) * gijHH_tdt_3D;
//    cout << "\n i= "<<i <<" depsBB33="<<d_eps_BB_3D(i)(3,3)<<" depsBB11="<<d_eps_BB_3D(i)(1,1)<<" depsBB22="<<d_eps_BB_3D(i)(2,2);
//    cout << "\n i= "<<i <<" depsBH33="<<depsBH(3,3)<<" depsBH11="<<depsBH(1,1)<<" depsBH22="<<depsBH(2,2);
//  };
//};
// //fin debug
 
 // choix entre calcul avec une boucle locale de Newton on non. Dans le premier cas il nous faut la version d_sig/d_eps
 // au lieu de d_sig/d_ddl
 bool mauvaise_convergence = false; // init
 switch (type_de_contrainte)
 {case NEWTON_LOCAL: // cas de la version d_sig/d_eps
   {
     // initialisation du tenseurs contrainte
     sig_HH_3D.Inita(0.);
     sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_tdt),plusZero);
     // passage des métriques de l'ordre 1 vers 3
     Passage_metrique_ordre1_vers_3(ex);
    
////--- debug
//     cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt";
//      for (int a = 1;a < 4; a++)
//        {cout << "\n giH_0("<<a<<"): "; (*umat_cont_3D->giH_0)(a).Affiche();
//        };
//// --- fin debug

     // passage des informations liées à la déformation  de 1 vers 3, et variation de volume
     Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_tdt,&d_epsBB,delta_epsBB
                                          ,jacobien_0,jacobien,&d_jacobien_tdt,*(ex.jacobien_t));
   
     // on appel la procédure de résolution de sig33(..)=0
       if ((sortie_post)&&(save_resul.indicateurs_resolution.Taille()!= 2)) // dimensionnement éventuelle de la sortie d'indicateurs
          save_resul.indicateurs_resolution.Change_taille(2);
// ----- pour ce faire on appelle une méthode de recherche de zero
     val_initiale(1)=save_resul.b_tsurb0; // on démarre la recherche à la valeur à t
     val_initiale(2)=save_resul.h_tsurh0; // on démarre la recherche à la valeur à t
     // on impose que les grandeurs soient dans les limites admises
     if (Limitation_h_b(val_initiale(2),val_initiale(1)))
       {if (Permet_affichage() > 3)
          cout << "\n val initiales:  LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt(... " << endl;
       };
     racine.Zero();            // init du résultat à 0., mais c'est une grandeur de sortie donc cela ne sert à rien
     der_at_racine.Initialise(0.); // init de la matrice dérivée à 0.
     try // on met le bloc sous surveillance
      {
       //  résolution de l'équation constitutive d'avancement discrétisée en euler implicite
       int nb_incr_total,nb_iter_total; // variables intermédiaires d'indicateurs, pas utilisées pour l'instant

       // dans le cas où on utilise une précision qui est pilotée
       { // opération de transmission de la métrique: encapsulé ici
         const Met_abstraite::Impli* ex_impli = &ex;
         const Met_abstraite::Expli_t_tdt* ex_expli_tdt = NULL;
         const Met_abstraite::Umat_cont* ex_expli = NULL;

         if (fct_tolerance_residu != NULL)
           {// 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 = fct_tolerance_residu->Li_enu_etendu_scalaire();
            List_io <TypeQuelconque >& li_quelc = fct_tolerance_residu->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 = fct_tolerance_residu->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 de pilotage de la precision "
                      << " doit calculer un scalaire or le tableau de retour est de taille "
                      << tab_val.Taille() << " ce n'est pas normal !\n";
                 cout << " LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt\n";
                 Sortie(1);
               };
            #endif
            // on récupère le premier élément du tableau uniquement
            double tol = tab_val(1);
            #ifdef MISE_AU_POINT
            if (Permet_affichage() >5)
               cout << "\n Newton_prec: tol_= "<< tol;
            #endif
            alg_zero.Modif_prec_res_abs(tol);
          };

         if (fct_tolerance_residu_rel != NULL)
           {// 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 = fct_tolerance_residu_rel->Li_enu_etendu_scalaire();
            List_io <TypeQuelconque >& li_quelc = fct_tolerance_residu_rel->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 = fct_tolerance_residu_rel->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 de pilotage de la precision relative "
                      << " doit calculer un scalaire or le tableau de retour est de taille "
                      << tab_val.Taille() << " ce n'est pas normal !\n";
                 cout << " LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt\n";
                 Sortie(1);
               };
            #endif
            // on récupère le premier élément du tableau uniquement
            double tol_rel = tab_val(1);
            #ifdef MISE_AU_POINT
            if (Permet_affichage() > 5)
               cout << ", tol_relative= "<< tol_rel;
            #endif
            alg_zero.Modif_prec_res_rel(tol_rel);
          };
       };
       
       bool conver=alg_zero.Newton_raphson
                (*this,&LoiContraintesPlanesDouble::Residu_constitutif,&LoiContraintesPlanesDouble::Mat_tangente_constitutif
                 ,val_initiale,racine,der_at_racine,nb_incr_total,nb_iter_total
                 ,maxi_delta_var_eps_sur_iter_pour_Newton);
       if(sortie_post) // sauvegarde éventuelle des indicateurs
              {save_resul.indicateurs_resolution(1)+=nb_incr_total;
               save_resul.indicateurs_resolution(2)+=nb_iter_total;
////---- debug
//               cout << "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt: indicateurs_resolution(1)= "<< save_resul.indicateurs_resolution(1)
//                    << "  indicateurs_resolution(2)=" << save_resul.indicateurs_resolution(2)
//                    << " nb_incr_total "<< nb_incr_total << " nb_iter_total "<< nb_iter_total<< endl;
////---- fin debug
              };
       // on vérifie qu'il n'y a pas de pb de convergence
       double absracinemax=racine.Max_val_abs();
       if ((!conver) || (!isfinite(absracinemax)) || (isnan(absracinemax)) )
           { if (Permet_affichage() > 0)
               { cout << "\n non convergence sur l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                      << "\n b/b_0(t+dt)= " << racine(1) << " a t = " << save_resul.b_tsurb0
                      << " h/h_0(t+dt)= " << racine(2) << " a t = " << save_resul.h_tsurh0
                      << "\n nb_incr_total=" << nb_incr_total
                      << " nb_iter_total=" << nb_iter_total
                      << "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt (...";
               };
             // on garde en mémoire
             mauvaise_convergence=true;
           };
       // on vérifie que les nouvelles dimensions transversales ne sont pas négatives
       if ((racine(1) < 0.) || (racine(2) < 0.) )
           { if (Permet_affichage() > 0)
               { cout << "\n **** erreur dans la resolution : on obtient une "
                      << " dimension transversale negative "
                      << "\n b/b_0(t+dt)= " << racine(1) << " a t = " << save_resul.b_tsurb0
                      << ", h/h_0(t+dt)= " << racine(2) << " a t = " << save_resul.h_tsurh0
                      << "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt (...";
               };
             // on garde en mémoire
             mauvaise_convergence=true;
           };
      }
     catch (ErrNonConvergence_Newton erreur)
         {
          if (Permet_affichage() > 0)
               { cout << "\n erreur de non convergence avec l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                      << " on obtient une valeur infinie  ou NaN "
                      << "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt (...";
               };
          // on garde en mémoire
          mauvaise_convergence=true;
         }
     catch (ErrSortieFinale)
          // cas d'une direction voulue vers la sortie
          // on relance l'interuption pour le niveau supérieur
        { ErrSortieFinale toto;
          throw (toto);
        }
     catch ( ... )
        { // dans le cas d'une erreur inconnue, on génère également une exception
          if (Permet_affichage() > 0)
               { cout << "\n erreur non identifiee sur l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                      << "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt (...";
               };
          // on garde en mémoire
          mauvaise_convergence=true;
        };
     if (!mauvaise_convergence)
        { // arrivée ici, cela veut dire que tout à bien fonctionné
          save_resul.bsurb0 = racine(1); // récup de la solution
          save_resul.hsurh0 = racine(2); // récup de la solution
          // on met à jour les modules
          module_compressibilite= module_compressibilite_3D;
          module_cisaillement= module_cisaillement_3D;
    
         
          // calcul de la variation de la déformation d'épaisseur et de largeur en fonction de la def_11
          Calcul_d_eps_eg_11(); // calcul des termes d_eps_ef_11
         
          // récup de la variation de d sig^{11}/ d eps_22 et 33
          Tableau <Tenseur1HH> d_sig11_deps_gh_HH(2);
          d_sig11_deps_gh_HH(1).Coor(1,1)=d_sigma_deps_3D(1,1,2,2);
          d_sig11_deps_gh_HH(2).Coor(1,1)=d_sigma_deps_3D(1,1,3,3);
          // construction de la variation de d sig^{11} / d eps_{11)
          Tenseur1HH d_sig11_deps_11(d_sigma_deps_3D(1,1,1,1));
//      //debug
//      cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt cas Newton_local avant ";
//      d_sig11_deps_11.Ecriture(cout);
//      // fin debug
          d_sig11_deps_11.Coor(1,1) +=   d_sigma_deps_3D(1,1,2,2) * d_eps_ef_11(1)
                                  + d_sigma_deps_3D(1,1,3,3) * d_eps_ef_11(2);
         
////      //debug
//      cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt cas Newton_local apres ";
//      d_sig11_deps_11.Ecriture(cout);
////      // fin debug
         
          // passage des tenseurs résultats à l'ordre 1
          ((Tenseur1HH*) &sigHH_tdt)->Affectation_trans_dimension(sig_HH_3D,false);
          // on calcul la matrice tangente en contrainte plane double
          // on a : d_sigHH_tdt/d_ddl = d_sigHH_tdt/d_eps * d_eps/d_ddl
      //debug
      //cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt cas Newton_local ";
      //d_sigma_deps_3D.Ecriture(cout);
      // fin debug
          
           if (Permet_affichage() > 7)
              { cout << "\n ContraintesPlanes: dans le repere locale d_sigma_deps_3D=  \n";
                int e=1;
                for (int i=1;i<4;i++) for (int j=1;j<4;j++) for (int k=1;k<4;k++)for (int l=1;l<4;l++,e++)
                   { cout << "("<<i<<","<<j<<","<<k<<","<<l<<")= "<<d_sigma_deps_3D(i,j,k,l) << " ; ";
                     if (e>6) {cout << "\n"; e=1;}
                   };
                Tenseur3HHHH  inter_HHHH;
                d_sigma_deps_3D.ChangeBase(inter_HHHH,giB_tdt_3D);
                cout << "\n dans le repere orthonormee d_sigma_deps_3D=  \n";
                e=1;
                for (int i=1;i<4;i++) for (int j=1;j<4;j++) for (int k=1;k<4;k++)for (int l=1;l<4;l++,e++)
                   { cout << "("<<i<<","<<j<<","<<k<<","<<l<<")= "<<inter_HHHH(i,j,k,l) << " ; ";
                     if (e>6) {cout << "\n"; e=1;}
                   };
              };
            
           for (int i = 1; i<= taille; i++)
            { // on fait uniquement une égalité d'adresse et de ne pas utiliser
              // le constructeur d'ou la profusion d'* et de ()
             
              Tenseur1HH & dsigHH = *((Tenseur1HH*) (d_sigHH(i)));  // passage en dim 1
              const Tenseur1BB & depsBB = *((Tenseur1BB *) (d_epsBB(i))); //    "
              dsigHH.Coor(1,1) = d_sig11_deps_11(1,1) * depsBB(1,1);
             
//      //debug
//      cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt cas Newton_local (2) dsigHH=";
//      dsigHH.Ecriture(cout);
//      // fin debug
             };
           break;
         };
       // sinon on ne fait pas de break, donc on continue avec la méthode de perturbation
   };

    default: // cas de la version d_sig/d_ddl, on encore du cas où la méthode de Newton n'a pas convergé


//debug
//cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt cas Newton_local ";
//d_sigma_deps_3D.Ecriture(cout);
// fin debug
    {
     // initialisation du tenseurs contrainte
     sig_HH_3D.Inita(0.);
     sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_tdt),plusZero);
     // récup de l'épaisseur et la largeur de départ
     save_resul.hsurh0 = sauve_hsurh0;
     save_resul.bsurb0 = sauve_bsurb0;
     // on impose que les grandeurs sauvegardées soient dans les limites admises
     if (Limitation_h_b(sauve_hsurh0,sauve_bsurb0))
      {if (Permet_affichage() > 3)
         cout << "calcul direct sans Newton "
              <<  "\n LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt(... " << endl;
      };
     // passage des métriques de l'ordre 1 vers 3
     Passage_metrique_ordre1_vers_3(ex);
     // passage des informations liées à la déformation  de 1 vers 3, et variation de volume
     Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_tdt,&d_epsBB,delta_epsBB
                                         ,jacobien_0,jacobien,&d_jacobien_tdt,*(ex.jacobien_t));
   
     lois_interne->Calcul_DsigmaHH_tdt(sig_HH_t_3D,Deps_BB_3D,tab_ddl,giB_t_3D,gijBB_t_3D,gijHH_t_3D
                                    ,giB_tdt_3D,d_giB_tdt_3D,giH_tdt_3D,d_giH_tdt_3D
                                    ,eps_BB_3D,d_eps_BB_3D_P,delta_eps_BB_3D,gijBB_tdt_3D,gijHH_tdt_3D,d_gijBB_tdt_3D_P
                                    ,d_gijHH_tdt_3D_P,jacobien_0_3D,jacobien_tdt_3D,d_jacobien_tdt_3D
                                    ,sig_HH_3D,d_sig_HH_3D_P
                                    ,save_resul.l_energ,save_resul.l_energ_t,module_compressibilite,module_cisaillement,*impli_3D
                                    );

    // passage des tenseurs résultats à l'ordre 1
    ((Tenseur1HH*) &sigHH_tdt)->Affectation_trans_dimension(sig_HH_3D,false);
    //	sigHH_tdt.Ecriture(cout);
      // récup de l'opérateur tangent
    for (int k=1;k<=taille;k++)
          ((Tenseur1HH*) d_sigHH(k))->Affectation_trans_dimension(*d_sig_HH_3D_P(k),false);
     
    if (mauvaise_convergence)
     {if (Permet_affichage() > 0)
       { cout << "\n valeur final de  h/h_0(t+dt)= " << save_resul.hsurh0
              << " et de  b/b_0(t+dt)= " << save_resul.bsurb0;
       };
      // on annulle les dérivées des épaisseurs
      save_resul.d_hsurh0.Zero();save_resul.d_bsurb0.Zero();
     };

//debug
//cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt sig33_3D= "<<sig_HH_3D(3,3)<<endl;
// fin debug
   }
  break;
 };
 
  // informations éventuelles
  #ifdef MISE_AU_POINT
  if  (Permet_affichage() > 7)
    { cout << "\nLoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt ";
      TenseurHH* ptHH = NevezTenseurHH(sig_HH_3D);
      sig_HH_3D.BaseAbsolue(*ptHH,giB_tdt_3D);
      cout << "\n sigma apres CP2: ";
      ptHH->Ecriture(cout);
      delete ptHH;
    };
  #endif
 // sig_HH_3D.Ecriture(cout);
			       
	(*save_resul.l_sigoHH) = sig_HH_3D; // sauvegarde en locale
	// ---calcul des invariants de déformation et de vitesse de déformation
 Calcul_invariants_et_def_cumul();
	
	energ = save_resul.l_energ; // récup des énergies
 
 // --- on remet à jour éventuellement l'épaisseur
 // dans le cas d'une contrainte par perturbation
//  if ((type_de_contrainte == PERTURBATION )||mauvaise_convergence)
 if (type_de_contrainte == PERTURBATION )
    // calcul de la déformation d'épaisseur correspondant à la condition de contraintes planes
    { //Tenseur1BH sigBH = gijBB_tdt * sigHH_tdt;
      Tenseur3BH sigBH = gijBB_tdt_3D * sig_HH_3D;
      Calcul_d_eps_trans_parVarVolume(jacobien_0,module_compressibilite,jacobien,sigHH_tdt,d_jacobien_tdt
                    ,d_sigHH,d_gijBB_tdt,gijBB_tdt);
      if  ((Permet_affichage() > 0) && mauvaise_convergence)
          { cout << "\n valeur final de  h/h_0(t+dt)= " << save_resul.hsurh0
                 << " et de  b/b_0(t+dt)= " << save_resul.bsurb0;
          };
    };

//debug
//cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt: sigHH_tdt  ";
//sigHH_tdt.Ecriture(cout);
//for (int i = 1; i<= taille; i++)
// { // on fait uniquement une égalité d'adresse et de ne pas utiliser
//   // le constructeur d'ou la profusion d'* et de ()
//   Tenseur1HH & dsigHH = *((Tenseur1HH*) (d_sigHH(i)));  // passage en dim 1
//   cout << "\n d_sigHH("<<i<<") ";
//    dsigHH.Ecriture(cout);
// };
// fin debug

// fin debug
  LibereTenseur();
  LibereTenseurQ();
//---debug
//fichier.close();
//---fin debug
};
		  	
        // calcul des contraintes et ses variations  par rapport aux déformations a t+dt
        // en_base_orthonormee:  le tenseur de contrainte en entrée est  en orthonormee
        //                  le tenseur de déformation et son incrémentsont également en orthonormees
        //                 si = false: les bases transmises sont utilisées
        // ex: contient les éléments de métrique relativement au paramétrage matériel = X_(0)^a
void LoiContraintesPlanesDouble::Calcul_dsigma_deps
           (bool en_base_orthonormee, TenseurHH & sigHH_t,TenseurBB& DepsBB
            ,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB,double& jacobien_0,double& jacobien
            ,TenseurHH& sigHH_tdt,TenseurHHHH& d_sigma_deps
            ,EnergieMeca & energ,const EnergieMeca & toto
            ,double& module_compressibilite,double&  module_cisaillement
            ,const Met_abstraite::Umat_cont& ex
           )
 { // dans le cas particulier ou on veut utiliser le comportement dans une direction quelconque
   if (calcul_en_3D_via_direction_quelconque)
    {Passage_Calcul_1D_3D_dsigma_deps(en_base_orthonormee,sigHH_t,DepsBB,epsBB_tdt,delta_epsBB
                                     ,jacobien_0,jacobien,sigHH_tdt,d_sigma_deps,energ,toto
                                     ,module_compressibilite,module_cisaillement,ex);
     return;
    };
   //   --- sinon cas normal---
   // récup du conteneur spécifique
   SaveResul_LoiContraintesPlanesDouble & save_resul = *((SaveResul_LoiContraintesPlanesDouble*) saveResul);
   module_compressibilite=module_cisaillement=0.; // init
   energ.Inita(0.); // initialisation des énergies mises en jeux
	      
//   // initialisation du tenseurs contrainte
//   sig_HH_3D.Inita(0.);
   // --- pour les contraintes passage en 3D
   bool plusZero = true;
   // on affecte les contraintes a t: en fait pour les lois incrémentales, les infos à t
   // sont déjà stocké, donc cela ne sert à rien, mais pour une loi élastique par exemple ce n'est pas le cas
   sig_HH_t_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_t),plusZero);
   // idem pour tdt, mais là cela n'a pas d'importance, mais ça sert d'init
//   sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_tdt),plusZero);
   // --- pour la cinématique
   // passage des informations spécifique à la loi le_SaveResul
   lois_interne->IndiqueSaveResult(save_resul.le_SaveResul);
   lois_interne->IndiquePtIntegMecaInterne(ptintmeca_en_cours);// idem pour ptintmeca
   lois_interne->IndiqueDef_en_cours(def_en_cours); // idem pour def en cours
   // on sauvegarde les dimensions transverse, car elles vont être modifiées et si on doit
   // repartir au départ, ce ne sera plus possible sans cette sauvegarde
   double sauve_hsurh0=save_resul.hsurh0;
   double sauve_bsurb0=save_resul.bsurb0;
//   // passage des métriques de l'ordre 1 vers 3
//   Passage_metrique_ordre1_vers_3(ex);
//   // passage des informations liées à la déformation  de 1 vers 3, et variation de volume
//   Tableau <TenseurBB *>* toto = NULL; // pour dire que ce n'est pas attribué
//   Vecteur* titi = NULL;                // "    "    "
//   Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_tdt,toto,delta_epsBB
//                                              ,jacobien_0,jacobien,titi);
 
   // choix entre calcul avec une boucle locale de Newton on non. Dans le premier cas il nous faut la version d_sig/d_eps
   // au lieu de d_sig/d_ddl
   bool mauvaise_convergence = false; // init
   switch (type_de_contrainte)
   {case NEWTON_LOCAL: // cas de la version d_sig/d_eps
     {
       // initialisation du tenseurs contrainte
       sig_HH_3D.Inita(0.);
       sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_tdt),plusZero);
       // passage des métriques de l'ordre 1 vers 3
       Passage_metrique_ordre1_vers_3(ex);
//---- debug
//if ((*(umat_cont_3D->giH_0))(2).Norme() < ConstMath::petit)
//   {cout << "\n debug LoiContraintesPlanesDouble::Calcul_dsigma_deps ";
//    Passage_metrique_ordre1_vers_3(ex);
//   };
//cout << "\n debug LoiContraintesPlanesDouble::Calcul_dsigma_deps ";
//for (int a = 1;a < 4; a++)
//  {cout << "\n giB_0("<<a<<"): "; (*(save_resul.meti_ref_00.giB_))(a).Affiche();
//   cout << "\n giH_0("<<a<<"): "; (*(save_resul.meti_ref_00.giH_))(a).Affiche();
//  };

//-----fin debug
       // passage des informations liées à la déformation  de 1 vers 3, et variation de volume
       Tableau <TenseurBB *>* toto = NULL; // pour dire que ce n'est pas attribué
       Vecteur* titi = NULL;                // "    "    "
       Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_tdt,toto,delta_epsBB
                                             ,jacobien_0,jacobien,titi,*(ex.jacobien_t));
     
       // on appel la procédure de résolution de sig33(..)=0
       if ((sortie_post)&&(save_resul.indicateurs_resolution.Taille()!= 2)) // dimensionnement éventuelle de la sortie d'indicateurs
            save_resul.indicateurs_resolution.Change_taille(2);
  // ----- pour ce faire on appelle une méthode de recherche de zero
       val_initiale(1)=save_resul.b_tsurb0; // on démarre la recherche à la valeur à t
       val_initiale(2)=save_resul.h_tsurh0; // on démarre la recherche à la valeur à t
       // on impose que les grandeurs soient dans les limites admises
       if (Limitation_h_b(val_initiale(2),val_initiale(1)))
         {if (Permet_affichage() > 3)
            cout << "\n val initiales: LoiContraintesPlanesDouble::Calcul_dsigma_deps(... " << endl;
         };

//// ---- debut
//         // on vérifie que les anciennes transversales ne sont pas négatives
//         if ((val_initiale(1) < 0.) || (val_initiale(2) < 0.) )
//             { cout << "\n debug LoiContraintesPlanesDouble::Calcul_DsigmaHH_tdt :  "
//                    << " initialement "
//                    << "\n save_resul.b_tsurb0 = " << save_resul.b_tsurb0
//                    << ", save_resul.h_tsurh0 " << save_resul.h_tsurh0 << endl;
//               Sortie(1);
//             };
////------ fin debug

       racine.Zero();            // init du résultat à 0., mais c'est une grandeur de sortie donc cela ne sert à rien
       der_at_racine.Initialise(0.); // init de la matrice dérivée à 0.
       try // on met le bloc sous surveillance
        {
         //  résolution de l'équation constitutive d'avancement discrétisée en euler implicite
         int nb_incr_total,nb_iter_total; // variables intermédiaires d'indicateurs, pas utilisées pour l'instant

         // dans le cas où on utilise une précision qui est pilotée
         { // opération de transmission de la métrique: encapsulé ici
           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;

           if (fct_tolerance_residu != NULL)
             {// 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 = fct_tolerance_residu->Li_enu_etendu_scalaire();
              List_io <TypeQuelconque >& li_quelc = fct_tolerance_residu->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 = fct_tolerance_residu->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 de pilotage de la precision "
                        << " doit calculer un scalaire or le tableau de retour est de taille "
                        << tab_val.Taille() << " ce n'est pas normal !\n";
                   cout << " LoiContraintesPlanesDouble::Calcul_dsigma_deps\n";
                   Sortie(1);
                 };
              #endif
              // on récupère le premier élément du tableau uniquement
              double tol = tab_val(1);
              #ifdef MISE_AU_POINT
              if (Permet_affichage() > 5)
                 cout << "\n Newton_prec: tol_= "<< tol;
              #endif
              alg_zero.Modif_prec_res_abs(tol);
            };

           if (fct_tolerance_residu_rel != NULL)
             {// 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 = fct_tolerance_residu_rel->Li_enu_etendu_scalaire();
              List_io <TypeQuelconque >& li_quelc = fct_tolerance_residu_rel->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 = fct_tolerance_residu_rel->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 de pilotage de la precision relative "
                        << " doit calculer un scalaire or le tableau de retour est de taille "
                        << tab_val.Taille() << " ce n'est pas normal !\n";
                   cout << " LoiContraintesPlanesDouble::Calcul_dsigma_deps\n";
                   Sortie(1);
                 };
              #endif
              // on récupère le premier élément du tableau uniquement
              double tol_rel = tab_val(1);
              #ifdef MISE_AU_POINT
              if (Permet_affichage() > 5)
                 cout << ", tol_relative= "<< tol_rel;
              #endif
              alg_zero.Modif_prec_res_rel(tol_rel);
            };
         };
       
         bool conver=alg_zero.Newton_raphson
                             (*this,&LoiContraintesPlanesDouble::Residu_constitutif
                             ,&LoiContraintesPlanesDouble::Mat_tangente_constitutif
                             ,val_initiale,racine,der_at_racine,nb_incr_total,nb_iter_total
                             ,maxi_delta_var_eps_sur_iter_pour_Newton);
         if(sortie_post) // sauvegarde éventuelle des indicateurs
                {save_resul.indicateurs_resolution(1)+=nb_incr_total;
                 save_resul.indicateurs_resolution(2)+=nb_iter_total;
                };
         // on vérifie qu'il n'y a pas de pb de convergence
         double absracinemax=racine.Max_val_abs();
         if ((!conver) || (!isfinite(absracinemax)) || (isnan(absracinemax)) )
             { if (Permet_affichage() > 0)
                 { cout << "\n non convergence sur l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                        << "\n b/b_0(t+dt)= " << racine(1) << " a t = " << save_resul.b_tsurb0
                        << " h/h_0(t+dt)= " << racine(2) << " a t = " << save_resul.h_tsurh0
                        << "\n nb_incr_total=" << nb_incr_total
                        << " nb_iter_total=" << nb_iter_total
                        << "\n LoiContraintesPlanesDouble::Calcul_deps_tdt (...";
                 };
               // on garde en mémoire
               mauvaise_convergence=true;
             };
         // on vérifie que les nouvelles dimensions transversales ne sont pas négatives
         if ((racine(1) < 0.) || (racine(2) < 0.) )
             { if (Permet_affichage() > 0)
                 { cout << "\n **** erreur dans la resolution : on obtient une "
                        << " dimension transversale negative "
                        << "\n b/b_0(t+dt)= " << racine(1) << " a t = " << save_resul.b_tsurb0
                        << ", h/h_0(t+dt)= " << racine(2) << " a t = " << save_resul.h_tsurh0
                        << "\n LoiContraintesPlanesDouble::Calcul_deps_tdt (...";
                 };
               // on garde en mémoire
               mauvaise_convergence=true;
             };
        }
       catch (ErrNonConvergence_Newton erreur)
           {
            if (Permet_affichage() > 0)
                 { cout << "\n erreur de non convergence avec l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                        << " on obtient une valeur infinie  ou NaN "
                        << "\n LoiContraintesPlanesDouble::Calcul_deps_tdt (...";
                 };
            // on garde en mémoire
            mauvaise_convergence=true;
           }
       catch (ErrSortieFinale)
            // cas d'une direction voulue vers la sortie
            // on relance l'interuption pour le niveau supérieur
          { ErrSortieFinale toto;
            throw (toto);
          }
       catch ( ... )
          { // dans le cas d'une erreur inconnue, on génère également une exception
            if (Permet_affichage() > 0)
                 { cout << "\n erreur non identifiee sur l'algo de la resolution de sig22_33(bsurb0,hsurh0)=(0,0) "
                        << "\n LoiContraintesPlanesDouble::Calcul_deps_tdt (...";
                 };
            // on garde en mémoire
            mauvaise_convergence=true;
          };
       if (!mauvaise_convergence)
          { // arrivée ici, cela veut dire que tout à bien fonctionné
            save_resul.bsurb0 = racine(1); // récup de la solution
            save_resul.hsurh0 = racine(2); // récup de la solution
            // on met à jour les modules
            module_compressibilite= module_compressibilite_3D;
            module_cisaillement= module_cisaillement_3D;      
           
            // calcul de la variation de la déformation d'épaisseur et de largeur en fonction de la def_11
            Calcul_d_eps_eg_11(); // calcul des termes d_eps_ef_11
           
            // récup de la variation de d sig^{11}/ d eps_22 et 33
            Tableau <Tenseur1HH> d_sig11_deps_gh_HH(2);
            d_sig11_deps_gh_HH(1).Coor(1,1)=d_sigma_deps_3D(1,1,2,2);
            d_sig11_deps_gh_HH(2).Coor(1,1)=d_sigma_deps_3D(1,1,3,3);
            #ifdef MISE_AU_POINT
            if  (Permet_affichage() > 8)
             { cout << "\nLoiContraintesPlanesDouble::Calcul_dsigma_deps: bonne convergence de Newton ";
               cout << "\n d_sigma_deps_3D(1,1,1,1) "<< d_sigma_deps_3D(1,1,1,1)
                    << "\n d_sigma_deps_3D(1,1,2,2) "<< d_sigma_deps_3D(1,1,2,2)
                    << "\n d_sigma_deps_3D(1,1,3,3) "<< d_sigma_deps_3D(1,1,3,3)
                    << "\n d_eps_ef_11(1) "<< d_eps_ef_11(1) << ", d_eps_ef_11(2) "<< d_eps_ef_11(2)
                    << flush;
             };
            #endif
            // construction de la variation de d sig^{11} / d eps_{11)
            Tenseur1HH d_sig11_deps_11(d_sigma_deps_3D(1,1,1,1));
            d_sig11_deps_11.Coor(1,1) +=   d_sigma_deps_3D(1,1,2,2) * d_eps_ef_11(1)
                                    + d_sigma_deps_3D(1,1,3,3) * d_eps_ef_11(2);
            // on sauvegarde dans le format ad hoc
            d_sigma_deps.Inita(0.);
            d_sigma_deps.Change(1,1,1,1,d_sig11_deps_11(1,1));
            if ((!isfinite(d_sigma_deps_3D(1,1,1,1))) || (isnan(d_sigma_deps_3D(1,1,1,1))) )
                {cout << "\n *** attention d_sigma_deps_3D(1,1,1,1)= "<< d_sigma_deps_3D(1,1,1,1);
                 if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
                 cout << "\nLoiContraintesPlanesDouble::Calcul_dsigma_deps:";
                 cout << flush;
                };

            // passage des tenseurs résultats à l'ordre 1
            ((Tenseur1HH*) &sigHH_tdt)->Affectation_trans_dimension(sig_HH_3D,false);
            // on calcul la matrice tangente en contrainte plane double
            // on a : d_sigHH_tdt/d_ddl = d_sigHH_tdt/d_eps * d_eps/d_ddl
           
            #ifdef MISE_AU_POINT
            if  (Permet_affichage() > 7)
             { cout << "\nLoiContraintesPlanesDouble::Calcul_dsigma_deps: bonne convergence de Newton ";
               TenseurHH* ptHH = NevezTenseurHH(sig_HH_3D);
               sig_HH_3D.BaseAbsolue(*ptHH,giB_tdt_3D);
               cout << "\n sigma apres CP2: ";
               ptHH->Ecriture(cout);
               delete ptHH;
             };
             if (Permet_affichage() > 8)
                { cout << "\n dans le repere locale d_sigma_deps_3D=  \n";
                  int e=1;
                  for (int i=1;i<4;i++) for (int j=1;j<4;j++) for (int k=1;k<4;k++)for (int l=1;l<4;l++,e++)
                     { cout << "("<<i<<","<<j<<","<<k<<","<<l<<")= "<<d_sigma_deps_3D(i,j,k,l) << " ; ";
                       if (e>6) {cout << "\n"; e=1;}
                     };
                  Tenseur3HHHH  inter_HHHH;
                  d_sigma_deps_3D.ChangeBase(inter_HHHH,giB_tdt_3D);
                  cout << "\n dans le repere orthonormee d_sigma_deps_3D=  \n";
                  e=1;
                  for (int i=1;i<4;i++) for (int j=1;j<4;j++) for (int k=1;k<4;k++)for (int l=1;l<4;l++,e++)
                     { cout << "("<<i<<","<<j<<","<<k<<","<<l<<")= "<<inter_HHHH(i,j,k,l) << " ; ";
                       if (e>6) {cout << "\n"; e=1;}
                     };
                };
            #endif
            break;
           };
         // sinon on ne fait pas de break, donc on continue avec la méthode de perturbation
     };

      default: // cas de la version d_sig/d_ddl, on encore du cas où la méthode de Newton n'a pas convergé
       {
        // initialisation du tenseurs contrainte
        sig_HH_3D.Inita(0.);
        sig_HH_3D.Affectation_trans_dimension(*((Tenseur1HH*) &sigHH_tdt),plusZero);
        // récup de l'épaisseur et la largeur de départ
        // on impose que les grandeurs sauvegardées soient dans les limites admises
        if (Limitation_h_b(sauve_hsurh0,sauve_bsurb0))
         {if (Permet_affichage() > 3)
            cout << "calcul direct sans Newton "
                 <<  "\n LoiContraintesPlanesDouble::Calcul_dsigma_deps(... " << endl;
         };
        save_resul.hsurh0 = sauve_hsurh0;
        save_resul.bsurb0 = sauve_bsurb0;
        // passage des métriques de l'ordre 1 vers 3
        Passage_metrique_ordre1_vers_3(ex);
        // passage des informations liées à la déformation  de 1 vers 3, et variation de volume
        Tableau <TenseurBB *>* toto = NULL; // pour dire que ce n'est pas attribué
        Vecteur* titi = NULL;                // "    "    "
        Passage_deformation_volume_ordre1_vers_3(DepsBB,epsBB_tdt,toto,delta_epsBB
                                               ,jacobien_0,jacobien,titi,*(ex.jacobien_t));
       
        bool en_base_orthonormee = false; // ici les tenseurs ne sont pas forcément en orthonormee
        lois_interne->Calcul_dsigma_deps(en_base_orthonormee,sig_HH_t_3D,Deps_BB_3D
                                        ,eps_BB_3D,delta_eps_BB_3D,jacobien_0_3D,jacobien_tdt_3D
                                        ,sig_HH_3D,d_sigma_deps_3D
                                        ,save_resul.l_energ,save_resul.l_energ_t,module_compressibilite,module_cisaillement
                                        ,*umat_cont_3D);

       if ((!isfinite(d_sigma_deps_3D(1,1,1,1))) || (isnan(d_sigma_deps_3D(1,1,1,1))) )
           {cout << "\n *** attention d_sigma_deps_3D(1,1,1,1)= "<< d_sigma_deps_3D(1,1,1,1);
            if (Ptintmeca_en_cours() != NULL) Ptintmeca_en_cours()->Signature();
            cout << "\nLoiContraintesPlanesDouble::Calcul_dsigma_deps:";
            cout << flush;
           };
      // passage des tenseurs résultats à l'ordre 1
      ((Tenseur1HH*) &sigHH_tdt)->Affectation_trans_dimension(sig_HH_3D,false);
      // maintenant on renseigne le tenseur de sortie
      bool pluszero = true;
      d_sigma_deps.Affectation_trans_dimension(d_sigma_deps_3D, pluszero);
     
      if (mauvaise_convergence)
       {if (Permet_affichage() > 0)
         { cout << "\n valeur final de  h/h_0(t+dt)= " << save_resul.hsurh0
                << " et de  b/b_0(t+dt)= " << save_resul.bsurb0;
         };
        // on annulle les dérivées des épaisseurs
        save_resul.d_hsurh0.Zero();save_resul.d_bsurb0.Zero();
       };

     }
    break;
   };
 
   // sig_HH_3D.Ecriture(cout);
            
   (*save_resul.l_sigoHH) = sig_HH_3D; // sauvegarde en locale
   // ---calcul des invariants de déformation et de vitesse de déformation
   Calcul_invariants_et_def_cumul();
   
   energ = save_resul.l_energ; // récup des énergies
   
   // --- on remet à jour éventuellement l'épaisseur
   // dans le cas d'une contrainte par perturbation
//   if ((type_de_contrainte == PERTURBATION )||mauvaise_convergence)
   if (type_de_contrainte == PERTURBATION )
    // calcul de la déformation d'épaisseur correspondant à la condition de contraintes planes
    { //Tenseur1BH sigBH = gijBB_tdt * sigHH_tdt;
      Tenseur3BH sigBH = gijBB_tdt_3D * sig_HH_3D;
      Tenseur3BH sigBH_t = gijBB_t_3D * sig_HH_t_3D;
      Calcul_eps_trans_parVarVolume1(sigBH_t,jacobien_0,module_compressibilite,jacobien,sigBH,*(ex.jacobien_t));
      if  ((Permet_affichage() > 0) && mauvaise_convergence)
          { cout << "\n valeur final de  h/h_0(t+dt)= " << save_resul.hsurh0
                 << " et de  b/b_0(t+dt)= " << save_resul.bsurb0;
          };
    };

   LibereTenseur();
   LibereTenseurQ();
};








   
   
